12.2 Add line numbers to source code

In this section, we show an example of defining a source hook to add line numbers as comments to the source code. For example, for this code chunk:

```{r}
if (TRUE) {
  x <- 1:10
  x + 1
}
```

We want the output to be:

if (TRUE) {    # 1
  x <- 1:10    # 2
  x + 1        # 3
}              # 4

The full example is below:

---
title: Add line numbers to source code
---

We set up a `source` hook to add line numbers to the source
code. The numbers appear in comments at the end of each line.

```{r, include=FALSE}
local({
  hook_source <- knitr::knit_hooks$get('source')
  knitr::knit_hooks$set(source = function(x, options) {
    x <- xfun::split_lines(x)
    n <- nchar(x, 'width')
    i <- seq_along(x)  # line numbers
    n <- n + nchar(i)
    s <- knitr:::v_spaces(max(n) - n)
    x <- paste(x, s, '  # ', i, sep = '', collapse = '\n')
    hook_source(x, options)
  })
})
```

Now we can test the new hook. When you knit this document, you
will see line numbers in trailing comments.

```{r}
if (TRUE) {
  x <- 1:10
  x + 1
}
```

The main trick in the above example is to determine the number of spaces needed before the comment on each line, so the comments can align to the right. The number depends on the widths of each line of code. We leave it to readers to digest the code in the hook function. Note that an internal function knitr:::v_spaces() is used to generate spaces of specified lengths, e.g.,

knitr:::v_spaces(c(1, 3, 6, 0))
## [1] " "      "   "    "      " ""

The method introduced in Section 5.7 may be the actual way in which you want to add line numbers to source code. The syntax is cleaner, and it works for both source code and text output blocks. The above source hook trick mainly aims to show you one possibility of manipulating the source code with a custom function.