--- title: Reusing book contents author: - name: Aaron Lun email: infinite.monkeys.with.keyboards@gmail.com date: "Revised: May 16, 2020" output: html_document package: rebook vignette: > %\VignetteIndexEntry{Reusing book content} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, echo=FALSE, results="asis"} library(rebook) chapterPreamble() ``` # Introduction This package implements utilities for an opinionated way of re-using content in `r CRANpkg("bookdown")` books. The general idea is that you have objects from a "donor" chapter that you want to re-use in another "acceptor" chapter, but you do not want to repeat the code from the former in the latter. Most of these ideas were developed in the process for the [Orchestrating single-cell analysis](https://osca.bioconductor.org) book, but are hopefully applicable to other projects. # Exploiting the cache The general idea here is that we compile potential donor chapters with `r CRANpkg("knitr")` caching turned on. This allows us to retrieve arbitrary objects from the cache in later code, thus avoiding the need to (i) re-type the code required to generate the object and (ii) repeat the possibly time-consuming compilation process. To demonstrate, we will use an example donor chapter from this package. We copy it to a temporary location so as avoid modifying the contents of the installation directory. ```{r} example0 <- system.file("example", "test.Rmd", package="rebook") example <- tempfile(fileext=".Rmd") file.copy(example0, example) ``` To perform this retrieval inside some acceptor chapter (in this case, this vignette), we call the `extractCached()` function on the location of the donor chapter. This will search through the cache to identify the object and pull it out into the current R session. For example: ```{r, results="asis"} extractCached(example, chunk="godzilla-1954", object="godzilla") ``` ```{r} godzilla ``` Multiple objects can be retrieved in this manner: ```{r, results="asis"} extractCached(example, chunk="ghidorah-1964", object=c("godzilla", "ghidorah")) ``` ```{r} godzilla ghidorah ``` Searching is done by chunk so as to disambiguate between objects with the same name across multiple chunks. This includes objects that are repeatedly modified, allowing us to retrieve the object different states within the donor. For example, we can pull out the same named variable but with a different value: ```{r, results="asis"} extractCached(example, chunk="godzilla-2014", object="godzilla") ``` ```{r} godzilla ``` We can also pull out objects that are not actually referenced in the requested chunk, as long as it was created in one of the preceding chunks: ```{r, results="asis"} extractCached(example, chunk="godzilla-2014", object=c("mechagodzilla", "godzilla")) ``` ```{r} godzilla mechagodzilla ``` If the donor chapter has not yet been compiled, `extractCached()` will compile it to create the cache from which to extract content. This allows us to refer to donor chapters that follow the current acceptor chapter; no extra time is used as the `r CRANpkg("bookdown")` compilation of the donor can simply use the newly cached content. Note that this system imposes some restrictions on the formatting of the code chunks in the donor report; see `?extractCached` for more details. # Pretty printing As one can see from the examples above, `extractCached()` will create a collapsible HTML element containing the code used to generate the requested object(s). This informs reader about the provenance of the object without overwhelming them. The collapsible element class is defined using code in `chapterPreamble()`, which should be called at the top of every chapter to set up the compilation environment. This is also used to achieve pretty `sessionInfo()` printing, as shown below. # Session info ```{r, results="asis"} prettySessionInfo() ```