Line Highlighting Within Code Chunks (Knitted Notebook)

Question:
Is there a simple way of highlighting particular lines of code within a code chunk and/or code fence when knitting R Notebooks into HTML documents?

Example:
Here's an example of what I'm hoping to accomplish, wherein the goal is to highlight the second line of a three-line chunk:

highlight

Similar Functionality:
This appears to be possible using the xaringan package for slides (also by @yihui; see examples of that), but I don't seem to be able to do it when producing a regular HTML document.

Current Work-Around:
I have been able to develop a very clunky work-around for doing this:

<div id="unique_div_id">
<style>
#unique_div_id a[data-line-number="2"]{
background-color: yellow;
}
</style>

```r
df %>%
  select(var, var2) %>%
  count(var2)
\```

</div>

Please excuse the formatting quirks above, and the insertion of the forward slash to not prematurely end this code chunk in the post editor.

While this works, it means having to create a new div for every chunk; giving each div a unique ID name; and repeating the CSS for every line of code that should be highlighted (and for every code chunk).

Is there any existing functionality within knitr that can accomplish this more simply (e.g., ```r[highlight_line=c(2)] or, better yet, using operators within the code fence like xaringan does it)? Or, is this a feature request that needs to be made on GitHub? Or, is there some way that I can at least programatically anticipate the div that will be assigned to that code chunk so I can pre-fill the CSS selector?

Thanks for reading, and any assistance you might offer!

Is there any reason that the highlight needs to be in the chunk with echo=TRUE?

Thanks for the response, @technocrat.

The reason I wish to do this is because I use dplyr's piping functionality a lot in my code examples for my students. I present the code in a step-by-step fashion, and sometimes that requires editing lines that came up at different points in the command chain. The highlighting helps call attention to exactly which lines were modified within a multi-line chunk. It's a small touch but one that I think helps reduce confusion.

(It would be especially helpful if fragments of a line within a code chunk could be highlighted, to demonstrate where new arguments were introduced, but I imagine that gets more complex quite quickly.)

As an aside, I should note that while my example above included a code fence without evaluation, it also works if we do a chunk with evaluation (i.e., start with ```{r}).

Ok, got it. This is to highlight "live" code, then. I can't recall seeing it, and I only have vague ideas of how to jump through the hoops to accomplish it. Will let you know if I stumble across anything?

Sure thing. Thanks, @technocrat!

Also, perhaps a better illustration of what I hope to accomplish is this great ggplot tutorial. You'll see that, toward the middle of the page, it starts to employ subtle line highlighting within code chunks. However, it appears that this is being done within the Gatsby markdown-based site generator (which supports this functionality, as does Hugo), and not knitr (which can evaluate R code).

Yeah, I saw that. Under the hood it's all CSS and Javascript, not "live code". A screencast might be an option. I've seen online courses that show live code, with highlighting, as a speeded up video from an IDE. Of course, that's not knitr, sadly.

In Xaringan, this is done in javascript as a feature of remark.js

1 Like

Thanks for the response, @cderv. Calling an extra JavaScript library would certainly be overkill.

It strikes me that what I probably have, then, is a feature request for knitr.

There's no need to load a whole JS library, it seems. Instead, all that is needed is some new functionality to add a CSS class to the echo of the code.

For example, let's say I knit a new Notebook with the following YAML header:

title: "R Notebook"
output:
  html_document:
    theme: spacelab
    highlight: pygment

In the body of the notebook, I include just the following code chunk:

{r}
library(tidyverse)
df <- data.frame(var=character(), var2=character())
df %>%
  select(var, var2) %>%
  count(var2)

The resulting HTML file includes the following in the source for that chunk:

<pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb5-1" data-line-number="1">df &lt;-<span class="st"> </span><span class="kw">data.frame</span>(<span class="dt">var=</span><span class="kw">character</span>(), <span class="dt">var2=</span><span class="kw">character</span>())</a>
<a class="sourceLine" id="cb5-2" data-line-number="2">df <span class="op">%&gt;%</span></a>
<a class="sourceLine" id="cb5-3" data-line-number="3"><span class="st">  </span><span class="kw">select</span>(var, var2) <span class="op">%&gt;%</span></a>
<a class="sourceLine" id="cb5-4" data-line-number="4"><span class="st">  </span><span class="kw">count</span>(var2)</a></code></pre>

What's missing is the ability to add an additional CSS class to each line based on the data-line-number attribute of the a elements within the code tag.

Then, a simple custom CSS file (which we can already include in the YAML header) could be used to style that class to set things like the background color of that line, or the text of the color for that line, and so on.

So, the new feature would be to add a new chunk option called something like stylinelines, in which a vector of lines could be specified along with the additional style that would be set. Here's an illustration of what that would look like:

{r stylelines=list(c(3), "highlight")}
df <- data.frame(var=character(), var2=character())
df %>%
  select(var, var2) %>%
  count(var2)

Which, in turn, should be able to produce the following HTML:

<pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb5-1" data-line-number="1">df &lt;-<span class="st"> </span><span class="kw">data.frame</span>(<span class="dt">var=</span><span class="kw">character</span>(), <span class="dt">var2=</span><span class="kw">character</span>())</a>
<a class="sourceLine" id="cb5-2" data-line-number="2">df <span class="op">%&gt;%</span></a>
<a class="sourceLine highlight" id="cb5-3" data-line-number="3"><span class="st">  </span><span class="kw">select</span>(var, var2) <span class="op">%&gt;%</span></a>
<a class="sourceLine" id="cb5-4" data-line-number="4"><span class="st">  </span><span class="kw">count</span>(var2)</a></code></pre>

And, within a CSS file, one would just add the following:

.highlight {
  background-color: yellow;
}

Based on my quick testing (by manually editing the class for that one line in Firefox's Inspector), that is able to demonstrate the result shown in the opening post.

I'm sure implementing what seems like a simple feature would actually be pretty complicated, and the package maintainers may not find it worth the effort. However, if I were to make such a request, what would be the best way to direct it? The Issues page on knitr's GitHub page?

1 Like

An issue captioned "feature request" is the way that I'd go. Might also float it in pander

Maybe this new package can help here

1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.