Use a process sentinel when you want to react to a process exiting. e.g.:
Refer to C-hig (elisp)Sentinels
In this case shell
only calls shell-mode
when (and after) starting the inferior process, so we can use shell-mode-hook
to add the sentinel.
As @Tobias points out in the comments, set-process-sentinel
will clobber any existing sentinel for that process. shell
will always have a sentinel (exactly what it is can vary), and we can call it first.
(defun my-shell-mode-hook ()
"Custom `shell-mode' behaviours."
;; Kill the buffer when the shell process exits.
(let* ((proc (get-buffer-process (current-buffer)))
(sentinel (process-sentinel proc)))
(set-process-sentinel
proc
`(lambda (process signal)
;; Call the original process sentinel first.
(funcall #',sentinel process signal)
;; Kill the buffer on an exit signal.
(and (memq (process-status process) '(exit signal))
(buffer-live-p (process-buffer process))
(kill-buffer (process-buffer process)))))))
(add-hook 'shell-mode-hook 'my-shell-mode-hook)
Alternatively, @Tobias has provided an alternative using advice-add
:
(defun add-process-sentinel (sentinel &optional process)
"Add SENTINEL to PROCESS.
PROCESS defaults to the process of the current buffer.
Use this function with care.
If there is already a process sentinel SENTINEL is used as after-advice.
That can fail if the process sentinel is reset by some other function."
(unless process
(setq process (get-buffer-process (current-buffer))))
(let ((old (process-sentinel process)))
(cond
((symbolp old)
(advice-add old :after sentinel))
((null old)
(set-process-sentinel process sentinel))
(t (warn "Cannot set sentinel %S for process %S." sentinel process)))))
(defun my-shell-mode-hook ()
"Custom `shell-mode' behaviours."
;; Kill the buffer when the shell process exits.
(add-process-sentinel
(lambda (process signal)
(and (memq (process-status process) '(exit signal))
(buffer-live-p (process-buffer process))
(kill-buffer (process-buffer process))))))
(add-hook 'shell-mode-hook 'my-shell-mode-hook)
&rest _
. – Tobias Mar 13 '19 at 07:07shell-mode
. You need to havecomint-input-ring-file-name
set if you want to useshell-write-history-on-exit
. – Tobias Mar 13 '19 at 07:12shell-mode
tries to setcomint-input-ring-file-name
from the environment variableHISTFILE
or if that does not exist it tries to set it to some defaults like~/.bash_history
. The automagic setting did not work for me, but(setenv "HISTFILE" "~/.bash-history")
before starting the shell did work. Nevertheless your add-on sentinel did not run yet. – Tobias Mar 13 '19 at 07:28shell-write-history-on-exit
is called? That sentinel is set only for shells matchingshell-dumb-shell-regexp
– phils Mar 13 '19 at 07:29