- Watch the video on YouTube!
- Check out the final code on GitHub
- Episode 9 of the Emacs From Scratch series
¶term-mode
(use-package term :config (setq explicit-shell-file-name "bash") ;;(setq explicit-zsh-args '()) (setq term-prompt-regexp "^[^#$%>\n]*[#$%>] *"))
C-c C-p
/C-c C-n
- go back and forward in the buffer’s prompts (also[[
and]]
with evil-mode)C-c C-k
- Enter char-modeC-c C-j
- Return to line-mode- If you have
evil-collection
installed,term-mode
will enter char mode when you use Evil’s Insert mode - Caveat - editing the input line with Evil motions doesn’t work
NOTE: term-mode doesn’t work on Windows: “Spawning child process: invalid argument”
¶For better color support
Make sure the tic
program is available on your machine (could be part of ncurses
package).
(use-package eterm-256color :hook (term-mode . eterm-256color-mode))
echo "Hello System Crafters!" | cowsay | lolcat -h 0.7
¶ansi-term
ansi-term
is a specialization of term-mode.
Minor differences:
- C-x is prefix key instead of C-c
- Buffers are managed slightly differently
Same caveats for Windows still apply.
¶vterm (emacs-libvterm)
vterm on GitHub
NOTE: This one needs to compile a native library, make sure to install its dependencies!
Differences to term
:
- Written in native code, much faster and better emulation
- There is no
line-mode
/char-mode
split
(use-package vterm :commands vterm :config (setq term-prompt-regexp "^[^#$%>\n]*[#$%>] *") ;;(setq vterm-shell "zsh") (setq vterm-max-scrollback 10000))
- Read docs on
vterm-use-vterm-prompt-detection-method
for prompt detection
¶shell-mode
Runs a shell program on your computer in a more controlled buffer. Does not operate as a terminal emulator.
C-c C-p
/C-c C-n
- go back and forward in the buffer’s promptsM-p
/M-n
- go back and forward in the input historyC-c C-u
- delete the current input string backwards up to the cursorcounsel-shell-history
- A searchable history of commands typed into the shell
Pros/Cons
Better colors:
xterm-color on GitHub
(setq comint-output-filter-functions (remove 'ansi-color-process-output comint-output-filter-functions)) (add-hook 'shell-mode-hook (lambda () ;; Disable font-locking in this buffer to improve performance (font-lock-mode -1) ;; Prevent font-locking from being re-enabled in this buffer (make-local-variable 'font-lock-function) (setq font-lock-function (lambda (_) nil)) (add-hook 'comint-preoutput-filter-functions 'xterm-color-filter nil t)))
In Windows if you like PowerShell you can use this config:
;; Kudos to Jeffrey Snover: https://docs.microsoft.com/en-us/archive/blogs/dotnetinterop/run-powershell-as-a-shell-within-emacs (setq explicit-shell-file-name "powershell.exe") (setq explicit-powershell.exe-args '())
¶Eshell
(defun efs/configure-eshell () ;; Save command history when commands are entered (add-hook 'eshell-pre-command-hook 'eshell-save-some-history) ;; Truncate buffer for performance (add-to-list 'eshell-output-filter-functions 'eshell-truncate-buffer) ;; Bind some useful keys for evil-mode (evil-define-key '(normal insert visual) eshell-mode-map (kbd "C-r") 'counsel-esh-history) (evil-define-key '(normal insert visual) eshell-mode-map (kbd "<home>") 'eshell-bol) (evil-normalize-keymaps) (setq eshell-history-size 10000 eshell-buffer-maximum-lines 10000 eshell-hist-ignoredups t eshell-scroll-to-bottom-on-input t)) (use-package eshell :hook (eshell-first-time-mode . efs/configure-eshell))
counsel-eshell-history
- A searchable history of commands typed into the shell
(use-package eshell-git-prompt) :config (eshell-git-prompt-use-theme 'powerline))
Running programs in a term-mode buffer:
(with-eval-after-load 'esh-opt (setq eshell-destroy-buffer-when-process-dies t) (setq eshell-visual-commands '("htop" "zsh" "vim")))
Pros:
- Replicates Bash with cross-platform elisp functions
- Consistent shell experience across all OSes
- You can run Emacs commands and arbitrary Emacs Lisp in the shell
- You can pipe output of commands directly into an Emacs buffer
- Supports TRAMP!
Cons:
- Completions are not great out of the box compared to Bash
- Eshell commands can be very slow compared to the real programs
- Piping is much less functional than in “real” shells
- Subshell syntax is a bit different -
${}
instead of$()
- Programs that read input (like language REPLs) can operate strangely
- Tools that depend on setting shell environment (
nvm
,virtualenv
, etc) don’t work - Can be a little slow on Windows
Interesting articles:
¶Recommendations
- Use
term
oransi-term
if you’re on Linux / macOS and don’t care as much about output speed - Use
vterm
if you’re on Linux / macOS and want faster output and better terminal emulation - Use
shell
on Windows if you want to use PowerShell, Bash, or WSL - Use
eshell
on any OS if you want a consistent shell experience everywhere with Lisp superpowers full Emacs integration