R Markdown: Automatically render output on saving file

If you are familiar with R Notebooks, you will know that the HTML output is re-generated every time you save the .Rmd file. I tried looking for a similar solution for non-notebook .Rmd files, but came up empty-handed.

I then tried tweaking my entr-based approach from my previous post and came up with this shell command that I ran for a bit in RStudio’s built-in terminal:

$ ls filename.Rmd | entr Rscript -e 'rmarkdown::render("filename.Rmd")'

This worked well enough but it was tedious to type out the whole thing. I wondered of the R community on Twitter had an alternative:

However, I didn’t get any help, so I decided to persist on my own. I remembered that Dirk Eddelbuettel had written a bunch of scripts for his littler package. I poked through the examples and came across the render.r. This was perfect!

I copied this to my /usr/local/bin directory and ran chmod +x render.r to make it an executable. I tried running the following within the RStudio terminal and it worked, but when I tried using my desktop’s terminal, I got an error:

$ ls filename.Rmd | entr render.r filename.Rmd
Error in library(docopt) : there is no package called ‘docopt’

I didn’t have the time to troubleshoot the issue. When I replaced r with Rscript in the #! line at the top, the code ran without errors, so I decided to stick with the change (for now).

I then spent some time writing a small bash script so I wouldn’t have to remember to enter the correct filename twice. I named it redoer and ran chmod +x redoer before dropping it into /usr/local/bin as well.

If you run it without a filename for an argument or with an argument that doesn’t have the .Rmd extension, it spits out error messages:

$ redoer
Please enter a valid .Rmd filename.

$ redoer dir/
This is not a valid file.

$ redoer filename.html
Please enter a valid .Rmd filename.

I am happy with the result. It works in both the RStudio terminal and the standalone terminal. I run the command redoer filename.Rmd once and it keeps rebuilding the output files as defined in the YAML frontmatter. When I am done, I need to hit Ctrl+c to terminate the process. (It is worth noting that the output files will not open in the RStudio viewer when built.)

Here are the sources for the files, if you want to grab them:

  1. render.r (© Dirk Eddelbuettel, GPL ≥ 2):
#!/usr/bin/env r
#
# Another example to run a shiny app
#
# (Littler replaced with Rscript by Achintya)
#
# Copyright (C) 2016  Dirk Eddelbuettel
#
# Released under GPL (>= 2)

suppressMessages(library(docopt))       # we need docopt (>= 0.3) as on CRAN

## configuration for docopt
doc <- "Usage: render.r [-h] [-x] [FILES...]

-h --help            show this help text
-x --usage           show help and short example usage"

opt <- docopt(doc)          # docopt parsing

if (opt$usage) {
    cat(doc, "\n\n")
    cat("Examples:
  render.r foo.Rmd bar.Rmd        # convert two given files

render.r is part of littler which brings 'r' to the command-line.
See http://dirk.eddelbuettel.com/code/littler.html for more information.\n")
    q("no")
}

library(rmarkdown)

## helper function 
renderArg <- function(p) {
    if (!file.exists(p)) stop("No file '", p, "' found. Aborting.", call.=FALSE)
    render(p)
}

## render files using helper function 
sapply(opt$FILES, renderArg)
  1. redoer (© Achintya Rao, CC0):
#! /bin/bash

if [ -f $1 ] ; then
    case $1 in
        *.Rmd) ls $1 | entr render.r $1;;
        *) echo "Please enter a valid .Rmd filename.";;
    esac
else
    echo "This is not a valid file."
fi

I am a novice with both R and bash, so if you have a way to improve any of my code or have suggestions for how to rebuild the R Markdown output files on saving the source files, please annotate this blog post or reach out to me on Scholar.Social or on Twitter.