让Emacs在编织后自动乳胶化您的Rnw文件

时间:2014-07-22 17:47:40

标签: r emacs knitr ess auctex

我想在编织.Rnw文件后启动一个LaTeX。元代码应该是这样的:

(defun knit ()
  (interactive)
  (setq rproc (ess-get-process ess-current-process-name))
  (setq c "knit('foo.rnw')\n")
  (process-send-string rproc c)
  ;; Wait for ESS to finish 
  (shell-command-to-string   "cd foo/path & pdflatex foo"))

主要问题是让Emacs等待劣质缓冲区完成编织并且仅在开始胶乳之后。我找到了几个有趣的函数:(ess-wait-for-process ...)(劣等 - 标记为繁忙...)`,这可能有效,但我无法理解。

请注意(shell-command-to-string ...仅供参考。最终的选择可能是:

(TeX-command "LaTeX" 'rnw-to-tex-ext -1))

knit2pdf()可能是另一条路,但我将失去AUCTeX的好处。


PS:我的问题被SE机器人认为是“主观的,可能会被关闭”?

2 个答案:

答案 0 :(得分:1)

我使用texi2pdf并让R在编织后执行,但这显然相当于knit2pdf。我想知道你是否可以使用systemknit命令之后调用你想要的任何tex命令,类似于我使用texi2pdf的方式。

我不是emacs专家,但是我在.emacs文件中的功能是值得的。

; use knitr (was Sweave) script as compile function for Rnw files
(defun ess-swv-SweaveSh ()
  "Use knitr script to knit an Rnw file and create a pdf."
  (interactive)
  (let 
    ((compilation-buffer-name-function (function (lambda(ign)(concat "*" (buffer-file-name) "*")))))
    (compile  (concat "Rscript -e \".n <- '" (buffer-file-name) "'; library(knitr); knit(.n); library(tools); texi2pdf(sub('Rnw$','tex',.n))\"" ))
  )
)

答案 1 :(得分:1)

可能的解决方案是检查劣质ESS流程的'busy属性。 等待它为nil的while循环阻止命令回显。这就是您看到(redisplay)的原因。为了避免给亲爱的人施加压力,我还设置了刷新延迟(sleep-for .5) 为了防止ESS卡住,60秒后循环存在。如果您有重量级密码,请调整它。

最后,我将胶乳附加到AUCTeX。因此,您可以借助LaTeX-command-style文档自定义TeX-expand-list

该功能自动为knit和latex设置文件的正确名称,并将R working dir设置为要编织的.Rnw文件,以便您可以获取其他脚本或加载数据。
因此,您可以使用M-x knit随处运行它,也可以将其与快捷方式相关联。 该函数在编织前保存缓冲区的最后一次更改,如果没有可用的话,打开一个劣质的R缓冲区;否则它使用现有的。

(defun knit ()
  "Save the buffer, knit and latex"
  (interactive) ; You will associate this to you favourite key

  (let* (
    ;; Get names & path
        (cur-dir (file-name-directory (buffer-file-name)))
    (rnw-name (file-name-nondirectory (buffer-file-name)))
    (tex-name (concat (file-name-base (buffer-file-name)) ".tex"))

    ;; Create knit command
    (cmd (format "require(knitr); setwd('%s'); knit('%s')"  cur-dir rnw-name))

    ;; Time the knitting  
    (start-time (float-time))
    (wait  60)   ; Lifeboat to exit loop if smt wrong
    )

    ;; Save rnw buffer... you are lazy, I know)
    (save-buffer)


    ;; Send string to R at low-level 
    ;;(setq rproc (ess-get-process ess-current-process-name))
    ;;(process-send-string rproc c)

    ;; or Send line with the ESS wrapper 
    (ess-eval-linewise cmd)

    ;; While loop to check when 
    (setq start-time (float-time)
      wait  60) ; Lifeboat to exit loop after x secs 

    ;; Wait for 'busy property nil, nut not more than wait seconds
    (setq rproc (ess-get-process ess-current-process-name))
    (while  (< (- (float-time) start-time) wait)
      (sleep-for .5)
      ;; (accept-process-output rproc .5) ;alt. way for  process-send-string
      (redisplay)
      (if (not (process-get rproc  'busy)) 
      (setq wait 0)
    (message "Knitting... ")))
    (message "Knitting finished, starting latexing")

    ;; Set LaTeX your fav options. See TeX-expand-list for % pars 
    (setq LaTeX-command-style '(("" "%(PDF)%(latex) -file-line-error %S%(PDFout)")))
    ;; TeX-command requires a 'file function (anonymous here) returning the filename.
    ;; TeX-command/TeX-expand-list say 'file has one opt arg: extension.
    ;; Actually they are 2, despite the second seems always passed true.
    (TeX-command "LaTeX"  (lambda (&optional ext dummy) tex-name))))