<?xml version="1.0"?>
<!DOCTYPE content [ <!ENTITY nbsp " "> ]>
<rdf:RDF xml:base="http://snarfed.org/rdf"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:dc="http://purl.org/dc/elements/1.1/">

<rdf:Description rdf:about="http://snarfed.org">
  <dc:title> snarfed.org  </dc:title>
  <dc:description> draw group stream of consciousness </dc:description>
  <dc:creator> Ryan Barrett &lt;snarfed at ryanb dot org&gt; </dc:creator>
  <dc:language> en </dc:language>
  <dc:format> text/html </dc:format>
  <dc:rights> Copyright 2002-2007 Ryan Barrett </dc:rights>
</rdf:Description>

<rdf:Description rdf:about="http://snarfed.org/space/why%20I%20don%27t%20run%20shells%20inside%20Emacs">
  <dc:title> why I don't run shells inside Emacs </dc:title>
  <dc:creator> Ryan Barrett &lt;snarfed at ryanb dot org&gt; </dc:creator>
  <dc:date> 2003-01-01T05:00:00Z </dc:date>
  <dc:language> en </dc:language>
  <dc:format> text/html </dc:format>
  <dc:rights> Copyright 2002-2007 Ryan Barrett </dc:rights>

  <content>
    <p><a href="http://rxvt.org/"><img src="/space/terminal.jpg" alt="terminal.jpg" title="" /></a><a href="http://tcsh.org/"><img src="/space/tcsh_oyster_catcher.jpg" alt="tcsh_oyster_catcher.jpg" title="" /></a><a href="http://gnu.org/software/emacs/"><img src="/space/gnu.jpg" alt="gnu.jpg" title="" /></a></p>

<p>This article details
my experience running shells inside <a href="http://gnu.org/software/emacs/">Emacs</a>. I
take a while to warm up, so if you're impatient, feel free to skip to the <a href="/space/why+I+don't+run+shells+inside+Emacs#pros_and_cons">pros
and cons</a>, the <a href="/space/why+I+don't+run+shells+inside+Emacs#settings">.emacs
settings</a>, or the <a href="/space/why+I+don't+run+shells+inside+Emacs#related">related
articles</a>.</p>

<p>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,
<a href="http://www.tcsh.org/">tcsh</a> inside <a href="http://rxvt.org/">rxvt</a>.</p>

<p>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: <em>copying without the mouse</em>.</p>

<p>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 <a href="http://gnu.org/software/emacs/">Emacs</a>,
<a href="http://iki.fi/tuomov/ion/">Ion</a>, <a href="http://www.washington.edu/pine/">Pine</a>,
<a href="http://gaim.sf.net">Gaim</a>, and <a href="http://getfirefox.com/">Firefox</a>'s blessed
<a href="http://www.mozilla.org/access/type-ahead/">Find As You Type</a>, I can do pretty
much everything with the keyboard. The only thing I <em>can't</em> do with the keyboard
is copy text from a terminal. And that irks me.</p>

<p>A voice in the back of my head had been nagging me about this for a while.
<em>Ryan, you can fix this,</em> it said, <em>and you know how.</em> It was right. I didn't
want to admit it, but I did know how, and it did too. <em>Why don't you try running
your shells inside Emacs?</em></p>

<p>I had a laundry list of reasons. Half of <a href="http://ryan.barrett.name/dotfiles/cshrc">my
.cshrc</a> would be usless. I'd forgo
<a href="http://www.caliban.org/ruby/acoc.shtml">acoc</a>'s wonderful colorized command
output. Emacs'
<a href="http://gnu.org/software/emacs/manual/html_node/Shell-Mode.html">shell-mode</a>
would never do history management as well as native tcsh. And I wouldn't get
that cool transparent background. :P</p>

<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. <em>You could fix
that, you know.</em> Sigh. I knew.</p>

<p>Finally, it got the better of me. I wrote <em>try emacs shell mode</em> on my todo
list, and a few days later, I tried it. <code>M-x shell</code> 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:</p>

