Skip to content

Commit 43698f0

Browse files
gadenbuiecpsievert
andauthored
feat: Run examples from any package (#4005)
* chore: `inst/shiny` -> `inst/examples-shiny` * feat(runExamples): Find examples in any package * refactor: code style * refactor: small code style changes * docs: fix runApp typo * chore: include package name in valid examples message * chore(runExample): check that `package` is installed * chore: use braced package name * Update news --------- Co-authored-by: Carson Sievert <[email protected]>
1 parent c73e1a2 commit 43698f0

File tree

3 files changed

+59
-23
lines changed

3 files changed

+59
-23
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
* Added `onUnhandledError()` to register a function that will be called when an unhandled error occurs in a Shiny app. Note that this handler doesn't stop the error or prevent the session from closing, but it can be used to log the error or to clean up session-specific resources. (thanks @JohnCoene, #3993)
1818

19+
* `runExamples()` now uses the `{bslib}` package to build the user interface (UI). It also gains a `package` argument so that other packages can leverage this same function to run Shiny app examples. For more, see `?runExamples`. (#3963, #4005)
20+
1921
## Bug fixes
2022

2123
* Notifications are now constrained to the width of the viewport for window widths smaller the default notification panel size. (#3949)

R/runapp.R

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,16 @@ stopApp <- function(returnValue = invisible()) {
447447
#' @param display.mode The mode in which to display the example. Defaults to
448448
#' `showcase`, but may be set to `normal` to see the example without
449449
#' code or commentary.
450+
#' @param package The package in which to find the example (defaults to
451+
#' `"shiny"`).
452+
#'
453+
#' To provide examples in your package, store examples in the
454+
#' `inst/examples-shiny` directory of your package. Each example should be
455+
#' in its own subdirectory and should be runnable when [runApp()] is called
456+
#' on the subdirectory. Example apps can include a `DESCRIPTION` file and a
457+
#' `README.md` file to provide metadata and commentary about the example. See
458+
#' the article on [Display Modes](https://shiny.posit.co/r/articles/build/display-modes/)
459+
#' on the Shiny website for more information.
450460
#' @inheritParams runApp
451461
#'
452462
#' @examples
@@ -462,34 +472,46 @@ stopApp <- function(returnValue = invisible()) {
462472
#' system.file("examples", package="shiny")
463473
#' }
464474
#' @export
465-
runExample <- function(example=NA,
466-
port=getOption("shiny.port"),
467-
launch.browser = getOption('shiny.launch.browser', interactive()),
468-
host=getOption('shiny.host', '127.0.0.1'),
469-
display.mode=c("auto", "normal", "showcase")) {
470-
legacy <- getOption('shiny.legacy.examples', FALSE)
471-
examplesDir <- if (isTRUE(legacy)) 'examples' else 'examples-shiny'
472-
examplesDir <- system_file(examplesDir, package='shiny')
475+
runExample <- function(
476+
example = NA,
477+
port = getOption("shiny.port"),
478+
launch.browser = getOption("shiny.launch.browser", interactive()),
479+
host = getOption("shiny.host", "127.0.0.1"),
480+
display.mode = c("auto", "normal", "showcase"),
481+
package = "shiny"
482+
) {
483+
if (!identical(package, "shiny") && !is_installed(package)) {
484+
rlang::check_installed(package)
485+
}
486+
487+
use_legacy_shiny_examples <-
488+
identical(package, "shiny") &&
489+
isTRUE(getOption('shiny.legacy.examples', FALSE))
490+
491+
examplesDir <- system_file(
492+
if (use_legacy_shiny_examples) "examples" else "examples-shiny",
493+
package = package
494+
)
495+
473496
dir <- resolve(examplesDir, example)
497+
474498
if (is.null(dir)) {
499+
valid_examples <- sprintf(
500+
'Valid examples in {%s}: "%s"',
501+
package,
502+
paste(list.files(examplesDir), collapse = '", "')
503+
)
504+
475505
if (is.na(example)) {
476-
errFun <- message
477-
errMsg <- ''
478-
}
479-
else {
480-
errFun <- stop
481-
errMsg <- paste('Example', example, 'does not exist. ')
506+
message(valid_examples)
507+
return(invisible())
482508
}
483509

484-
errFun(errMsg,
485-
'Valid examples are "',
486-
paste(list.files(examplesDir), collapse='", "'),
487-
'"')
488-
}
489-
else {
490-
runApp(dir, port = port, host = host, launch.browser = launch.browser,
491-
display.mode = display.mode)
510+
stop("Example '", example, "' does not exist. ", valid_examples)
492511
}
512+
513+
runApp(dir, port = port, host = host, launch.browser = launch.browser,
514+
display.mode = display.mode)
493515
}
494516

495517
#' Run a gadget

man/runExample.Rd

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)