diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index cf67ef5..0000000 --- a/.appveyor.yml +++ /dev/null @@ -1,63 +0,0 @@ -init: - ps: | - $ErrorActionPreference = "Stop" - Invoke-WebRequest https://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" - Import-Module '..\appveyor-tool.ps1' -install: - ps: Bootstrap - - -cache: - - C:\RLibrary - -environment: - matrix: - - R_VERSION: devel - POPPLERQT5FILE: 'dev\windows\appveyor\poppler-qt5-debug.zip' - CRAN: https://cran.rstudio.com - - R_VERSION: release - RTOOLS_VERSION: 32 - CRAN: https://cran.rstudio.com - POPPLERQT5FILE: 'dev\windows\appveyor\poppler-qt5-debug.zip' - global: - NOT_CRAN: true - -build_script: - - travis-tool.sh install_deps -# - travis-tool.sh install_r devtools -# - Rscript -e 'devtools::install_github("romainfrancois/bibtex")' -# - travis-tool.sh install_github romainfrancois/bibtex -# - Rscript -e "install.packages('covr', repos = 'https://cran.rstudio.com')" -# - travis-tool.sh install_github jimhester/covr -# - travis-tool.sh install_github rstats-db/RSQLite - - -test_script: - - travis-tool.sh run_tests - -on_failure: - - travis-tool.sh dump_logs - - 7z a failure.zip *.Rcheck\* - - appveyor PushArtifact failure.zip - -# on_success: -# - R -e "covr::coveralls(type = 'all')" - -artifacts: - - path: '*.Rcheck\**\*.log' - name: Logs - - - path: '*.Rcheck\**\*.out' - name: Logs - - - path: '*.Rcheck\**\*.fail' - name: Logs - - - path: '*.Rcheck\**\*.Rout' - name: Logs - - - path: '\*_*.tar.gz' - name: Bits - - - path: '\*_*.zip' - name: Bits \ No newline at end of file diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 3dd3202..4e9c64e 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -1,6 +1,6 @@ # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples/check-standard.yml # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help -on: [push, workflow_dispatch] +on: [push, workflow_dispatch, merge_group] name: R-CMD-check diff --git a/DESCRIPTION b/DESCRIPTION index 1ac5cd3..a6e91ab 100755 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,9 +1,11 @@ Package: RefManageR -Version: 1.4.0 +Version: 1.4.3 Title: Straightforward 'BibTeX' and 'BibLaTeX' Bibliography Management -Authors@R: person(c("Mathew", "W."), "McLean", role = c("aut", "cre"), +Authors@R: c(person(c("Mathew", "W."), "McLean", role = c("aut", "cre"), email = "mathew.w.mclean@gmail.com", - comment = c(ORCID = "0000-0002-7891-9645")) + comment = c(ORCID = "0000-0002-7891-9645")), + person("Andy", "Bunn", role = "ctb", + email = "bunna@wwu.edu", comment = "function latexify used by toBiblatex")) Maintainer: Mathew W. McLean Description: Provides tools for importing and working with bibliographic references. It greatly enhances the 'bibentry' class by providing a class @@ -27,6 +29,8 @@ Imports: httr, lubridate (>= 1.5.0), stringr, + stringi, + R.utils, methods, bibtex (>= 0.4.1) Suggests: @@ -38,5 +42,5 @@ Depends: R (>= 3.0) VignetteBuilder: knitr BugReports: https://github.com/ropensci/RefManageR/issues -URL: https://github.com/ropensci/RefManageR/ -RoxygenNote: 7.2.1 +URL: https://github.com/ropensci/RefManageR/, https://docs.ropensci.org/RefManageR/ +RoxygenNote: 7.3.2 diff --git a/NAMESPACE b/NAMESPACE index f5e416d..d8fecac 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -49,6 +49,7 @@ export(as.BibEntry) export(fields) export(is.BibEntry) export(toBiblatex) +importFrom(R.utils,captureOutput) importFrom(bibtex,do_read_bib) importFrom(httr,GET) importFrom(httr,POST) @@ -73,6 +74,9 @@ importFrom(methods,hasArg) importFrom(plyr,llply) importFrom(plyr,progress_text) importFrom(stats,setNames) +importFrom(stringi,stri_trans_nfc) +importFrom(stringi,stri_trans_nfd) +importFrom(stringi,stri_unescape_unicode) importFrom(stringr,str_length) importFrom(stringr,str_sub) importFrom(stringr,str_trim) @@ -82,7 +86,6 @@ importFrom(tools,Rd2txt) importFrom(tools,Rd2txt_options) importFrom(tools,bibstyle) importFrom(tools,deparseLatex) -importFrom(tools,encoded_text_to_latex) importFrom(tools,getBibstyle) importFrom(tools,latexToUtf8) importFrom(tools,loadPkgRdMacros) diff --git a/R/ReadPDFs.R b/R/ReadPDFs.R index a816a47..c3a33f9 100755 --- a/R/ReadPDFs.R +++ b/R/ReadPDFs.R @@ -89,8 +89,28 @@ ReadPDFs <- function (path, .enc = 'UTF-8', recursive = TRUE, out, pages.idx)) }else { + .findPages <- function(files) + { + n.files <- length(files) + page.bounding.boxes <- lapply(files, function(x) + system2("pdfinfo", paste(shQuote('-enc'), + shQuote(.enc), shQuote("-box"), + shQuote(normalizePath(x))), + stdout = TRUE, stderr = TRUE)) + pages.idx <- lapply(page.bounding.boxes, grep, pattern = "^Pages:") + pages <- rep(Inf, n.files) + for (i in seq_along(pages.idx)) + { + if (length(pages.idx[[i]])) + pages[i] <- as.integer(sub("^Pages:\\s+(\\d+)", "\\1", + page.bounding.boxes[[i]][pages.idx[[i]]], + perl = TRUE)) + } + return(pages) + } + doi.meta.ind <- logical(n.files) - pages <- rep(Inf, n.files) + pages <- .findPages(files) } ######################################## diff --git a/R/ReadPubMed.R b/R/ReadPubMed.R index c2581a8..2667a78 100644 --- a/R/ReadPubMed.R +++ b/R/ReadPubMed.R @@ -120,6 +120,7 @@ GetPubMedByID <- function(id, db = "pubmed", ...){ ## temp <- postForm(base.url, .params = parms) ## tdoc <- xmlParse(temp) temp <- POST(base.url, query = parms) + stop_for_status(temp) tdoc <- read_xml(temp) ## Note: directly using xpathApply on tdoc won't work if some results are diff --git a/R/RefManageR-package.R b/R/RefManageR-package.R index 544fa5b..94e3be0 100644 --- a/R/RefManageR-package.R +++ b/R/RefManageR-package.R @@ -1,20 +1,8 @@ -#' Import and Manage BibTeX and BibLaTeX references with RefManageR -#' -#' RefManageR provides tools for importing and working with -#' bibliographic references. It greatly enhances the bibentry class by -#' providing a class BibEntry which stores BibTeX and BibLaTeX references, -#' supports UTF-8 encoding, and can be easily searched by any field, by date -#' ranges, and by various formats for name lists (author by last names, -#' translator by full names, etc.). Entries can be updated, combined, sorted, printed -#' in a number of styles, and exported. BibTeX and BibLaTeX .bib files can be -#' read into R and converted to BibEntry objects. Interfaces to NCBI's -#' Entrez, CrossRef, and Zotero are provided for importing references and -#' references can be created from locally stored PDFs using Poppler. Includes -#' functions for citing and generating a bibliography with hyperlinks for -#' documents prepared with RMarkdown or RHTML. +#' @keywords internal +"_PACKAGE" + #' @name RefManageR-package #' @aliases RefManageR refmanager -#' @docType package #' @author McLean, M. W. \email{mathew.w.mclean@@gmail.com} #' @details #' \bold{Importing and Creating References} @@ -56,7 +44,7 @@ #' \code{\link{Cite}}. Its interface is similar to \code{\link{options}}. #' @keywords package #' @references McLean, M. W. (2014). Straightforward Bibliography Management in R Using the RefManageR Package. -#' \href{https://arxiv.org/abs/1403.2036}{arXiv: 1403.2036 [cs.DL]}. Submitted. +#' \href{https://arxiv.org/abs/1403.2036}{arXiv: 1403.2036 [cs.DL]}. #' @references Kime, P., M. Wemheuer, and P. Lehman (2022). The biblatex Package. #' \url{http://mirrors.ibiblio.org/CTAN/macros/latex/contrib/biblatex/doc/biblatex.pdf}. #' @references Hornik, K., D. Murdoch, and A. Zeileis (2012). diff --git a/R/WriteBib.R b/R/WriteBib.R index 600575f..5a17a2b 100644 --- a/R/WriteBib.R +++ b/R/WriteBib.R @@ -21,7 +21,6 @@ #' @note To write the contents of \code{bib} \dQuote{as is}, the argument #' \code{biblatex} should be \code{TRUE}, otherwise #' conversion is done as in \code{\link{toBibtex.BibEntry}}. -#' @importFrom tools encoded_text_to_latex #' @author McLean, M. W. based on \code{write.bib} by Gaujoux, R. #' in package \code{bibtex}. #' @export diff --git a/R/toBiblatex.R b/R/toBiblatex.R index 76da930..1c4177d 100644 --- a/R/toBiblatex.R +++ b/R/toBiblatex.R @@ -10,6 +10,9 @@ #' @param extra.fields character vector; fields that are not supported in standard BibTeX styles are by default dropped #' in the result return by the toBibtex function. #' Any fields specified in extra.fields will \emph{not} be dropped if present in an entry. +#' @param encoded.names.to.latex if \code{TRUE} (the default) then name list fields +#' such as \sQuote{author} and \sQuote{editor} will have non-ASCII characters +#' translated to LaTeX escape sequences. #' @param ... ignored #' @export #' @return an object of class \dQuote{Bibtex} - character vectors where each element holds one line of a BibTeX or BibLaTeX file @@ -49,8 +52,9 @@ #' \item \emph{rest} - to Misc #' } #' @seealso \code{\link{toBibtex}}, \code{\link{BibEntry}}, \code{\link{print.BibEntry}} -#' @author McLean, M. W. \email{mathew.w.mclean@@gmail.com} -#' @importFrom tools encoded_text_to_latex parseLatex deparseLatex latexToUtf8 +#' @author McLean, M. W. \email{mathew.w.mclean@@gmail.com}, Andy Bunn for code for +#' translating non-ASCII characters to LaTeX. +#' @importFrom tools parseLatex deparseLatex latexToUtf8 #' @keywords database IO utilities #' @aliases toBibtex.BibEntry toBibtex #' @examples @@ -60,14 +64,16 @@ #' toBiblatex(bib[70:72]) #' toBibtex(bib[70:72]) #' } -toBiblatex <- function(object, ...){ +toBiblatex <- function(object, encoded.names.to.latex = TRUE, ...){ format_bibentry1 <- function(object) { object <- unclass(object)[[1L]] rval <- paste0("@", attr(object, "bibtype"), "{", attr(object, "key"), ",") - nl.ind <- which(names(object) %in% .BibEntryNameList) - for (i in nl.ind) - object[i] <- encoded_text_to_latex(format_author(object[[i]]), "UTF-8") + if (encoded.names.to.latex) { + nl.ind <- which(names(object) %in% .BibEntryNameList) + for (i in nl.ind) + object[i] <- EncodedNameListToLaTeX(object[[i]]) + } rval <- c(rval, vapply(names(object), function(n) paste0(" ", n, " = {", object[[n]], "},"), ""), "}", "") return(rval) @@ -81,3 +87,215 @@ toBiblatex <- function(object, ...){ class(rval) <- "Bibtex" rval } + +#' Wrapper for dplr::latexify that returns original +#' text if translation to LaTeX fails +#' @noRd +#' @seealso \url{https://github.com/ropensci/RefManageR/issues/106} +EncodedNameListToLaTeX <- function(name.list, encoding = "UTF-8") +{ + formatted.text <- format_author(name.list) + out <- latexify(formatted.text, encoding, doublebackslash = FALSE) + if (grepl("^[{]?[?]", out)) + return(formatted.text) + return(out) +} + +#' Modified version of dplR::latexify +#' @importFrom stringi stri_trans_nfc stri_trans_nfd stri_unescape_unicode +#' @importFrom R.utils captureOutput +#' @author Andy Bunn +#' @noRd +latexify <- function(x, + doublebackslash = FALSE, + dashdash = TRUE, + quotes = c("straight", "curved"), + packages = c("fontenc", "textcomp")) +{ + y <- as.character(x) + encBytes <- Encoding(y) == "bytes" + if (any(encBytes)) { + y[encBytes] <- captureOutput(cat(y[encBytes], sep = "\n")) + } + y <- stri_trans_nfd(y) + Letters <- paste0(c(LETTERS, letters), collapse = "") + fontenc <- "fontenc" %in% packages + textcomp <- "textcomp" %in% packages + eurosym <- "eurosym" %in% packages + straightQuotes <- match.arg(quotes) == "straight" + y <- gsub("(?![[:space:]])[[:cntrl:]]", "", y, perl = TRUE) + y <- gsub("[[:space:]]+", " ", y) + substitutions <- list(c("\\\\^", "\\\\textasciicircum{}"), + c("~", "\\\\textasciitilde{}"), c("<", "\\\\textless{}"), + c(">", "\\\\textgreater{}"), c("\\\\|", "\\\\textbar{}"), + c("([#$%&_])", "\\\\\\1"), if (isTRUE(dashdash)) { + c("-", "\\\\mbox{-}") + }, if (textcomp && straightQuotes) { + c("'", "\\\\textquotesingle{}") + }, if (textcomp && straightQuotes) { + c("`", "\\\\textasciigrave{}") + }, c("\"", if (fontenc && straightQuotes) { + "\\\\textquotedbl{}" + } else { + "\\\\textquotedblright{}" + }), c("/", "\\\\slash{}")) + substitutions <- substitutions[!vapply(substitutions, is.null, + logical(1))] + substitutions <- c(substitutions, list(c("\\u0132", "\\\\IJ{}"), + c("\\u0133", "\\\\ij{}"), + c("\\u01f1", "DZ"), c("\\u01f2", "Dz"), + c("\\u01f3", "dz"), c("\\u01c4", "DZ\\u033c"), + c("\\u01c5", "Dz\\u030c"), + c("\\u01c6", "dz\\u030c"), + c("\\u01c7", "LJ"), c("\\u01c8", "Lj"), + c("\\u01c9", "lj"), c("\\u01ca", "NJ"), + c("\\u01cb", "Nj"), c("\\u01cc", "nj"), + c("\\ufb00", "ff"), c("\\ufb01", "fi"), + c("\\ufb02", "fl"), c("\\ufb03", "ffi"), + c("\\ufb04", "ffl"), c("\\ufb05", "\\u017ft"), + c("\\ufb06", "st"))) + above <- list(diaeresis = c("\\u0308", "\""), acute = c("\\u0301", "'"), + dotabove = c("\\u0307", "."), macron = c("\\u0304", "="), + circumflex = c("\\u0302", "^"), grave = c("\\u0300", "`"), + tilde = c("\\u0303", "~"), doubleacute = c("\\u030b", "H"), + ringabove = c("\\u030a", "r"), breve = c("\\u0306", "u"), + caron = c("\\u030c", "v"), invbreve = c("\\u0311", "newtie")) + + below <- list(macronbelow = c("\\u0331", "b"), cedilla = c("\\u0327", "c"), + dotbelow = c("\\u0323", "d"), tie = c("\\u0361", "t"), + ogonek = c("\\u0328", "k")) + accents <- c(above, below) + command <- paste0("\\\\[", Letters, "]+|\\\\.") + combining <- paste0(vapply(accents, "[", character(1), 1), + collapse = "") + accPre <- paste0("(", command, "|.)({})?(?