<p><a name="pros_and_cons"></a></p>

<ul>
<li><p><strong>Copying with the keyboard.</strong> 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!</p></li>
<li><p><strong>Session management.</strong> 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 <em>at home</em>, over VPN, just by
connecting to my work Emacs!</p></li>
<li><p><strong>Tcsh integration.</strong> Emacs was surprisingly sociable with tcsh. It obeyed
<a href="http://ryan.barrett.name/dotfiles/cshrc">my .cshrc</a>, read and wrote its
command history to <code>~/.history</code>, and generally played nice.</p></li>
<li><p><strong>ANSI color codes.</strong> Wonder of wonders, Emacs could even display color
codes properly. Just do `M-x
<a href="http://www.gnu.org/software/emacs/manual/html_node/Shell-Options.html#index-shell_002dpushd_002ddunique-3323">ansi-color-for-comint-mode-on</a>`.</p></li>
<li><p><strong>Find-file-at-point.</strong> This handy little elisp function opens, in a new
Emacs buffer, the filename that your cursor is currently on. After an <code>ls</code>, if I
wanted to look at a file, I just moved up to it and hit <code>M-C-f</code> (bound to
<code>find-file-at-point</code>), and Emacs would open the file. Slick.</p></li>
</ul>

<p>It wasn't perfect, though. Here's what didn't work well:</p>

<ul>
<li><p><strong>Not a terminal.</strong> 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 <a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Term-Mode.html">Term
mode</a>,
which provides a full terminal, but that defeats the purpose of running inside
emacs.</p></li>
<li><p><strong>History.</strong> 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.</p></li>
<li><p><strong>Remote completion.</strong> 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 <a href="http://www.gnu.org/software/tramp/">TRAMP</a>, and
it worked, but it was unbearably, unusably slow. Sigh.</p></li>
<li><p><strong>Case-sensitive completion.</strong> File and directory tab completion is case
sensitive. It doesn't obey the completion-ignore-case variable. Boo.</p></li>
<li><p><strong>Slow color code parsing.</strong> My joy at finding <code>ansi-color-for-comint-mode-on</code>
turned to horror as soon as I did an <code>ls -l</code> in a large directory. Emacs' color
code parsing is dog slow. I could use <code>ansi-color-for-comint-mode-filter</code> to just
ignore the color codes, but I couldn't bear to go without them.</p></li>
</ul>

<p>So, you might ask, what was the verdict? The jury's still out. I'm currently
wrestling <a href="http://www.gnu.org/software/screen/">GNU screen</a> into submission,
since it also allows <a href="http://www.delorie.com/gnu/docs/screen/screen_73.html">keyboard navigation and
copy/paste</a> over shell
contents. So far, I've <a href="/space/synchronizing GNU screen's paste buffer and the X selection">synchronized its paste buffer and the X
selection</a>, and I've <a href="/space/Emacs keybindings in GNU screen's copy-scrollback mode">Emacs-ified its
copy-scrollback mode</a>. Stay tuned for
more!</p>

<p>Here's what I added to <a href="http://ryan.barrett.name/dotfiles/emacs">my .emacs</a> to
make shell-mode behave the way I wanted:</p>

<p><a name="settings"></a></p>

