org-mode/existing_tools/RweaveOrg/RweaveOrg.R
2009-02-05 15:04:09 -08:00

359 lines
13 KiB
R

require(utils)
RweaveOrg = function () {
list(setup = RweaveOrgSetup, runcode = RweaveOrgRuncode,
writedoc = RweaveOrgWritedoc, finish = RweaveOrgFinish,
checkopts = RweaveOrgOptions)
}
RweaveOrgSetup <-
function (file, syntax, output = NULL, quiet = FALSE, debug = FALSE,
echo = TRUE, eval = TRUE, keep.source = FALSE, split = FALSE,
stylepath, pdf = TRUE, eps = TRUE) {
if (is.null(output)) {
prefix.string <- basename(sub(syntax$extension, "", file))
output <- paste(prefix.string, "org", sep = ".")
}
else prefix.string <- basename(sub("\\.org$", "", output))
if (!quiet)
cat("Writing to file ", output, "\n", "Processing code chunks ...\n",
sep = "")
output <- file(output, open = "w+")
if (missing(stylepath)) {
p <- as.vector(Sys.getenv("SWEAVE_STYLEPATH_DEFAULT"))
stylepath <- if (length(p) >= 1 && nzchar(p[1]))
identical(p, "TRUE")
else TRUE
}
if (stylepath) {
styfile <- file.path(R.home("share"), "texmf", "Sweave")
if (.Platform$OS.type == "windows")
styfile <- gsub("\\\\", "/", styfile)
if (length(grep(" ", styfile)))
warning(gettextf("path to '%s' contains spaces,\n",
styfile), gettext("this may cause problems when running LaTeX"),
domain = NA)
}
else styfile <- "Sweave"
options <- list(prefix = TRUE, prefix.string = prefix.string,
engine = "R", print = FALSE, eval = eval, fig = FALSE,
pdf = pdf, eps = eps, width = 6, height = 6, term = TRUE,
echo = echo, keep.source = keep.source, results = "verbatim",
split = split, strip.white = "true", include = TRUE,
pdf.version = "1.1", pdf.encoding = "default", concordance = FALSE,
expand = TRUE)
options <- RweaveOrgOptions(options)
list(output = output, styfile = styfile, havesty = FALSE,
haveconcordance = FALSE, debug = debug, quiet = quiet,
syntax = syntax, options = options, chunkout = list(),
srclines = integer(0), srcfile = srcfile(file))
}
makeRweaveOrgCodeRunner <-
function (evalFunc = RweaveEvalWithOpt)
{
RweaveOrgRuncode <- function(object, chunk, options) {
if (!(options$engine %in% c("R", "S"))) {
return(object)
}
if (!object$quiet) {
cat(formatC(options$chunknr, width = 2), ":")
if (options$echo)
cat(" echo")
if (options$keep.source)
cat(" keep.source")
if (options$eval) {
if (options$print)
cat(" print")
if (options$term)
cat(" term")
cat("", options$results)
if (options$fig) {
if (options$eps)
cat(" eps")
if (options$pdf)
cat(" pdf")
}
}
if (!is.null(options$label))
cat(" (label=", options$label, ")", sep = "")
cat("\n")
}
chunkprefix <- RweaveChunkPrefix(options)
if (options$split) {
chunkout <- object$chunkout[chunkprefix][[1]]
if (is.null(chunkout)) {
chunkout <- file(paste(chunkprefix, "tex", sep = "."),
"w")
if (!is.null(options$label))
object$chunkout[[chunkprefix]] <- chunkout
}
}
else chunkout <- object$output
saveopts <- options(keep.source = options$keep.source)
on.exit(options(saveopts))
SweaveHooks(options, run = TRUE)
chunkexps <- try(parse(text = chunk), silent = TRUE)
RweaveTryStop(chunkexps, options)
openSinput <- FALSE
openSchunk <- FALSE
if (length(chunkexps) == 0)
return(object)
srclines <- attr(chunk, "srclines")
linesout <- integer(0)
srcline <- srclines[1]
srcrefs <- attr(chunkexps, "srcref")
if (options$expand)
lastshown <- 0
else lastshown <- srcline - 1
thisline <- 0
for (nce in 1:length(chunkexps)) {
ce <- chunkexps[[nce]]
if (nce <= length(srcrefs) && !is.null(srcref <- srcrefs[[nce]])) {
if (options$expand) {
srcfile <- attr(srcref, "srcfile")
showfrom <- srcref[1]
showto <- srcref[3]
}
else {
srcfile <- object$srcfile
showfrom <- srclines[srcref[1]]
showto <- srclines[srcref[3]]
}
dce <- getSrcLines(srcfile, lastshown + 1, showto)
leading <- showfrom - lastshown
lastshown <- showto
srcline <- srclines[srcref[3]]
while (length(dce) && length(grep("^[[:blank:]]*$",
dce[1]))) {
dce <- dce[-1]
leading <- leading - 1
}
}
else {
dce <- deparse(ce, width.cutoff = 0.75 * getOption("width"))
leading <- 1
}
if (object$debug)
cat("\nRnw> ", paste(dce, collapse = "\n+ "),
"\n")
if (options$echo && length(dce)) {
if (!openSinput) {
if (!openSchunk) {
cat("#+BEGIN_LaTeX\n", file = chunkout, append = TRUE)
cat("\\begin{Schunk}\n", file = chunkout, append = TRUE)
linesout[thisline + 1:2] <- srcline
thisline <- thisline + 2
openSchunk <- TRUE
}
cat("\\begin{Sinput}", file = chunkout, append = TRUE)
openSinput <- TRUE
}
cat("\n", paste(getOption("prompt"), dce[1:leading],
sep = "", collapse = "\n"), file = chunkout,
append = TRUE, sep = "")
if (length(dce) > leading)
cat("\n", paste(getOption("continue"), dce[-(1:leading)],
sep = "", collapse = "\n"), file = chunkout,
append = TRUE, sep = "")
linesout[thisline + 1:length(dce)] <- srcline
thisline <- thisline + length(dce)
}
tmpcon <- file()
sink(file = tmpcon)
err <- NULL
if (options$eval)
err <- evalFunc(ce, options)
cat("\n")
sink()
output <- readLines(tmpcon)
close(tmpcon)
if (length(output) == 1 & output[1] == "")
output <- NULL
RweaveTryStop(err, options)
if (object$debug)
cat(paste(output, collapse = "\n"))
if (length(output) > 0 & (options$results != "hide")) {
if (openSinput) {
cat("\n\\end{Sinput}\n", file = chunkout, append = TRUE)
linesout[thisline + 1:2] <- srcline
thisline <- thisline + 2
openSinput <- FALSE
}
if (options$results == "verbatim") {
if (!openSchunk) {
cat("#+BEGIN_LaTeX\n", file = chunkout, append = TRUE)
cat("\\begin{Schunk}\n", file = chunkout,
append = TRUE)
linesout[thisline + 1:2] <- srcline
thisline <- thisline + 2
openSchunk <- TRUE
}
cat("\\begin{Soutput}\n", file = chunkout,
append = TRUE)
linesout[thisline + 1] <- srcline
thisline <- thisline + 1
}
output <- paste(output, collapse = "\n")
if (options$strip.white %in% c("all", "true")) {
output <- sub("^[[:space:]]*\n", "", output)
output <- sub("\n[[:space:]]*$", "", output)
if (options$strip.white == "all")
output <- sub("\n[[:space:]]*\n", "\n", output)
}
cat(output, file = chunkout, append = TRUE)
count <- sum(strsplit(output, NULL)[[1]] == "\n")
if (count > 0) {
linesout[thisline + 1:count] <- srcline
thisline <- thisline + count
}
remove(output)
if (options$results == "verbatim") {
cat("\n\\end{Soutput}\n", file = chunkout,
append = TRUE)
linesout[thisline + 1:2] <- srcline
thisline <- thisline + 2
}
}
}
if (openSinput) {
cat("\n\\end{Sinput}\n", file = chunkout, append = TRUE)
linesout[thisline + 1:2] <- srcline
thisline <- thisline + 2
}
if (openSchunk) {
cat("\\end{Schunk}\n", file = chunkout, append = TRUE)
cat("#+END_LaTeX\n", file = chunkout, append = TRUE)
linesout[thisline + 1:2] <- srcline
thisline <- thisline + 2
}
if (is.null(options$label) & options$split)
close(chunkout)
if (options$split & options$include) {
cat("#+LaTeX: \\input{", chunkprefix, "}\n", sep = "", file = object$output,
append = TRUE)
linesout[thisline + 1] <- srcline
thisline <- thisline + 1
}
if (options$fig && options$eval) {
if (options$eps) {
grDevices::postscript(file = paste(chunkprefix,
"eps", sep = "."), width = options$width, height = options$height,
paper = "special", horizontal = FALSE)
err <- try({
SweaveHooks(options, run = TRUE)
eval(chunkexps, envir = .GlobalEnv)
})
grDevices::dev.off()
if (inherits(err, "try-error"))
stop(err)
}
if (options$pdf) {
grDevices::pdf(file = paste(chunkprefix, "pdf",
sep = "."), width = options$width, height = options$height,
version = options$pdf.version, encoding = options$pdf.encoding)
err <- try({
SweaveHooks(options, run = TRUE)
eval(chunkexps, envir = .GlobalEnv)
})
grDevices::dev.off()
if (inherits(err, "try-error"))
stop(err)
}
if (options$include) {
chunksuffix <- ifelse(options$eps, "eps", "pdf")
cat("[[./", paste(chunkprefix, chunksuffix, sep = "."), "]]\n",
sep = "", file = object$output, append = TRUE)
linesout[thisline + 1] <- srcline
thisline <- thisline + 1
}
}
object$linesout <- c(object$linesout, linesout)
return(object)
}
RweaveOrgRuncode
}
RweaveOrgRuncode <- makeRweaveOrgCodeRunner()
RweaveOrgWritedoc <-
function (object, chunk) {
linesout <- attr(chunk, "srclines")
## This part of the function adds the appropriate \usepackage
## directive and begins the document. Skip this for now, but
## eventually add in detection for #+LATEX_PREAMBLE
### if (length(grep("\\usepackage[^\\}]*Sweave.*\\}", chunk)))
### object$havesty <- TRUE
### if (!object$havesty) {
### begindoc <- "^[[:space:]]*\\\\begin\\{document\\}"
### which <- grep(begindoc, chunk)
### if (length(which)) {
### chunk[which] <- sub(begindoc, paste("\\\\usepackage{",
### object$styfile, "}\n\\\\begin{document}", sep = ""),
### chunk[which])
### linesout <- linesout[c(1:which, which, seq(from = which +
### 1, length.out = length(linesout) - which))]
### object$havesty <- TRUE
### }
### }
while (length(pos <- grep(object$syntax$docexpr, chunk))) {
cmdloc <- regexpr(object$syntax$docexpr, chunk[pos[1]])
cmd <- substr(chunk[pos[1]], cmdloc, cmdloc + attr(cmdloc,
"match.length") - 1)
cmd <- sub(object$syntax$docexpr, "\\1", cmd)
if (object$options$eval) {
val <- as.character(eval(parse(text = cmd), envir = .GlobalEnv))
if (length(val) == 0)
val <- ""
}
else val <- paste("\\\\verb{<<", cmd, ">>{", sep = "")
chunk[pos[1]] <- sub(object$syntax$docexpr, val, chunk[pos[1]])
}
while (length(pos <- grep(object$syntax$docopt, chunk))) {
opts <- sub(paste(".*", object$syntax$docopt, ".*", sep = ""),
"\\1", chunk[pos[1]])
object$options <- SweaveParseOptions(opts, object$options,
RweaveOrgOptions)
if (isTRUE(object$options$concordance) && !object$haveconcordance) {
savelabel <- object$options$label
object$options$label <- "concordance"
prefix <- RweaveChunkPrefix(object$options)
object$options$label <- savelabel
object$concordfile <- paste(prefix, "org", sep = ".")
chunk[pos[1]] <- sub(object$syntax$docopt, paste("\\\\input{",
prefix, "}", sep = ""), chunk[pos[1]])
object$haveconcordance <- TRUE
}
else chunk[pos[1]] <- sub(object$syntax$docopt, "", chunk[pos[1]])
}
cat(chunk, sep = "\n", file = object$output, append = TRUE)
object$linesout <- c(object$linesout, linesout)
return(object)
}
RweaveOrgFinish <-
function (object, error = FALSE) {
outputname <- summary(object$output)$description
inputname <- object$srcfile$filename
if (!object$quiet && !error)
cat("\n", gettextf("You can now run org-export-as-latex on '%s'", outputname),
"\n", sep = "")
close(object$output)
if (length(object$chunkout) > 0)
for (con in object$chunkout) close(con)
if (object$haveconcordance) {
linesout <- object$linesout
vals <- rle(diff(linesout))
vals <- c(linesout[1], as.numeric(rbind(vals$lengths,
vals$values)))
concordance <- paste(strwrap(paste(vals, collapse = " ")),
collapse = " %\n")
special <- paste("\\special{concordance:", outputname,
":", inputname, ":%\n", concordance, "}\n", sep = "")
cat(special, file = object$concordfile)
}
invisible(outputname)
}
RweaveOrgOptions <- RweaveLatexOptions