Introduction

This package implements utilities for an opinionated way of re-using content in 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 book, but are hopefully applicable to other projects.

Exploiting the cache

The general idea here is that we compile potential donor chapters with 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.

example0 <- system.file("example", "test.Rmd", package="rebook")
example <- tempfile(fileext=".Rmd")
file.copy(example0, example)
## [1] TRUE

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:

extractCached(example, chunk="godzilla-1954", object="godzilla")
#--- godzilla-1954 ---#
godzilla <- "RAWR!"
godzilla
## [1] "RAWR!"

Multiple objects can be retrieved in this manner:

extractCached(example, chunk="ghidorah-1964", object=c("godzilla", "ghidorah"))
#--- godzilla-1954 ---#
godzilla <- "RAWR!"

#--- ghidorah-1964 ---#
godzilla <- "GAO GAO"
ghidorah <- "pew pew"
mothra = "Oh, I'm not in this one." # WRONG!
godzilla
## [1] "GAO GAO"
ghidorah
## [1] "pew pew"

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:

extractCached(example, chunk="godzilla-2014", object="godzilla")
#--- godzilla-1954 ---#
godzilla <- "RAWR!"

#--- ghidorah-1964 ---#
godzilla <- "GAO GAO"
ghidorah <- "pew pew"
mothra = "Oh, I'm not in this one." # WRONG!

#--- godzilla-1978 ---#
godzilla <- "rawr rawr"
mechagodzilla <- "beep beep"

#--- godzilla-2014 ---#
godzilla <- "I'm back."
muto <- "Hi."
godzilla
## [1] "I'm back."

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:

extractCached(example, chunk="godzilla-2014", object=c("mechagodzilla", "godzilla"))
#--- godzilla-1954 ---#
godzilla <- "RAWR!"

#--- ghidorah-1964 ---#
godzilla <- "GAO GAO"
ghidorah <- "pew pew"
mothra = "Oh, I'm not in this one." # WRONG!

#--- godzilla-1978 ---#
godzilla <- "rawr rawr"
mechagodzilla <- "beep beep"

#--- godzilla-2014 ---#
godzilla <- "I'm back."
muto <- "Hi."
godzilla
## [1] "I'm back."
mechagodzilla
## [1] "beep beep"

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 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

prettySessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.5 LTS

Matrix products: default
BLAS:   /home/biocbuild/bbs-3.12-bioc/R/lib/libRblas.so
LAPACK: /home/biocbuild/bbs-3.12-bioc/R/lib/libRlapack.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=C              
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] BiocStyle_2.18.0 rebook_1.0.0    

loaded via a namespace (and not attached):
 [1] codetools_0.2-16    XML_3.99-0.5        ps_1.4.0           
 [4] digest_0.6.27       R6_2.4.1            stats4_4.0.3       
 [7] magrittr_1.5        evaluate_0.14       graph_1.68.0       
[10] rlang_0.4.8         stringi_1.5.3       callr_3.5.1        
[13] rmarkdown_2.5       tools_4.0.3         stringr_1.4.0      
[16] processx_3.4.4      parallel_4.0.3      xfun_0.18          
[19] yaml_2.2.1          compiler_4.0.3      BiocGenerics_0.36.0
[22] BiocManager_1.30.10 htmltools_0.5.0     CodeDepends_0.6.5  
[25] knitr_1.30