12.1 Redact source code

Sometimes we may not want to fully display our source code in the report. For example, you may have a password in a certain line of code. We mentioned in Section 11.7 that you can use the chunk option echo to select which expressions in the R code to display (e.g., show the second expression via echo = 2). In this section, we provide a more flexible method that does not require you to specify the indices of expressions.

The basic idea is that you add a special comment to the code (e.g., # SECRET!!). When this comment is detected in a line of code, you omit that line. Below is a full example using the source hook:

---
title: Using the `source` hook to hide certain lines of code
---

First, we set up a `source` hook to exclude the lines of code
that contain the string `# SECRET!!` at the end.

```{r, include=FALSE}
local({
  hook_source <- knitr::knit_hooks$get('source')
  knitr::knit_hooks$set(source = function(x, options) {
    x <- x[!grepl('# SECRET!!$', x)]
    hook_source(x, options)
  })
})
```

Now we can test the new hook. When you knit this document, you
will not see the lines with the special comment `# SECRET!!`.

```{r}
1 + 1  # normal code to be displayed

# please use your real username and password
auth <- httr::authenticate("user", "passwd")
auth <- httr::authenticate("yihui", "horsebattery")  # SECRET!!
httr::GET("http://httpbin.org/basic-auth/user/passwd", auth)
```

The key part in the above source hook is this line, which matches the trailing comment # SECRET!! in the source code vector x via grepl() and exclude the matches:

x <- x[!grepl("# SECRET!!$", x)]

Precisely speaking, the above hook will exclude whole expressions containing the trailing comment # SECRET!!, instead of individual lines, because x is actually a vector of R expressions. For example, for the code chunk below:

1 + 1
if (TRUE) {
  # SECRET!!
  1:10
}

The value of x in the source hook is:

c("1 + 1", "if (TRUE) { # SECRET!!\n  1:10\n}")

If you want to hide lines instead of expressions of R code, you will have to split x into individual lines. You may consider using the function xfun::split_lines(). The body of the hook function will be:

x <- xfun::split_lines(x)  # split into individual lines
x <- x[!grepl("# SECRET!!$", x)]
x <- paste(x, collapse = "\n")  # combine into a single string
hook_source(x, options)

This example shows you how to manipulate the source code string, and grepl() is certainly not the only choice of string manipulation. In Section 12.2, we will show another example.