dired and ansi-term: BFF
10 Jan 2015In the comments to my previous post on ansi-term, I discovered sane-term - a package that cycles though your terminals in Emacs, as well as implements some of the tips that I gave. While it's nice and all, and you should check it out if you're looking for something like that, it's not really for me. I will describe the system that I'm currently using below.
What is the best list length for cycling?
In my opinion, it's one or two. If it's one, you're not really cycling, if it's two, it's fine. Anything more than that causes stress, since you have to check each time if the outcome of the cycle ended up being the one that you wanted.
That's why I usually have only one *ansi-term*
active in my Emacs
session at all times. Here's how it looks like:
(defun terminal ()
"Switch to terminal. Launch if nonexistent."
(interactive)
(if (get-buffer "*ansi-term*")
(switch-to-buffer "*ansi-term*")
(ansi-term "/bin/bash"))
(get-buffer-process "*ansi-term*"))
(defalias 'tt 'terminal)
At one point, I had terminal
bound to C-t, until I found
a command even better suited for that binding, which was
smex. The actual terminal
command isn't bound right now, I just launch it from smex
on very
rare occasions.
How I launch terminal 95% of the time
From dired
of course. The shell's natural way of switching the
directory with cd
is extremely inefficient compared to dired
. So
any time I want to have a shell in a specific directory, I first
navigate there with dired
, sometimes combined with
ido-find-file
. Then I get my current *ansi-term*
and tell it to
switch to the current dired
buffer's directory with `
binding:
(define-key dired-mode-map (kbd "`") 'dired-open-term)
(defun dired-open-term ()
"Open an `ansi-term' that corresponds to current directory."
(interactive)
(let ((current-dir (dired-current-directory)))
(term-send-string
(terminal)
(if (file-remote-p current-dir)
(let ((v (tramp-dissect-file-name current-dir t)))
(format "ssh %s@%s\n"
(aref v 1) (aref v 2)))
(format "cd '%s'\n" current-dir)))))
I also have a similar eshell
setup, although I have yet to
comprehend why eshell
is great and am using *ansi-term*
most of the
time instead.
(define-key dired-mode-map (kbd "'")
(lambda ()
(interactive)
(eshell-cmd
(format "cd %s"
(expand-file-name
default-directory)))))
How I launch dired
100% of the time
With dired-jump
, of course. This command will examine your current
buffer's default-directory
and open a dired
buffer there. All you
need is:
(require 'dired-x)
The dired-jump
command will be bound automatically to C-x
C-j. I have it also bound to C-:, since that's more
convenient to press with my keyboard layout.
It's also better in the common situation when I want to jump to a
dired
buffer from *ansi-term*
. In that situation, C-x
C-j will not work by default, and will call term-line-mode
instead. But it will work once you are in term-line-mode
. You can
go back to the default term-char-mode
with C-x C-k. To
avoid this nonsense, just bind dired-jump
to some binding that's
convenient for you and works from *ansi-term*
.
What I do when I need more than one terminal
Then I just name one: since the default one is supposed to be named
*ansi-term*
, if I create one named e.g. *jekyll*
, it will be
ignored by dired-open-term
. This is exactly what I want, since I just
create named terminals for long running processes like jekyll serve
.
And I can switch to the named terminals with just ido-switch-buffer
.
Here is the very simple code:
(defun named-term (name)
(interactive "sName: ")
(ansi-term "/bin/bash" name))