Reuse Rmd hunks in package vignettes, README, blog posts and more

Jonathan Carroll (@carroll_jono) posted a twitter poll that turned out to be quite interesting this weekend:

What I love to see in a README

Personally, I usually find out about a package while browsing GitHub or a blog post that leads me to check out the package on GitHub. So I’m very partial to a highly explanatory README.

When I run into a new package, I’m hoping the README answers the following questions

  1. Why would I want to use this package?
  2. What does it look like to use this package?

So basically: an explanation of the problem the package solves and at least a short introduction to the functions or syntax of the package.

There are a lot of READMEs out there that just answer the first question with a very basic description of the package, or maybe even a detailed overview of the problem the package solves, but they don’t showcase the package in action. I might not be the typical user, but this always seems like a missed opportunity to me.

Of course, writing good documentation is tricky. And considering that a good package also has vignettes, a README, a related ([blogdown]) blog post, and possibly even a pkgdown site, making sure the documentation is up-to-date in all of these places can put undue burden on the package developers.

Don’t Repeat Yourself, Clone Yourself

In the spirit of Don’t Repeat Yourself and maximizing the potential of knitr and R Markdown – and the fact that you can use R Markdown for all of the above pieces – I remembered recently reading about child documents in knitr.

I posted my idea to Jonathan’s thread and shortly afterwards @BrodieGaslam wrote back with an idea that really makes the best of child documents. Here’s the full idea:

Write repeatable sections in short .Rmd files.

Using Brodie’s vetr packge as an example, these files are stored in vignettes/rmdhunks:

├── alike.Rmd
├── rmdhunks
│   ├── declarative-checks.Rmd
│   ├── microbenchmark.Rmd
│   ├── related-packages.Rmd
│   ├── trust-but-verify.Rmd
│   ├── valaddin.Rmd
│   └── vetting-expressions.Rmd
├── styles.css
└── vetr.Rmd

Notice related-packages.Rmd. It’s a short R Markdown file with a list of (not surprisingly) related packages – the kind of section that might be included in both the package overview vignette and the README.

vignettes/rmdhunks/related-packages.Rmd >

* `stopifnot` by R Core
* [`vetr`]( by Yours Truly
* [`asserthat`]( by Hadley Wickham
* [`assertive`]( by Richie Cotton
* [`checkmate`]( by Michel Lang

The following packages also perform related tasks ...

Reference the repeatable sections using the child chunk option.

Knitr provides a child document chunk option that you can use to embed R Markdown from an external file. Anywhere that you would re-use the documentation, you simply include the following, such as in the vetr package vignette. Again, the following are from the vetr package documentation files.

vignettes/vetr.Rmd >

## Alternatives

There are many alternatives available to `vetr`.  We do a survey of the
following in our [parameter validation functions][4] review:
```{r child='./rmdhunks/related-packages.Rmd'} 

This R Markdown “hunk” can be used anywhere else you need it, such as in the package README.Rmd file.


## Alternatives

There are many alternatives available to `vetr`.  We do a survey of the
following in our [parameter validation functions][5] review:

```{r child='vignettes/rmdhunks/related-packages.Rmd'} 

The major advantage here is to be able to update the documentation in one place and have those changes propagate to “parent” documents. It’s also useful to be able to arrange or choose the content shown in certain places. For example, READMEs typically include installation instructions, but these would be redundant if included in the package vignettes.

The above examples can be extended for use in pkgdown articles (which are essentially an extension of vignettes) or for blogdown posts if you develope your package and blog source on the same machine.

Thanks @BrodieGaslam for the tip and @carroll_jono for kicking off this thread!