Skip to content

Instantly share code, notes, and snippets.

@christophergandrud
Last active May 8, 2017 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christophergandrud/d6400a99b37bf702bcad81af03437da6 to your computer and use it in GitHub Desktop.
Save christophergandrud/d6400a99b37bf702bcad81af03437da6 to your computer and use it in GitHub Desktop.
Convert an R reStructuredText document (Rrst) to R Markdown (Rmd)
#' Converts an R reStructuredText document (Rrst) to R Markdown (Rmd)
#'
#' @param input character string with the path of the file to convert
#' @param output optional character string with the path for the output file
#' @param out_dir optional character string with the output directory. Not used
#' if \code{output} is supplied.
#' @param output_file logical whether to return the output to a file or not.
#' If \code{FALSE}, then \code{output} and \code{out_dir} are ignored.
#'
#' @importFrom readr read_file write_file
#' @importFrom tools file_path_sans_ext
rrst_to_rmd <- function(input, output, out_dir, output_file = TRUE) {
library(readr)
library(tools)
if (!file.exists(input))
stop(sprintf('Unable to find %s', input))
# Find basic file name and file path
input_name <- file_path_sans_ext(basename(input))
# Read file into R
txt <- read_file(input)
# Function to replace rst blocks
block_replace <- function(txt, block_open, replace_open, replace_close) {
txt <- gsub(sprintf('(%s)(\\n\\n)', block_open), '\\1', txt, perl = TRUE)
txt <- gsub(sprintf('(%s)(\\n\\n)', block_open), '\\1', txt, perl = TRUE)
txt <- gsub(sprintf('(%s)(\\s+)', block_open), '\\1', txt)
txt <- gsub(sprintf('%s.+?\\K(\\n{1} +)', block_open), 'PLACEHOLDER', txt,
perl = TRUE)
txt <- gsub(sprintf('%s.*\\K\\n\\n', block_open), replace_close, txt, perl = TRUE)
txt <- gsub(sprintf('.. %s', block_open), replace_open, txt, perl = TRUE)
txt <- gsub('PLACEHOLDER', '\n ', txt, perl = TRUE)
return(txt)
}
#### Conversions -----------------------------------------------------------
# h1
txt_edit <- gsub('\\n~~~~*\\n', '\n======\n', txt)
# h2
txt_edit <- gsub('\\n\\+\\+\\+\\+*\\n', '\n------\n', txt_edit)
# h3
txt_edit <- gsub('\\n\\!\\!\\!\\!*\\n', '\\!\\!\\!\\!\\!\\!\\!\\!\n',
txt_edit)
txt_edit <- gsub('(\\n\\n){1}(.+?)(\\!\\!\\!\\!\\!\\!\\!\\!)',
'\n\n### \\2', txt_edit, perl = TRUE)
# hyperlinks
txt_edit <- gsub('``', 'INLINEPLACEHOLDER', txt_edit)
txt_edit <- gsub('(>)(`){1}(_)', ')', txt_edit, perl = TRUE)
txt_edit <- gsub('(`){1}(.*?)(<)', '[\\2](', txt_edit, perl = TRUE)
# inline math
txt_edit <- gsub('(?<!`)(?<=(?!``).)`(?!`)', '$', txt_edit, perl = TRUE)
txt_edit <- gsub(":math:", '', txt_edit)
# inline code chunks
txt_edit <- gsub('INLINEPLACEHOLDER', '`', txt_edit)
# display code chunks
txt_edit <- gsub('\\n\\.\\. \\{', '\n```{', txt_edit)
txt_edit <- gsub('\\n\\.\\. \\.\\.', '\n```', txt_edit)
# math block
txt_edit <- block_replace(txt_edit, block_open = 'math::',
replace_open = '\n$$\n ',
replace_close = '\n$$\n\n')
# static source block
txt_edit <- block_replace(txt_edit, block_open = 'sourcecode:: r',
replace_open = '\n```{r eval=FALSE}\n',
replace_close = '\n```\n\n')
# image
txt_edit <- block_replace(txt_edit, block_open = 'image::',
replace_open = '[](',
replace_close = ')\n\n')
# Cleanup
txt_edit <- gsub('\\n\\n\\n', '\n\n', txt_edit)
txt_edit <- gsub('(\\s)(\\])', '\\2', txt_edit, perl = TRUE)
# Return output ------------------------------------------------------------
if (isTRUE(output_file)) {
if (missing(output)) {
if (missing(out_dir))
input_path <- dirname(input)
else input_path <- out_dir
output <- paste0(input_path, '/', input_name, '.Rmd')
}
write_file(txt_edit, path = output)
}
else
return(txt_edit)
}
# Implements rrst_to_rmd.R in a specific context
library(devtools)
library(tools)
library(readr)
library(whisker)
library(rmarkdown)
converterfun_url <- 'https://gist.githubusercontent.com/christophergandrud/d6400a99b37bf702bcad81af03437da6/raw/0cfca6ccdc4b05cd0ade36c3de6c479b69be79e8/rrst_to_rmd.R'
source(converterfun_url)
doc_template <- '~/Desktop/doc_rmd/header_template.txt'
out_path <- '~/Desktop/doc_rmd/out'
setwd('~/Desktop/docsource/')
files <-list.files()
rrst_files <- files[grepl('.Rrst$', files)]
rrst_files <- rrst_files[!(rrst_files %in% c('features.Rrst', 'index.Rrst',
'zelig-lsmixed.Rrst',
'zelig-relogit.Rrst',
'zeligei-eiml.Rrst',
# 'zeligei-eirxc.Rrst',
'zeliggam_logitgam.Rrst'))]
# rrst to rmd
for (i in rrst_files) {
message(i)
input <- i
base_rmd <- rrst_to_rmd(input = input, output_file = FALSE)
base_rmd <- gsub('^...*?======', '', base_rmd)
base_rmd <- gsub('\\$getcoef\\(\\)', '$get_coef()', base_rmd)
base_rmd <- gsub('\\$getvcov\\(\\)', '$get_vcov()', base_rmd)
base_rmd <- gsub('\\$getpredict\\(\\)', '$get_predict()', base_rmd)
input_name <- file_path_sans_ext(basename(input))
header <- whisker.render(read_file(doc_template),
data = list(page_name = input_name,
page_name2 = sprintf('{%s}', input_name)))
input_name <- gsub('-', '_', input_name)
cat(header, base_rmd, file = sprintf('%s/%s.Rmd', out_path, input_name))
}
# Can compile to html
rmd_files <- gsub('\\.Rrst', '.Rmd', rrst_files)
rmd_files <- gsub('-', '_', rmd_files)
setwd(out_path)
for (i in rmd_files)
render(i)
@christophergandrud
Copy link
Author

christophergandrud commented Apr 21, 2017

Note this is pretty limited in that it currently only converts:

  • headers up to level 3

  • hyperlinks

  • inline and display code chunks (including non-evaluated sourcecode:: r

  • inline and display equations

A lot of the other syntax is shared between RST and R Markdown.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment