Como testar se o shell zsh atual já executou comandos 'dircolors' e 'stty'?

2

Estou usando o zsh versão 5.3.1:

% zsh --version
zsh 5.3.1 (x86_64-pc-linux-gnu)

Estou tentando definir uma ligação de chave, usando a seqüência de teclas C-x r , para recarregar a configuração de zsh . Graças a @Gilles , incluí este código no meu ~/.zshrc :

reread_zshrc () {
. ~/.zshrc
}
zle -N reread_zshrc
bindkey '^Xr' reread_zshrc

Funciona, exceto que quando eu clico em C-x r , zsh reclama com os erros:

stty: 'standard input': Bad file descriptor
stty: 'standard input': Bad file descriptor
dircolors: /home/user/.dircolors: Bad file descriptor

Eu posso reproduzir esses erros com o seguinte zshrc :

stty -ixon
stty quit undef
eval "$(dircolors -b ~/.dircolors)"

reread_zshrc () {
. ~/.zshrc
}

zle -N reread_zshrc
bindkey '^Xr' reread_zshrc

Aqui estão os motivos pelos quais incluí os comandos 2 stty e o comando dircolors no meu zshrc .

stty -ixon impede que o driver do terminal interprete C-s e C-q como controles de fluxo do terminal: por padrão, C-s congela o terminal e C-q descongelam. Ele permite usar C-s e C-q em atalhos de teclado para o shell ou o editor de texto, sem congelar o terminal.

stty quit undef impede que o driver do terminal envie o sinal SIGQUIT quando C-\ for pressionado. Novamente, ele permite usar essa chave em uma ligação de chave sem o processo de primeiro plano para sair.

eval "$(dircolors -b ~/.dircolors)" pergunta ao comando ls para ler sua configuração em ~/.dircolors . Permite personalizar as cores da saída de um comando ls .

Eu suponho que eu preciso proteger essas 3 linhas de serem re-sourced por zsh se elas já tiverem sido executadas no shell atual. Mas eu não sei qual condição para escrever:

if <stty and dircolors haven't been executed already>; then
  stty -ixon
  stty quit undef
  eval "$(dircolors -b ~/.dircolors)"
if

Além disso, eu gostaria de entender melhor essas mensagens de erro, porque se eu as executar em um% inter_de% shell interativo, elas não causarão nenhum problema. Por que eles só geram erros dessa ligação de chave?

    
por user547381 11.06.2017 / 13:52

1 resposta

4

Em zle widgets, parece que zsh fecha stdin. Suponho que zsh queira evitar comandos nesses widgets interferindo diretamente na entrada do usuário, mas seria mais sensato redirecionar o stdin de / dev / null ( que será corrigido na próxima versão ).

Quando stdin (descritor de arquivo 0) é fechado, isso significa que o primeiro arquivo que um comando abre se torna seu stdin (como os descritores de arquivo são alocados a partir do primeiro livre).

Em dircolors , isso aciona um bug. dircolors abre seu ~/.dircolors e, em seguida, tenta torná-lo stdin sem perceber que já era stdin (porque esse é o fd open() retorna). Portanto, o dup2(0,0) (dup stdin em si mesmo) falha com um erro EBADF que dircolors reporta.

stty define as configurações do terminal aberto em seu stdin. Aqui, stdin é fechado, então stty retorna com um erro.

Aqui, você pode alterar seu widget para restaurar o stdin no terminal:

reread_zshrc () . ~/.zshrc < $TTY

Mas note que alterar as configurações do tty a partir de um widget zle (embora eu não saiba o que seu comando stty faz) é uma má ideia pois zle define o tty em um modo especial para edição de linha com o qual você não quer se atrapalhar (e no final da edição, as configurações normais do tty serão restauradas de qualquer maneira, então as alterações que você está fazendo serão perdidas).

Então, talvez você devesse fazer stdin /dev/null (como você não quer fazer coisas com o terminal lá), mas stty ainda reclama (como /dev/null não é um dispositivo tty), então você também pode querer redirecionar o stderr para o / dev / null para ocultar essas mensagens de erro (embora ele possa ocultar as mensagens de erro all ):

reread_zshrc() . ~/.zshrc < /dev/null 2> /dev/null
    
por 11.06.2017 / 18:28