A possible solution is to check the 'busy
property of the inferior ESS process.
The while loop waiting for it to be nil
blocks command echo. This is why you see (redisplay)
. To avoid stressing your dear one, I set also a refresh delay (sleep-for .5)
.
Just in case ESS gets stuck the loop exists after 60 seconds. Adjust it, if you have heavy weight code.
Finally I attached latexing to AUCTeX. Therefore you can customise LaTeX-command-style
with the help of TeX-expand-list
documentation.
The function automatically sets the proper name for files to knit and latex, and sets R working dir to the .Rnw file to be knitted, so you can source other scripts or load data.
So you can run it everywhere with M-x knit
or perhaps associate it with a shortcut.
The function saves the buffer with last changes before knitting and opens an inferior R buffer if there is none available; otherwise it uses the existing one.
(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))))