Werden wir Helden für einen Tag

Home | About | Archive

Advent of emacs #18: How I do R package development in emacs

Posted on Dec 18, 2022 by Chung-hong Chan

ESS is great. ESS’s integration with the R package devtools makes it a greater tool. By default, the integration isn’t activated. One needs to explicitly activate ess-r-package.

(use-package ess
  (require 'ess-r-mode)
  (require 'ess-r-package))

Now, I am ready to create my newest R package: M-x ess-r-devtools-create-package

Well, I’ve created an R package! There are many operations one can do, just run M-x ess-r-devtools-execute-command.


During the package development cycle, I need to do the following very frequently (actually, I wanted to say extremely frequently to show that I am super prudent): run the unit tests, check the package, refresh the documentation, and above all, load the package.

Actually, all of the above have their own emacs command: ess-r-devtools-test-package, ess-r-devtools-check-package 1, ess-r-devtools-document-package, ess-r-devtools-load-package. They have key bindings too, but I can never remember them. At the same time, these commands are too long, even with helm it is difficult to find them quickly. My strategy is to create some aliases:

(defalias 'lp 'ess-r-devtools-load-package)
(defalias 'lt 'ess-r-devtools-test-package)
(defalias 'lc 'ess-r-devtools-check-package)
(defalias 'ld 'ess-r-devtools-document-package)

So that I can run them pretty easily, e.g. M-x lp.


The default ess-r-package-auto-enable-namespaced-evaluation as t is kind of annoying. By default, after I M-x lp a package foo containing a function bar; I can’t directly run bar(). Instead, I need to explicitly run foo::bar(). This isn’t the default behavior of many R IDEs, e.g. RStudio.

I set the mentioned variable to nil instead. BTW, I did that multiple times already, maybe it deserves an explanation. A Boolean value in Emacs lisp has only t and nil.

(setq ess-r-package-auto-enable-namespaced-evaluation nil)

By doing so, all code is evaluated in the global namespace. Using the above example, I can directly run bar() after M-x lp.

Previewing Rd

ESS actually has a neat suite of commands to handle “Rd” (R Documentation) files. But I believe no one would want to edit “Rd” files manually (It probably is handled by roxygen2 automatically now). A command that is quite helpful to dealing with this is Rd-preview-help (default to C-c C-p).

flycheck and eglot

By default, ESS enables flycheck (on the fly syntax checking), but you’ll need to install the R package lintr.

ESS makes some amendments to the default linter (e.g. the 80 character rule is not checked), which I found very reasonable.

The newest kids on the block are the whole LSP craze and eglot. The next version of emacs (version 29) will have eglot built-in. When the R package languageserver is installed and eglot is enabled, I got some full-fledged IDE experience.

To be honest, I am a bit overwhelmed by the amount of information, especially the hover-on help system. I don’t want to switch it on by default. But I agree that xref-find-defintion (jump to the definition of the symbol) is quite useful. As it is new, I haven’t invested a lot of time customizing it. “But that can well be my prejudice.”™

  1. there are even ess-r-rhub-check-package 

Powered by Jekyll and profdr theme