Leia / dev / tty de dentro de uma função de conclusão

3

Por que o código a seguir não está funcionando para a conclusão do comando foo ? Quando eu a fonte, em seguida, digite foo <Tab> , o shell trava e não aceita qualquer entrada até que eu pressione ^C (que sai da conclusão do comando).

Minha hipótese é que /dev/tty já está sendo lido pelo shell e, de alguma forma, ele faz com que cat consiga lê-lo também, mas, nesse caso, ainda preciso de uma solução alternativa.

_foo() {
    _values 'foo' "$(cat < /dev/tty)"
}

compdef _foo foo

Observe que este exemplo é deliberadamente simplificado: o caso de uso real está executando um programa de interface de terminal (pense em ncurses) em vez de cat .

    
por Nison Maël 23.01.2018 / 21:49

2 respostas

1

Durante a conclusão, você está no editor de linhas zsh, portanto, o próprio editor de linhas da disciplina de linha de terminal está desativado como se você tivesse executado:

stty -icanon -echo

Nesse modo, cat não pode sair porque não há como significar o fim da entrada ( ^D faz parte do comportamento do editor de linhas da disciplina icanon ) e você não verá o eco de o que você digita.

Você poderia fazer:

_foo() {
  _values 'foo' "$(
    {
      s=$(stty -g)
      stty sane
      cat
      stty $s
    } < /dev/tty)"
  zle -I
}

Ou seja, coloque o dispositivo terminal no estado esperado por cat (onde você pode pressionar ^D em uma linha vazia ou duas vezes para finalizar a entrada) antes de executar cat e restaurá-lo depois. E nós dizemos que ele tem que redesenhar seu prompt e armazenar em buffer, pois o eco do que você digitaria dentro do editor de linha de linha de linha poderia atrapalhar as coisas ( zle -I para invalidar ).

    
por 29.01.2018 / 18:10
0

Isso provavelmente é muito simplificado, cat lerá /dev/tty por um bom tempo. Com uma conclusão _foo de

#compdef foo
_values 'foo' "$(promptfor)"

e um promptfor de

#!/usr/bin/env expect
set fh [open /dev/tty r+]
stty raw -echo
set key [read $fh 1]            ;# read from tty
puts stdout $key                ;# to ZSH
flush stdout
stty -raw echo

minha ZSH na guia foo irá então completar qualquer tecla que for pressionada enquanto promptfor for executado.

Se você tiver um tipo de daemon por perto, provavelmente precisará de algo mais sofisticado como um soquete que o ZSH e seu daemon possam usar para realizar as comunicações necessárias; read no ZSH pode ler de um descritor de arquivos arbitrário ou coprocessado ...

    
por 24.01.2018 / 01:14