From 10c00ff606b5370845c6750934829b27cd34ebce Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 18 Mar 2026 22:23:39 +0000 Subject: [PATCH] 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 --- R/aa_helper_functions.R | 10 +++++++++- R/ab.R | 2 +- R/ab_from_text.R | 2 +- R/amr_selectors.R | 4 ++-- R/av_from_text.R | 2 +- R/count.R | 4 ++-- R/custom_antimicrobials.R | 2 +- R/custom_microorganisms.R | 6 +++--- R/interpretive_rules.R | 12 ++++++------ R/mo.R | 6 +++--- R/mo_property.R | 4 ++-- R/sir.R | 4 ++-- R/sir_calc.R | 2 +- 13 files changed, 34 insertions(+), 26 deletions(-) diff --git a/R/aa_helper_functions.R b/R/aa_helper_functions.R index f3339ad30..c3fdf4178 100644 --- a/R/aa_helper_functions.R +++ b/R/aa_helper_functions.R @@ -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 ) diff --git a/R/ab.R b/R/ab.R index cd8a2d43b..03392112e 100755 --- a/R/ab.R +++ b/R/ab.R @@ -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}().") } } diff --git a/R/ab_from_text.R b/R/ab_from_text.R index 1b0e77efa..2d6087fd8 100755 --- a/R/ab_from_text.R +++ b/R/ab_from_text.R @@ -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 diff --git a/R/amr_selectors.R b/R/amr_selectors.R index 1d3d99b99..dd4387405 100755 --- a/R/amr_selectors.R +++ b/R/amr_selectors.R @@ -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") { diff --git a/R/av_from_text.R b/R/av_from_text.R index 3d9da809f..e1ca7592d 100755 --- a/R/av_from_text.R +++ b/R/av_from_text.R @@ -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 diff --git a/R/count.R b/R/count.R index 1c17d3806..ad804ea5e 100755 --- a/R/count.R +++ b/R/count.R @@ -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( diff --git a/R/custom_antimicrobials.R b/R/custom_antimicrobials.R index 48714d420..e00bca55c 100755 --- a/R/custom_antimicrobials.R +++ b/R/custom_antimicrobials.R @@ -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 diff --git a/R/custom_microorganisms.R b/R/custom_microorganisms.R index be37a348b..5535de31f 100755 --- a/R/custom_microorganisms.R +++ b/R/custom_microorganisms.R @@ -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, ...) { diff --git a/R/interpretive_rules.R b/R/interpretive_rules.R index d796cce8e..e23158aab 100755 --- a/R/interpretive_rules.R +++ b/R/interpretive_rules.R @@ -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))")) ) } diff --git a/R/mo.R b/R/mo.R index baac5213e..793018982 100755 --- a/R/mo.R +++ b/R/mo.R @@ -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)) } diff --git a/R/mo_property.R b/R/mo_property.R index 0e6fb2b3c..552200f49 100755 --- a/R/mo_property.R +++ b/R/mo_property.R @@ -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) } } diff --git a/R/sir.R b/R/sir.R index 3e864f7fb..e12470ffc 100755 --- a/R/sir.R +++ b/R/sir.R @@ -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 ) } diff --git a/R/sir_calc.R b/R/sir_calc.R index b7a338001..5fcb8ba51 100755 --- a/R/sir_calc.R +++ b/R/sir_calc.R @@ -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 ) }