The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
library(tidyOhdsiSolutions)
# Disable ANSI colour codes so rendered HTML output is clean
options(pkg.no_color = TRUE)handyCli is a zero-dependency console messaging system
built on base R. It provides styled, consistently prefixed messages for
every severity level, structured output helpers
(msg_list(), msg_kv()), progress and spinner
indicators, a timing wrapper, and safe error-handling utilities.
All functions write to message() (stderr) so they are
silenceable with suppressMessages() and do not pollute
stdout() or function return values.
Each message type carries a distinct prefix symbol.
msg_info("Loading configuration from disk")
#> i Loading configuration from disk
msg_success("All 42 concept sets validated")
#> v All 42 concept sets validated
msg_warn("Column 'mappedSourceCode' is missing — using NA")
#> ! Column 'mappedSourceCode' is missing — using NA
msg_danger("Connection pool exhausted (non-fatal, retrying)")
#> x Connection pool exhausted (non-fatal, retrying)
msg_process("Uploading results to the remote schema")
#> -> Uploading results to the remote schema
msg_bullet("concept_id 201826 — Type 2 Diabetes Mellitus")
#> * concept_id 201826 — Type 2 Diabetes Mellitus
msg_todo("Verify descendant flag for hypertension concept set")
#> - Verify descendant flag for hypertension concept setUse msg_header() and msg_rule() to visually
group output in long-running pipelines.
msg_header("Step 1: Validate Input")
#> --------------------------- Step 1: Validate Input ---------------------------
msg_info("Checking required columns")
#> i Checking required columns
msg_success("Validation passed")
#> v Validation passed
msg_blank()
#>
msg_header("Step 2: Build Cohort")
#> ---------------------------- Step 2: Build Cohort ----------------------------
msg_process("Assembling concept set expressions")
#> -> Assembling concept set expressions
msg_rule()
#> --------------------------------------------------------------------------------
msg_info("Pipeline complete")
#> i Pipeline completemsg_list() is useful for displaying a set of labelled
items, such as cohort components or domain breakdowns.
msg_kv() aligns keys and values into two columns — handy
for configuration summaries or run metadata.
run_info <- list(
Package = "tidyOhdsiSolutions",
Version = as.character(packageVersion("tidyOhdsiSolutions")),
R_version = paste0(R.version$major, ".", R.version$minor),
Date = format(Sys.Date())
)
msg_kv(run_info)
#> Package tidyOhdsiSolutions
#> Version 0.1.0
#> R_version 4.5.3
#> Date 2026-04-08Combine msg_header() and message functions to annotate
each iteration of a processing loop.
concept_sets <- list(
diabetes = c(201826L, 442793L),
hypertension = c(320128L),
obesity = c(433736L, 4215968L)
)
for (nm in names(concept_sets)) {
msg_header(nm)
msg_info("Concepts: ", paste(concept_sets[[nm]], collapse = ", "))
msg_success("Processed ", length(concept_sets[[nm]]), " concept(s)")
msg_blank()
}
#> ---------------------------------- diabetes ----------------------------------
#> i Concepts: 201826, 442793
#> v Processed 2 concept(s)
#>
#> -------------------------------- hypertension --------------------------------
#> i Concepts: 320128
#> v Processed 1 concept(s)
#>
#> ---------------------------------- obesity -----------------------------------
#> i Concepts: 433736, 4215968
#> v Processed 2 concept(s)
#> msg_try()msg_try() wraps an expression so errors and warnings are
caught and styled without stopping the loop. The on_error
argument controls the behaviour: "warn" downgrades errors
to styled warnings; "ignore" silences them.
sources <- list(
schema_a = list(valid = TRUE, rows = 1200L),
schema_b = list(valid = FALSE, rows = 0L),
schema_c = list(valid = TRUE, rows = 850L)
)
results <- vector("list", length(sources))
names(results) <- names(sources)
for (nm in names(sources)) {
results[[nm]] <- msg_try(
on_error = "warn",
expr = {
src <- sources[[nm]]
if (!src$valid) stop("Schema '", nm, "' failed validation")
msg_success(nm, ": ", src$rows, " rows loaded")
src$rows
}
)
}
#> v schema_a: 1200 rows loaded
#> ! Schema 'schema_b' failed validation
#> v schema_c: 850 rows loadedmsg_verbose() only emits output when
getOption("pkg.verbose") is TRUE (or the
verbose argument is set explicitly). This lets callers opt
in/out without modifying the function body.
process_file <- function(path, verbose = TRUE) {
msg_verbose("Opening: ", path, verbose = verbose)
# ... processing ...
msg_verbose("Done: ", path, verbose = verbose)
invisible(path)
}
# Verbose on (default)
process_file("data/concepts.csv")
#> i Opening: data/concepts.csv
#> i Done: data/concepts.csv
# Verbose off
process_file("data/concepts.csv", verbose = FALSE)msg_timed()msg_timed() evaluates an expression, prints a labelled
elapsed-time message, and returns the result invisibly. It is composable
— the timed block can be any R expression, including a whole
pipeline.
concept_ids <- as.list(c(201826L, 442793L, 320128L, 433736L))
processed <- msg_timed(
msg = "Total batch time",
expr = lapply(concept_ids, function(id) {
msg_info("Processing concept_id ", id)
id * 2L # stand-in for real work
})
)
#> i Processing concept_id 201826
#> i Processing concept_id 442793
#> i Processing concept_id 320128
#> i Processing concept_id 433736
#> i Total batch time: 0.00smsg_abort()msg_abort() throws a proper R error condition so it
integrates with tryCatch() and
withCallingHandlers() like any other error.
validate_schema <- function(x) {
if (!is.data.frame(x)) {
msg_abort("Expected a data.frame, got: ", class(x)[1])
}
invisible(x)
}
# Catch the error and show its message
tryCatch(
validate_schema("not a data frame"),
error = function(e) msg_danger("Caught: ", conditionMessage(e))
)
#> x Caught: x Expected a data.frame, got: charactermsg_warning()msg_warning() emits a proper R warning while also
printing a styled console message.
msg_try() on_error modes# "warn" — downgrade error to a styled warning
msg_try(stop("something went wrong"), on_error = "warn")
#> ! something went wrong
# "message" — emit as a styled danger message, no stop
msg_try(stop("non-critical failure"), on_error = "message")
#> x non-critical failure
# "ignore" — silently swallow the error
msg_try(stop("ignored error"), on_error = "ignore")
msg_info("Execution continued after all three")
#> i Execution continued after all threemsg_debug() is a no-op unless
options(pkg.debug = TRUE) is set, making it safe to leave
in production code.
# Default: pkg.debug = FALSE, so nothing is printed
msg_debug("SQL query: SELECT * FROM concept WHERE ...")
msg_info("(no debug output above — pkg.debug is FALSE)")
#> i (no debug output above — pkg.debug is FALSE)options(pkg.debug = TRUE)
msg_debug("SQL query: SELECT * FROM concept WHERE ...")
#> [DEBUG] SQL query: SELECT * FROM concept WHERE ...
options(pkg.debug = FALSE) # resetmsg_progress() is designed for interactive terminal use.
In rendered documents the \r cursor updates do not display,
so the code below is shown but not evaluated.
files <- paste0("file_", seq_len(8), ".csv")
pb <- msg_progress(length(files), prefix = "Loading")
for (f in files) {
Sys.sleep(0.1) # simulated I/O
pb$tick()
}
pb$done("All files loaded")Similarly, the animated spinner is for interactive use only.
sp <- msg_spinner("Querying vocabulary server")
for (i in seq_len(30)) {
Sys.sleep(0.05)
sp$spin()
}
sp$done("Query complete")The example below combines several handyCli helpers to
produce readable console output for a multi-step pipeline.
run_pipeline <- function(concept_sets, verbose = TRUE) {
msg_header("tidyOhdsiSolutions Pipeline")
msg_kv(list(
Steps = as.character(length(concept_sets)),
Verbose = as.character(verbose)
))
msg_blank()
results <- vector("list", length(concept_sets))
names(results) <- names(concept_sets)
for (nm in names(concept_sets)) {
msg_process("Processing: ", nm)
results[[nm]] <- msg_try(on_error = "warn", expr = {
ids <- concept_sets[[nm]]
if (length(ids) == 0L) stop("'", nm, "' has no concept IDs")
msg_verbose(" concept IDs: ", paste(ids, collapse = ", "),
verbose = verbose)
ids
})
}
msg_blank()
msg_rule()
succeeded <- sum(!vapply(results, is.null, logical(1L)))
msg_success(succeeded, " / ", length(concept_sets), " concept sets processed")
invisible(results)
}
concept_sets <- list(
diabetes = c(201826L, 442793L),
hypertension = c(320128L),
empty_set = integer(0) # will trigger a warning
)
out <- run_pipeline(concept_sets, verbose = TRUE)
#> ------------------------ tidyOhdsiSolutions Pipeline -------------------------
#> Steps 3
#> Verbose TRUE
#>
#> -> Processing: diabetes
#> i concept IDs: 201826, 442793
#> -> Processing: hypertension
#> i concept IDs: 320128
#> -> Processing: empty_set
#> ! 'empty_set' has no concept IDs
#>
#> --------------------------------------------------------------------------------
#> v 2 / 3 concept sets processedThese binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.