Como criar uma ligação de chave re-sourcing a configuração do shell sem que um novo comando seja salvo no histórico?

1

Eu gostaria de criar uma associação de chave, usando a seqüência de teclas C-x r , para recarregar a configuração de bash , armazenada em ~/.bashrc , e a da biblioteca readline armazenada em ~/.inputrc .

Para recarregar a configuração da readline, acho que eu poderia usar a função re-read-init-file , que é descrita em man 3 readline :

re-read-init-file (C-x C-r)
        Read in the contents of the inputrc file, and incorporate any bindings or variable  assignments  found there.

Para recarregar a configuração de bash , eu poderia usar o comando source ou . . No entanto, não tenho certeza qual é a melhor maneira de combinar um comando shell com uma função readline. Então, eu criei a combinação de duas combinações de teclas:

bind '"\C-xr":      ". ~/.bashrc \C-x\C-z1\C-m"'
bind '"\C-x\C-z1":  re-read-init-file'

Quando eu alcanço C-x r no bash, aqui está o que acontece:

. ~/.bashrc    '~/.bashrc' is inserted on the command line
C-x C-z 1      'C-x C-z 1' is typed which is bound to 're-read-init-file'
C-m            'C-m' is hit which executes the current command line

Parece funcionar porque, dentro do tmux, se eu tiver 2 painéis, um para editar ~/.inputrc ou ~/.bashrc , o outro com um shell e eu alterar um arquivo de configuração, depois de atingir C-x r no shell , Posso ver a mudança tendo efeito (seja um novo alias ou uma nova ligação de chave), sem a necessidade de fechar o painel para reabrir um novo shell.

Mas existe uma maneira melhor de alcançar o mesmo resultado? Em particular, é possível executar os comandos sem deixar uma entrada no histórico? Porque se eu acertar C-p para recuperar o último comando executado, eu recebo . ~/.bashrc , enquanto eu preferiria obter diretamente o comando que foi executado antes de eu fornecer novamente a configuração do shell.

Eu tenho o mesmo problema com zsh :

bindkey -s '^Xr' '. ~/.zshrc^M'

Mais uma vez, depois de atingir C-x r , o comando . ~/.zshrc é registrado no histórico. Existe uma maneira melhor de reutilizar a configuração de zsh ?

    
por user547381 10.06.2017 / 21:14

2 respostas

1

Não injete um comando na linha de comando para executá-lo! Isso é muito frágil - o que você está tentando presumir que não há nada digitado no prompt atual ainda. Em vez disso, vincule a chave a um comando shell, em vez de vinculá-lo a um comando line edition.

No bash, use bind -x .

bind -x '"\C-xr": . ~/.bashrc'

Se você também quiser reler a configuração da linha de leitura, não há uma maneira não-lúdica de misturar comandos de linha de leitura e comandos bash em uma ligação de chave. Uma maneira desajeitada é ligar a chave a uma macro readline que contém duas seqüências de teclas, uma ligada ao comando readline que você quer executar e uma ligada ao comando bash.

bind '"\e[99i~": re-read-init-file'
bind -x '"\e[99b~": . ~/.bashrc'
bind '"\C-xr": "\e[99i~\e[99b~"'

Em zsh, use zle -N para declarar uma função como um widget, então bindkey para vincular esse widget a um chave.

reread_zshrc () {
  . ~/.zshrc
}
zle -N reread_zshrc
bindkey '^Xr' reread_zshrc
    
por 11.06.2017 / 01:16
0

Em man bash , encontrei a variável de ambiente HISTIGNORE , cuja descrição é a seguinte:

HISTIGNORE

        A  colon-separated list  of patterns  used to  decide which  command
        lines should be saved on the  history list. Each pattern is anchored
        at the  beginning of the line  and must match the  complete line (no
        implicit '*' is  appended). Each pattern is tested  against the line
        after the checks  specified by HISTCONTROL are  applied. In addition
        to the  normal shell  pattern matching  characters, '&'  matches the
        previous history  line. '&'  may be escaped  using a  backslash; the
        backslash  is removed  before  attempting a  match.  The second  and
        subsequent lines  of a multi-line  compound command are  not tested,
        and are added to the history regardless of the value of HISTIGNORE.

Então, eu exportei o seguinte valor em ~/.bashrc :

bind '"\C-xr":   ". ~/.bashrc \C-x\C-z1\C-m"'
bind '"\C-x\C-z1":  re-read-init-file'

export HISTIGNORE="clear:history:. ~/.bashrc "

A última linha deve impedir que bash salve qualquer comando clear , history e mais importante . ~/.bashrc .

Para zsh , encontrei a opção HIST_IGNORE_SPACE , descrita em man zshoptions :

HIST_IGNORE_SPACE (-g)

        Remove command lines  from the history list when the  first character on
        the line  is a  space, or when  one of the  expanded aliases  contains a
        leading space. Only  normal aliases (not global or  suffix aliases) have
        this behaviour.  Note that the  command lingers in the  internal history
        until the  next command is entered  before it vanishes, allowing  you to
        briefly reuse or edit the line. If you want to make it vanish right away
        without entering another command, type a space and press return.

De acordo com o que diz, se esta opção estiver habilitada, zsh deve remover do histórico qualquer comando que comece com um espaço. No entanto, permanece temporariamente no histórico interno, até que o próximo comando seja executado. Então, eu configurei essa opção em ~/.zshrc e, em seguida, redefinei a ligação de chave para recomprar a configuração do shell da seguinte forma:

    setopt HIST_IGNORE_SPACE
    bindkey -s '^Xr' ' . ~/.zshrc^M ^M'
#                     │            │
#                     │            └─ command containing only a space to force 'zsh'
#                     │               to “forget“ the previous command immediately
#                     └─ space added to prevent 'zsh' from logging the command
    
por 10.06.2017 / 23:24