Running Shells in Emacs: An Overview

To use Emacs effectively, you must learn to use all that Emacs has to offer. One of Emacs’s strongest selling-points is its shell integration and terminal emulation. If you come from other editors or IDEs you’re probably using an external terminal window (like xterm), a terminal multiplexer (like GNU Screen) or console window (in Windows) and switching back and forth. But there’s a better way…

If you use Emacs as your shell you will have all the functionality that Emacs provides plus you get almost all of the advantages provided by the shell itself, but built into Emacs. This article is only a quick overview of all the shells: I plan on tackling each one, in-depth, later on.

All external, interactive shells in Emacs are derived from something called comint-mode. comint-mode introduces low-level functions for dealing with interactive shells that require user input, a history ring, and so on. Shells like M-x shell and M-x python-shell inherit from comint mode.

Emacs provides you with three shell ways of interacting with a shell (like bash or zsh), and these shells are often called inferior shells. Confusingly, there is a shell (called “shell” or “shell mode”) which, by the nature of how it works, is also an inferior shell. Yeah, confusing…

The Inferior Shell (“Shell Mode”)

The inferior shell is what you get when you run M-x shell. It is a wrapper around your default shell. It is governed by explicit-shell-file-name, the ESHELL environment variable or shell-file-name, in that order.

NOTE: If you change the default shell, you must create a new variable called explicit-<filename>-args where filename is obviously the filename of the new shell – and the variable istself should contain a list of arguments. If you’re on Windows, make sure you include the extension!

Here’s a quick example of how to get bash working in Windows:

(setq explicit-shell-file-name "C:/path/to/bash.exe")
(setq shell-file-name "bash")
(setq explicit-bash.exe-args '("--noediting" "--login" "-i"))
(setenv "SHELL" shell-file-name)
(add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m)

The example above is just a quick-and-dirty example. There’s a better, and more complete, way of getting Cygwin bash to work in Windows.

All shell does is redirect the input and output to Emacs, and that means interactive console programs (like top, ssh, midnight commander, etc.) won’t work properly.

This limitation can be a problem as, traditionally, some UNIX apps behave differently (by suppressing the prompt for instance) if they detect their input and output is redirected. To get around this, some programs will let you force it to run in interactive mode.

If you’re on Windows it is the simplest thing to use out-of-the-box, as, even without interactive support, it is vastly superior to the standard command prompt. In fact, it is my preferred shell as I do a lot of Windows development and need a “native” shell to ensure my stuff works correctly on machines that may not have Cygwin set up.

I replace the redundant “help” binding on f1 with shell:

(global-set-key [f1] 'shell)

Terminal Emulator

The Emacs terminal emulator is exactly that; it emulates the VT100-style ANSI escape codes, just like xterm or rxvt. Emacs’s emulator isn’t complete or perfect, so some interactive programs won’t work properly, but most things like top and ssh will. To run the terminal emulator, type M-x term or M-x ansi-term (for full ANSI support). I recommend the latter.

Due to the way terminal emulators work, most of Emacs’s common keybindings are reserved for the subshell itself; to get around this you can switch between line mode and char mode. In line mode the terminal buffer will behave much like shell mode and normal Emacs buffers. In char mode each character is sent directly to the underlying inferior shell without preprocessing by Emacs.

To switch between the two modes type C-c C-j to switch to line mode, and C-c C-k to switch to char mode. To save you from having to switch between modes for one-off commands you can use the alias C-c char which translates into C-x char.

MS Windows: The terminal emulator won’t work on Windows out of the box.

To summarize, Emacs’s Terminal Emulator is a more than adequate emulator and it is flexible and feature-rich enough to run even complex interactive programs like vim!

The Emacs Shell

Emacs comes with its own shell (as in, like bash or zsh) written in entirely in Emacs-Lisp. The shell, named eshell, is a feature-rich replacement for your standard-fare shells like bash with the added bonus of working on any platform Emacs runs on. This is especially useful if you’re on Windows but crave a Linux-like environment. It’s heavily inspired by the likes of bash, and has gone to some lengths to keep the syntax familiar. To invoke it, run M-x eshell.

As the shell is written entirely in elisp, that means you can also extend it with elisp; and the shell has provisions for inlining elisp and using the results as part of your commands. EShell is clever enough to redirect certain commands that Emacs itself offers, such as man, grep and so on. Very useful.

Despite the many advantages Eshell brings to the table, it is not a shoe-in replacement for a terminal emulator running bash.

EShell is a great shell but woefully underdocumented; therefore, I’ve written a guide to mastering Eshell.

Conclusion

Three excellent shell choices, all with their own advantages and disadvantages. If you’re looking for a faithful emulator, then ansi-term is the choice for you; if you are more interested in a dumb terminal that behaves like an Emacs buffer then use shell; if you want something fancier that you can tweak and customize like Emacs itself, eshell may be the right shell for you.

Whatever the case, the shells above should eliminate almost all external terminal emulators for all but the most complex interactive programs out there.