
rpkgkit standalone scripts
rpkgkit 0.1.23
Yuxi Yang
2026-11-06
Source:vignettes/standalone_tools.Rmd
standalone_tools.Rmd
library(rpkgkit)
dir <- tempdir()
dir.create(dir)
usethis::create_package(dir)
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}"
)The wrapped functions also take .envir, defaulting to
parent.frame() and forwarded to the cli function, so
{} interpolation is resolved in the caller’s environment
instead of inside the wrapper:
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!")Print frequency tables
The cli_table.R standalone script prints frequency
tables of a vector with cli styling. cli_table() uses two
aligned lines (headers, then counts), while
cli_table_oneline() collapses them into a single
header: count line. Both return the underlying
table object invisibly.
x <- c("apple", "pear", "apple", NA)
cli_table(x)
cli_table(x, head_format = ".strong", align = "center")
cli_table_oneline(x)
cli_table_oneline(mtcars$cyl, sep = " | ", count_format = NULL)Print data frames as kable-style tables
The cli_kable.R standalone script prints a data frame, a
matrix or any object as.data.frame() accepts as the pipe
table of knitr::kable(), the layout
kableExtra::kable() shows, with cli inline
classes instead of Markdown. The layout is the one of
kable(): padded cells, padding extra spaces
per column, a minimum column width of 3, rounded and right-aligned
numbers, and the :---|---: alignment rule below the
headers.
header_format (column headers),
rownames_format (row names) and value_format
(body values) style the table. Pass a single class to style everything,
or a named vector or named list to style only the columns or rows it
names: an unnamed element is the fallback style of everything that is
not named, which is how a part of the table is highlighted. The printed
lines are returned invisibly.
cli_kable(head(mtcars, 3))
# style the header of two columns only, with two different classes
cli_kable(head(mtcars, 3), header_format = c(cyl = ".val", wt = ".field"))Named formats reach the rows too, and the elements of a
value_format list can be named vectors of row names, so a
block of rows and columns can be highlighted:
cli_kable(
mtcars[1:6, c("mpg", "cyl", "disp", "wt")],
header_format = c(disp = ".strong", wt = ".strong"),
rownames_format = c("Hornet 4 Drive" = ".strong", "Valiant" = ".strong"),
value_format = list(
disp = c("Hornet 4 Drive" = ".field", "Valiant" = ".field"),
wt = c("Hornet 4 Drive" = ".field", "Valiant" = ".field")
)
)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:
try(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()
#> Error in inquire_standalone("r-lib/rlang") :
#> could not find function "inquire_standalone"
#> [1] "Error in inquire_standalone(\"r-lib/rlang\") : \n could not find function \"inquire_standalone\"\n"
try(browse_standalone()) |> head()
#> Error in browse_standalone() :
#> could not find function "browse_standalone"
#> [1] "Error in browse_standalone() : \n could not find function \"browse_standalone\"\n"Create a local standalone file with a standard metadata header:
library(rpkgkit)
#> ✔ rpkgkit v0.1.24 loaded [2 ms]
dir <- file.path(tempdir(), "R")
dir.create(dir, recursive = TRUE)
create_standalone("foo", path = dir, open = FALSE)
#> ✔ Created standalone file: /tmp/RtmpK00ZiL/R/standalone-foo.RValidate the standalone file layout
check_standalone() verifies that a custom standalone
file follows the layout consumed by
usethis::use_standalone(). It checks the # ---
header (the required repo, file,
last-updated and license slots, the optional
imports slot, and the format of each value), that every
documented function carries @noRd, and that a
# nocov start marker precedes all functions.
check_standalone(path = file.path(dir, "standalone-foo.R"))
#> ── standalone check results ──────────────────────────────── standalone-foo.R ──
#> ❯ The header slot `imports` is empty; remove it if there are no dependencies.
#> ... NOTE
#> ❯ The header has non-standard slots: `dependency`. ... NOTE
#> ❯ `repo` should look like `owner/repo`, got: R ... WARNING
#> ❯ No top-level function definitions found. ... NOTE
#> ✔ nocoverage start marker
#>
#> Duration: 0.01s
#> 0 error ✔ | 1 warning ✖ | 3 notes ✖Findings are printed in the style of devtools::check(),
and the counts are returned invisibly as
list(error = , warning = , note = ). An error in a check
point skips the remaining ones, while warnings and notes never stop the
run.
After editing standalone files, refresh their
last-updated field:
update_time_in_standalone(path = file.path(dir, "standalone-foo.R"))
#> ✔ Updated last-updated to "2026-11-06" in 1 file.Add a dated changelog entry to one or more standalone files:
add_changelog_in_standalone(
path = file.path(dir, "standalone-foo.R"),
"Added foo function"
)
#> ✔ Added changelog entry (2026-11-06) for /tmp/RtmpK00ZiL/R/standalone-foo.R.