Jonathan Lam

Core Developer @ Hudson River Trading


Blog

First thoughts on Emacs

On 5/23/2021, 5:09:53 PM

Return to blog


I've been a casual ViM user for some time now (6 years?), and it's a great experience. I love to work in the terminal and I love to type, and it worked fast on my first laptop when full IDEs were too painfully slow. The command mode and the movement keys are quickly intuitive, and you only have to learn a few major commands to be working efficiently. Of course, IDEs and other software support ViM-like editing and navigation1.

But I have a need to use Scheme Lisp to study SICP, and it (like many other editors) doesn't historically2 3 have advanced support for Lisp. The go-to environment for many Lisp-ers, in the longstanding tradition of GNU and Lisp, is Emacs. It has a popular development environment for CL called SLIME: the Superior Lisp Interaction Mode for Emacs.

General reactions

My first reaction to Emacs is that it opens in its own window like gvim, even if you call it from a terminal emulator. You can run it in a terminal emulator with the no-window command: emacs -nw, but this may cause some problems4.

My second opinion is captured by Randall Munroe perfectly:

Obligatory xkcd

Seriously, there are a lot of shortcuts5. Some other notes:

For the complete beginner

The most important resource for the beginner is the tutorial. Luckily, Emacs has a lot of help resources. On first opening Emacs, there's a link to the tutorial, which feels very similar to the vimtutor command. A few notes for the complete beginner:

Extensibility with elisp

Like every good ol' hackable piece of software, Emacs is built upon its own customization DSL, Emacs Lisp (elisp)! No other piece of software comes close with such a complete scripting language dedicated for its customization -- vimscript and other languages with the same purpose feel awfully narrow-minded in comparison. You can even write standalone scripts in elisp, as it is a regular Lisp.7

I hinted at the existence of elisp before when mentioning that every keyboard shortcut is mapped to a function in elisp. In this way, Emacs just feels like a program written in elisp, and the behavior of the program can be changed and extended by changing or adding more elisp. Due to the interpreted nature of Lisp, it is trivial to add new code to a running program, and thus to add new packages or modify elisp code on the fly.

Many elisp functions can be called from the editor directly, either by a keyboard shortcut or equivalently by using M-x [command]8. (Recall that you can find the function corresponding to a keyboard shortcut and vice versa using C-h c [keycombo] and C-h w [command], respectively.) There are some functions (e.g., helper functions) that cannot be called directly from the editor; functions that can be called directly from the editor have to be declared interactive. There are also many variables that can be used to customize features and packages.

One place you'll probably end up writing elisp code is the ~/.emacs file, which is run on Emacs startup. Other elisp code can be found in Emacs and package files with the .el extension that are located in the load-path variable.

The package experience

The packages are great. Installing these few packages really makes me feel the extensibility of Emacs.

Before mentioning any of these packages, I'd first like to make a note about modes in Emacs. When editing a buffer (file), you always have a major mode equipped, as well as any number of minor modes. The major mode dictates the general type of the buffer -- for example, there are major modes for file types like Lisp, LaTeX, Term (for a terminal buffer created with M-x term), and a generic catchall major mode called Fundamental. A minor mode implements a feature that can be toggled on/off independently of other major and minor modes. Examples include the fci-mode (for a column indicator similar to ViM's colorcolumn) and linum-mode (for line numbers). The major and a subset of the minor modes9 are shown in the modeline at the bottom of the Emacs window (just above the minibuffer). The mode string is indicated in parentheses, and may look something like:

(Scheme Chicken Paredit/A)
(Lisp Paredit adoc SLIME)
(Fundamental)

The most obvious effect of installing a new package is that it introduces new major and/or minor modes. Below I'll list the few that I got started with. My particular use case was that I wanted a development environment for Scheme (for SICP) and CL (for Practical Common Lisp).

The other thing to know before getting started with packages in Emacs is how to get them. Emacs supports ELPA (Emacs Lisp Package Archive) packages, which usually come from two major repositories: GnuELPA (enabled by default) and MELPA (has to be added manually). All of the packages listed below come from MELPA. To add MELPA to the list of package reporitories, you'll want to add the following to your Emacs config file (~/.emacs):

