# File src/library/tools/R/bibstyle.R # Part of the R package, http://www.R-project.org # # Copyright (C) 1995-2013 The R Core Team # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # A copy of the GNU General Public License is available at # http://www.r-project.org/Licenses/ # Functions for making Rd and human readable versions of bibentry records. # Clean up LaTeX accents and braces cleanupLatex <- function(x) { if (!length(x)) return(x) latex <- tryCatch(parseLatex(x), error = function(e)e) if (inherits(latex, "error")) { x } else { deparseLatex(latexToUtf8(latex), dropBraces=TRUE) } } makeJSS <- function() local({ # First, some utilities collapse <- function(strings) paste(strings, collapse="\n") # Add a period if there's no sentence punctuation already addPeriod <- function(string) sub("([^.?!])$", "\\1.", string) # Separate args by sep, add a period at the end. sentence <- function(..., sep = ", ") { strings <- c(...) if (length(strings)) { addPeriod(paste(strings, collapse = sep)) } } # Now some simple markup plain <- function(pages) if (length(pages)) collapse(pages) plainclean <- function(s) plain(cleanupLatex(s)) emph <- function(s) if (length(s)) paste0("\\emph{", collapse(s), "}") emphclean <- function(s) emph(cleanupLatex(s)) # This creates a function to label a field by adding a prefix or suffix (or both) label <- function(prefix=NULL, suffix=NULL, style=plain) { force(prefix); force(suffix); force(style) function(s) if (length(s)) style(paste0(prefix, collapse(s), suffix)) } labelclean <- function(prefix=NULL, suffix=NULL, style=plain) { f <- label(prefix, suffix, style) function(s) f(cleanupLatex(s)) } # Now the formatters for each particular field. These take # a character vector; if length zero, they return NULL, otherwise # a single element character vector putting everything together fmtAddress <- plainclean fmtBook <- emphclean fmtBtitle <- emphclean fmtChapter <- labelclean(prefix="chapter ") fmtDOI <- label(prefix="\\url{http://dx.doi.org/", suffix="}") fmtEdition <- labelclean(suffix=" edition") fmtEprint <- plain fmtHowpublished <- plainclean fmtISBN <- label(prefix = "ISBN ") fmtISSN <- label(prefix="ISSN ") fmtInstitution <- plainclean fmtNote <- plainclean fmtPages <- label(prefix="pp. ") fmtSchool <- plainclean fmtTechreportnumber <- labelclean(prefix="Technical Report ") fmtUrl <- label(prefix="\\url{", suffix="}") fmtTitle <- function(title) if (length(title)) paste0("\\dQuote{", addPeriod(collapse(cleanupLatex(title))), "}") fmtYear <- function(year) { if (!length(year)) year <- "????" paste0("(", collapse(year), ")") } # Now some more complicated ones that look at multiple fields volNum <- function(paper) { if (length(paper$volume)) { result <- paste0("\\bold{", collapse(paper$volume), "}") if (length(paper$number)) result <- paste0(result, "(", collapse(paper$number), ")") result } } ## Format one person object in short "Murdoch DJ" format shortName <- function(person) { if (length(person$family)) { result <- cleanupLatex(person$family) if (length(person$given)) paste(result, paste(substr(sapply(person$given, cleanupLatex), 1, 1), collapse="")) else result } else paste(cleanupLatex(person$given), collapse=" ") } # Format all authors for one paper authorList <- function(paper) { names <- sapply(paper$author, shortName) if (length(names) > 1) result <- paste( paste(names[-length(names)], collapse=", "), "and", names[length(names)]) else result <- names result } # Format all editors for one paper editorList <- function(paper) { names <- sapply(paper$editor, shortName) if (length(names) > 1) result <- paste( paste(names[-length(names)], collapse=", "), "and", names[length(names)], "(eds.)") else if (length(names)) result <- paste(names, "(ed.)") else result <- NULL result } extraInfo <- function(paper) { result <- paste(c(fmtDOI(paper$doi), fmtNote(paper$note), fmtEprint(paper$eprint), fmtUrl(paper$url)), collapse=", ") if (result != "") result } bookVolume <- function(book) { result <- "" if (length(book$volume)) result <- paste("volume", collapse(book$volume)) if (length(book$number)) result <- paste(result, "number", collapse(book$number)) if (length(book$series)) result <- paste(result, "series", collapse(book$series)) if (result != "") result } bookPublisher <- function(book) { if (length(book$publisher)) { result <- collapse(book$publisher) if (length(book$address)) result <- paste(result, collapse(book$address), sep = ", ") result } } procOrganization <- function(paper) { if (length(paper$organization)) { result <- collapse(cleanupLatex(paper$organization)) if (length(paper$address)) result <- paste(result, collapse(cleanupLatex(paper$address)), sep =", ") result } } formatArticle <- function(paper) { collapse(c(fmtPrefix(paper), sentence(authorList(paper), fmtYear(paper$year), sep = " "), fmtTitle(paper$title), sentence(fmtBook(paper$journal), volNum(paper), fmtPages(paper$pages)), sentence(fmtISSN(paper$issn), extraInfo(paper)))) } formatBook <- function(book) { authors <- authorList(book) if(!length(authors)) authors <- editorList(book) collapse(c(fmtPrefix(book), sentence(authors, fmtYear(book$year), sep = " "), sentence(fmtBtitle(book$title), bookVolume(book), fmtEdition(book$edition)), sentence(bookPublisher(book)), sentence(fmtISBN(book$isbn), extraInfo(book)))) } formatInbook <- function(paper) { authors <- authorList(paper) editors <- editorList(paper) if(!length(authors)) { authors <- editors editors <- NULL } collapse(c(fmtPrefix(paper), sentence(authors, fmtYear(paper$year), sep =" "), fmtTitle(paper$title), paste("In", sentence(editors, fmtBtitle(paper$booktitle), bookVolume(paper), fmtChapter(paper$chapter), fmtEdition(paper$edition), fmtPages(paper$pages))), sentence(bookPublisher(paper)), sentence(fmtISBN(paper$isbn), extraInfo(paper)))) } formatIncollection <- function(paper) { collapse(c(fmtPrefix(paper), sentence(authorList(paper), fmtYear(paper$year), sep = " "), fmtTitle(paper$title), paste("In", sentence(editorList(paper), fmtBtitle(paper$booktitle), bookVolume(paper), fmtEdition(paper$edition), fmtPages(paper$pages))), sentence(bookPublisher(paper)), sentence(fmtISBN(paper$isbn), extraInfo(paper)))) } formatInProceedings <- function(paper) collapse(c(fmtPrefix(paper), sentence(authorList(paper), fmtYear(paper$year), sep = " "), fmtTitle(paper$title), paste("In", sentence(editorList(paper), fmtBtitle(paper$booktitle), bookVolume(paper), fmtEdition(paper$edition), fmtPages(paper$pages))), sentence(procOrganization(paper)), sentence(fmtISBN(paper$isbn), extraInfo(paper)))) formatManual <- function(paper) { collapse(c(fmtPrefix(paper), sentence(authorList(paper), fmtYear(paper$year), sep = " "), sentence(fmtBtitle(paper$title), bookVolume(paper), fmtEdition(paper$edition)), sentence(procOrganization(paper)), sentence(fmtISBN(paper$isbn), extraInfo(paper)))) } formatMastersthesis <- function(paper) { collapse(c(fmtPrefix(paper), sentence(authorList(paper), fmtYear(paper$year), sep = " "), sentence(fmtBtitle(paper$title)), sentence("Master's thesis", fmtSchool(paper$school), fmtAddress(paper$address)), sentence(extraInfo(paper)))) } formatPhdthesis <- function(paper) { collapse(c(fmtPrefix(paper), sentence(authorList(paper), fmtYear(paper$year), sep = " "), sentence(fmtBtitle(paper$title)), sentence("PhD thesis", fmtSchool(paper$school), fmtAddress(paper$address)), sentence(extraInfo(paper)))) } formatMisc <- function(paper) { collapse(c(fmtPrefix(paper), sentence(authorList(paper), fmtYear(paper$year), sep = " "), fmtTitle(paper$title), sentence(fmtHowpublished(paper$howpublished)), sentence(extraInfo(paper)))) } formatProceedings <- function(book) { if (is.null(book$editor)) editor <- "Anonymous (ed.)" else editor <- editorList(book) collapse(c(fmtPrefix(book), # not paper sentence(editor, fmtYear(book$year), sep = " "), sentence(fmtBtitle(book$title), bookVolume(book)), sentence(procOrganization(book)), sentence(fmtISBN(book$isbn), fmtISSN(book$issn), extraInfo(book)))) } formatTechreport <- function(paper) { collapse(c(fmtPrefix(paper), sentence(authorList(paper), fmtYear(paper$year), sep = " "), fmtTitle(paper$title), sentence(fmtTechreportnumber(paper$number), fmtInstitution(paper$institution), fmtAddress(paper$address)), sentence(extraInfo(paper)))) } formatUnpublished <- function(paper) { collapse(c(fmtPrefix(paper), sentence(authorList(paper), fmtYear(paper$year), sep = " "), fmtTitle(paper$title), sentence(extraInfo(paper)))) } sortKeys <- function(bib) { result <- character(length(bib)) for (i in seq_along(bib)) { authors <- authorList(bib[[i]]) if (!length(authors)) authors <- editorList(bib[[i]]) if (!length(authors)) authors <- "" result[i] <- authors } result } # Replace this if you want a bibliography style # that puts a prefix on each entry, e.g. [n] # The formatting routine will have added a field .index # as a 1-based index within the complete list. fmtPrefix <- function(paper) NULL cite <- function(key, bib, ...) utils::citeNatbib(key, bib, ...) # the defaults are JSS style environment() }) bibstyle <- local({ styles <- list(JSS = makeJSS()) default <- "JSS" function(style, envir, ..., .init = FALSE, .default=TRUE) { newfns <- list(...) if (missing(style) || is.null(style)) { if (!missing(envir) || length(newfns) || .init) stop("Changes require specified 'style'") style <- default } else { if (!missing(envir)) { stopifnot(!.init) styles[[style]] <<- envir } if (.init) styles[[style]] <<- makeJSS() if (length(newfns) && style == "JSS") stop("The default JSS style may not be modified.") for (n in names(newfns)) assign(n, newfns[[n]], envir=styles[[style]]) if (.default) default <<- style } styles[[style]] } }) getBibstyle <- function(all = FALSE) { if (all) names(environment(bibstyle)$styles) else environment(bibstyle)$default } toRd.bibentry <- function(obj, style=NULL, ...) { obj <- sort(obj, .bibstyle=style) style <- bibstyle(style) env <- new.env(hash = FALSE, parent = style) bib <- unclass(obj) result <- character(length(bib)) for (i in seq_along(bib)) { env$paper <- bib[[i]] result[i] <- with(env, switch(attr(paper, "bibtype"), Article = formatArticle(paper), Book = formatBook(paper), InBook = formatInbook(paper), InCollection = formatIncollection(paper), InProceedings = formatInProceedings(paper), Manual = formatManual(paper), MastersThesis = formatMastersthesis(paper), Misc = formatMisc(paper), PhdThesis = formatPhdthesis(paper), Proceedings = formatProceedings(paper), TechReport = formatTechreport(paper), Unpublished = formatUnpublished(paper), paste("bibtype", attr(paper, "bibtype"),"not implemented") )) } result }