Blogdown w/ Polymode

John Haman

2020/04/13

Categories: R Emacs Tags: R Emacs

Polymode is a nifty little Emacs “mode” that lets you run multiple major modes in the same buffer. This is one heck of a hack because Emacs typically requires one major mode per buffer.1

In particular, you can have a buffer with markdown-mode and ESS running simulaneously, which if exactly what we need to edit Rmarkdown files. When the point is in an R code fence, ESS mode is active, otherwise markdown-mode is active.

I’ve tried it before, but only recently wrote enough elisp to overcome some of pain points that let me write this blog from the comfort of my Emacs session. I don’t think it’s quite perfect, but I have never had a bug-free experience with a markdown system that mixes one or more programming languages with prose2.

The major competitor in the literate programming game is Org-mode. But Org requires you to set the session in every code block or script, and does not write self-contained html (without some insane perl hacks). Also you can’t collaborate in Org, everyone is on Rmarkdown these days.

Mixing in Evil

Of course, we want to use vim keybindings everywhere, so I have a little general code block that sets up a lot of the important code bindings. This sets all the nice polymode commands to the “,” key, which I don’t use for anything except major mode specific commands.

  (general-define-key
   :prefix ","
   :states '(normal visual)
   :keymaps 'polymode-mode-map
   "j" 'polymode-next-chunk
   "k" 'polymode-previous-chunk
   "i" 'polymode-insert-new-chunk
   "u" 'polymode-insert-new-chunk-code-only
   "U" 'polymode-insert-new-chunk-output-only
   "p" 'polymode-insert-new-plot
   "o" 'polymode-insert-yaml
   "d" 'polymode-kill-chunk
   "e" 'polymode-export
   "E" 'polymode-set-exporter
   "w" 'polymode-weave
   "W" 'polymode-set-weaver
   "$" 'polymode-show-process-buffer
   "n" 'polymode-eval-region-or-chunk
   "," 'polymode-eval-region-or-chunk
   "N" 'polymode-eval-buffer
   "1" 'polymode-eval-buffer-from-beg-to-point
   "0" 'polymode-eval-buffer-from-point-to-end)

  1. You can have as many minor modes as you like.

  2. including org-mode