(require 'package)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/"))

With the config file buffer still open, do M-x ev-b to run the file (eval buffer), M-x package-refresh-contents to fetch the package lists from the MELPA repository, and M-x package-install RET [package] RET to install a package.

SLIME and geiser

SLIME -- the Superior Lisp Interaction Mode for Emacs -- lives up to its (flamboyant) name. It introduces a REPL major mode and several minor modes that makes Emacs really feel like an IDE rather than just a text editor: you can easily switch between the REPL and the buffer, autodoc symbols as you type them, evaluate the current definition under your cursor, etc. It feels really slick and I haven't encountered any bugs yet.

geiser is the Scheme equivalent of SLIME. Like SLIME, it supports several variants of the Scheme (Chez, Chibi, Chicken, Gambit, Gauche, Guile, Kawa, MIT, Racket, and Sktlos). I was using Chez and my experience was mixed -- there seems to be problems with using Geiser's compliation functions for latest version of Chez (9.5.4) so I had to install 9.4. Even then, there are still some problems when compiling a script after entering debug mode, but this goes away after restarting the REPL. It's manageable at least. The latest versions of Chicken Scheme and Guile Scheme, which I also had installed on my computer, seemed to work OOTB without a problem, but I didn't do anything in depth outside of with Chez.

ParEdit

You can't do be efficient in Lisp without a good way to manage your parens. ParEdit introduces a minor mode for "performing structured editing of S-expression data." This means that your parens will always10 be balanced! As opposed to the sloppy method of having dangling, broken parens as you work, this method is defensive and also allows you to perform "structural navigation" through sexprs, such as moving forward or backward over one complete sexpr. (It also works on square and curly braces, quotes, and even has the paredit-comment-dwim smart commenting tool!)

It really feels like magic once you start using it, and the associated terminology ("slurpage and barfage") feels magical too.

Magit

I've used this package for one day and it already feels like a Magical Git. Considering how much I already love the git CLI, I was surprised I could love something more. When you enter the Magit major mode, my gut reaction is it feels ViM-like with its single letter commands (e.g., c for commit or s to stage), and yet it's able to show you multiple buffers easily and neatly using ediff, which has all of Emacs's navigational and buffer-management utilities. Now I can do git status even more frequently than I could before simply by opening the magit buffer.

Closing remarks

One thing I didn't mention at all was the Emacs-ViM rivalry. It didn't come up at all from Internet searches when I was learning Emacs commands. On the contrary, I didn't see any mention of ViM except when explicitly searching for Emacs equivalents of certain ViM commands (perhaps this is closer to the nature of the rivalry?). There is a ViM emulation mode for Emacs called Evil, whose name is a suggestive of the rivalry but the purpose indicates that ViM has some goods that Emacs can use. Converely, as mentioned in an earlier footnote, there have also been attempts to bring some of Emacs to ViM, such as the ports of SLIME. The rivalry seems good-natured at the very least.

Even with ViM, which is relatively simple, I was still learning new shortcuts or tricks every now and then for six years. With Emacs, I think I can count on learning how to become more productive for an entire lifetime. Moreover, many actions are still uncomfortable today but I feel somewhat confident that with some time, this discomfort can all be scripted away in elisp or shortcuts can be found through practice.

It's early to tell, but I think I'll really like Emacs. It's been a steep learning curve, and I expect there to continue to be a steep learning curve, but the number of cool and efficiency-boosting features in this little piece of software is incredible. I think the coolest thing is to be able to have major modes for non-text buffers (such as Magit or the SLIME REPL), which allows you to interact with and navigate many different programs as if they were files.11 Details like shift-selection and image support, which ViM misses, makes Emacs feel like it lies on the boundary between text editor and full-blown IDE.


Footnotes

1. Most IDEs have plugins for ViM-mode editing; the hjkl-navigation system works on Google Drive and jk-scrolling is common in system utilities like less or man; people have created many applications, like qutebrowser with ViM-bindings

2. In this world of abundant software, people have of course filled the void; there are ViM equivalents of many of the SLIME environment (see slimv and vlime, but I wanted to try my hand at the acclaimed SLIME (and Emacs in general).

3. The only dedicated Lisp editor I know of is DrRacket for Racket and Schemes

4. In particular, Emac's key bindings may overlap with that of the terminal emulator. I noticed this immediately with C-h, which is the prefix for all of the help commands in Emacs, but is linked to the Backspace character in xterm. You can make make C-h (Bksp) act as a regular backspace using M-x normal-erase-is-backspace-mode, but then you lose the backspace ability. There's probably another way to get around this (fiddling with your terminal settings to unassociate Backspace and C-h?) but I haven't found out yet. YMMV -- I notice that I don't have this problem in xfce4-terminal (another GUI-mode terminal emulator) or in the virtual terminals (the text-mode terminals Ctrl+Alt+F1 through Ctrl+Alt+F6). I figure it's easier to avoid the trouble and use the dedicated Emacs window.

5. Two fun commands I discovered while writing this post are M-x eww and M-x m. You know, when you want to send your code as mail or open Stack Overflow in Emacs. Eww can even display images!

6. As far as I know, without explicitly mapping the command to some key combination.

7. Some popular IDEs do allow for extensions via plugins, such as Atom (JS) and JetBrains IDEs (Kotlin). Emacs still has some leg up just because of how deeply elisp is integrated and how much can be customized, and because Lisp allows updating elisp code while emacs is running. However, the enormous community and industry support for plugins in these more mainstream editors makes them better to get more efficient in a short amount of time.

8. When you press M-x, the cursor appears in an area called the minibuffer at the bottom of the Emacs window, right underneath the modeline.

9. Since there are usually many minor modes enabled by default, many are hidden, such as fci-mode and linum-mode. Only "major" minor modes are shown, i.e., the ones you install via packages.

10. Most commands when paredit is enabled won't let you break the balanced-ness of your parens, kill-region and quoted-insert can either break or fix your parens while in paredit mode.

11. Perhaps this is another manifestation of the "everything is a file" from Unix philosophy?


© Copyright 2023 Jonathan Lam