This article details my experience running shells inside Emacs. I take a while to warm up, so if you're impatient, feel free to skip to the pros and cons, the .emacs settings, or the related articles.
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 inside rxvt.
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, Ion, Pine, Gaim, and Firefox's blessed Find As You Type, 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 would be usless. I'd forgo acoc's wonderful colorized command output. Emacs' shell-mode 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, 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`.
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 hitM-C-f(bound tofind-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, 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, 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-onturned to horror as soon as I did anls -lin a large directory. Emacs' color code parsing is dog slow. I could useansi-color-for-comint-mode-filterto 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 into submission, since it also allows keyboard navigation and copy/paste over shell contents. So far, I've synchronized its paste buffer and the X selection, and I've Emacs-ified its copy-scrollback mode. Stay tuned for more!
Here's what I added to my .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*")))
- synchronizing GNU screen's paste buffer and the X selection
- Emacs keybindings in GNU screen's copy-scrollback mode
- acoc.conf for context diffs
- control arrow keys in rxvt, tcsh, and emacs
- tcsh highlighting patch
- remove tcsh globbing in history search
- tcsh delete moves mark bug fix
- Emacs and remote X Windows
- minimal .emacs for fast startup
- emacs keybindings with number keys
- emacs keybindings in firefox
- emacs X resources
- emacs page up page down


