6

A minimal Rmarkdown document has a YAML header, markdown syntax and R code chunks. To edit such a multi-language file, I am using the Emacs editor, and the buffer in which the Rmd document is opened, is in polymode.

A typical document has more than one R chunk. When I am writing/debugging an R chunk in the middle of the Rmd document, I have a second buffer in the ESS mode with R running inside, and I often have to re-execute all previous chunks by sending the R commands from the Rmd file (1st buffer) into the into R console (2nd buffer).

Is there a single command allowing to execute all commands from all chunks?

From another question, it seems like org-mode can do this. But would it be possible to do it in my setting?

Community
  • 1
  • 1
tflutre
  • 3,354
  • 9
  • 39
  • 53

2 Answers2

5

If you only have R source code in your Rmarkdown, and want to be able to interactively evaluate it easily, spin from knitr might be easier (see here).

I prefer that (spin) solution, since all the markdown/Rmarkdown mumbo-jumbo is contained within normal R comments, so the buffer can be treated like regular source code. But, the following should evaluate all the R code chunks in a polymode buffer (not tested thoroughly).

(eval-when-compile
  (require 'polymode-core)  ;; SO format :('
  (defvar pm/chunkmode))
(declare-function pm-map-over-spans "polymode-core")
(declare-function pm-narrow-to-span "polymode-core")

(defun rmd-send-chunk ()
  "Send current R chunk to ess process."
  (interactive)
  (and (eq (oref pm/chunkmode :mode) 'r-mode) ;;'
       (pm-with-narrowed-to-span nil
         (goto-char (point-min))
         (forward-line)
         (ess-eval-region (point) (point-max) nil nil 'R)))) ;;'

(defun rmd-send-buffer (arg)
  "Send all R code blocks in buffer to ess process. With prefix
send regions above point."
  (interactive "P")
  (save-restriction
    (widen)
    (save-excursion
      (pm-map-over-spans
       'rmd-send-chunk (point-min) ;;'
       ;; adjust this point to send prior regions
       (if arg (point) (point-max))))))
Rorschach
  • 31,301
  • 5
  • 78
  • 129
  • awesome...!! Would there be a way to only send the chunks above where the cursor is? That is, assume there are 10 chunks in the Rmd buffer, and the cursor is between the 5th and 6th. Is there a way to send to the ESS buffer only the chunks 1 to 5? – tflutre Dec 07 '16 at 10:50
  • Thanks! For the newbies like me, here is how to use it: save the functions into a `.el` file; load it into Emacs via `M-x load-file`; open an `.Rmd` file with R chunks into a `polymode` buffer; open an `ESS` buffer; put the cursor somewhere in the middle of the `polymode` buffer; execute `C-u M-x rmd-send-buffer`. This will send all R chunks above the cursor from the `polymode` buffer into the `ESS` buffer. – tflutre Dec 07 '16 at 12:33
  • 1
    After updating `polymode` (recently refactored), these functions don't work anymore: `pm-map-over-spans: Wrong number of arguments: (lambda nil "Send current R chunk to ess process." (interactive) (and (eq (eieio-oref pm/chunkmode (quote :mode)) (quote r-mode)) (save-restriction (pm-narrow-to-span nil) (goto-char (point-min)) (forward-line) (ess-eval-region (point) (point-max) nil nil (quote R))))), 1`. I tried to debug but don't know Lisp enough. By any chance, would you have a solution? – tflutre Oct 05 '18 at 08:28
5

If using Poly-Markdown+R, the command to evaluate all R snippets in an Rmarkdown document is M-n v b.

Reference

DomQ
  • 4,184
  • 38
  • 37
  • Credit to @kaz_yos fpr pointing out issue 3; I just went from there and clicked my way through a couple of links to find the answer. – DomQ Sep 15 '19 at 15:58