From 85aa9618ae7a2948687df02372dfb99fc206a99d Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Mar 2021 07:35:21 -0600 Subject: [PATCH 1/4] Allow trailing commas in more places I grepped for list(...) and replaced with rlang::list2(...). This also enables !!! which is generally not important for Shiny because it automatically splices lists/tagLists, but I doubt it will affect any existing code. --- R/bootstrap-layout.R | 8 ++++---- R/bootstrap.R | 10 +++++----- R/reactives.R | 4 ++-- R/shiny-options.R | 2 +- R/utils.R | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/R/bootstrap-layout.R b/R/bootstrap-layout.R index 0bbb4419dc..60b8b60cf7 100644 --- a/R/bootstrap-layout.R +++ b/R/bootstrap-layout.R @@ -396,7 +396,7 @@ mainPanel <- function(..., width = 8) { #' } #' @export verticalLayout <- function(..., fluid = TRUE) { - lapply(list(...), function(row) { + lapply(rlang::list2(...), function(row) { col <- column(12, row) if (fluid) fluidRow(col) @@ -433,7 +433,7 @@ verticalLayout <- function(..., fluid = TRUE) { #' @export flowLayout <- function(..., cellArgs = list()) { - children <- list(...) + children <- rlang::list2(...) childIdx <- !nzchar(names(children) %||% character(length(children))) attribs <- children[!childIdx] children <- children[childIdx] @@ -516,7 +516,7 @@ inputPanel <- function(...) { #' @export splitLayout <- function(..., cellWidths = NULL, cellArgs = list()) { - children <- list(...) + children <- rlang::list2(...) childIdx <- !nzchar(names(children) %||% character(length(children))) attribs <- children[!childIdx] children <- children[childIdx] @@ -614,7 +614,7 @@ fillCol <- function(..., flex = 1, width = "100%", height = "100%") { } flexfill <- function(..., direction, flex, width = width, height = height) { - children <- list(...) + children <- rlang::list2(...) attrs <- list() if (!is.null(names(children))) { diff --git a/R/bootstrap.R b/R/bootstrap.R index 66d534d7bb..5cc6e06491 100644 --- a/R/bootstrap.R +++ b/R/bootstrap.R @@ -49,7 +49,7 @@ bootstrapPage <- function(..., title = NULL, responsive = deprecated(), theme = tags$head(tags$link(rel="stylesheet", type="text/css", href=theme)) }, # remainder of tags passed to the function - list(...) + rlang::list2(...) ) # If theme is a bslib::bs_theme() object, bootstrapLib() needs to come first @@ -447,7 +447,7 @@ navbarPage <- function(title, selected <- restoreInput(id = id, default = selected) # build the tabset - tabs <- list(...) + tabs <- rlang::list2(...) tabset <- buildTabset(tabs, "nav navbar-nav", NULL, id, selected) # function to return plain or fluid class name @@ -511,7 +511,7 @@ navbarPage <- function(title, navbarMenu <- function(title, ..., menuName = title, icon = NULL) { structure(list(title = title, menuName = menuName, - tabs = list(...), + tabs = rlang::list2(...), iconClass = iconClass(icon)), class = "shiny.navbarmenu") } @@ -754,7 +754,7 @@ tabsetPanel <- function(..., selected <- restoreInput(id = id, default = selected) # build the tabset - tabs <- list(...) + tabs <- rlang::list2(...) type <- match.arg(type) tabset <- buildTabset(tabs, paste0("nav nav-", type), NULL, id, selected) @@ -825,7 +825,7 @@ navlistPanel <- function(..., selected <- restoreInput(id = id, default = selected) # build the tabset - tabs <- list(...) + tabs <- rlang::list2(...) tabset <- buildTabset(tabs, "nav nav-pills nav-stacked", textFilter, diff --git a/R/reactives.R b/R/reactives.R index 2bcd4d8b71..f80cdafe99 100644 --- a/R/reactives.R +++ b/R/reactives.R @@ -568,7 +568,7 @@ ReactiveValues <- R6Class( #' @seealso [isolate()] and [is.reactivevalues()]. #' @export reactiveValues <- function(...) { - args <- list(...) + args <- rlang::list2(...) if ((length(args) > 0) && (is.null(names(args)) || any(names(args) == ""))) rlang::abort("All arguments passed to reactiveValues() must be named.") @@ -1915,7 +1915,7 @@ reactivePoll <- function(intervalMillis, session, checkFunc, valueFunc) { #' @export reactiveFileReader <- function(intervalMillis, session, filePath, readFunc, ...) { filePath <- coerceToFunc(filePath) - extraArgs <- list(...) + extraArgs <- rlang::list2(...) reactivePoll( intervalMillis, session, diff --git a/R/shiny-options.R b/R/shiny-options.R index bcd789c3a4..a82b4ee679 100644 --- a/R/shiny-options.R +++ b/R/shiny-options.R @@ -178,7 +178,7 @@ getShinyOption <- function(name, default = NULL) { #' @aliases shiny-options #' @export shinyOptions <- function(...) { - newOpts <- list(...) + newOpts <- rlang::list2(...) if (length(newOpts) > 0) { # If we're within a session, modify at the session level. diff --git a/R/utils.R b/R/utils.R index 40d036ba31..172be156ce 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1176,7 +1176,7 @@ reactiveStop <- function(message = "", class = NULL) { #' #' } validate <- function(..., errorClass = character(0)) { - results <- sapply(list(...), function(x) { + results <- sapply(rlang::list2(...), function(x) { # Detect NULL or NA if (is.null(x)) return(NA_character_) From 9305909c8f981a10aa15634eb350d890f3e5314d Mon Sep 17 00:00:00 2001 From: Carson Date: Mon, 22 Mar 2021 16:05:25 -0500 Subject: [PATCH 2/4] update news; no need to rlang:: --- NEWS.md | 2 ++ R/bootstrap-layout.R | 8 ++++---- R/bootstrap.R | 2 +- R/reactives.R | 4 ++-- R/shiny-options.R | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/NEWS.md b/NEWS.md index 9c266545f9..ea807517b9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,8 @@ shiny 1.6.0.9000 ### New features and improvements +* All uses of `list(...)` have been replaced with `rlang::list2(...)`. By effect, `{rlang}`'s `!!!` operator may now be used to "splice" a list of argument values into `...`. We think this'll be particularly useful for passing a list of `tabPanel()` to their consumers (i.e., `tabsetPanel()`, `navbarPage()`, etc). For example, `tabs <- list(tabPanel("A", "a"), tabPanel("B", "b")); navbarPage(!!!tabs)`. (#3315 and #3328) + * Numerous improvements tabset panels (i.e., `tabPanel()`, `navbarMenu()`, `tabsetPanel()`, `navbarPage()`, etc) (#3315): * Closed #3322: `tabsetPanel()` and `navlistPanel()` gain `header`/`footer` arguments (inspired by `navbarPage()`'s already existing `header`/`footer`), making it easier to include content that should appear on every tab. * Closed #3313 and #1823: More informative error when non-`tabPanel()`/`shiny.tag` objects are supplied to `...`. diff --git a/R/bootstrap-layout.R b/R/bootstrap-layout.R index 60b8b60cf7..1c57daf84b 100644 --- a/R/bootstrap-layout.R +++ b/R/bootstrap-layout.R @@ -396,7 +396,7 @@ mainPanel <- function(..., width = 8) { #' } #' @export verticalLayout <- function(..., fluid = TRUE) { - lapply(rlang::list2(...), function(row) { + lapply(list2(...), function(row) { col <- column(12, row) if (fluid) fluidRow(col) @@ -433,7 +433,7 @@ verticalLayout <- function(..., fluid = TRUE) { #' @export flowLayout <- function(..., cellArgs = list()) { - children <- rlang::list2(...) + children <- list2(...) childIdx <- !nzchar(names(children) %||% character(length(children))) attribs <- children[!childIdx] children <- children[childIdx] @@ -516,7 +516,7 @@ inputPanel <- function(...) { #' @export splitLayout <- function(..., cellWidths = NULL, cellArgs = list()) { - children <- rlang::list2(...) + children <- list2(...) childIdx <- !nzchar(names(children) %||% character(length(children))) attribs <- children[!childIdx] children <- children[childIdx] @@ -614,7 +614,7 @@ fillCol <- function(..., flex = 1, width = "100%", height = "100%") { } flexfill <- function(..., direction, flex, width = width, height = height) { - children <- rlang::list2(...) + children <- list2(...) attrs <- list() if (!is.null(names(children))) { diff --git a/R/bootstrap.R b/R/bootstrap.R index bb66a622e1..c57c5a36d3 100644 --- a/R/bootstrap.R +++ b/R/bootstrap.R @@ -49,7 +49,7 @@ bootstrapPage <- function(..., title = NULL, responsive = deprecated(), theme = tags$head(tags$link(rel="stylesheet", type="text/css", href=theme)) }, # remainder of tags passed to the function - rlang::list2(...) + list2(...) ) # If theme is a bslib::bs_theme() object, bootstrapLib() needs to come first diff --git a/R/reactives.R b/R/reactives.R index f80cdafe99..573bec2213 100644 --- a/R/reactives.R +++ b/R/reactives.R @@ -568,7 +568,7 @@ ReactiveValues <- R6Class( #' @seealso [isolate()] and [is.reactivevalues()]. #' @export reactiveValues <- function(...) { - args <- rlang::list2(...) + args <- list2(...) if ((length(args) > 0) && (is.null(names(args)) || any(names(args) == ""))) rlang::abort("All arguments passed to reactiveValues() must be named.") @@ -1915,7 +1915,7 @@ reactivePoll <- function(intervalMillis, session, checkFunc, valueFunc) { #' @export reactiveFileReader <- function(intervalMillis, session, filePath, readFunc, ...) { filePath <- coerceToFunc(filePath) - extraArgs <- rlang::list2(...) + extraArgs <- list2(...) reactivePoll( intervalMillis, session, diff --git a/R/shiny-options.R b/R/shiny-options.R index a82b4ee679..caf087ac2d 100644 --- a/R/shiny-options.R +++ b/R/shiny-options.R @@ -178,7 +178,7 @@ getShinyOption <- function(name, default = NULL) { #' @aliases shiny-options #' @export shinyOptions <- function(...) { - newOpts <- rlang::list2(...) + newOpts <- list2(...) if (length(newOpts) > 0) { # If we're within a session, modify at the session level. From 40013a7e9b81a8e637c01cc69a1922479d5428d9 Mon Sep 17 00:00:00 2001 From: Carson Date: Mon, 22 Mar 2021 16:06:35 -0500 Subject: [PATCH 3/4] missed one --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index 172be156ce..d93d3fa79e 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1176,7 +1176,7 @@ reactiveStop <- function(message = "", class = NULL) { #' #' } validate <- function(..., errorClass = character(0)) { - results <- sapply(rlang::list2(...), function(x) { + results <- sapply(list2(...), function(x) { # Detect NULL or NA if (is.null(x)) return(NA_character_) From 2ebf3730b362a1d1b354ac67bbe92eaa65c73285 Mon Sep 17 00:00:00 2001 From: Carson Sievert Date: Mon, 22 Mar 2021 17:29:49 -0500 Subject: [PATCH 4/4] Update NEWS.md Co-authored-by: Hadley Wickham --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index ea807517b9..0dd1b11c7b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,7 +9,7 @@ shiny 1.6.0.9000 ### New features and improvements -* All uses of `list(...)` have been replaced with `rlang::list2(...)`. By effect, `{rlang}`'s `!!!` operator may now be used to "splice" a list of argument values into `...`. We think this'll be particularly useful for passing a list of `tabPanel()` to their consumers (i.e., `tabsetPanel()`, `navbarPage()`, etc). For example, `tabs <- list(tabPanel("A", "a"), tabPanel("B", "b")); navbarPage(!!!tabs)`. (#3315 and #3328) +* All uses of `list(...)` have been replaced with `rlang::list2(...)`. This means that you can use trailing `,` without error and use rlang's `!!!` operator to "splice" a list of argument values into `...`. We think this'll be particularly useful for passing a list of `tabPanel()` to their consumers (i.e., `tabsetPanel()`, `navbarPage()`, etc). For example, `tabs <- list(tabPanel("A", "a"), tabPanel("B", "b")); navbarPage(!!!tabs)`. (#3315 and #3328) * Numerous improvements tabset panels (i.e., `tabPanel()`, `navbarMenu()`, `tabsetPanel()`, `navbarPage()`, etc) (#3315): * Closed #3322: `tabsetPanel()` and `navlistPanel()` gain `header`/`footer` arguments (inspired by `navbarPage()`'s already existing `header`/`footer`), making it easier to include content that should appear on every tab.