次のコードがコマンドを完了できないのはなぜですかfoo
?次のように入力すると、シェルがフリーズfoo <Tab>
して押すまで^C
(exitコマンドが完了します)、入力は許可されません。
私の仮定は、/dev/tty
シェルがそれを読み、それがcat
それを読む能力に何とか影響を与えるということです。ただし、この場合はまだ解決策が必要です。
_foo() {
_values 'foo' "$(cat < /dev/tty)"
}
compdef _foo foo
この例は意図的に単純化されています。実際のユースケースは、非ターミナルインタフェースプログラム(ncursesを考えてみてください)を実行することですcat
。
答え1
完了時にzsh行エディタにあるので、次のようにターミナル行ルールの独自の行エディタが無効になります。
stty -icanon -echo
このモードでは、入力の終わり(行ルールの行エディタの動作の一部)を通知できず、入力した内容のエコーが表示されないため、cat
終了する方法はありません。^D
icanon
次のことができます。
_foo() {
_values 'foo' "$(
{
s=$(stty -g)
stty sane
cat
stty $s
} < /dev/tty)"
zle -I
}
つまり、実行前にターミナルデバイスを期待したままにしてcat
(^D
空白行を押すか、ダブルクリックして入力を終了できます)、cat
実行後に復元します。私たちは、zleに、ラインルールラインエディタに入力したコンテンツのエコーが原因で混乱するので、プロンプトとバッファを再描画する必要があると言いますzle -I
(無効)。
答え2
これはおそらくとても簡単で、cat
読むのに/dev/tty
長い時間がかかります。_foo
完成する
#compdef foo
_values 'foo' "$(promptfor)"
promptfor
そして
#!/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
私のZSHは実行中に押すすべてのキーをfoo
tab完了します。promptfor
ある種のデーモンがある場合は、ZSHやデーモンが必要な通信を実行するために使用できるソケットなど、よりエキゾチックなものが必要な場合があります。read
ZSHでは、任意のファイル記述子または補助プロセスから読み取ることができます。