Using ESS (Emacs)

I’m writing this in the middle of 2022. We have many options to use for writing R code. RStudio is well-established these days, but VS Code is gaining in popularity, and the San Francisco crowd is popularizing Jupyter. There are some worthwhile lesser-known options too, like RKWard and - for Windows users - Tinn-R.

It’s the middle of 2022 and in spite of everything in the previous paragraph, I still use Emacs for interactive R programming. I won’t bother to explain why because the folks that understand already use Emacs. Everyone else thinks it’s a crusty tool used by people that are too set in their ways to move to something modern.1

ESS has some default behaviors that drive me crazy. Since this is Emacs, they’re easily fixed.

The first is the application of Emacs Lisp commenting style. Depending on how many # your comment starts with, the indentation could be in a variety of places. I most commonly use a single # for my comments, and that is indented to the 40th column. Others might like it, but I find it weird and annoying. ## is indented differently. It’s an easy fix. I drop the following into my init file:

(setq ess-indent-with-fancy-comments nil)

The second design mistake was to make ESS incompatible with cua-mode. It’s very common to turn on cua-mode, because that gives you standard keyboard shortcuts (Ctrl-c to copy, etc.) rather than the somewhat unusual Emacs defaults. The incompatibility with ESS is due to the choice of Ctrl-Enter to evaluate the current line of R code. That’s the beauty of interactive development with R, and it’ll only work if it’s convenient. The problem is that cua-mode defines its own binding for Ctrl-Enter. This too is easily fixed. Here’s what you’ll find inside my init file:

(defun cua-set-rectangle-mark ()
  (interactive)
  (ess-eval-line-and-step))

Since I don’t use cua-mode for its cua-set-rectangle-mark functionality (and if I’m being honest, I have no idea what it is), I redefine that function. This will never be an issue for me because I would only ever call that function by mistake. If you want that behavior, you’ll need to come up with a more elaborate solution.

The default indentation can seem screwy at first. You just have to get used to getting the indentation you want after you hit Enter. For some reason, it fixes the indentation of the current line after you’ve moved to the next.

Something else that can be annoying when you start is moving between your program and the terminal. I start an R process by hitting Alt-x and then running the command R. That splits the screen in two. The R program is on the left and the R terminal is on the right. It can be a bit sucky moving between the two, because you have to move to the end of the current terminal input line. You can’t even move to the start of the line. It has to the end of that line. You can use Ctrl-c Ctrl-z to move between the two. When moving to the terminal, it will always move the cursor to the correct place. Once there, you can scroll through the history of your commands using Alt-p (previous) and Alt-n (next).

I usually put additional things in my init file, but they change considerably over time, as they’re specific to the things I’m doing. I might define a function like rp to open the file I’m working on for my current research project. Or I’ll set up a snippet of text to insert. Various things like that. This is where Emacs really shines, as it lets me customize my workflow so precisely with a few lines of code in the init file, and it’s an important part of why I find the other solutions less desirable. After getting used to such easy, powerful customization options, it’s hard to move away.


  1. For the record, I use RStudio and Jupyter when teaching, and I use VS Code for other things. I use Emacs because it’s the better choice (a decision most offering an opinion on the matter are not in a position to make).↩︎