Hongchao Liu thinks that emacs is the “2D command-line interface”. Sure enough, I could do many things with the 2D command-line interface. However, there are still many things I prefer to use the 1D command-line interface, i.e. the Linux shell. Hate to admit, but I prefer to manage files with the Linux command line than the sometimes-cumbersome dired. “But that can well be my prejudice.”™
For a long time, I needed to find a good terminal emulator and settled with Kitty. But I use the boring gnome-terminal now.
One can also run shell inside emacs. Just talking about built-in ones, there are shell
, term
, ansi-term
, and eshell
. Advanced emacs users tend to use eshell, probably because it can execute both shell and emacs lisp.
But I am not very excited by mixing shell and emacs lisp 1. Instead, I use vterm by Lukas Fürmetz et al. Because it is fast, no-BS, highly compatible, and exactly as advertised: “Using vterm is like using Gnome Terminal inside Emacs”. Unlike eshell, vterm respects my .zshrc configuration file. Some tricky interactive shell programs such as top
and less
work, even hipster favorites such as htop
and bat
…
Installation was not straightforward. But with the currtent emacs 28, it is now super easy.
(use-package vterm)
I have two bullet points on how to use vterm more joyfully.
Running vterm inside emacs, instead of a standalone terminal emulator, is usually for copying and pasteing (or using the emacs terminology: killing and yanking) text from and to other buffers. For pasting yanking text to vterm, I recommand making C-y
(the usual yank
key combination) map to vterm-yank
, i.e.
(use-package vterm
:bind
(:map
vterm-mode-map
("C-y" . vterm-yank))
)
For copying killing text from vterm, it is a bit complicated. First, it is really 1D. And the cursor can really walk in one direction. The up and down arrow keys are used to look at command history in a shell. The orthodox emacs combinations, C-p
(previous-line
) and C-n
(next-line
) also functions as arrow keys.
In order to kill text from vterm, one needs to switch on copy mode by pressing M-x vterm-copy-mode
(or C-c C-t
) to enable “vterm-copy-mode”. Then the cursor can be moved in two dimensions and the usual way of killing text works. After that, just M-x vterm-copy-mode
once again to go back to the default mode, i.e. “vterm-copy-mode” disabled.
Another issue is that some shell programs use the same key combinations of emacs. For whatever reasons, you might need to run nano
under vterm sometimes 2. You might find that you can’t quit nano
by pressing C-x
. It is because emacs intercepts your C-x
and thinks: “um… maybe you still want to press something, e.g. e
.”
There are actually two solutions. First solution is to use the crazy array of vterm-send-*
commands. In this example, you can press M-x vterm-send-C-x
. However, my preferred solution is to use the command vterm-send-next-key
, i.e. M-x vterm-send-next-key
and then C-x
.
But it can get tedious very quickly. I map C-q
to the command vterm-send-next-key
(I will talk about C-q
later, I promise), i.e.
(use-package vterm
:bind
(:map
vterm-mode-map
("C-y" . vterm-yank)
("C-q" . vterm-send-next-key))
)
Therefore, I can just press C-q C-x
in this situation to quit. But, it can be more informative. I don’t like that vterm-send-next-key
doesn’t give me any visual clue that it is activated. I write myself a little command in emacs lisp.
(use-package vterm
:init
(defun vterm-send-next-key-verbose ()
(interactive)
(progn
(message "vterm-send-next-key enabled.")
(vterm-send-next-key)
))
:bind
(:map
vterm-mode-map
("C-y" . vterm-yank)
("C-q" . vterm-send-next-key-verbose))
)
After pressing C-q
, I know the next key will not be captured by emacs but capturd by the program running inside vterm.
After talking about the terminal, I will talk about how / why I use the GUI version of emacs but not the terminal version. Also, how I fix some quirks.
Deep-learnest’s remark on Mastodon: “I recommend M-x shell
for sessions where you need to capture large outputs, or for long-lived interactive sessions in the shell. The ability to have an infinite log of easily accessible text that you can navigate in the regular emacs ways is very powerful and eventually grows on you. I only use vterm for applications that need a proper terminal (htop, btop, nvtop, …), but for everything else I much prefer the feeling of M-x shell
.”
And yes, shell
is better in this case because the cursor is not walking in 1D (as vterm) but in 2D. Yanking and killing work the same way as a regular buffer.
Thank you, Deep-learnest!