1
votes

I'm using knitr to knit RMarkdown, and there have been multiple times where I have wanted to add code chunks programmatically, but failed to find a way to do so satisfactorily. Say I want to have knitr play a sound when a file has finished knitting. My way around this problem has been like so:

beep_on_knit <- function(beep_sound=3, sleep=3) {
  library(beepr)
  last_label <- tail(knitr::all_labels(),n=1)[[1]]
  knitr::knit_hooks$set(
    .beep_on_last_chunk =
      function(before, options) {
        if (options$label == last_label & !before) {
          beepr::beep(beep_sound)
          Sys.sleep(sleep)
          invisible(NULL)
        }
      })
  # Sets the options for every chunk so the hook will be run on them
  knitr::opts_chunk$set(.beep_on_last_chunk = TRUE)
}

However, having to edit the chunk properties of every single chunk (i.e., knitr::opts_chunk$set(.beep_on_last_chunk = TRUE) means that if I add this function to a document, it invalidates the cache of every previously cached chunk.

Is there a way to set the options of a specific chunk beforehand?

1

1 Answers

0
votes

I don't know why you need to set knitr::opts_chunk$set(.beep_on_last_chunk = TRUE) globally for the document. Is it possible for you to set .beep_on_last_chunk = TRUE only on the last chunk as a local chunk option? If this is possible, you won't need to test if (options$label == last_label) in the hook.

Alternatively, you may consider using the document hook, which is executed after the whole document has been knitted, e.g.,

knitr::knit_hooks$set(document = function(x) {
  beepr::beep(3)
  x
})