Informações do sistema:
macOS Sierra 10.12.6
zsh 5.4.2 (x86_64-apple-darwin16.7.0)
GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0)
Role até o EXEMPLOS na parte inferior, se quiser apenas analisar os exemplos simplificados que eu fiz.
OBSERVAÇÃO: não sou um grande usuário zsh
.
Eu estava vendo os fzf
keybindings para bash
e zsh
.
Observe como ambos executam um comando variável $(__fzfcmd)
. __fzfcmd
por padrão envia fzf
para stdout e a substituição de parâmetro apenas executa o comando ( fzf
) resultante da saída.
Uma diferença entre o script bash
e zsh
é que o bash
canaliza ainda mais a saída de $(__fzfcmd)
, mas zsh
apenas captura-o dentro de uma matriz. Meu palpite é por causa de um problema em zsh
quando você canaliza ainda mais a saída de fzf
, onde você não pode inserir fzf
e o processo enviado por fzf
não recebe nenhum stdin. Sua única opção é ^Z
ou ^C
. ^C
parece basear o processo por algum motivo. Ou talvez eles apenas o quisessem em uma matriz para que pudessem executar zle vi-fetch-history
em isso . A versão bash
faz alguma mágica na associação de chaves com "\e^": history-expand-line
Agora fzf
não é importante. Parece que você só precisa de um programa que produza o tty
para ser chamado por substituição de parâmetro para causar esse problema. Então, mostrarei alguns exemplos mais simples.
Aqui estão alguns outros comandos que saem para o tty
que pode causar esse problema em zsh
:
-
vipe (execute o editor no meio de um pipe)
-
'vim -'
(faz o vim ler o stdin. similar ao vipe, mas não sai para o stdout)
Nos exemplos abaixo, substitua todas as ocorrências de vipe
por vim -
se você não quiser fazer uma instalação separada. Lembre-se de que vim -
não exibe o conteúdo do editor como stdout vipe
.
EXEMPLOS:
1) echo 1 | vipe | cat # works in both bash and zsh
2) echo 1 | $(echo vipe) | cat # works in bash only. zsh problem with no output until I hit '^C':
^C
zsh: done echo 1 |
zsh: suspended (tty output) $(echo vipe) |
zsh: interrupt cat
# seems like the process is backgrounded. I can still see it in jobs command
3) cat <(echo 1 | $(echo vipe)) # zsh and bash has the problem. I'm guessing because
# the file isn't finished writing and cat is
# blocking vipe's tty output
# both their '^C' output is just:
^C # nothing special, as expected
4) cat < <(echo 1 | $(echo vipe)) # works in both bash and zsh
5) echo 1 | $(echo vipe) > >(cat) # works in both bash and zsh
# The following don't have and input pipe to vipe.
# Type something then send EOF with ^D
6) vipe | cat # works for both
7) $(echo vipe) | cat # works for both
Agora, estou principalmente imaginando por que 2)
tem um problema para zsh
, mas não para bash
e por que 4)
e 5)
corrigem o problema de zsh
.
Os requisitos para zsh
para ter esse problema parecem ser exatamente o que eu coloquei no título:
- tubo de entrada
- comando executado por substituição de variável / parâmetro que possui
tty
output
- tubo de saída
ATUALIZAÇÃO
Eu adicionei outra solução alternativa que não causa zsh
para ter esse problema, 5)
. É semelhante a 4)
, mas em vez de redirecionar stdout
diretamente para stin
, eu o redireciono para um arquivo que redireciona para stdin
usando a substituição do processo.