1
0
mirror of https://github.com/msberends/AMR.git synced 2026-03-19 07:42:25 +01:00

Implement cli::code_highlight() for R code examples in messages (issue #191)

Add highlight_code() helper that wraps cli::code_highlight() when cli >= 3.0.0
is available, falling back to plain code otherwise. Apply it to all inline
R code examples embedded in message/warning/stop strings across the package.

Also convert remaining backtick-quoted function and argument references in
messaging calls to proper cli markup: {.help AMR::fn}(), {.arg arg},
{.code expr}, and {.pkg pkg} throughout ab.R, ab_from_text.R, av_from_text.R,
amr_selectors.R, count.R, custom_antimicrobials.R, custom_microorganisms.R,
interpretive_rules.R, mo.R, mo_property.R, sir.R, sir_calc.R.

Fixes #191

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
This commit is contained in:
Claude
2026-03-18 22:23:39 +00:00
parent b7edf3e548
commit 10c00ff606
13 changed files with 34 additions and 26 deletions

View File

@@ -382,6 +382,14 @@ pkg_is_available <- function(pkg, also_load = FALSE, min_version = NULL) {
isTRUE(out)
}
highlight_code <- function(code) {
if (pkg_is_available("cli", min_version = "3.0.0")) {
cli::code_highlight(code)
} else {
code
}
}
import_fn <- function(name, pkg, error_on_fail = TRUE) {
if (isTRUE(error_on_fail)) {
stop_ifnot_installed(pkg)
@@ -396,7 +404,7 @@ import_fn <- function(name, pkg, error_on_fail = TRUE) {
getExportedValue(name = name, ns = asNamespace(pkg)),
error = function(e) {
if (isTRUE(error_on_fail)) {
stop_("function `", name, "()` is not an exported object from package '", pkg,
stop_("function {.code ", name, "()} is not an exported object from package '", pkg,
"'. Please create an issue at https://github.com/msberends/AMR/issues. Many thanks!",
call = FALSE
)

2
R/ab.R
View File

@@ -210,7 +210,7 @@ as.ab <- function(x, flag_multiple_results = TRUE, language = get_AMR_locale(),
progress <- progress_ticker(n = sum(!already_known), n_min = 25, print = info) # start if n >= 25
on.exit(close(progress))
if (any(x_new[!already_known & !is.na(x_new)] %in% unlist(AMR_env$AV_lookup$generalised_all, use.names = FALSE), na.rm = TRUE)) {
warning_("in `as.ab()`: some input seems to resemble antiviral drugs - use `as.av()` or e.g. `av_name()` for these, not `as.ab()` or e.g. `ab_name()`.")
warning_("in {.help AMR::as.ab}(): some input seems to resemble antiviral drugs - use {.help AMR::as.av}() or e.g. {.help AMR::av_name}() for these, not {.help AMR::as.ab}() or e.g. {.help AMR::ab_name}().")
}
}

View File

@@ -212,7 +212,7 @@ ab_from_text <- function(text,
}
})
} else {
stop_("`type` must be either 'drug', 'dose' or 'administration'")
stop_("{.arg type} must be either 'drug', 'dose' or 'administration'")
}
# collapse text if needed

View File

@@ -837,7 +837,7 @@ amr_select_exec <- function(function_name,
#' @export
#' @noRd
print.amr_selector <- function(x, ...) {
warning_("It should never be needed to print an antimicrobial selector class. Are you using data.table? Then add the argument `with = FALSE`, see our examples at `?amr_selector`.",
warning_("It should never be needed to print an antimicrobial selector class. Are you using {.pkg data.table}? Then add the argument {.code with = FALSE}, see our examples at {.help AMR::amr_selector}().",
immediate = TRUE
)
cat("Class 'amr_selector'\n")
@@ -1062,7 +1062,7 @@ message_agent_names <- function(function_name, agents, ab_group = NULL, examples
if (message_not_thrown_before(function_name, sort(agents))) {
if (length(agents) == 0) {
if (is.null(ab_group)) {
message_("For `", function_name, "()` no antimicrobial drugs found", examples, ".")
message_("For {.help AMR::", function_name, "}() no antimicrobial drugs found", examples, ".")
} else if (ab_group == "administrable_per_os") {
message_("No orally administrable drugs found", examples, ".")
} else if (ab_group == "administrable_iv") {

View File

@@ -168,7 +168,7 @@ av_from_text <- function(text,
}
})
} else {
stop_("`type` must be either 'drug', 'dose' or 'administration'")
stop_("{.arg type} must be either 'drug', 'dose' or 'administration'")
}
# collapse text if needed

View File

@@ -128,7 +128,7 @@ count_resistant <- function(...,
# other arguments for meet_criteria are handled by sir_calc()
meet_criteria(guideline, allow_class = "character", is_in = c("EUCAST", "CLSI"), has_length = 1)
if (is.null(getOption("AMR_guideline")) && missing(guideline) && message_not_thrown_before("count_resistant", "eucast_default", entire_session = TRUE)) {
message_("`count_resistant()` assumes the EUCAST guideline and thus considers the 'I' category susceptible. Set the `guideline` argument or the `AMR_guideline` option to either \"CLSI\" or \"EUCAST\", see `?AMR-options`.")
message_("{.help AMR::count_resistant}() assumes the EUCAST guideline and thus considers the 'I' category susceptible. Set the {.arg guideline} argument or the {.code AMR_guideline} option to either \"CLSI\" or \"EUCAST\", see {.code ?AMR-options}.")
message_("This message will be shown once per session.")
}
tryCatch(
@@ -152,7 +152,7 @@ count_susceptible <- function(...,
# other arguments for meet_criteria are handled by sir_calc()
meet_criteria(guideline, allow_class = "character", is_in = c("EUCAST", "CLSI"), has_length = 1)
if (is.null(getOption("AMR_guideline")) && missing(guideline) && message_not_thrown_before("count_susceptible", "eucast_default", entire_session = TRUE)) {
message_("`count_susceptible()` assumes the EUCAST guideline and thus considers the 'I' category susceptible. Set the `guideline` argument or the `AMR_guideline` option to either \"CLSI\" or \"EUCAST\", see `?AMR-options`.")
message_("{.help AMR::count_susceptible}() assumes the EUCAST guideline and thus considers the 'I' category susceptible. Set the {.arg guideline} argument or the {.code AMR_guideline} option to either \"CLSI\" or \"EUCAST\", see {.code ?AMR-options}.")
message_("This message will be shown once per session.")
}
tryCatch(

View File

@@ -155,7 +155,7 @@ add_custom_antimicrobials <- function(x) {
AMR_env$ab_previously_coerced <- AMR_env$ab_previously_coerced[which(!AMR_env$ab_previously_coerced$ab %in% c(x$ab, x$generalised_name) & !AMR_env$ab_previously_coerced$x %in% c(x$ab, x$generalised_name)), , drop = FALSE]
class(AMR_env$AB_lookup$ab) <- c("ab", "character")
message_("Added ", nr2char(nrow(x)), " record", ifelse(nrow(x) > 1, "s", ""), " to the internal `antimicrobials` data set.")
message_("Added ", nr2char(nrow(x)), " record", ifelse(nrow(x) > 1, "s", ""), " to the internal {.code antimicrobials} data set.")
}
#' @rdname add_custom_antimicrobials

View File

@@ -281,9 +281,9 @@ add_custom_microorganisms <- function(x) {
AMR_env$MO_lookup <- unique(rbind_AMR(AMR_env$MO_lookup, new_df))
class(AMR_env$MO_lookup$mo) <- c("mo", "character")
if (nrow(x) <= 3) {
message_("Added ", vector_and(italicise(x$fullname), quotes = FALSE), " to the internal `microorganisms` data set.")
message_("Added ", vector_and(italicise(x$fullname), quotes = FALSE), " to the internal {.code microorganisms} data set.")
} else {
message_("Added ", nr2char(nrow(x)), " records to the internal `microorganisms` data set.")
message_("Added ", nr2char(nrow(x)), " records to the internal {.code microorganisms} data set.")
}
}
@@ -303,7 +303,7 @@ clear_custom_microorganisms <- function() {
AMR_env$custom_mo_codes <- character(0)
AMR_env$mo_previously_coerced <- AMR_env$mo_previously_coerced[which(AMR_env$mo_previously_coerced$mo %in% AMR_env$MO_lookup$mo), , drop = FALSE]
AMR_env$mo_uncertainties <- AMR_env$mo_uncertainties[0, , drop = FALSE]
message_("Cleared ", nr2char(n - n2), " custom record", ifelse(n - n2 > 1, "s", ""), " from the internal `microorganisms` data set.")
message_("Cleared ", nr2char(n - n2), " custom record", ifelse(n - n2 > 1, "s", ""), " from the internal {.code microorganisms} data set.")
}
abbreviate_mo <- function(x, minlength = 5, prefix = "", hyphen_as_space = FALSE, ...) {

View File

@@ -1050,9 +1050,9 @@ interpretive_rules <- function(x,
cat(paste0(font_grey(strrep("-", 0.95 * getOption("width", 100))), "\n"))
if (isFALSE(verbose) && total_n_added + total_n_changed > 0) {
cat("\n", word_wrap("Use `eucast_rules(..., verbose = TRUE)` (on your original data) to get a data.frame with all specified edits instead."), "\n\n", sep = "")
cat("\n", word_wrap("Use ", highlight_code("eucast_rules(..., verbose = TRUE)"), " (on your original data) to get a data.frame with all specified edits instead."), "\n\n", sep = "")
} else if (isTRUE(verbose)) {
cat("\n", word_wrap("Used 'Verbose mode' (`verbose = TRUE`), which returns a data.frame with all specified edits.\nUse `verbose = FALSE` to apply the rules on your data."), "\n\n", sep = "")
cat("\n", word_wrap("Used 'Verbose mode' ({.code verbose = TRUE}), which returns a data.frame with all specified edits.\nUse {.code verbose = FALSE} to apply the rules on your data."), "\n\n", sep = "")
}
}
@@ -1063,12 +1063,12 @@ interpretive_rules <- function(x,
warn_lacking_sir_class <- warn_lacking_sir_class[!is.na(warn_lacking_sir_class)]
warning_(
"in {.help AMR::eucast_rules}(): not all columns with antimicrobial results are of class 'sir'. Transform them on beforehand, with e.g.:\n",
" - ", x_deparsed, " %>% as.sir(", ifelse(length(warn_lacking_sir_class) == 1,
" - ", highlight_code(paste0(x_deparsed, " %>% as.sir(", ifelse(length(warn_lacking_sir_class) == 1,
warn_lacking_sir_class,
paste0(warn_lacking_sir_class[1], ":", warn_lacking_sir_class[length(warn_lacking_sir_class)])
), ")\n",
" - ", x_deparsed, " %>% mutate_if(is_sir_eligible, as.sir)\n",
" - ", x_deparsed, " %>% mutate(across(where(is_sir_eligible), as.sir))"
), ")")), "\n",
" - ", highlight_code(paste0(x_deparsed, " %>% mutate_if(is_sir_eligible, as.sir)")), "\n",
" - ", highlight_code(paste0(x_deparsed, " %>% mutate(across(where(is_sir_eligible), as.sir))"))
)
}

6
R/mo.R
View File

@@ -483,7 +483,7 @@ as.mo <- function(x,
}
} else if (is.null(getOption("AMR_keep_synonyms")) && length(AMR_env$mo_renamed$old) > 0 && message_not_thrown_before("as.mo", "keep_synonyms_warning", entire_session = TRUE)) {
# keep synonyms is TRUE, so check if any do have synonyms
warning_("Function `as.mo()` returned ", nr2char(length(unique(AMR_env$mo_renamed$old))), " outdated taxonomic name", ifelse(length(unique(AMR_env$mo_renamed$old)) > 1, "s", ""), ". Use `as.mo(..., keep_synonyms = FALSE)` to clean the input to currently accepted taxonomic names, or set the R option `AMR_keep_synonyms` to `FALSE`. This warning will be shown once per session.", call = FALSE)
warning_("{.help AMR::as.mo}() returned ", nr2char(length(unique(AMR_env$mo_renamed$old))), " outdated taxonomic name", ifelse(length(unique(AMR_env$mo_renamed$old)) > 1, "s", ""), ". Use ", highlight_code("as.mo(..., keep_synonyms = FALSE)"), " to clean the input to currently accepted taxonomic names, or set the R option {.code AMR_keep_synonyms} to {.code FALSE}. This warning will be shown once per session.", call = FALSE)
}
# Apply Becker ----
@@ -907,7 +907,7 @@ rep.mo <- function(x, ...) {
print.mo_uncertainties <- function(x, n = 10, ...) {
more_than_50 <- FALSE
if (NROW(x) == 0) {
cat(font_blue(word_wrap("No uncertainties to show. Only uncertainties of the last call to `as.mo()` or any `mo_*()` function are stored.\n\n")))
cat(font_blue(word_wrap("No uncertainties to show. Only uncertainties of the last call to {.help AMR::as.mo}() or any mo_*() function are stored.\n\n")))
return(invisible(NULL))
} else if (NROW(x) > 50) {
more_than_50 <- TRUE
@@ -1032,7 +1032,7 @@ print.mo_uncertainties <- function(x, n = 10, ...) {
#' @noRd
print.mo_renamed <- function(x, extra_txt = "", n = 25, ...) {
if (NROW(x) == 0) {
cat(font_blue(word_wrap("No renamed taxonomy to show. Only renamed taxonomy of the last call of `as.mo()` or any `mo_*()` function are stored.\n")))
cat(font_blue(word_wrap("No renamed taxonomy to show. Only renamed taxonomy of the last call of {.help AMR::as.mo}() or any mo_*() function are stored.\n")))
return(invisible(NULL))
}

View File

@@ -1043,10 +1043,10 @@ find_mo_col <- function(fn) {
)
if (!is.null(df) && !is.null(mo) && is.data.frame(df)) {
if (message_not_thrown_before(fn = fn)) {
message_("Using column '", font_bold(mo), "' as input for `", fn, "()`")
message_("Using column '", font_bold(mo), "' as input for {.help AMR::", fn, "}()")
}
return(df[, mo, drop = TRUE])
} else {
stop_("argument `x` is missing and no column with info about microorganisms could be found.", call = -2)
stop_("argument {.arg x} is missing and no column with info about microorganisms could be found.", call = -2)
}
}

View File

@@ -1277,8 +1277,8 @@ as_sir_method <- function(method_short,
}
if (is.null(mo)) {
stop_("No information was supplied about the microorganisms (missing argument {.arg mo} and no column of class 'mo' found). See {.help AMR::as.sir}().\n\n",
"To transform certain columns with e.g. mutate(), use `data %>% mutate(across(..., as.sir, mo = x))`, where x is your column with microorganisms.\n",
"To transform all ", method_long, " in a data set, use `data %>% as.sir()` or `data %>% mutate_if(is.", method_short, ", as.sir)`.",
"To transform certain columns with e.g. mutate(), use ", highlight_code("data %>% mutate(across(..., as.sir, mo = x))"), ", where x is your column with microorganisms.\n",
"To transform all ", method_long, " in a data set, use ", highlight_code("data %>% as.sir()"), " or ", highlight_code(paste0("data %>% mutate_if(is.", method_short, ", as.sir)")), ".",
call = FALSE
)
}

View File

@@ -173,7 +173,7 @@ sir_calc <- function(...,
if (print_warning == TRUE) {
if (message_not_thrown_before("sir_calc")) {
warning_("Increase speed by transforming to class 'sir' on beforehand:\n",
" your_data %>% mutate_if(is_sir_eligible, as.sir)",
highlight_code(" your_data %>% mutate_if(is_sir_eligible, as.sir)"),
call = FALSE
)
}