Skip to content

Instantly share code, notes, and snippets.

@cimentadaj
Last active September 2, 2018 20:07
Show Gist options
  • Save cimentadaj/c6ebf73f34dde6d3cc1679288465e2c2 to your computer and use it in GitHub Desktop.
Save cimentadaj/c6ebf73f34dde6d3cc1679288465e2c2 to your computer and use it in GitHub Desktop.
library(tidyverse)
## This gist allows to add keywords to bibentries
## It checks whether the keyword exists and if it doesn't
## it adds it. It does this by parsing all entries from a file,
## matchin these entries to the .bib file and adding the keyword
## only to those keywords that matched. This is handy when wanting
## to create a new chapter and add that chapters keyword only for the authors
## actually cited in that chapter
## Only specify three arguments
keyword <-"conclusion"
where <- "back"
path_bib <- "./main_file/bibliography.bib"
path_chapter <- "./conclusion/conclusion.Rnw"
which_citations <- function(x) {
raw_cits <- unlist(str_extract_all(x, "cite\\{[:alnum:]+\\}"))
all_citations <- unique(str_replace_all(raw_cits, "\\{|\\}|cite", ""))
all_citations
}
extract_bib_entries <- function(x) {
#Criteria for a bib entry is whther starts with @
bib_entries <- split(x, cumsum(str_detect(all_bib, "^@")) + 1)
# Why +1 ? because cumsum starts at zero and this messes up indexing
# later on by one number, i.e. pos 125 in the name of the list
# is actually 126 in the index.
bib_entries
}
matching_entries <- function(citations, bib_entries) {
all_bibtex <- map(bib_entries, ~ str_extract_all(.x[1], "\\{.+,")[[1]])
cleaned_index <- str_replace_all(all_bibtex, "\\{|,", "")
entries_to_fix <- bib_entries[cleaned_index %in% citations]
entries_to_fix
}
replace_keywords <- function(x, chosen_keyword, .where = c("front", "back")) {
.where <- match.arg(.where)
keywords <- str_detect(x, "keywords")
if (any(keywords)) {
extracted_keywords <- str_extract(x[keywords], "\\{.+\\}")
splitted_entry <- str_split(str_replace_all(extracted_keywords, "\\{|\\}", ""), ",")[[1]]
# If chosen keyword is not already in the keyword field, then write it
if (!chosen_keyword %in% splitted_entry) {
position <- switch(.where,
"front" = paste0("{", chosen_keyword,", \\1}"),
"back" = paste0("{\\1, ", chosen_keyword,"}"))
new_keyword <- str_replace_all(x[keywords], "\\{(.+)\\}", position)
x[keywords] <- new_keyword
}
} else {
closing_brace <- max(which(str_detect(x, "\\}")))
first_part <- x[1:(closing_brace - 2)]
new_keyword <- paste0(" keywords={", chosen_keyword,"},")
x <- c(first_part, new_keyword, x[(closing_brace - 1):length(x)])
}
x
}
all_lines <- read_lines(path_chapter)
all_bib <- read_lines(path_bib)
all_citations <- which_citations(all_lines)
all_bib_entries <- extract_bib_entries(all_bib)
entries_matched <- matching_entries(all_citations, all_bib_entries)
# Change keyword here!
correct_entries <- map(entries_matched, replace_keywords, keyword, where)
all_bib_entries[as.numeric(names(correct_entries))] <- correct_entries
final_bib_file <- reduce(all_bib_entries, `c`)
write_lines(final_bib_file, path_bib)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment