why I don't run shells inside Emacs
[](http://rxvt.org/)[](http://tcsh.org/)[](http://gnu.org/software/emacs/)
This article details
my experience running shells inside [Emacs](http://gnu.org/software/emacs/). I
take a while to warm up, so if you're impatient, feel free to skip to the [pros
and cons](/space/why+I+don't+run+shells+inside+Emacs#pros_and_cons), the [.emacs
settings](/space/why+I+don't+run+shells+inside+Emacs#settings), or the [related
articles](/space/why+I+don't+run+shells+inside+Emacs#related).
When I'm working, I pretty much live inside Emacs. It's my IDE, debugger, text
editor, email composer, spreadsheet, file manager, and all-around scratch pad.
The only other app that's as ubiquitous in my work routine is my shell,
[tcsh](http://www.tcsh.org/) inside [rxvt](http://rxvt.org/).
I've customized the hell out of both Emacs and tcsh to make them work the way I
want. I have Emacs whipped into shape, and tcsh too, mostly, except for one
thing: _copying without the mouse_.
I hate the mouse. It's good for some things, but not my work. Switching between
the mouse and the keyboard wreaks havoc on my muscle memory and fine-motor flow.
Thanks to [Emacs](http://gnu.org/software/emacs/),
[Ion](http://iki.fi/tuomov/ion/), [Pine](http://www.washington.edu/pine/),
[Gaim](http://gaim.sf.net), and [Firefox](http://getfirefox.com/)'s blessed
[Find As You Type](http://www.mozilla.org/access/type-ahead/), I can do pretty
much everything with the keyboard. The only thing I _can't_ do with the keyboard
is copy text from a terminal. And that irks me.
A voice in the back of my head had been nagging me about this for a while.
_Ryan, you can fix this,_ it said, _and you know how._ It was right. I didn't
want to admit it, but I did know how, and it did too. _Why don't you try running
your shells inside Emacs?_
I had a laundry list of reasons. Half of [my
.cshrc](http://ryan.barrett.name/dotfiles/cshrc) would be usless. I'd forgo
[acoc](http://www.caliban.org/ruby/acoc.shtml)'s wonderful colorized command
output. Emacs'
[shell-mode](http://gnu.org/software/emacs/manual/html_node/Shell-Mode.html)
would never do history management as well as native tcsh. And I wouldn't get
that cool transparent background. :P
The voice in the back of my head didn't go away, though. Every time I reached
for the mouse to copy something out of a terminal, it piped up. _You could fix
that, you know._ Sigh. I knew.
Finally, it got the better of me. I wrote _try emacs shell mode_ on my todo
list, and a few days later, I tried it. `M-x shell` was all it took, and it worked
surprisingly well. What's more, most of my reasons for avoiding it were
unfounded. Here's what worked well:
* **Copying with the keyboard.** This goes without saying. What's more, all of
my Emacs muscle memory for navigating and searching now applied to the entire
contents of my shell!
* **Session management.** All of my shells were at my fingertips, regardless
of which Emacs frame I was currently in. No more context switching into a
different Ion frame on a different virtual desktop just to check on a command.
Even better, I could continue using my work shells _at home_, over VPN, just by
connecting to my work Emacs!
* **Tcsh integration.** Emacs was surprisingly sociable with tcsh. It obeyed
[my .cshrc](http://ryan.barrett.name/dotfiles/cshrc), read and wrote its
command history to `~/.history`, and generally played nice.
* **ANSI color codes.** Wonder of wonders, Emacs could even display color
codes properly. Just do `M-x
[ansi-color-for-comint-mode-on](http://www.gnu.org/software/emacs/manual/html_node/Shell-Options.html#index-shell_002dpushd_002ddunique-3323)`.
* **Find-file-at-point.** This handy little elisp function opens, in a new
Emacs buffer, the filename that your cursor is currently on. After an `ls`, if I
wanted to look at a file, I just moved up to it and hit `M-C-f` (bound to
`find-file-at-point`), and Emacs would open the file. Slick.
It wasn't perfect, though. Here's what didn't work well:
* **Not a terminal.** I gained keyboard navigation at the expense of having
a true terminal emulator. I couldn't run any app that needed anything more
than a dumb terminal - Pine, BitTorrent, less, and others. I could use [Term
mode](http://www.gnu.org/software/emacs/manual/html_node/emacs/Term-Mode.html),
which provides a full terminal, but that defeats the purpose of running inside
emacs.
* **History.** As I suspected, command history wasn't quite as good as stock
tcsh. It worked ok for history in the current shell's session, but I didn't have
access to history from previous sessions.
* **Remote completion.** Emacs could tab-complete local, files and
directories, but as soon as I sshed to another machine, it was helpless. OK,
that's not quite true...I tried [TRAMP](http://www.gnu.org/software/tramp/), and
it worked, but it was unbearably, unusably slow. Sigh.
* **Case-sensitive completion.** File and directory tab completion is case
sensitive. It doesn't obey the completion-ignore-case variable. Boo.
* **Slow color code parsing.** My joy at finding `ansi-color-for-comint-mode-on`
turned to horror as soon as I did an `ls -l` in a large directory. Emacs' color
code parsing is dog slow. I could use `ansi-color-for-comint-mode-filter` to just
ignore the color codes, but I couldn't bear to go without them.
So, you might ask, what was the verdict? The jury's still out. I'm currently
wrestling [GNU screen](http://www.gnu.org/software/screen/) into submission,
since it also allows [keyboard navigation and
copy/paste](http://www.delorie.com/gnu/docs/screen/screen_73.html) over shell
contents. So far, I've [synchronized its paste buffer and the X
selection](/space/synchronizing GNU screen's paste buffer and the X selection), and I've [Emacs-ified its
copy-scrollback mode](/space/Emacs keybindings in GNU screen's copy-scrollback mode). Stay tuned for
more!
Here's what I added to [my .emacs](http://ryan.barrett.name/dotfiles/emacs) to
make shell-mode behave the way I wanted:
(custom-set-variables
'(comint-scroll-to-bottom-on-input t) ; always insert at the bottom
'(comint-scroll-to-bottom-on-output t) ; always add output at the bottom
'(comint-scroll-show-maximum-output t) ; scroll to show max possible output
'(comint-completion-autolist t) ; show completion list when ambiguous
'(comint-input-ignoredups t) ; no duplicates in command history
'(comint-completion-addsuffix t) ; insert space/slash after file completion
)
; interpret and use ansi color codes in shell output windows
(ansi-color-for-comint-mode-on)
; make completion buffers disappear after 3 seconds.
(add-hook 'completion-setup-hook
(lambda () (run-at-time 3 nil
(lambda () (delete-windows-on "*Completions*")))))
;; run a few shells.
(shell "*shell5*")
(shell "*shell6*")
(shell "*shell7*")
; C-5, 6, 7 to switch to shells
(global-set-key [(control 5)]
(lambda () (interactive) (switch-to-buffer "*shell5*")))
(global-set-key [(control 6)]
(lambda () (interactive) (switch-to-buffer "*shell6*")))
(global-set-key [(control 7)]
(lambda () (interactive) (switch-to-buffer "*shell7*")))
See also:
* [synchronizing GNU screen's paste buffer and the X
selection](/space/synchronizing GNU screen's paste buffer and the X selection)
* [Emacs keybindings in GNU screen's copy-scrollback mode](/space/Emacs keybindings in GNU screen's copy-scrollback mode)
* [acoc.conf for context diffs](/space/acoc.conf for context diffs)
* [control arrow keys in rxvt, tcsh, and emacs](/space/control arrow keys in rxvt, tcsh, and emacs)
* [tcsh highlighting patch](/space/tcsh highlighting patch)
* [remove tcsh globbing in history search](/space/remove tcsh globbing in history search)
* [tcsh delete moves mark bug fix](/space/tcsh delete moves mark bug fix)
* [Emacs and remote X Windows](/space/Emacs and remote X Windows)
* [minimal .emacs for fast startup](/space/minimal .emacs for fast startup)
* [emacs keybindings with number keys](/space/emacs keybindings with number keys)
* [emacs keybindings in firefox](/space/emacs keybindings in firefox)
* [emacs X resources](/space/emacs X resources)
* [emacs page up page down](/space/emacs page up page down)