Disclaimer: I don't use eshell, so take this with a grain of salt.
eshell
appears to call eshell-write-history
to write history, which takes an optional argument append
which defaults to nil
. This argument seems to be unused in eshell
presently, but does appear to work (it passes the argument through to write-region
, which does properly append).
There are a couple of options here.
(setq eshell-save-history-on-exit nil)
and calleshell-write-history
yourself- Redefine
eshell-write-history
to satisfy your requirement.
Personally, I'd go with 1.
As an example:
(setq eshell-save-history-on-exit nil)
(defun eshell-append-history ()
"Call `eshell-write-history' with the `append' parameter set to `t'."
(when eshell-history-ring
(let ((newest-cmd-ring (make-ring 1)))
(ring-insert newest-cmd-ring (car (ring-elements eshell-history-ring)))
(let ((eshell-history-ring newest-cmd-ring))
(eshell-write-history eshell-history-file-name t)))))
(add-hook eshell-pre-command-hook #'eshell-append-history)
Thanks to @joseph-garvin for the corrected, working eshell-append-history
function
This doesn't handle dynamically loading the new history contents into a shell (eg run command X
in shell A, and having it appear in history in shell B without reloading; like zsh's SHARE_HISTORY). I don't know how efficient eshell-read-history
is, so I'd be hesitant to run it in a hook.
It is also possible that you will end up with duplicate entries with this eshell-append-history
function. You may need to do some shenanigans with clearing all but the most recent entry from eshell-history-ring
, then resetting it to the old value after writing history.
E.g.
(let ((old-ring (copy-list eshell-history-ring)))
(setq eshell-history-ring (list (car eshell-history-ring)))
; write
(setq eshell-history-ring old-ring))