diff --git a/DESCRIPTION b/DESCRIPTION index c720fb293..ff6e53d3f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: tinytex Type: Package Title: Helper Functions to Install and Maintain TeX Live, and Compile LaTeX Documents -Version: 0.60.1 +Version: 0.60.2 Authors@R: c( person("Yihui", "Xie", role = c("aut", "cre", "cph"), email = "xie@yihui.name", comment = c(ORCID = "0000-0003-0645-5666")), person(given = "Posit Software, PBC", role = c("cph", "fnd")), diff --git a/NEWS.md b/NEWS.md index 746798eda..d7fa0d987 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# CHANGES IN tinytex VERSION 0.61 + +- The `bib_engine` argument of `latexmk()` now defaults to `NULL`, in which case the bibliography engine is inferred from the auxiliary files generated during compilation: if a `.bcf` file is found (produced by **biblatex** with the `biber` backend), `biber` is used, otherwise `bibtex`. Previously the default was always `bibtex`, so the bibliography of a **biblatex** + **biber** document was silently not built unless you set `bib_engine = 'biber'` or the global option `tinytex.bib_engine` (thanks, @HughParsonage, #19). + # CHANGES IN tinytex VERSION 0.60 - Fixed the CTAN repository URL detection in `normalize_repo()`: when a URL like `https://tlnet.yihui.org` already serves `tlpkg/texlive.tlpdb` at its root, don't append `/systems/texlive/tlnet` to it. Also hardened `is_tlnet()` to check the `Content-Type` header instead of only the HTTP status code, so servers that return 200 with an HTML page for all URLs (e.g., Cloudflare Pages' SPA fallback) no longer fool the detection (thanks, @Gael-Hammer rstudio/tinytex-releases#59, @mfisher5 #508). diff --git a/R/latex.R b/R/latex.R index 5839700e1..cb43264d0 100644 --- a/R/latex.R +++ b/R/latex.R @@ -44,8 +44,11 @@ #' @param file A LaTeX file path. #' @param engine A LaTeX engine (can be set in the global option #' `tinytex.engine`, e.g., `options(tinytex.engine = 'xelatex')`). -#' @param bib_engine A bibliography engine (can be set in the global option -#' `tinytex.bib_engine`). +#' @param bib_engine A bibliography engine, either `'bibtex'` or `'biber'` (can +#' be set in the global option `tinytex.bib_engine`). By default (`NULL`), the +#' engine is inferred from the auxiliary files generated during compilation: +#' if a `.bcf` file is found (produced by \pkg{biblatex} with the `biber` +#' backend), `'biber'` is used; otherwise `'bibtex'` is used. #' @param engine_args Command-line arguments to be passed to `engine` (can #' be set in the global option `tinytex.engine_args`, e.g., #' `options(tinytex.engine_args = '-shell-escape')`). @@ -72,7 +75,7 @@ #' the `pdf_file` argument). latexmk = function( file, engine = c('pdflatex', 'xelatex', 'lualatex', 'latex', 'tectonic'), - bib_engine = c('bibtex', 'biber'), engine_args = NULL, emulation = TRUE, + bib_engine = NULL, engine_args = NULL, emulation = TRUE, min_times = 1, max_times = 10, install_packages = emulation && tlmgr_writable(), pdf_file = NULL, clean = TRUE ) { @@ -160,7 +163,7 @@ lualatex = function(...) latexmk(engine = 'lualatex', emulation = TRUE, ...) # a quick and dirty version of latexmk (should work reasonably well unless the # LaTeX document is extremely complicated) latexmk_emu = function( - file, engine, bib_engine = c('bibtex', 'biber'), engine_args = NULL, min_times = 1, max_times = 10, + file, engine, bib_engine = NULL, engine_args = NULL, min_times = 1, max_times = 10, install_packages = FALSE, clean ) { aux = c( @@ -239,8 +242,11 @@ latexmk_emu = function( stop("Failed to build the index via ", idx_engine, call. = FALSE) }) } - # generate bibliography - bib_engine = match.arg(bib_engine) + # generate bibliography; if bib_engine is not specified, infer it from the aux + # files: biblatex with the biber backend generates a .bcf file, in which case + # we use biber, otherwise bibtex + if (is.null(bib_engine)) bib_engine = if (file.exists(aux_files['bcf'])) 'biber' else 'bibtex' + bib_engine = match.arg(bib_engine, c('bibtex', 'biber')) install_cmd(bib_engine) pkgs_last = character() aux = aux_files[if ((biber <- bib_engine == 'biber')) 'bcf' else 'aux'] diff --git a/man/latexmk.Rd b/man/latexmk.Rd index d75f49f08..9f1a357f5 100644 --- a/man/latexmk.Rd +++ b/man/latexmk.Rd @@ -10,7 +10,7 @@ latexmk( file, engine = c("pdflatex", "xelatex", "lualatex", "latex", "tectonic"), - bib_engine = c("bibtex", "biber"), + bib_engine = NULL, engine_args = NULL, emulation = TRUE, min_times = 1, @@ -32,8 +32,11 @@ lualatex(...) \item{engine}{A LaTeX engine (can be set in the global option \code{tinytex.engine}, e.g., \code{options(tinytex.engine = 'xelatex')}).} -\item{bib_engine}{A bibliography engine (can be set in the global option -\code{tinytex.bib_engine}).} +\item{bib_engine}{A bibliography engine, either \code{'bibtex'} or \code{'biber'} (can +be set in the global option \code{tinytex.bib_engine}). By default (\code{NULL}), the +engine is inferred from the auxiliary files generated during compilation: +if a \code{.bcf} file is found (produced by \pkg{biblatex} with the \code{biber} +backend), \code{'biber'} is used; otherwise \code{'bibtex'} is used.} \item{engine_args}{Command-line arguments to be passed to \code{engine} (can be set in the global option \code{tinytex.engine_args}, e.g., diff --git a/tests/test-all.R b/tests/test-all.R new file mode 100644 index 000000000..cc2ca9081 --- /dev/null +++ b/tests/test-all.R @@ -0,0 +1,4 @@ +library(testit) +test_pkg('tinytex', 'test-cran') +if (!is.na(Sys.getenv('CI', NA)) && tinytex:::tlmgr_available()) + test_pkg('tinytex', 'test-ci') diff --git a/tests/test-ci.R b/tests/test-ci.R deleted file mode 100644 index 2b581e14e..000000000 --- a/tests/test-ci.R +++ /dev/null @@ -1,2 +0,0 @@ -# run tests on CI servers (these tests depend on TeX Live) -if (!is.na(Sys.getenv('CI', NA)) && tinytex:::tlmgr_available()) testit::test_pkg('tinytex', 'test-ci') diff --git a/tests/test-ci/bib/biber.tex b/tests/test-ci/bib/biber.tex new file mode 100644 index 000000000..15489e74f --- /dev/null +++ b/tests/test-ci/bib/biber.tex @@ -0,0 +1,7 @@ +\documentclass{article} +\usepackage[backend=biber]{biblatex} +\addbibresource{refs.bib} +\begin{document} +\cite{R-base} +\printbibliography +\end{document} diff --git a/tests/test-ci/bib/refs.bib b/tests/test-ci/bib/refs.bib new file mode 100644 index 000000000..48749e264 --- /dev/null +++ b/tests/test-ci/bib/refs.bib @@ -0,0 +1,8 @@ +@Manual{R-base, + title = {R: A Language and Environment for Statistical Computing}, + author = {{R Core Team}}, + organization = {R Foundation for Statistical Computing}, + address = {Vienna, Austria}, + year = {2016}, + url = {https://www.R-project.org/}, +} diff --git a/tests/test-ci/test-latex.R b/tests/test-ci/test-latex.R index 3b001c64e..77af7e678 100644 --- a/tests/test-ci/test-latex.R +++ b/tests/test-ci/test-latex.R @@ -12,3 +12,14 @@ assert('latexmk() generates the PDF output to the dir of the .tex file by defaul # can also specify a custom pdf output path (latexmk('sub/test.tex', pdf_file = 'foo.pdf') %==% 'foo.pdf') }) + +assert('latexmk() infers biber from the .bcf file when bib_engine is not set', { + # a biblatex + biber document does not generate the \bibdata/\bibstyle info in + # the .aux file that bibtex needs, so bibtex would silently do nothing; the + # bibliography is only built if biber is (correctly) inferred from the .bcf + owd = setwd('bib'); on.exit(setwd(owd), add = TRUE) + latexmk('biber.tex', clean = FALSE) + bbl = readLines('biber.bbl', warn = FALSE) + file.remove(list.files('.', '^biber[.](aux|bbl|bcf|blg|log|pdf|run[.]xml)$')) + (any(grepl('R Core Team', bbl, fixed = TRUE))) +}) diff --git a/tests/test-cran.R b/tests/test-cran.R deleted file mode 100644 index 12ebe690c..000000000 --- a/tests/test-cran.R +++ /dev/null @@ -1 +0,0 @@ -testit::test_pkg('tinytex', 'test-cran')