Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore opts_current after each code chunk, and also after knit() exits #2292

Merged
merged 5 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
4 changes: 4 additions & 0 deletions R/block.R
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
}
Expand Down
12 changes: 4 additions & 8 deletions R/output.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions R/parser.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))
}

Expand Down