Combinar el historial de múltiples eshells

9

Antes de cambiar a eshell, tenía la configuración de zsh para que:

  • Escriba en el archivo de historial después de cada comando
  • Agregue al archivo de historial en lugar de sobrescribirlo para que, al ejecutar varios shells, todos se fusionen en un gran historial

Ambas opciones de zsh están documentadas aquí (ver APPEND_HISTORY e INC_APPEND_HISTORY).

Esto es súper útil cuando se combina con un tamaño de historial grande porque puede abrir un nuevo shell semanas después de emitir un comando y encontrarlo en su historial (sin estas opciones un historial grande es inútil ya que solo contendrá el historial del último cierre cáscara). También significa que puede abrir nuevos shells y hacer que conozcan de inmediato sus comandos más recientes en otros shells. ¿Hay alguna forma de configurar eshell con este comportamiento? La primera viñeta parece bastante fácil, pero agregar parece más complicado ...

Joseph Garvin
fuente

Respuestas:

3

Descargo de responsabilidad: no uso eshell, así que tómalo con un grano de sal.

eshellparece llamar eshell-write-historypara escribir el historial, que toma un argumento opcional appendque por defecto es nil. Parece que este argumento no se utiliza eshellactualmente, pero parece funcionar (pasa el argumento a write-region, que se adjunta correctamente).

Hay un par de opciones aquí.

  1. (setq eshell-save-history-on-exit nil)y llamate a eshell-write-historyti mismo
  2. Redefina eshell-write-historypara satisfacer sus necesidades.

Personalmente, iría con 1.

Como ejemplo:

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

Gracias a @ joseph-garvin por la eshell-append-historyfunción de trabajo corregida

Esto no se encarga de cargar dinámicamente los nuevos contenidos del historial en un shell (por ejemplo, ejecutar el comando Xen el shell A y hacer que aparezca en el historial en el shell B sin volver a cargar; como SHARE_HISTORY de zsh). No sé qué tan eficiente eshell-read-historyes, así que dudaría en ejecutarlo en un gancho.

También es posible que termine con entradas duplicadas con esta eshell-append-historyfunción. Es posible que deba hacer algunas travesuras borrando todas las entradas eshell-history-ring, excepto la más reciente , y luego restableciéndolas al valor anterior después de escribir el historial.

P.ej

(let ((old-ring (copy-list eshell-history-ring)))
  (setq eshell-history-ring (list (car eshell-history-ring)))
  ; write
  (setq eshell-history-ring old-ring))
J David Smith
fuente
Gracias, esto se ve genial. Sin embargo, a su primer fragmento le falta una cita al final de la cadena de documentación.
Joseph Garvin
Tuve que editarlo un poco, resulta que los anillos deben ser modificados por las funciones ring- * o te encuentras con errores. También uso el enlace dinámico para anular temporalmente la definición de eshell-history-ring en lugar de hacer una copia. Si pone el código aquí en su respuesta, lo marcaré como aceptado desde que empezó a rodar: pastebin.com/zEE7B6d7
Joseph Garvin
@JosephGarvin hecho!
J David Smith
Esta solución funciona muy bien, pero también tuvo que establecer eshell-exit-hooka cero, puesto que esto automáticamente se carga cuando se inicia eshell: (add-hook 'eshell-exit-hook 'eshell-write-history nil t). Configuré el gancho para que sea localmente nulo (es globalmente nulo por defecto):(add-hook 'eshell-mode-hook '(lambda () (setq eshell-exit-hook nil)))
GDP2