From c126fc0270268ac13bf6a73c601903620d39ae4d Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Mon, 30 Sep 2024 11:13:29 -0400 Subject: [PATCH 1/3] Rework `view()` to better work with RStudio and Positron --- R/view.R | 57 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/R/view.R b/R/view.R index a2ebece3e..8cdbeca01 100644 --- a/R/view.R +++ b/R/view.R @@ -24,28 +24,55 @@ view <- function(x, title = NULL, ..., n = NULL) { check_dots_empty() - if (!interactive()) return(invisible(x)) + if (!rlang::is_interactive()) { + return(invisible(x)) + } + + # The user's expression and the environment to re-evaluate it in + quo <- enquo0(x) + expr <- quo_get_expr(quo) + env <- quo_get_env(quo) if (is.null(title)) { - title <- expr_deparse(substitute(x), width = Inf) + title <- as_label(expr) } + # Retrieve the `View()` function, which includes the special + # hooks created by RStudio or Positron + fn <- get("View", envir = as.environment("package:utils")) + if (!is.data.frame(x)) { - if (is.null(n)) { - n <- get_tibble_option_view_max() - } - x <- head(x, n + 1) - x <- as.data.frame(x) - if (nrow(x) > n) { - message("Showing the first ", n, " rows.") - x <- head(x, n) - } + return(view_with_coercion(x, n, title, fn)) + } + + # Make a `View()` call that we evaluate in the parent frame, + # as if the user called `View()` directly rather than `view()`. + # If `expr` directly references a data frame in the parent frame, this + # allows RStudio and Positron to "track" that original object + # for live updates in the data viewer. + inject((!!fn)(!!expr, !!title), env = env) + + invisible(x) +} + +view_with_coercion <- function(x, n, title, fn) { + if (is.null(n)) { + n <- get_tibble_option_view_max() + } + + x <- head(x, n + 1) + x <- as.data.frame(x) + + if (nrow(x) > n) { + message("Showing the first ", n, " rows.") + x <- head(x, n) } - view_fun <- get("View", envir = as.environment("package:utils")) - # Construct call with defused arguments, some versions of RStudio evaluate - # in the global environment (?). - eval_tidy(quo(view_fun(!!x, !!title))) + # Since we just created `x`, there won't be anything for + # RStudio or Positron to "track", so don't even make an effort + # to try and evaluate in the parent frame with the original + # expression + fn(x, title) invisible(x) } From 102e4e45fdc1b23443b98f4ff03f8ca35a3de833 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Mon, 30 Sep 2024 14:43:38 -0400 Subject: [PATCH 2/3] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kirill Müller --- R/view.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/view.R b/R/view.R index 8cdbeca01..ffad65696 100644 --- a/R/view.R +++ b/R/view.R @@ -24,7 +24,7 @@ view <- function(x, title = NULL, ..., n = NULL) { check_dots_empty() - if (!rlang::is_interactive()) { + if (!is_interactive()) { return(invisible(x)) } @@ -65,7 +65,7 @@ view_with_coercion <- function(x, n, title, fn) { if (nrow(x) > n) { message("Showing the first ", n, " rows.") - x <- head(x, n) + x <- x[seq_len(n), , drop = FALSE] } # Since we just created `x`, there won't be anything for From ac8e110f92e11288ba786bf752f438830edb47df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Mon, 30 Sep 2024 20:53:38 +0200 Subject: [PATCH 3/3] Much better with `vec_slice()` --- R/view.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/view.R b/R/view.R index ffad65696..390575e65 100644 --- a/R/view.R +++ b/R/view.R @@ -65,7 +65,7 @@ view_with_coercion <- function(x, n, title, fn) { if (nrow(x) > n) { message("Showing the first ", n, " rows.") - x <- x[seq_len(n), , drop = FALSE] + x <- vec_slice(x, seq_len(n)) } # Since we just created `x`, there won't be anything for