Shell Settings


EShell is a shell written in elisp. This makes it both less capable than other terminal emulators and also gives it some interesting features.

EXPERIMENTAL EShell “Smart Shell”

  • State "EXPERIMENTAL" from [2017-07-25 Tue 12:49]
(require 'em-smart)
(setq eshell-where-to-jump 'begin)
(setq eshell-review-quick-commands nil)
(setq eshell-smart-space-goes-to-end t)

EXPERIMENTAL EShell ‘visual’ commands

  • State "EXPERIMENTAL" from [2017-07-25 Tue 12:50]
(eval-after-load 'eshell
     (require 'em-term)
     (add-to-list 'eshell-visual-commands "bundle")
     (add-to-list 'eshell-visual-commands "tail")
     (add-to-list 'eshell-visual-commands "rake")
     (add-to-list 'eshell-visual-commands "rspec")))

Opening EShells

First, a short-cut to quickly open a shell. Repeated invocations will bring back the same shell so we don't end up with a bunch of them running about.

(global-set-key (kbd "C-x m") 'eshell)

It's nice to have an easy short-cut to launch into a shell in the current buffer's directory. We'll start with a function to launch it:

(defun toby/eshell-in-buffer-dir ()
  "Open eshell in the current buffer's directory"
  (let ((dir default-directory))
    (let ((b (get-buffer eshell-buffer-name)))
      (unless b (eshell)))
    (display-buffer eshell-buffer-name t)
    (switch-to-buffer-other-window eshell-buffer-name)
    (unless (equalp dir default-directory)
      (cd dir)

and a binding to launch it:

(global-set-key (kbd "C-x C-m") 'toby/eshell-in-buffer-dir)

Sometimes what you want is a real terminal:

(global-set-key (kbd "C-x M") 'multi-term)
(global-set-key (kbd "C-c n") 'multi-term-next)

One great feature of Eshell is its ability to call Emacs functions as though they were shell commands. Here we'll define an alias ff that will open a file from the Eshell command line into an Emacs buffer:

(defun toby/eshell-hooks ()
  (linum-mode nil)
  (defalias 'ff 'find-file))

(add-hook 'eshell-mode-hook 'toby/eshell-hooks)

Comint Mode

Adjust some comint parameters (the mode that handles terminal buffers). comint-mode is the parent mode of many shell modes.

(setq comint-buffer-maximum-size 5240)
(add-hook 'comint-output-filter-functions 'comint-truncate-buffer)
(add-hook 'comint-output-filter-functions 'comint-watch-for-password-prompt)

Let's add a function to easily clear an active shell buffer:

(defun clear-shell ()
  "Clear the current shell buffer"
  (let ((comint-buffer-maximum-size 0))

Binding s-k to kill-buffer doesn't make sense to me.

(global-unset-key (kbd "s-k"))
(defun set-my-shell-bindings ()
  (local-set-key (kbd "<up>")   'comint-previous-input)
  (local-set-key (kbd "<down>") 'comint-next-input)
  (local-set-key (kbd "s-k")    'clear-shell))

(add-hook 'term-exec-hook
           (lambda ()
             (set-buffer-process-coding-system 'utf-8-unix 'utf-8-unix))))

(add-hook 'shell-mode-hook  'set-my-shell-bindings)
(add-hook 'eshell-mode-hook 'set-my-shell-bindings)

Other Shells

Sometimes, to get proper shell colors in emacs, updating terminfo can be required:

tic -o ~/.terminfo /usr/local/Cellar/emacs/current/share/emacs/24.3/etc/e/eterm-color.ti

Set up the multi-term package and term mode hooks:

(require-package 'multi-term)
(setq multi-term-program "/bin/zsh")

(defun toby/term-hook ()
  (linum-mode -1)
  (setq-local show-trailing-whitespace nil)
  ;; yas mode can break the TAB character in terminals
  (yas-minor-mode -1))

(defun toby/term-exec-hook ()
  (set-buffer-process-coding-system 'utf-8-unix 'utf-8-unix))

(add-hook 'term-mode-hook 'toby/term-hook)
(add-hook 'eshell-mode-hook 'toby/term-hook)
(add-hook 'term-exec-hook 'toby/term-exec-hook)

Author: Toby Tripp

Created: 2018-02-09 Fri 15:33