<div class='p-shadow'><pre><code>(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*")))
</code></pre></div>

<p><br class='clearing' /><a name="related"></a>
See also:</p>

<ul>
<li><a href="/space/synchronizing GNU screen's paste buffer and the X selection">synchronizing GNU screen's paste buffer and the X
selection</a></li>
<li><a href="/space/Emacs keybindings in GNU screen's copy-scrollback mode">Emacs keybindings in GNU screen's copy-scrollback mode</a></li>
<li><a href="/space/acoc.conf for context diffs">acoc.conf for context diffs</a></li>
<li><a href="/space/control arrow keys in rxvt, tcsh, and emacs">control arrow keys in rxvt, tcsh, and emacs</a></li>
<li><a href="/space/tcsh highlighting patch">tcsh highlighting patch</a></li>
<li><a href="/space/remove tcsh globbing in history search">remove tcsh globbing in history search</a></li>
<li><a href="/space/tcsh delete moves mark bug fix">tcsh delete moves mark bug fix</a></li>
<li><a href="/space/Emacs and remote X Windows">Emacs and remote X Windows</a></li>
<li><a href="/space/minimal .emacs for fast startup">minimal .emacs for fast startup</a></li>
<li><a href="/space/emacs keybindings with number keys">emacs keybindings with number keys</a></li>
<li><a href="/space/emacs keybindings in firefox">emacs keybindings in firefox</a></li>
<li><a href="/space/emacs X resources">emacs X resources</a></li>
<li><a href="/space/emacs page up page down">emacs page up page down</a></li>
</ul>

  </content>

  <rdf:Seq>

<rdf:li>
<rdf:Description rdf:about="#1149075188.0">
  <dc:source> http://snarfed.org/ </dc:source>
  <dc:title> why I don't run shells inside Emacs-1 </dc:title>
  <dc:creator> Guest </dc:creator>
  <dc:date> cmt_pubDate </dc:date>
  <dc:format> text/html </dc:format>

  <content>
    
Maybe TRAMP filename completion might be usable if you used the OpenSSH 4.0+ ControlMaster feature?<p class="paragraph"/> <i class="italic">- <span class="nobr"><a href="http://marc.abramowitz.info">Marc</a></span></i>

  </content>
</rdf:Description>
</rdf:li>

<rdf:li>
<rdf:Description rdf:about="#1149099809.0">
  <dc:source> http://snarfed.org/ </dc:source>
  <dc:title> why I don't run shells inside Emacs-2 </dc:title>
  <dc:creator> ryan </dc:creator>
  <dc:date> cmt_pubDate </dc:date>
  <dc:format> text/html </dc:format>

  <content>
    
fascinating! i'd never heard of
<span class="nobr"><a href="http://www.debian-administration.org/articles/290">ControlMaster</a></span>
before.<p class="paragraph"/>sadly, the machines i work on regularly all have openssh 3.7.x, and some of them would be bears to upgrade. still, i'll keep it in mind. thanks!

  </content>
</rdf:Description>
</rdf:li>

<rdf:li>
<rdf:Description rdf:about="#1150154513.0">
  <dc:source> http://snarfed.org/ </dc:source>
  <dc:title> why I don't run shells inside Emacs-3 </dc:title>
  <dc:creator> Guest </dc:creator>
  <dc:date> cmt_pubDate </dc:date>
  <dc:format> text/html </dc:format>

  <content>
    
If you're on Linux, you could try solving the secure access to remote filesystems problem on a different level that would take care of the filename completion: sshfs or shfs. I've only used the former; it worked perfectly with Emacs.
<span class="nobr"><a href="http://fuse.sourceforge.net/sshfs.html">&#104;ttp://fuse.sourceforge.net/sshfs.html</a></span>
<span class="nobr"><a href="http://shfs.sourceforge.net/faq.html">&#104;ttp://shfs.sourceforge.net/faq.html</a></span><p class="paragraph"/> <i class="italic">- <span class="nobr"><a href="http://www.mememachinego.com/">Zed</a></span></i>

  </content>
</rdf:Description>
</rdf:li>

<rdf:li>
<rdf:Description rdf:about="#1206373395.71">
  <dc:source> http://snarfed.org/ </dc:source>
  <dc:title> why I don't run shells inside Emacs </dc:title>
  <dc:creator> Gregory Collins </dc:creator>
  <dc:date> cmt_pubDate </dc:date>
  <dc:format> text/html </dc:format>

  <content>
    Have you tried eshell? (M-x eshell)
  </content>
</rdf:Description>
</rdf:li>

  </rdf:Seq>
</rdf:Description>
</rdf:RDF>
