#+TITLE: #+STARTUP: showall * C-d to close eshell :eshell:emacs:elisp:config: :PROPERTIES: :PUBDATE: <2013-08-17 Sat 2:25> :END: One of the "tricks" that I have learned to use when working with terminals is using ~C-d~ to close them, or when working on a TTY logout. It somehow grew to the extent that if I can't use it, I get annoyed, like with ~eshell~. I have customized ~ansi-term~ to immediately close its buffer after the shell quits. This makes it very easy to start an ~ansi-term~, which I've bound to ~C-c t~, run a quick command (perhaps ~make~, or similar), ~C-d~, and I'm out. I want that for my ~eshell~ too. There are a few conditions that I want met before the buffer is killed, though. 1. Since ~eshell~ is an Emacs mode like any other, ~C-d~ is usually used to forward-kill characters, I don't want to lose this. 2. I only want it to quit when the line of input is empty. The following piece of code make sure these conditions are met. 1. It interactively calls =delete-char=, which keeps keybindings like ~C-4 C-d~ to delete 4 characters working. 2. It catches the error condition which is signaled whenever =delete-char= can't do it's job (like when there's nothing left to delete in the buffer). 3. It checks to make sure that the signaled error is the =end-of-buffer= error. I don't want to kill the buffer if I try to delete more characters than are in the buffer because I feel that could cause irritating surprises. 4. It checks of the cursor is at the ~eshell~ prompt. This, combined with only responding to the =end-of-buffer= error, makes sure we're on an empty line and not just at the end of the input. Sometimes keys are pressed at the wrong time and I don't want to have to re-type a command just because I was being an idiot. 5. If the right conditions aren't met, signal the error again so I can see what's going on. #+BEGIN_SRC emacs-lisp (defun eshell-C-d () "Either call `delete-char' interactively or quit." (interactive) (condition-case err (call-interactively #'delete-char) (error (if (and (eq (car err) 'end-of-buffer) (looking-back eshell-prompt-regexp)) (kill-buffer) (signal (car err) (cdr err)))))) #+END_SRC I then bind this to =C-d= in eshell. #+BEGIN_SRC emacs-lisp (add-hook 'eshell-mode-hook (lambda () (local-set-key (kbd "C-d") #'eshell-C-d))) #+END_SRC