yihui / knitr

A general-purpose tool for dynamic report generation in R
https://yihui.org/knitr/
2.36k stars 873 forks source link

WISH: Make it possible to call globalCallingHandlers() in a chunk #2324

Open HenrikBengtsson opened 5 months ago

HenrikBengtsson commented 5 months ago

(I'm not sure if this one is for the evaluate or the knitr package, but I start here)

Background

In R (>= 4.0.0), we have globalCallingHandlers() for registering global calling handlers, which are functions that handle conditions that haven't been handled previously by local calling handlers, e.g. withCallingHandlers(), tryCatch(), suppressWarnings(), etc. For example,

> globalCallingHandlers(foo = function(c) message("Woo hoo"))

will generate a message if a condition of class foo "bubbles" all the way to the global handlers.

R does not allow you to register global calling handlers in a context with active, local handlers. For instance, if we would try:

tryCatch({
  globalCallingHandlers(foo = function(c) message("Woo hoo"))
}, error = function(e) NULL)         

we get an error (that cannot be caught/handled):

Error in globalCallingHandlers(foo = function(c) message("Woo hoo")):
should not be called with handlers on the stack

Issue

Because of the above, and how code chunks are wrapped in condition handlers when evaluated, if we add a code chunk:

```{r}
globalCallingHandlers(foo = function(c) message("Woo hoo"))
```

we get:

```r
globalCallingHandlers(foo = function(c) message("Woo hoo"))
```

```
## Error in globalCallingHandlers(foo = function(c) message("Woo hoo")): should not be called with handlers on the stack
```

Wish

Make it possible to configure a code chunk such that it is evaluated without calling handlers. I understand that this limits what can be relayed, e.g. message and warning conditions. It also prevents handling of errors, unless something can be hacked around options(error = function(...) ...).

See also

This is related to feature requests for being able to register a global calling handler for progress updates by the progressr package, e.g. https://github.com/HenrikBengtsson/progressr/issues/166

yihui commented 2 weeks ago

Just for the record, I looked into this issue in February and found it was not straightforward to solve in knitr, but I had this issue in mind when designing litedown. With litedown, when you have chunk options message=NA and warning=NA, the code chunk won't be evaluated inside withCallingHandlers(), so globalCallingHandlers() will work, e.g.,

---
title: "Test globalCallingHandlers()"
knit: litedown:::knit
---

```{r, message=NA, warning=NA}
globalCallingHandlers(foo = function(c) message("Woo hoo"))