RweaveOrg.R 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. require(utils)
  2. RweaveOrg = function () {
  3. list(setup = RweaveOrgSetup, runcode = RweaveOrgRuncode,
  4. writedoc = RweaveOrgWritedoc, finish = RweaveOrgFinish,
  5. checkopts = RweaveOrgOptions)
  6. }
  7. RweaveOrgSetup <-
  8. function (file, syntax, output = NULL, quiet = FALSE, debug = FALSE,
  9. echo = TRUE, eval = TRUE, keep.source = FALSE, split = FALSE,
  10. stylepath, pdf = TRUE, eps = TRUE) {
  11. if (is.null(output)) {
  12. prefix.string <- basename(sub(syntax$extension, "", file))
  13. output <- paste(prefix.string, "org", sep = ".")
  14. }
  15. else prefix.string <- basename(sub("\\.org$", "", output))
  16. if (!quiet)
  17. cat("Writing to file ", output, "\n", "Processing code chunks ...\n",
  18. sep = "")
  19. output <- file(output, open = "w+")
  20. if (missing(stylepath)) {
  21. p <- as.vector(Sys.getenv("SWEAVE_STYLEPATH_DEFAULT"))
  22. stylepath <- if (length(p) >= 1 && nzchar(p[1]))
  23. identical(p, "TRUE")
  24. else TRUE
  25. }
  26. if (stylepath) {
  27. styfile <- file.path(R.home("share"), "texmf", "Sweave")
  28. if (.Platform$OS.type == "windows")
  29. styfile <- gsub("\\\\", "/", styfile)
  30. if (length(grep(" ", styfile)))
  31. warning(gettextf("path to '%s' contains spaces,\n",
  32. styfile), gettext("this may cause problems when running LaTeX"),
  33. domain = NA)
  34. }
  35. else styfile <- "Sweave"
  36. options <- list(prefix = TRUE, prefix.string = prefix.string,
  37. engine = "R", print = FALSE, eval = eval, fig = FALSE,
  38. pdf = pdf, eps = eps, width = 6, height = 6, term = TRUE,
  39. echo = echo, keep.source = keep.source, results = "verbatim",
  40. split = split, strip.white = "true", include = TRUE,
  41. pdf.version = "1.1", pdf.encoding = "default", concordance = FALSE,
  42. expand = TRUE)
  43. options <- RweaveOrgOptions(options)
  44. list(output = output, styfile = styfile, havesty = FALSE,
  45. haveconcordance = FALSE, debug = debug, quiet = quiet,
  46. syntax = syntax, options = options, chunkout = list(),
  47. srclines = integer(0), srcfile = srcfile(file))
  48. }
  49. makeRweaveOrgCodeRunner <-
  50. function (evalFunc = RweaveEvalWithOpt)
  51. {
  52. RweaveOrgRuncode <- function(object, chunk, options) {
  53. if (!(options$engine %in% c("R", "S"))) {
  54. return(object)
  55. }
  56. if (!object$quiet) {
  57. cat(formatC(options$chunknr, width = 2), ":")
  58. if (options$echo)
  59. cat(" echo")
  60. if (options$keep.source)
  61. cat(" keep.source")
  62. if (options$eval) {
  63. if (options$print)
  64. cat(" print")
  65. if (options$term)
  66. cat(" term")
  67. cat("", options$results)
  68. if (options$fig) {
  69. if (options$eps)
  70. cat(" eps")
  71. if (options$pdf)
  72. cat(" pdf")
  73. }
  74. }
  75. if (!is.null(options$label))
  76. cat(" (label=", options$label, ")", sep = "")
  77. cat("\n")
  78. }
  79. chunkprefix <- RweaveChunkPrefix(options)
  80. if (options$split) {
  81. chunkout <- object$chunkout[chunkprefix][[1]]
  82. if (is.null(chunkout)) {
  83. chunkout <- file(paste(chunkprefix, "tex", sep = "."),
  84. "w")
  85. if (!is.null(options$label))
  86. object$chunkout[[chunkprefix]] <- chunkout
  87. }
  88. }
  89. else chunkout <- object$output
  90. saveopts <- options(keep.source = options$keep.source)
  91. on.exit(options(saveopts))
  92. SweaveHooks(options, run = TRUE)
  93. chunkexps <- try(parse(text = chunk), silent = TRUE)
  94. RweaveTryStop(chunkexps, options)
  95. openSinput <- FALSE
  96. openSchunk <- FALSE
  97. if (length(chunkexps) == 0)
  98. return(object)
  99. srclines <- attr(chunk, "srclines")
  100. linesout <- integer(0)
  101. srcline <- srclines[1]
  102. srcrefs <- attr(chunkexps, "srcref")
  103. if (options$expand)
  104. lastshown <- 0
  105. else lastshown <- srcline - 1
  106. thisline <- 0
  107. for (nce in 1:length(chunkexps)) {
  108. ce <- chunkexps[[nce]]
  109. if (nce <= length(srcrefs) && !is.null(srcref <- srcrefs[[nce]])) {
  110. if (options$expand) {
  111. srcfile <- attr(srcref, "srcfile")
  112. showfrom <- srcref[1]
  113. showto <- srcref[3]
  114. }
  115. else {
  116. srcfile <- object$srcfile
  117. showfrom <- srclines[srcref[1]]
  118. showto <- srclines[srcref[3]]
  119. }
  120. dce <- getSrcLines(srcfile, lastshown + 1, showto)
  121. leading <- showfrom - lastshown
  122. lastshown <- showto
  123. srcline <- srclines[srcref[3]]
  124. while (length(dce) && length(grep("^[[:blank:]]*$",
  125. dce[1]))) {
  126. dce <- dce[-1]
  127. leading <- leading - 1
  128. }
  129. }
  130. else {
  131. dce <- deparse(ce, width.cutoff = 0.75 * getOption("width"))
  132. leading <- 1
  133. }
  134. if (object$debug)
  135. cat("\nRnw> ", paste(dce, collapse = "\n+ "),
  136. "\n")
  137. if (options$echo && length(dce)) {
  138. if (!openSinput) {
  139. if (!openSchunk) {
  140. cat("#+BEGIN_LaTeX\n", file = chunkout, append = TRUE)
  141. cat("\\begin{Schunk}\n", file = chunkout, append = TRUE)
  142. linesout[thisline + 1:2] <- srcline
  143. thisline <- thisline + 2
  144. openSchunk <- TRUE
  145. }
  146. cat("\\begin{Sinput}", file = chunkout, append = TRUE)
  147. openSinput <- TRUE
  148. }
  149. cat("\n", paste(getOption("prompt"), dce[1:leading],
  150. sep = "", collapse = "\n"), file = chunkout,
  151. append = TRUE, sep = "")
  152. if (length(dce) > leading)
  153. cat("\n", paste(getOption("continue"), dce[-(1:leading)],
  154. sep = "", collapse = "\n"), file = chunkout,
  155. append = TRUE, sep = "")
  156. linesout[thisline + 1:length(dce)] <- srcline
  157. thisline <- thisline + length(dce)
  158. }
  159. tmpcon <- file()
  160. sink(file = tmpcon)
  161. err <- NULL
  162. if (options$eval)
  163. err <- evalFunc(ce, options)
  164. cat("\n")
  165. sink()
  166. output <- readLines(tmpcon)
  167. close(tmpcon)
  168. if (length(output) == 1 & output[1] == "")
  169. output <- NULL
  170. RweaveTryStop(err, options)
  171. if (object$debug)
  172. cat(paste(output, collapse = "\n"))
  173. if (length(output) > 0 & (options$results != "hide")) {
  174. if (openSinput) {
  175. cat("\n\\end{Sinput}\n", file = chunkout, append = TRUE)
  176. linesout[thisline + 1:2] <- srcline
  177. thisline <- thisline + 2
  178. openSinput <- FALSE
  179. }
  180. if (options$results == "verbatim") {
  181. if (!openSchunk) {
  182. cat("#+BEGIN_LaTeX\n", file = chunkout, append = TRUE)
  183. cat("\\begin{Schunk}\n", file = chunkout,
  184. append = TRUE)
  185. linesout[thisline + 1:2] <- srcline
  186. thisline <- thisline + 2
  187. openSchunk <- TRUE
  188. }
  189. cat("\\begin{Soutput}\n", file = chunkout,
  190. append = TRUE)
  191. linesout[thisline + 1] <- srcline
  192. thisline <- thisline + 1
  193. }
  194. output <- paste(output, collapse = "\n")
  195. if (options$strip.white %in% c("all", "true")) {
  196. output <- sub("^[[:space:]]*\n", "", output)
  197. output <- sub("\n[[:space:]]*$", "", output)
  198. if (options$strip.white == "all")
  199. output <- sub("\n[[:space:]]*\n", "\n", output)
  200. }
  201. cat(output, file = chunkout, append = TRUE)
  202. count <- sum(strsplit(output, NULL)[[1]] == "\n")
  203. if (count > 0) {
  204. linesout[thisline + 1:count] <- srcline
  205. thisline <- thisline + count
  206. }
  207. remove(output)
  208. if (options$results == "verbatim") {
  209. cat("\n\\end{Soutput}\n", file = chunkout,
  210. append = TRUE)
  211. linesout[thisline + 1:2] <- srcline
  212. thisline <- thisline + 2
  213. }
  214. }
  215. }
  216. if (openSinput) {
  217. cat("\n\\end{Sinput}\n", file = chunkout, append = TRUE)
  218. linesout[thisline + 1:2] <- srcline
  219. thisline <- thisline + 2
  220. }
  221. if (openSchunk) {
  222. cat("\\end{Schunk}\n", file = chunkout, append = TRUE)
  223. cat("#+END_LaTeX\n", file = chunkout, append = TRUE)
  224. linesout[thisline + 1:2] <- srcline
  225. thisline <- thisline + 2
  226. }
  227. if (is.null(options$label) & options$split)
  228. close(chunkout)
  229. if (options$split & options$include) {
  230. cat("#+LaTeX: \\input{", chunkprefix, "}\n", sep = "", file = object$output,
  231. append = TRUE)
  232. linesout[thisline + 1] <- srcline
  233. thisline <- thisline + 1
  234. }
  235. if (options$fig && options$eval) {
  236. if (options$eps) {
  237. grDevices::postscript(file = paste(chunkprefix,
  238. "eps", sep = "."), width = options$width, height = options$height,
  239. paper = "special", horizontal = FALSE)
  240. err <- try({
  241. SweaveHooks(options, run = TRUE)
  242. eval(chunkexps, envir = .GlobalEnv)
  243. })
  244. grDevices::dev.off()
  245. if (inherits(err, "try-error"))
  246. stop(err)
  247. }
  248. if (options$pdf) {
  249. grDevices::pdf(file = paste(chunkprefix, "pdf",
  250. sep = "."), width = options$width, height = options$height,
  251. version = options$pdf.version, encoding = options$pdf.encoding)
  252. err <- try({
  253. SweaveHooks(options, run = TRUE)
  254. eval(chunkexps, envir = .GlobalEnv)
  255. })
  256. grDevices::dev.off()
  257. if (inherits(err, "try-error"))
  258. stop(err)
  259. }
  260. if (options$include) {
  261. chunksuffix <- ifelse(options$eps, "eps", "pdf")
  262. cat("[[./", paste(chunkprefix, chunksuffix, sep = "."), "]]\n",
  263. sep = "", file = object$output, append = TRUE)
  264. linesout[thisline + 1] <- srcline
  265. thisline <- thisline + 1
  266. }
  267. }
  268. object$linesout <- c(object$linesout, linesout)
  269. return(object)
  270. }
  271. RweaveOrgRuncode
  272. }
  273. RweaveOrgRuncode <- makeRweaveOrgCodeRunner()
  274. RweaveOrgWritedoc <-
  275. function (object, chunk) {
  276. linesout <- attr(chunk, "srclines")
  277. ## This part of the function adds the appropriate \usepackage
  278. ## directive and begins the document. Skip this for now, but
  279. ## eventually add in detection for #+LATEX_PREAMBLE
  280. ### if (length(grep("\\usepackage[^\\}]*Sweave.*\\}", chunk)))
  281. ### object$havesty <- TRUE
  282. ### if (!object$havesty) {
  283. ### begindoc <- "^[[:space:]]*\\\\begin\\{document\\}"
  284. ### which <- grep(begindoc, chunk)
  285. ### if (length(which)) {
  286. ### chunk[which] <- sub(begindoc, paste("\\\\usepackage{",
  287. ### object$styfile, "}\n\\\\begin{document}", sep = ""),
  288. ### chunk[which])
  289. ### linesout <- linesout[c(1:which, which, seq(from = which +
  290. ### 1, length.out = length(linesout) - which))]
  291. ### object$havesty <- TRUE
  292. ### }
  293. ### }
  294. while (length(pos <- grep(object$syntax$docexpr, chunk))) {
  295. cmdloc <- regexpr(object$syntax$docexpr, chunk[pos[1]])
  296. cmd <- substr(chunk[pos[1]], cmdloc, cmdloc + attr(cmdloc,
  297. "match.length") - 1)
  298. cmd <- sub(object$syntax$docexpr, "\\1", cmd)
  299. if (object$options$eval) {
  300. val <- as.character(eval(parse(text = cmd), envir = .GlobalEnv))
  301. if (length(val) == 0)
  302. val <- ""
  303. }
  304. else val <- paste("\\\\verb{<<", cmd, ">>{", sep = "")
  305. chunk[pos[1]] <- sub(object$syntax$docexpr, val, chunk[pos[1]])
  306. }
  307. while (length(pos <- grep(object$syntax$docopt, chunk))) {
  308. opts <- sub(paste(".*", object$syntax$docopt, ".*", sep = ""),
  309. "\\1", chunk[pos[1]])
  310. object$options <- SweaveParseOptions(opts, object$options,
  311. RweaveOrgOptions)
  312. if (isTRUE(object$options$concordance) && !object$haveconcordance) {
  313. savelabel <- object$options$label
  314. object$options$label <- "concordance"
  315. prefix <- RweaveChunkPrefix(object$options)
  316. object$options$label <- savelabel
  317. object$concordfile <- paste(prefix, "org", sep = ".")
  318. chunk[pos[1]] <- sub(object$syntax$docopt, paste("\\\\input{",
  319. prefix, "}", sep = ""), chunk[pos[1]])
  320. object$haveconcordance <- TRUE
  321. }
  322. else chunk[pos[1]] <- sub(object$syntax$docopt, "", chunk[pos[1]])
  323. }
  324. cat(chunk, sep = "\n", file = object$output, append = TRUE)
  325. object$linesout <- c(object$linesout, linesout)
  326. return(object)
  327. }
  328. RweaveOrgFinish <-
  329. function (object, error = FALSE) {
  330. outputname <- summary(object$output)$description
  331. inputname <- object$srcfile$filename
  332. if (!object$quiet && !error)
  333. cat("\n", gettextf("You can now run org-export-as-latex on '%s'", outputname),
  334. "\n", sep = "")
  335. close(object$output)
  336. if (length(object$chunkout) > 0)
  337. for (con in object$chunkout) close(con)
  338. if (object$haveconcordance) {
  339. linesout <- object$linesout
  340. vals <- rle(diff(linesout))
  341. vals <- c(linesout[1], as.numeric(rbind(vals$lengths,
  342. vals$values)))
  343. concordance <- paste(strwrap(paste(vals, collapse = " ")),
  344. collapse = " %\n")
  345. special <- paste("\\special{concordance:", outputname,
  346. ":", inputname, ":%\n", concordance, "}\n", sep = "")
  347. cat(special, file = object$concordfile)
  348. }
  349. invisible(outputname)
  350. }
  351. RweaveOrgOptions <- RweaveLatexOptions