Andrie, thank you so much! That's exactly what I was looking for. I had this vague notion that I had seen it somewhere previously. I suspect it was that SO question. Thanks for the Sunday answer!
I'm hitting a weird implementation snag, however. If I hide the hook code at the top of a chapter in a code block, it seems to work great. I'm doing a multi chapter book and I plan on using this over and over. So it makes sense to me to add it to my _common.R file which is referenced in my _bookdown.yaml as a before chapter script:
before_chapter_script: "_common.R"
So my understanding is that the _common.R gets sourced on the top of each chapter before it is rendered. However if I add the hook_output code chunk I get the following error:
==> rmarkdown::render_site(encoding = 'UTF-8')
R -e 'bookdown::render_book("index.Rmd", output=bookdown::gitbook())'
R version 3.4.4 (2018-03-15) -- "Someone to Lean On"
Copyright (C) 2018 The R Foundation for Statistical Computing
Platform: x86_64-apple-darwin15.6.0 (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
Natural language support but running in an English locale
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
> bookdown::render_book("index.Rmd", output=bookdown::gitbook())
processing file: index.Rmd
|................................ | 50%
label: unnamed-chunk-1 (with options)
List of 2
$ include: logi FALSE
$ cache : logi FALSE
|.................................................................| 100%
inline R code fragments
output file: index.knit.md
processing file: 01_GettingStarted.Rmd
|. | 1%
label: unnamed-chunk-1 (with options)
List of 2
$ include: logi FALSE
$ cache : logi FALSE
|.. | 3%
label: unnamed-chunk-2 (with options)
List of 2
$ include: logi FALSE
$ cache : logi FALSE
|... | 4%
label: unnamed-chunk-3 (with options)
List of 2
$ include: logi FALSE
$ cache : logi FALSE
|.... | 6%
ordinary text without R code
|..... | 7%
label: unnamed-chunk-4 (with options)
List of 2
$ echo: logi FALSE
$ eval: logi TRUE
|..... | 8%
ordinary text without R code
|...... | 10%
label: unnamed-chunk-5
Error in substring(file, 1L, 1L) : node stack overflow
Calls: local ... hook_output -> hook_output -> .handleSimpleError -> h -> cat
Execution halted
Error in Rscript_render(f, render_args, render_meta) :
Failed to compile 01_GettingStarted.Rmd
Calls: <Anonymous> ... render_new_session -> tryCatch -> tryCatchList -> Rscript_render
Execution halted
make: *** [book] Error 1
Error in render_book_script(output_format, envir, quiet) :
Error 2 attempting to render book
Calls: <Anonymous> -> <Anonymous> -> in_dir -> render_book_script
Execution halted
Exited with status 1.
And this is mighty verbose, but here's my _common.R file in its entirety:
set.seed(42)
options(digits = 3)
library(tidyverse)
library(knitr)
knitr::opts_chunk$set(
comment = "#>",
collapse = TRUE,
cache = TRUE,
out.width = "70%",
fig.align = 'center',
fig.width = 6,
fig.asp = 0.618, # 1 / phi
fig.show = "hold"
)
options(dplyr.print_min = 6, dplyr.print_max = 6)
hook_output <- knit_hooks$get("output")
knit_hooks$set(output = function(x, options) {
lines <- options$output.lines
if (is.null(lines)) {
return(hook_output(x, options)) # pass to default hook
}
x <- unlist(strsplit(x, "\n"))
more <- "etc ..."
if (length(lines)==1) { # first n lines
if (length(x) > lines) { # truncate the output, but add ....
x <- c(head(x, lines), more)
}
} else {
x <- c(more, x[lines], more)
}
# paste these lines together
x <- paste(c(x, ""), collapse = "\n")
hook_output(x, options)
})