Объединить историю из нескольких эшелонов

9

Перед переключением на eshell я настроил zsh так, чтобы он:

  • Выпишите в файл истории после каждой команды
  • Добавлять, а не перезаписывать файл истории, чтобы при запуске нескольких оболочек все они были объединены в одну большую историю

Обе опции zsh описаны здесь (см. APPEND_HISTORY и INC_APPEND_HISTORY).

Это очень полезно в сочетании с большим размером истории, потому что вы можете открыть новую оболочку через несколько недель после ввода команды и найти ее в своей истории (без этих опций большая история бесполезна, поскольку она будет содержать только историю последних закрытых команд). ракушка). Это также означает, что вы можете открывать новые оболочки и получать от них информацию о ваших последних командах в других оболочках. Есть ли способ настроить eshell с таким поведением? Первая пуля кажется достаточно легкой, но добавление выглядит сложнее ...

Джозеф Гарвин
источник

Ответы:

3

Отказ от ответственности: я не использую eshell, поэтому возьмите это с зерном соли.

eshellПо-видимому, вызывается eshell-write-historyдля записи истории, которая принимает необязательный аргумент по appendумолчанию nil. Этот аргумент, кажется, не используется в eshellнастоящее время, но, похоже, работает (он передает аргумент до write-region, который правильно добавляется).

Здесь есть несколько вариантов.

  1. (setq eshell-save-history-on-exit nil)и назови eshell-write-historyсебя
  2. Переопределить, eshell-write-historyчтобы удовлетворить ваши требования.

Лично я бы пошел с 1.

Например:

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

Спасибо @ joseph-garvin за исправленную, работающую eshell-append-historyфункцию

Это не обрабатывает динамическую загрузку нового содержимого истории в оболочку (например, запустить команду Xв оболочке A и сделать так, чтобы она появлялась в истории в оболочке B без перезагрузки; например, SHARE_HISTORY в zsh). Я не знаю, насколько это эффективно eshell-read-history, поэтому я не решался бы запустить его на крючок.

Также возможно, что в результате вы получите дублирующиеся записи с этой eshell-append-historyфункцией. Возможно, вам придется выполнить некоторые махинации с очисткой всех, кроме самой последней записи, с eshell-history-ringпоследующим сбросом ее к старому значению после записи истории.

Например

(let ((old-ring (copy-list eshell-history-ring)))
  (setq eshell-history-ring (list (car eshell-history-ring)))
  ; write
  (setq eshell-history-ring old-ring))
Дж Дэвид Смит
источник
Спасибо, это выглядит великолепно. В вашем первом фрагменте отсутствует цитата в конце строки документации.
Джозеф Гарвин
Я должен был отредактировать его, оказывается, кольца нужно изменить функциями ring- *, иначе вы столкнетесь с ошибками. Также я использую динамическое связывание для временного переопределения определения eshell-history-ring вместо создания копии. Если вы добавите здесь код в свой ответ, я отмечу его как принятый, так как вы получили результат: pastebin.com/zEE7B6d7
Джозеф Гарвин
@ ДжозефГарвин готов!
J David Smith
Это решение отлично работает, но я также должен был набор eshell-exit-hookк нулю , так как это автоматически загружается при eshell начинается: (add-hook 'eshell-exit-hook 'eshell-write-history nil t). Я установил хук на локальный ноль, например, так (по умолчанию он равен нулю):(add-hook 'eshell-mode-hook '(lambda () (setq eshell-exit-hook nil)))
GDP2