For teaching purposes, I would like to purl
the chunks of my .Rnw
file into separate files. This answer explains how to do it:
How to purl each chunks in .Rmd file to multiple .R files using Knitr
BUT the method does not preserve the chunk options. Since the chunks I have produce plots, it's important to preserve the fig.width
and fig.height
options. Ideally I would like a chunk that looks like this:
<<plot, fig.width = 3, fig.height = 5, outwidth = '.75\\textwidth'>>=
plot (1,1)
@
to become a file named plot.R
that looks like this:
#+ fig.width = 3, fig.height = 5
plot (1,1)
That is, turn the chunk options fig.width
and fig.height
into a format that will be recognized by spin()
, as purl()
does, and get rid of the chunk options that are irrelevant, or create problems for spin()
into Word, such as out.width
. All in the spirit of creating code files that are user-friendly.
Since the answer you refer to doesn't copy the header line from the results of purl
, you lose everything besides the chunk name. While you could adapt it to paste in the headers, it's actually not hard to build a function to parse the output of purl
—much easier than trying to parse a Rmd
or Rnw
document, anyway, and easier than sorting out exactly how knitr
does so.
purl_chunks <- function(input_file){
purled <- knitr::purl(input_file) # purl original file; save name to variable
lines <- readLines(purled) # read purled file into a character vector of lines
starts <- grep('^## ----.*-+', lines) # use grep to find header row indices
stops <- c(starts[-1] - 1L, length(lines)) # end row indices
# extract chunk names from headers
names <- sub('^## ----([^-]([^,=]*[^,=-])*)[,-][^=].*', '\\1', lines[starts])
names <- ifelse(names == lines[starts], '', paste0('_', names)) # clean if no chunk name
# make nice file names with chunk number and name (if exists)
file_names <- paste0('chunk_', seq_along(starts), names, '.R')
for(chunk in seq_along(starts)){ # loop over header rows
# save the lines in the chunk to a file
writeLines(lines[starts[chunk]:stops[chunk]], con = file_names[chunk])
}
unlink(purled) # delete purled file of entire document
}
A couple notes:
.Rnw
and .Rmd
files both purl
the same, it works for either.1L
) for purl
's documentation
parameter. 0L
wouldn't have chunk headers and is thus pointless here anyway, but it would handle 2L
(which would include text chunks as roxygen
comments) stupidly. It could be rebuilt for such, though, if you wanted text chunks with the following code chunk.purl
don't look exactly like your example above (they start with ## ----
and are filled with hyphens), they spin
properly; results obey chunk options.