summaryrefslogtreecommitdiffstats
path: root/articles/c-d_to_close_eshell.org
diff options
context:
space:
mode:
Diffstat (limited to 'articles/c-d_to_close_eshell.org')
-rw-r--r--articles/c-d_to_close_eshell.org56
1 files changed, 56 insertions, 0 deletions
diff --git a/articles/c-d_to_close_eshell.org b/articles/c-d_to_close_eshell.org
new file mode 100644
index 0000000..525e462
--- /dev/null
+++ b/articles/c-d_to_close_eshell.org
@@ -0,0 +1,56 @@
+#+TITLE: C-d to close eshell
+
+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