From b20d7a5daacdeea993d3e375b012f420a8fb1532 Mon Sep 17 00:00:00 2001 From: Blake Vernon Date: Fri, 25 Sep 2026 11:50:36 -0600 Subject: [PATCH 1/4] return early if eval is false --- R/knitr_engine.R | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/R/knitr_engine.R b/R/knitr_engine.R index e7222886..3628270a 100644 --- a/R/knitr_engine.R +++ b/R/knitr_engine.R @@ -16,37 +16,40 @@ eng_extendrsrc <- function(options) { eng_impl(options, rust_source) } - eng_impl <- function(options, extendr_engine) { - if (!requireNamespace("knitr", quietly = TRUE)) { - cli::cli_abort( - "The {.pkg knitr} package is required to run the extendr chunk engine.", - class = "rextendr_error" - ) + rlang::check_installed("knitr") + + # code to output to html + code_out <- glue_collapse(options$code, sep = "\n") + + # wrap up source code in rust syntax + options$engine <- "rust" + + # default chunk output + out <- "" + + if (isFALSE(options$eval)) { + return(knitr::engine_output(options, code_out, out)) } - if (!is.null(options$preamble)) { - code <- c( - lapply(options$preamble, function(x) knitr::knit_code$get(x)), - recursive = TRUE - ) - code <- c(code, options$code) + # code to compile + if (!rlang::is_null(options$preamble)) { + code <- c(unlist(knitr::knit_code$get(options$preamble)), options$code) } else { code <- options$code } - - code <- glue_collapse(code, sep = "\n") # code to compile - code_out <- glue_collapse(options$code, sep = "\n") # code to output to html + code <- glue_collapse(code, sep = "\n") # engine.opts is a list of arguments to be passed to rust_eval, e.g. # engine.opts = list(dependencies = list(`pulldown-cmark` = "0.8")) opts <- options$engine.opts - if (!is.environment(opts$env)) { - # default env is knit_global() + # default env is knit_global() + if (!rlang::is_environment(opts$env)) { opts$env <- knitr::knit_global() } + # try to compile cli::cli_alert_success("Compiling Rust extendr code chunk...") compiled_code <- rlang::try_fetch( do.call(extendr_engine, c(list(code = code), opts)), @@ -58,12 +61,9 @@ eng_impl <- function(options, extendr_engine) { } ) - out <- "" - # if compilation succeeded (and code should be evaluated) - if (isTRUE(options$eval) && rlang::is_function(compiled_code)) { + if (rlang::is_function(compiled_code)) { cli::cli_alert_success("Evaluating Rust extendr code chunk...") - out <- utils::capture.output({ result <- withVisible( compiled_code() @@ -79,6 +79,5 @@ eng_impl <- function(options, extendr_engine) { out <- cli::ansi_strip(compiled_code$stderr) } - options$engine <- "rust" # wrap up source code in rust syntax knitr::engine_output(options, code_out, out) } From 7ff40062882649df772a1ad585867a97ebb62d3d Mon Sep 17 00:00:00 2001 From: Blake Vernon Date: Fri, 25 Sep 2026 11:51:03 -0600 Subject: [PATCH 2/4] add test for early return --- tests/testthat/test-knitr-engine.R | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/testthat/test-knitr-engine.R b/tests/testthat/test-knitr-engine.R index a930da81..8b86cad5 100644 --- a/tests/testthat/test-knitr-engine.R +++ b/tests/testthat/test-knitr-engine.R @@ -66,3 +66,15 @@ test_that("knitr-engine surfaces cargo errors", { options$error <- FALSE expect_error(eng_extendrsrc(options), class = "system_command_status_error") }) + +test_that("knitr-engine does not compile when eval = FALSE", { + skip_if_not_installed("knitr") + + options <- knitr::opts_chunk$merge(list( + code = "not valid rust", + eval = FALSE + )) + + expect_equal(eng_extendr(options), "not valid rust") + expect_equal(eng_extendrsrc(options), "not valid rust") +}) From 9bce26feb2cc7a2ac6727832cb596706e572224c Mon Sep 17 00:00:00 2001 From: Blake Vernon Date: Fri, 25 Sep 2026 12:03:59 -0600 Subject: [PATCH 3/4] update news --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index e18ac2ff..9e175b31 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ ## Added * knitr engines now print compile errors if chunk option `error = TRUE` ([#546](https://github.com/extendr/rextendr/pull/546)) +* knitr engines now return early rather than compiling when `eval = FALSE` ([#548](https://github.com/extendr/rextendr/pull/548)) ## Fixed * The `libgcc_eh` mock in the `Makevars.win.in` template moved from the cargo From f608a41c90d36cea10ca52e49084198eb8ac10d3 Mon Sep 17 00:00:00 2001 From: Josiah Parry Date: Fri, 25 Sep 2026 11:12:08 -0700 Subject: [PATCH 4/4] Update R/knitr_engine.R --- R/knitr_engine.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/knitr_engine.R b/R/knitr_engine.R index 3628270a..aa08112a 100644 --- a/R/knitr_engine.R +++ b/R/knitr_engine.R @@ -27,7 +27,7 @@ eng_impl <- function(options, extendr_engine) { # default chunk output out <- "" - + # skip compilation when eval is false if (isFALSE(options$eval)) { return(knitr::engine_output(options, code_out, out)) }