3

I am using cli::cli_abort to handle errors.

As context for an error message, I am trying to print the contents of a matrix. I can achieve this via capture.output, though when the message is processed by cli::cli_abort the whitespace gets collapsed and you can no longer see the matrix columns easily.

The following reproducible example (hopefully!) illustrates:

do_something_with_matrix <- function(x) {

  # provide a way to format the matrix as a string vector
  format_mtx <- function(x, method = c("collapse", "preserve")) {
    method <- match.arg(method)
    mtx_lines <- if (method == "collapse") {
      c("Matrix values [Note: spaces get collapsed, hard-to-read columns]:",
        capture.output(x))
    } else {
      out_txt <- gsub(" ", "_", capture.output(x))
      c("Matrix values [Note: spaces replaced with '_' to prevent collapsing]:",
        out_txt)
    }
    names(mtx_lines) <- rep("i", length(mtx_lines))
    mtx_lines
  }

  # check the input
  if (isTRUE(any(x < 0))) {

    # display the matrix, replacing spaces with '_' to stop them collapsing
    cli::cli_inform(c(
      format_mtx(x, "preserve")
    ))

    # abort since input is invalid
    cli::cli_abort(c(
      "{.var x} must contain only positive values",
      "x" = "You've supplied a matrix with one or more negative values.",
      # display the matrix with spaces as-is (they will be collapsed)
      format_mtx(x)
    ))
  }

  # do <whatever> with x [...]
}

# --- --- ---
# Example usage

# create a matrix
mtx_data <- matrix(c( 6.62, 3.33, 1.94,
                      -4.1, 3.52,  0.5,
                      1.94,  0.5, 1.95),
                   3, 3)

do_something_with_matrix(mtx_data)
# ℹ Matrix values [Note: spaces replaced with '_' to prevent collapsing]:
# ℹ _____[,1]__[,2]_[,3]
# ℹ [1,]_6.62_-4.10_1.94
# ℹ [2,]_3.33__3.52_0.50
# ℹ [3,]_1.94__0.50_1.95
# Error in `do_something_with_matrix()`:
# ! `x` must contain only positive values
# ✖ You've supplied a matrix with one or more negative values.
# ℹ Matrix values [Note: spaces get collapsed, hard-to-read columns]:
# ℹ [,1] [,2] [,3]
# ℹ [1,] 6.62 -4.10 1.94
# ℹ [2,] 3.33 3.52 0.50
# ℹ [3,] 1.94 0.50 1.95
# Run `rlang::last_error()` to see where the error occurred.

I have searched for a way to do this but not yet managed to come up with anything. I wondered if the use_cli_format argument to rlang::abort might help, but looking at the code for cli::cli_abort shows that this arg is set to TRUE so I can't change it (anyway I'm not sure if that could help):

> cli::cli_abort
# function (message, ..., .envir = parent.frame(), call = .envir) 
# {
#   message[] <- vcapply(message, format_inline, .envir = .envir)
#   rlang::abort(message, ..., call = call, use_cli_format = TRUE)
# }
# <bytecode: 0x5562464367c8>
# <environment: namespace:cli>

Is there a way to preserve the spaces/columns in the printed matrix values? Or would there be an altogether better way to display the user-supplied matrix in the event of an error?

toni
  • 31
  • 3

0 Answers0