Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collapse error message into a single block when the error message is modified to print in red

How can I get a printed error message in RMarkdown to collapse into a single block when the error message itself was modified to print in red?

In this example collapse = T works as expected.

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, collapse = TRUE)
```

```{r error=T}
x <- c(1,2,3,4,5)
x * 10
X * 10
```

In this example, I modified the error message to be formatted in red (based on this answer). But then it doesn't collapse with the rest:

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, collapse = TRUE)
knitr::knit_hooks$set(error = function(x, options) {
  paste0("<pre style=\"color: red;\"><code>", x, "</code></pre>")
})
```

```{r error=T}
x <- c(1,2,3,4,5)
x * 10
X * 10
```  

I tried to specify collapse = T again in the specific code chunk but this won't work either:

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, collapse = TRUE)
knitr::knit_hooks$set(error = function(x, options) {
  paste0("<pre style=\"color: red;\"><code>", x, "</code></pre>")
})
```

```{r error=T, collapse = T}
x <- c(1,2,3,4,5)
x * 10
X * 10
```   
like image 742
Stefan Avatar asked Mar 04 '19 04:03

Stefan


2 Answers

With the current development version of knitr (remotes::install_github('yihui/knitr')), you can specify the CSS class for error messages. Here is an example:

```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE)
```

```{css, echo=FALSE}
.red { 
  color: red;
  padding-top: 0;
  margin-top: -15px;
  border-top-color: #f5f5f5;
}
```


```{r error=T, class.error='red'}
x <- c(1,2,3,4,5)
x * 10
X * 10
```

Output:

Custom class for errors in knitr

like image 141
Yihui Xie Avatar answered Nov 15 '22 11:11

Yihui Xie


When knitting to HTML, the highlighting is done in the last step, when the site is generated. The collapsing of chunks is done prior to that.

What complicates this is the fact that errors are highlighted just like strings and cannot be distinguished from actual string output.

Adding classes by altering a hook (like ```{.myClass} ...source code... ```) does not help us, since this will break the chunk collapsing mechanism and even if I fix this (can be done by simply changing the underlying regex inside the chunk hook) the class is not present anymore when the site has rendered.

So in the end I only came up with the following.

---
title: "test"
output: html_document
---

<script>
$(document).ready(function() {
  window.setTimeout(function() {
    $(".hljs-comment:contains('####')").css("color", "red");
    var tmp = $(".hljs-comment:contains('####')").text();
    $(".hljs-comment:contains('####')").text(tmp.replace("####", "##"));
  }, 15);
});
</script>



# Header 1

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, collapse = T)

default_hook <- knitr::knit_hooks$get("error")
knitr::knit_hooks$set(error = function(x, options) {
  x <- paste0("##", x)
  default_hook(x, options)
})
```

```{r error=T}
x <- c(1,2,3,4,5)
x * 10
X * 10
```  

Here we change the error hook in that sense that two additional hashes are prepended to the output. In the Javascript snippet we then look for these lines, change the font color to red and delete the hashes again. This is done with a delay of 15ms. Why? If we execute the code immediately, the elements carrying the classes generated by highligh.js are not yet present. So we have to be a little slower.

enter image description here

like image 36
Martin Schmelzer Avatar answered Nov 15 '22 09:11

Martin Schmelzer