Skip to contents

An alternative to match.arg() with improved error messages via cli. Returns the first choice if x is NULL, and supports partial matching.

Usage

match_arg(
  x,
  choices,
  several.ok = FALSE,
  ignore.case = TRUE,
  .context = NULL,
  .arg = rlang::caller_arg(x),
  .call
)

Arguments

x

a string (or character vector if several.ok = TRUE) to match against choices. If NULL, the first element of choices is returned.

choices

a character vector of valid values.

several.ok

logical; if TRUE, x may contain more than one element. Defaults to FALSE.

ignore.case

logical; if FALSE, the matching is case sensitive, and if TRUE (the default), case is ignored.

.context

an optional character string providing context for error messages (e.g., a function or object name). Prepended to the error message when supplied before being evaluated by cli.

.arg

the name of the argument supplied to x to appear in error messages. The default is to extract the argument's name using rlang::caller_arg(). Ignored if .msg is supplied.

.call

the execution environment of a currently running function, e.g. .call = rlang::current_env(). The corresponding function call is retrieved and mentioned in error messages as the source of the error. Passed to err(). Set to NULL to omit call information. The default is to search along the call stack for the first user-facing function in another package, if any.

Value

A character string (or vector, if several.ok = TRUE) of the matched element(s) from choices. If there is no match, an error is thrown. When several.ok = TRUE, no error is thrown if there is at least one match.

Details

Partial matching is supported via pmatch(). If no match is found, an error is thrown listing the valid choices.

Checks are run on x prior to matching: first, arg_supplied() is used to check whether x was supplied; then arg_string() (if several.ok = TRUE) or arg_character() (if several.ok = FALSE) is used to check whether x is a valid string or character vector, respectively.

When ignore.case = TRUE (the default), an initial case-sensitive match is run, and if any values in x are unmatched, a second, case-insensitive match is run. When ignore.case = FALSE, only the first match is run. This ensures that exact matches (on both content and case) are prioritized before case-insensitive matches.

See also

  • match.arg() for the base R version

  • pmatch() for the function implementing partial string matching

  • arg_element() for a version without type checking and that doesn't support partial matching

  • rlang::arg_match() for a similar rlang function that doesn't support partial matching.

Examples

f <- function(z = NULL) {
  match_arg(z, c("None", "Exact", "Partial"),
            ignore.case = TRUE)
}

try(f())            # "None" (first choice returned)
#> [1] "None"
try(f("partial"))   # "Partial"
#> [1] "Partial"
try(f("p"))         # "Partial" (partial match)
#> [1] "Partial"
try(f(c("e", "p"))) # Error: several.ok = FALSE
#> Error : `z` must be a string.

# several.ok = TRUE
g <- function(z = NULL) {
  match_arg(z, c("None", "Exact", "Partial"),
            several.ok = TRUE)
}

try(g("exact"))               # Error: case not ignored
#> [1] "Exact"
try(g("Exact"))               # "Exact"
#> [1] "Exact"
try(g(c("Exact", "Partial"))) # "Exact", "Partial"
#> [1] "Exact"   "Partial"
try(g(c("Exact", "Wrong")))   # "Exact"
#> [1] "Exact"
try(g(c("Wrong1", "Wrong2"))) # Error: no match
#> Error : `z` should be at least one of "None", "Exact", or "Partial".

h <- function(z = NULL) {
  match_arg(z, c("None", "Exact", "Partial"),
            .context = "in {.fun h},")
}

try(h("Wrong")) # Error with context
#> Error : In `h()`, `z` should be one of "None", "Exact", or "Partial".