cli icon indicating copy to clipboard operation
cli copied to clipboard

Passing multiline strings (e.g., `waldo::compare()` outputs) to `cli_abort`

Open mjkanji opened this issue 3 years ago • 3 comments

Hi! Is there any way to pass a multi-line string to cli_abort? Specificially, I'm trying to use the output of waldo::compare() to generate more informative error messages, but cli_abort removes all the newline characters from the output, making it very difficult to read.

I tried circumventing the issue by passing compare_obj to rlang::abort via ... but this unfortunately also doesn't work and cli_abort still removes the newline characters, while using rlang::abort directly doesn't result in this behaviour.

df1 <- tibble::tibble(x = 1:3, y = 4:6)
df2 <- tibble::tibble(x = 1:3, y = c(4.0, 5.0, 7.0))
compare_obj <- waldo::compare(df1, df2)

if (length(compare_obj) != 0) {
  cli::cli_abort(c("The data frames don't match", compare_obj))
}
#> Error:
#> ! The data frames don't match
#> old vs new y old[1, ] 4 old[2, ] 5 - old[3, ] 6 + new[3, ] 7
#> `old$y` is an integer vector (4, 5, 6) `new$y` is a double vector (4, 5, 7)

if(length(compare_obj) != 0) {
  cli::cli_abort(c("The data frames don't match"), body = compare_obj)
}
#> Error:
#> ! The data frames don't match
#> old vs new y old[1, ] 4 old[2, ] 5 - old[3, ] 6 + new[3, ] 7
#> `old$y` is an integer vector (4, 5, 6) `new$y` is a double vector (4, 5, 7)

if(length(compare_obj) != 0) {
  rlang::abort(c("The data frames don't match"), body = compare_obj)
}
#> Error:
#> ! The data frames don't match
#> old vs new
#>            y
#>   old[1, ] 4
#>   old[2, ] 5
#> - old[3, ] 6
#> + new[3, ] 7
#> `old$y` is an integer vector (4, 5, 6)
#> `new$y` is a double vector (4, 5, 7)
Session Info
sessionInfo()
#> R version 4.1.2 (2021-11-01)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 22000)
#> 
#> Matrix products: default
#> 
#> locale:
#> [1] LC_COLLATE=English_United States.1252 
#> [2] LC_CTYPE=English_United States.1252   
#> [3] LC_MONETARY=English_United States.1252
#> [4] LC_NUMERIC=C                          
#> [5] LC_TIME=English_United States.1252    
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] rstudioapi_0.13   knitr_1.37        magrittr_2.0.1    R.cache_0.15.0   
#>  [5] rlang_1.0.1       fastmap_1.1.0     fansi_0.5.0       stringr_1.4.0    
#>  [9] styler_1.6.2      highr_0.9         tools_4.1.2       xfun_0.29        
#> [13] R.oo_1.24.0       utf8_1.2.2        cli_3.2.0         withr_2.4.3      
#> [17] htmltools_0.5.2   ellipsis_0.3.2    yaml_2.2.1        digest_0.6.29    
#> [21] tibble_3.1.6      lifecycle_1.0.1   crayon_1.4.2      purrr_0.3.4      
#> [25] R.utils_2.11.0    vctrs_0.3.8       fs_1.5.2          glue_1.6.1       
#> [29] evaluate_0.14     rmarkdown_2.11    reprex_2.0.1      stringi_1.7.6    
#> [33] compiler_4.1.2    pillar_1.6.4      R.methodsS3_1.8.1 backports_1.4.1  
#> [37] pkgconfig_2.0.3

mjkanji avatar Feb 23 '22 06:02 mjkanji

There is no way currently. Ideally \f should work, but it errors:

❯ cli::cli_text("first line\fsecond line")
first line
second line

❯ cli::cli_abort("first line\fsecond line")
Error in vapply(X, FUN, FUN.VALUE = character(1), ..., USE.NAMES = USE.NAMES) :
  values must be length 1,
 but FUN(X[[1]]) result is length 2

gaborcsardi avatar Feb 23 '22 08:02 gaborcsardi

Thank you for the explanation! It would definitely be great to add that as a feature in the future.

Though, what about the fact that passing body = compare_obj to rlang::abort via ... also seems to process the text, instead of just passing the argument to rlang::abort without any modifications (since it works when using rlang::abort directly, I'm assuming the issue is on the cli side). Is this expected behaviour?

mjkanji avatar Feb 23 '22 08:02 mjkanji

Yes, cli re-wraps text to the screen width.

If you are not happy about that, and as a current workaround, you can still use rlang::abort() directly, there is nothing wrong with that.

We are planning to have API for more advanced formatting within cli_abort() at some point.

gaborcsardi avatar Feb 23 '22 08:02 gaborcsardi

This will be fixed in #460

gaborcsardi avatar Aug 23 '22 11:08 gaborcsardi