Skip to main content
added new code from @joseph-garvin
Source Link
J David Smith
  • 2.7k
  • 1
  • 19
  • 27

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.

  1. (setq eshell-save-history-on-exit nil) and call eshell-write-history yourself
  2. 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))

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.

  1. (setq eshell-save-history-on-exit nil) and call eshell-write-history yourself
  2. 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'.
    (eshell-write-history eshell-history-file-name t))
(add-hook eshell-pre-command-hook #'eshell-append-history)

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))

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.

  1. (setq eshell-save-history-on-exit nil) and call eshell-write-history yourself
  2. 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))
Source Link
J David Smith
  • 2.7k
  • 1
  • 19
  • 27

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.

  1. (setq eshell-save-history-on-exit nil) and call eshell-write-history yourself
  2. 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'.
    (eshell-write-history eshell-history-file-name t))
(add-hook eshell-pre-command-hook #'eshell-append-history)

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))