From c190cb35cc0c7c6d30bc3d53dd0184b4483634fb Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Sat, 20 Jun 2026 18:31:28 -0700 Subject: [PATCH 1/3] fiix issue 630 --- R/tinyplot_add.R | 30 +++++++++++++++++++++++------- man/tinyplot_add.Rd | 9 ++++++++- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/R/tinyplot_add.R b/R/tinyplot_add.R index baf234b9f..4b4d4f5cb 100644 --- a/R/tinyplot_add.R +++ b/R/tinyplot_add.R @@ -19,7 +19,10 @@ #' #' @param ... All named arguments override arguments from the previous calls. #' Arguments not supplied to [tinyplot_add] remain unchanged from the previous -#' call. +#' call. Arguments are captured unevaluated and spliced into the updated call, +#' so those that rely on non-standard evaluation against `data`---e.g. +#' `subset = cyl == 4` or `weights = wt`---behave the same as in a direct +#' [`tinyplot`] call. #' #' @examples #' tinyplot(Sepal.Width ~ Sepal.Length | Species, @@ -37,6 +40,10 @@ #' # type = "lm", #' # add = TRUE) #' +#' ## Arguments relying on non-standard evaluation (e.g. `subset`) work too: +#' tinyplot(mpg ~ wt, data = mtcars) +#' tinyplot_add(subset = cyl == 4, col = "red", pch = 16) +#' #' @returns No return value, called for side effect of producing a plot. #' #' @export @@ -47,16 +54,25 @@ tinyplot_add = function(...) { stop("No previous tinyplot call found.") } - args = list(...) - for (n in names(args)) { - if (n != "") { - cal[[n]] = args[[n]] + # Capture the dots as *unevaluated* expressions rather than evaluated values. + # This way, arguments that rely on non-standard evaluation against `data` + # (e.g. `subset = cyl == 4`, `weights = wt`, or a bare-name formula) are + # spliced into the rebuilt call and only resolved when it is finally + # evaluated through the formula method's `model.frame`. Using `list(...)` + # here would instead force evaluation in this frame, where data-scoped + # variables are not visible. (#630) + args = match.call(expand.dots = FALSE)[["..."]] + nms = names(args) + for (i in seq_along(args)) { + n = if (is.null(nms)) "" else nms[[i]] + if (!is.null(n) && n != "") { + cal[[n]] = args[[i]] } } # allow first argument in tinyplot_add() to be unnamed - if (isTRUE(names(args)[1] == "")) { - cal[[2]] = args[[1]] + if (length(args) >= 1L && (is.null(nms) || nms[[1L]] == "")) { + cal[[2]] = args[[1L]] } cal[["add"]] = TRUE diff --git a/man/tinyplot_add.Rd b/man/tinyplot_add.Rd index 4b3a510aa..ba4634ab9 100644 --- a/man/tinyplot_add.Rd +++ b/man/tinyplot_add.Rd @@ -12,7 +12,10 @@ plt_add(...) \arguments{ \item{...}{All named arguments override arguments from the previous calls. Arguments not supplied to \link{tinyplot_add} remain unchanged from the previous -call.} +call. Arguments are captured unevaluated and spliced into the updated call, +so those that rely on non-standard evaluation against \code{data}---e.g. +\code{subset = cyl == 4} or \code{weights = wt}---behave the same as in a direct +\code{\link{tinyplot}} call.} } \value{ No return value, called for side effect of producing a plot. @@ -53,4 +56,8 @@ tinyplot_add(type = "lm") ## or : plt_add(type = "lm") # type = "lm", # add = TRUE) +## Arguments relying on non-standard evaluation (e.g. `subset`) work too: +tinyplot(mpg ~ wt, data = mtcars) +tinyplot_add(subset = cyl == 4, col = "red", pch = 16) + } From c84a3c205e68c7091c175632bcdec9b38c27829d Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Sat, 20 Jun 2026 18:34:09 -0700 Subject: [PATCH 2/3] news --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index 454bd69ab..8f45e6ab2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -236,6 +236,10 @@ Theme fixes: - Fixed `xlab = NA` / `ylab = NA` gotchas: a barplot with `xlab = NA` no longer errors, and spineplots no longer clip their category and tick labels when `xlab`/`ylab` are set to `NA` under a dynamic theme. (#635 @grantmcdermott) +- `tinyplot_add()` (`plt_add()`) now captures its arguments unevaluated, so + arguments that rely on non-standard evaluation against `data` (e.g., + `plt_add(..., subset = <>)`) resolve correctly instead of erroring with + "object not found". (#638 @grantmcdermott) ## v0.6.1 From 71d55b5bfb7cc5e0f330363bad6f304e8c5fc4ae Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Sat, 20 Jun 2026 18:34:35 -0700 Subject: [PATCH 3/3] add test --- .../_tinysnapshot/tinyplot_add_subset.svg | 104 ++++++++++++++++++ inst/tinytest/test-tinyplot_add.R | 7 ++ 2 files changed, 111 insertions(+) create mode 100644 inst/tinytest/_tinysnapshot/tinyplot_add_subset.svg diff --git a/inst/tinytest/_tinysnapshot/tinyplot_add_subset.svg b/inst/tinytest/_tinysnapshot/tinyplot_add_subset.svg new file mode 100644 index 000000000..c32d17fef --- /dev/null +++ b/inst/tinytest/_tinysnapshot/tinyplot_add_subset.svg @@ -0,0 +1,104 @@ + + + + + + + + + + + + + +wt +mpg + + + + + +2 +3 +4 +5 + + + + + + +10 +15 +20 +25 +30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inst/tinytest/test-tinyplot_add.R b/inst/tinytest/test-tinyplot_add.R index 1f5914efe..d5a578369 100644 --- a/inst/tinytest/test-tinyplot_add.R +++ b/inst/tinytest/test-tinyplot_add.R @@ -118,3 +118,10 @@ f = function() { tinyplot_add(type = "jitter", cex = 0.5, alpha = 0.3) } expect_snapshot_plot(f, label = "tinyplot_add_jitter_on_grouped_violin") + +# subset NSE in tinyplot_add (#630) +f = function() { + tinyplot(mpg ~ wt, data = mtcars) + tinyplot_add(subset = cyl == 4, col = "red", pch = 16) +} +expect_snapshot_plot(f, label = "tinyplot_add_subset")