35

Q: how can I get ESS (R) to plot directly to an Emacs buffer?

When interacting with R through ESS, R defaults to spawning a separate graphics window outside of Emacs to draw its plots. (One can, of course, choose other graphical devices, which is how we plot to PDF, etc.) Two issues: first, the new window steals focus from Emacs, and second, it sure would be nice to keep everything nice and tidy within the Emacs ecosystem.

So: is there any way to plot "directly" (or even indirectly) to an Emacs buffer and, more importantly, do so without a lot of manual intervention by the user?

There had been some prior discussion in this old Stack Overflow thread, but the partial solutions proposed are not ideal. They mostly involve changing the plotting device in R (say, to PNG), plotting to a temporary file, and then manually visiting that file in an Emacs buffer. That all strikes me as very clunky, especially if the goal is to use the plot window/buffer interactively and draw many plots in a session (or add layers to them on the fly).

I'm speculating here, but it strikes me that, since both R and Emacs support SVG, that might be a useful format to use. However, it's not clear to me if/how one could hook into the R process to communicate on the fly. Is there a way to have R spit SVG code directly into an Emacs buffer, or would it need to go through the intermediary of a temporary file? How could one convince Emacs to visit a new temporary file automagically when R creates it, or update such a plot buffer when the temporary file gets updated/overwritten by a new plot?

2
  • 3
    Emacs doesn't have to use a file and can instead use a string to insert an image into a buffer, see the docstring of create-image. I can't help you with actually making R and Emacs communicate with each other to achieve that though.
    – wasamasa
    Oct 17, 2014 at 14:59
  • 1
    This has been discussed on the ESS mailing list: see stat.ethz.ch/pipermail/ess-help/2013-November/009559.html
    – Ista
    Jan 24, 2015 at 23:42

3 Answers 3

6

Not completly an answer to the question, but when one use R in org-mode's babel:

* My example
#+name: simple-org-example
#+begin_src R :session *my-R* :dir "." :results output graphics :file example.svg :width 18 :height 9
  plot(cyl~mpg,data=mtcars)
#+end_src

Doing a C-c C-c on this in org-mode will create a *my-R* buffer with an interacting ESS buffer, create the plot in the example.svg file and then you can click (or press enter) on the created link to the file, that will open it.

Org-mode is able to inline image, but it do it when toggling this functionality (with M-x org-toggle-inline-images) or on opening the file, but not on running a code in it.

So this is not a complete solution.

1
  • 3
    You can get the image to display automatically by setting (add-hook 'org-babel-after-execute-hook 'org-display-inline-images), but this is (I think) still not really what the OP wanted.
    – Ista
    Jan 24, 2015 at 23:45
2

I just posted an answer to the old post you are referring to in your question. As I wrote there, this may not work for you since it would be quite a dramatic change in your overall computer workflow.

But exwm, by allowing any non-emacs window to be an emacs buffer, allows to have R plots in emacs buffers which are controlled by the usual emacs settings and keybindings.

Here is an example of what this looks like:

enter image description here

3
  • Could you share your config to achieve this? Looks very nice! Thanks. Apr 19, 2022 at 15:47
  • Hi Maikol, I now use i3-wm, so I have long deleted my EXWM configuration. But this is simply 2 Emacs buffers side by side, one running an actual Emacs buffer and the other one running an X11 window for the plot (inside an EXWM Emacs buffer).
    – prosoitos
    Apr 20, 2022 at 19:07
  • With EXWM, each X11 window becomes an Emacs buffer and you can organize them the way you would any other Emacs buffer (e.g. with display-buffer-alist)
    – prosoitos
    Apr 20, 2022 at 19:09
0

As an alternative, it is possible to write an elisp function to that will save the plot as a pdf and open in on a buffer next to the R process. See for example:

plot buffer

code:

(defvar rutils-show_plot_next_to_r_process t)

(defun add-pdf-to-rcode(rcomm fname)
  "add pdf(tmpfile) and dev.off() to R command"
  (let*  (
      (newc (concat "pdf('" fname "')\n" rcomm  "\n dev.off()"))
      )
    (eval newc)
      )
  )


(defun rutils-plot-region-or-paragraph()
  "execute region or paragraph and save tmp plot to pdf. Then open windows to show pdf"
  (interactive)
    (let*  (
      (fname (concat (make-temp-file "plot_") ".pdf"))
      )
      (progn
    (if (use-region-p)
        (ess-eval-linewise (add-pdf-to-rcode (buffer-substring (region-beginning) (region-end)) fname))
      (progn (ess-eval-linewise (add-pdf-to-rcode (thing-at-point 'paragraph) fname)))
      )
        (ess-switch-to-end-of-ESS)
        )
    (if (window-in-direction 'right)
        (progn
          (select-window (window-in-direction 'right))
          (find-file fname)
          )
      (progn
        (split-window-right)
        (select-window (window-in-direction 'right))
        (find-file fname)
        )
        )
    )
    )
    )
(define-key ess-mode-map (kbd "C-c g") 'rutils-plot-region-or-paragraph)

ref: https://www.fredgruber.org/post/plot_buffer/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.