Mesclar histórico de vários eshells

9

Antes de mudar para o eshell, eu tinha a configuração do zsh para que:

  • Grave no arquivo de histórico após cada comando
  • Acrescente ao invés de sobrescrever o arquivo de histórico, portanto, ao executar vários shells, todos eles serão mesclados em um grande histórico

As duas opções do zsh estão documentadas aqui (consulte APPEND_HISTORY e INC_APPEND_HISTORY).

Isso é super útil quando combinado com um grande tamanho de histórico, porque você pode abrir um novo shell semanas após emitir um comando e encontrá-lo em seu histórico (sem essas opções, um histórico grande é inútil, pois conterá apenas o histórico dos mais recentes Concha). Isso também significa que você pode abrir novos shells e fazer com que eles conheçam imediatamente seus comandos mais recentes em outros shells. Existe alguma maneira de configurar eshell com esse comportamento? A primeira bala parece fácil o suficiente, mas anexar parece mais difícil ...

Joseph Garvin
fonte

Respostas:

3

Disclaimer: Eu não uso eshell, então leve isso com um grão de sal.

eshellparece chamar eshell-write-historypara escrever o histórico, que usa um argumento opcional appendque é o padrão nil. Esse argumento parece não ser usado no eshellmomento, mas parece funcionar (ele passa o argumento para write-region, que é anexado corretamente).

Existem algumas opções aqui.

  1. (setq eshell-save-history-on-exit nil)e chame a eshell-write-historysi mesmo
  2. Redefina eshell-write-historypara satisfazer sua exigência.

Pessoalmente, eu iria com 1.

Como um exemplo:

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

Graças a @ joseph-garvin pela eshell-append-historyfunção de trabalho corrigida

Isso não lida com o carregamento dinâmico do novo conteúdo do histórico em um shell (por exemplo, execute o comando Xno shell A e faça com que apareça no histórico no shell B sem recarregar; como o SHARE_HISTORY do zsh). Eu não sei o quão eficiente eshell-read-historyé, então eu hesitaria em executá-lo em um gancho.

Também é possível que você acabe com entradas duplicadas com esta eshell-append-historyfunção. Pode ser necessário fazer algumas travessuras para limpar todas as entradas eshell-history-ring, exceto a mais recente , e depois redefini-la para o valor antigo após escrever o histórico.

Por exemplo

(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
fonte
Obrigado, isso parece ótimo. No entanto, seu primeiro snippet está faltando uma citação no final da sequência de caracteres.
Joseph Garvin
Eu tive que editar alguns, acontece que os anéis precisam ser modificados pelas funções ring- * ou você pode encontrar erros. Também uso a ligação dinâmica para substituir temporariamente a definição de eshell-history-ring em vez de fazer uma cópia. Se você colocar o código aqui em sua resposta que eu vou marcar como aceite desde que você tem a bola rolar: pastebin.com/zEE7B6d7
Joseph Garvin
@JosephGarvin done!
J David Smith
Esta solução funciona muito bem, mas eu também tinha que definir eshell-exit-hooka zero, porque isso automaticamente será carregado quando eshell começa: (add-hook 'eshell-exit-hook 'eshell-write-history nil t). Eu defini o gancho para ser localmente nulo dessa maneira (é globalmente nulo por padrão):(add-hook 'eshell-mode-hook '(lambda () (setq eshell-exit-hook nil)))
GDP2 18/07/16