web-dev-qa-db-ja.com

Zsh:vared組み込みのタイムアウト

vared を使用してユーザー入力を求めるwhileループがあります。タイムアウトさせ、デフォルトの変数を実行し、一定時間後にユーザー入力がない場合はプロンプトにループバックする方法を探しています。 readコマンドとそのtimeout引数を知っていますが、これはvaredでどういうわけか可能ですか?

また、プロンプトに出力されないvaredのデフォルトを設定する方法はありますか?

local command

while :

   do
     echo "Enter a command or type 'quit' to exit:"
     vared -p "[*]: " command

     if [ "$command" = "quit" ]; then
         break

     else
         run command
     fi

     clear

   done
2
Le_Prometheen

あなたは次のようなことをすることができます:

default=foobar
if
  command=$(
    saved_settings=$(stty -g)
    trap 'stty $saved_settings; exit 1' ALRM
    v=
    TMOUT=10 vared -p "Enter a command [$default]: " v &&
      printf %s $v
  )
then
  command=${command:-$default}
  printf 'Got: "%s"\n' $command
else
  print timeout
fi

変数をデフォルト値でprimingする代わりに、空の文字列でプライミングし、変数がまだ空の場合にのみデフォルト値に設定しますvaredが戻ります。

タイムアウトを処理するために、サブシェルで$TMOUT特殊変数を使用します。これにより、zle$TMOUT秒後にそのサブシェルを終了します。

これは10秒のグローバルタイムアウトです。別のアプローチは、端末回線の分野の文字間タイムアウト(stty time x、デシ秒で表されるx)を使用して、ユーザーに大きなコマンドを入力するのに十分な時間を与えるが、たとえば3の後にタイムアウトすることです。非アクティブの秒数:

default=foobar
if
  command=$(
    saved_settings=$(stty -g)
    trap 'stty $saved_settings' EXIT INT TERM ALRM
    zle-line-init() stty -icanon time 30 min 0 <&2
    zle -N zle-line-init
    v=
    vared -p "Enter a command [$default]: " v &&
      printf %s $v
  )
then
  command=${command:-$default}
  printf 'Got: "%s"\n' $command
else
  print
  print timeout
fi

これらはスクリプトで機能しますが、 現在、インタラクティブシェルでは機能しませんvaredとして、サブシェルでの実行を拒否することに注意してください。インタラクティブシェル内から実行する必要がある場合は、zshで修正されるまで、次を変更できます。

command=$(
  ...
)

command=$(default=$default zsh -c '
  ...
')
1