rpkgkit standalone scripts

library(rpkgkit)
dir <- file.path(tempdir(), "example")
usethis::create_package(dir, open = FALSE)
usethis::local_project(dir)
usethis::use_readme_md(open = FALSE)

Import standalone helpers

rpkgkit includes utilities that can also be imported directly into another project with usethis::use_standalone().

usethis::use_standalone("WangLabCSU/rpkgkit", "args_to_func")

Match arguments to functions

The args_to_func.R standalone script provides helpers for matching a list of arguments to compatible functions.

f1 <- function(a, b) a + b
f2 <- function(x, y, ...) x * y
f3 <- function(p, q) p - q

args <- list(a = 1, b = 2)
match_func_to_args(args, f1, f2, f3)
args <- list(a = 1, b = 2, x = 3, y = 4)
foo <- function(x, y = 1) x + y
filter_args_for_func(args, foo)

Show the caller of a cli message

The caller_cli.R standalone script decorates a cli function so its output identifies the caller.

decorated <- add_caller_to_cli(cli::cli_alert_info)
foo1 <- \() {
  decorated("<- where is this called from?")
}
foo2 <- \() foo1()
bar <- function() foo2()
bar()

Use colored cli output

The colorful_cli.R standalone script creates a cli environment with convenient color classes.

color_cli <- create_colorful_cli_env()
color_cli$cli_alert_danger("{.red This is a red message}")
color_cli$cli_alert_info("{.blue This is a blue message}")
color_cli$cli_alert_info("{.orange This is an orange message}")

color_cli2 <- create_colorful_cli_env(cli_theme = generate_color_theme())
color_cli2$cli_alert_success(
  "{.violetred3 R}{.orange a}{.yellow i}{.green n}{.cyan b}{.blue o}{.purple w}"
)

Add timestamps to cli output

The ts_cli.R standalone script creates timestamped cli functions.

ts_cli <- create_ts_cli_env()
ts_cli$cli_alert_info("Hello, world!")

Validate and transform arguments

The make_arg_validator.R standalone script builds reusable validators. Give it an unquoted block of checks and coercions written in terms of argument names; it returns a function that, called from inside your function, returns the validated arguments as a named list.

validate_add <- make_arg_validator({
  if (!type %in% c("sum", "product")) {
    rlang::abort("`type` must be \"sum\" or \"product\".", call = NULL)
  }
  n <- as.integer(max(n, 1L))
})

add <- function(type = c("sum", "product"), n = 1L) {
  args <- validate_add()
  switch(args$type, sum = sum(1:args$n), product = prod(1:args$n))
}

add("sum", 3)

Errors raised inside the block reach the caller unchanged, and an assignment to an existing argument is written back through the returned list:

list2env(validate_add(), envir = environment())

Only names that already existed in the caller’s frame are returned, so a validator updates arguments but never adds new ones. The same validator can be shared by several functions, and env can be passed explicitly to validate a list of options instead of a function frame.

Manage standalone files in a package

Use inquire_standalone() to inspect standalone files in a GitHub repository and browse_standalone() to search supported repositories.

try(inquire_standalone("r-lib/rlang")) |> head()
#> # A tibble: 6 × 9
#>   name               path  sha    size url   html_url git_url download_url type 
#>   <chr>              <chr> <chr> <int> <chr> <chr>    <chr>   <chr>        <chr>
#> 1 standalone-cli.R   R/st… 14c6… 18672 http… https:/… https:… https://raw… file 
#> 2 standalone-downst… R/st… 09b7…  9213 http… https:/… https:… https://raw… file 
#> 3 standalone-lazyev… R/st… 50ce…  2313 http… https:/… https:… https://raw… file 
#> 4 standalone-lifecy… R/st… 70f0…  6411 http… https:/… https:… https://raw… file 
#> 5 standalone-linked… R/st… 9ab2…  2167 http… https:/… https:… https://raw… file 
#> 6 standalone-obj-ty… R/st… e9c3…  7175 http… https:/… https:… https://raw… file
try(browse_standalone()) |> head()
#> ℹ Searching GitHub for standalone-*.R files
#> ■■■■■■■■■■■■■■■■                  50% | 100/200 items, page 1/2 | ETA  0s
#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■  100% | 200/200 items, page 2/2 | ETA  0s
#> # A tibble: 6 × 9
#>   repo        name  path  sha   url   html_url git_url repo_url repo_description
#>   <chr>       <chr> <chr> <chr> <chr> <chr>    <chr>   <chr>    <chr>           
#> 1 tidymodels… stan… R/st… 3f38… http… https:/… https:… https:/… A tidy unified …
#> 2 r-lib/rlang stan… R/st… 14c6… http… https:/… https:… https:/… Low-level API f…
#> 3 r-lib/rlang stan… R/st… a789… http… https:/… https:… https:/… Low-level API f…
#> 4 r-lib/rlang stan… R/st… 4da3… http… https:/… https:… https:/… Low-level API f…
#> 5 r-lib/rlang stan… R/st… 03ee… http… https:/… https:… https:/… Low-level API f…
#> 6 r-lib/rlang stan… R/st… 0c1d… http… https:/… https:… https:/… Low-level API f…

Create a local standalone file with a standard metadata header:

create_standalone("foo", open = FALSE)

After editing standalone files, refresh their last-updated field:

update_time_in_standalone(path = "./R/standalone-foo.R")

Add a dated changelog entry to one or more standalone files:

add_changelog_in_standalone("R/standalone-foo.R", "Added foo function")