diff --git a/NEWS.md b/NEWS.md index ad103bdeff..e1e5e7a876 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,12 @@ - Improved the error message to contain more specific information when YAML chunk options could not be parsed (thanks, @pedropark99, #2294). +## MAJOR CHANGES + +- The object `opts_current` will be restored after each code chunk has finished executing. Previously, it would not be restored, which means even for inline R expressions, `opts_current$get()` will inherit chunk options from a previous code chunk (thanks, @rundel, #1988). Besides, `opts_current$get('label')` will return a unique label for inline expressions. One possible application is to construct unique figure paths via `fig_path()` (e.g., ropensci/magick#310). + +- The naming scheme for unnamed chunks has changed: previously, the number `i` in the label `unnamed-chunk-i` denotes the i-th *unnamed* chunk; now it denotes the i-th chunk. Note that the "chunk" here includes both code chunks and prose (text) chunks, which means, for example, the 3rd code chunk could be the 5th chunk in the document, and its index will be 5. For child documents, the naming scheme will be `unnamed-chunk-i-j`, where `i` is the chunk index, and `j` is the index of the unnamed chunk. The suffix `j` is to make sure the label is unique. In general, you are recommended to label your code chunks explicitly and not to rely on this naming scheme when a code chunk has side-effects such as plots or cache. + ## BUG FIXES - Special characters in the chunk option `fig.alt` are properly escaped now (thanks, @jay-sf, #2290). diff --git a/R/block.R b/R/block.R index d9f7f449f0..731afb6b51 100644 --- a/R/block.R +++ b/R/block.R @@ -52,6 +52,7 @@ call_block = function(block) { } # save current chunk options in opts_current + optc = opts_current$get(); on.exit(opts_current$restore(optc), add = TRUE) opts_current$restore(params) if (opts_knit$get('progress')) print(block) @@ -545,6 +546,9 @@ merge_character = function(res) { } call_inline = function(block) { + optc = opts_current$get(); on.exit(opts_current$restore(optc), add = TRUE) + params = opts_chunk$merge(list(label = unnamed_chunk())) + opts_current$restore(params) if (opts_knit$get('progress')) print(block) in_input_dir(inline_exec(block)) } diff --git a/R/output.R b/R/output.R index 1c7b5ca167..506802b610 100644 --- a/R/output.R +++ b/R/output.R @@ -151,14 +151,10 @@ knit = function( useFancyQuotes = FALSE, device = pdf_null, knitr.in.progress = TRUE ) on.exit(options(oopts), add = TRUE) - # restore chunk options after parent exits - optc = opts_chunk$get(); ocode = knit_code$get(); optk = opts_knit$get() - on.exit({ - opts_chunk$restore(optc) - knit_code$restore(ocode) - opts_current$restore() - opts_knit$restore(optk) - }, add = TRUE) + # restore objects like chunk options after parent exits + opta = list(opts_chunk, opts_current, knit_code, opts_knit) + optv = lapply(opta, function(o) o$get()) + on.exit(for (i in seq_along(opta)) opta[[i]]$restore(optv[[i]]), add = TRUE) opts_knit$set( output.dir = getwd(), # record working directory in 1st run tangle = tangle, progress = opts_knit$get('progress') && !quiet diff --git a/R/parser.R b/R/parser.R index dad04ba981..ed3d6fd3f6 100644 --- a/R/parser.R +++ b/R/parser.R @@ -169,9 +169,9 @@ clean_empty_params = function(params) { } # autoname for unnamed chunk -unnamed_chunk = function(prefix = NULL, i = chunk_counter()) { +unnamed_chunk = function(prefix = NULL, suffix = child_mode()) { if (is.null(prefix)) prefix = opts_knit$get('unnamed.chunk.label') - paste(prefix, i, sep = '-') + paste(c(prefix, knit_concord$get('block'), if (suffix) chunk_counter()), collapse = '-') } # parse params from chunk header @@ -492,7 +492,7 @@ read_chunk = function( labels = trimws(gsub(lab, '\\3', sapply(groups, `[`, 1))) labels = gsub(',.*', '', labels) # strip off possible chunk options code = lapply(groups, strip_chunk, roxygen_comments) - for (i in which(!nzchar(labels))) labels[i] = unnamed_chunk() + for (i in which(!nzchar(labels))) labels[i] = unnamed_chunk(suffix = TRUE) knit_code$set(setNames(code, labels)) }