citEntry <- function(entry, textVersion, header=NULL, footer=NULL, ...) { z <- list(...) names(z) <- tolower(names(z)) if("author" %in% names(z)) z$author <- as.personList(z$author) attr(z, "entry") <- entry attr(z, "textVersion") <- textVersion attr(z, "header") <- header attr(z, "footer") <- footer class(z) <- "citation" z } citHeader <- function(...) { z <- paste(...) class(z) <- "citationHeader" z } citFooter <- function(...) { z <- paste(...) class(z) <- "citationFooter" z } readCitationFile <- function(file) { pcf <- parse(file) z <- list() k = 0 envir = new.env() for(expr in pcf){ x <- eval(expr, envir=envir) if(class(x)=="citation") z[[k <- k+1]] <- x else if(class(x)=="citationHeader") attr(z, "header") <- c(attr(z, "header"), x) else if(class(x)=="citationFooter") attr(z, "footer") <- c(attr(z, "footer"), x) } class(z) <- "citationList" z } ###********************************************************** print.citation <- function(x, bibtex=TRUE, ...){ if(!is.null(attr(x, "header"))){ writeLines(strwrap(attr(x, "header"))) cat("\n") } if(!is.null(attr(x, "textVersion"))){ writeLines(strwrap(attr(x, "textVersion"), prefix=" ")) cat("\n") } if(bibtex){ cat("A BibTeX entry for LaTeX users is\n\n") print(toBibtex(x), prefix=" ") } if(!is.null(attr(x, "footer"))){ cat("\n") writeLines(strwrap(attr(x, "footer"))) } } print.citationList <- function(x, bibtex=length(x)==1, ...) { cat("\n") if(!is.null(attr(x, "header"))){ writeLines(strwrap(attr(x, "header"))) cat("\n") } for(y in x) print(y, bibtex=bibtex) if(!is.null(attr(x, "footer"))){ cat("\n") writeLines(strwrap(attr(x, "footer"))) } cat("\n") } ###********************************************************** person <- function(first="", last="", middle="", email="") { z <- list(name=c(first=first, middle=middle, last=last), email=email) class(z) <- "person" z } as.person <- function(x) UseMethod("as.person") as.person.default <- function(x) { if(class(x)=="person") return(x) x <- as.character(x) if(length(grep("<.*>", x))>0) email <- sub(".*<([^>]*)>.*", "\\1", x) else email <- NULL name <- sub("[[:space:]]*<[^>]*>", "", x) name = unlist(strsplit(name, "[[:space:]]")) ## fix for email address only if(length(name)==0) name = "" ## and now create appropriate person objects if(length(name)==1) z <- person(last=name, email=email) else if(length(name)==2) z <- person(first=name[1], last=name[2], email=email) else z <- person(first=name[1], last=name[length(name)], middle=paste(name[-c(1, length(name))], collapse=" "), email=email) z } personList <- function(...) { z = list(...) if(any(sapply(z, function(x) class(x) != "person"))) stop("all arguments must be of class \"person\"") class(z) <- "personList" z } as.personList <- function(x) UseMethod("as.personList") as.personList.person <- function(x) personList(x) as.personList.default <- function(x) { if(class(x)=="personList") return(x) x <- as.character(x) ## first split into individual persons x <- unlist(strsplit(x,"[[:space:]]?(,|[[:space:]]and)[[:space:]]+")) x <- x[nchar(x)>0] z <- list() for(k in seq_along(x)) z[[k]] <- as.person(x[k]) class(z) <- "personList" z } as.character.person <- function(x, ...) { paste(x$name[nchar(x$name)>0], collapse=" ") } as.character.personList <- function(x, ...) { sapply(x, as.character) } ###********************************************************** toBibtex.person <- function(object, ...) { if(length(grep(" ", object$name["last"]))>0) object$name["last"] <- paste("{", object$name["last"], "}", sep="") as.character(object) } toBibtex.personList <- function(object, ...) { z <- sapply(object, toBibtex) paste(z, collapse = " and ") } toBibtex.citation <- function(object, ...) { z <- paste("@", attr(object, "entry"), "{,", sep="") if("author" %in% names(object)){ object$author <- toBibtex(object$author) } for(n in names(object)) z <- c(z, paste(" ", n, " = {", object[[n]], "},", sep="")) z <- c(z, "}") class(z) <- "Bibtex" z } toBibtex.citationList <- function(object, ...) { lapply(object, toBibtex) } ###********************************************************** citation <- function(package="base", lib.loc = NULL) { ## if we have a CITATION file, use it citfile <- system.file("CITATION", package=package, lib.loc=lib.loc)[1] if(nchar(citfile)>0){ return(readCitationFile(citfile)) } else if(package=="base"){ ## avoid infinite recursion for broken installation stop("broken installation, no CITATION file in the base package.") } ## else auto-generate citation info desc <- packageDescription(pkg=package, lib.loc = lib.loc) ## base packages without a CITATION file use the base citation if((!is.null(desc$Priority)) && (desc$Priority=="base")) { cit <- citation("base") attr(cit, "header")[1] <- paste("The '", package, "' package is part of R. ", attr(cit, "header")[1], sep="") return(cit) } if(length(desc)==1 && is.na(desc)) stop(gettextf("package '%s' not found", package), domain = NA) z <- list(title = paste(package, ": ", desc$Title, sep=""), author = as.personList(desc$Author), year = sub(".*((19|20)[[:digit:]]{2}).*", "\\1", desc$Date), note = paste("R package version", desc$Version) ) if(is.null(desc$Date)){ warning(gettextf("no date field in DESCRIPTION file of package '%s'", package), domain = NA) } else if(length(z$year)==0){ warning(gettextf("could not determine year for '%s' from package DESCRIPTION file", package), domain = NA) } z$url <- desc$URL class(z) <- "citation" attr(z, "entry") <- "Manual" attr(z, "package") <- package attr(z, "header") <- paste("To cite package", sQuote(package), "in publications use:") attr(z, "footer") <- paste("ATTENTION: This citation information has been auto-generated", "from the package DESCRIPTION file and may need manual editing,", "see ", sQuote("help(\"citation\")"), ".") author <- as.character(z$author) if(length(author)>1) author <- paste(paste(author[1:(length(author)-1)], collapse=", "), author[length(author)], sep=" and ") attr(z, "textVersion") <- paste(author, " (", z$year, "). ", z$title, ". ", z$note, ". ", z$url, sep="") z }