連続出力をrofiにパイプ

連続出力をrofiにパイプ

文字列をrofiにパイプするbashスクリプトを作成しようとしています。これらの文字列は関数によって継続的に生成されますgen_x

この関数はgen_x時々(条件が満たされた場合にのみ)新しい文字列を出力します。私は現在、gen_x無限ループでifステートメント(関数)を実装しています。この機能をrofiにパイプしたいです。 rofiで項目が選択されると、rofiは選択した項目を出力し、gen_xrofiは終了する必要があります。

毎回新しい要素を出力する無限ループを使用すると(図を参照gen_b)、スクリプトは上記のように正確に実行されます。ただし、関数でifステートメントを実装し、条件がtrueの場合にのみ新しい要素を印刷すると、プログラムは終了しません。これがrofiのためかどうかはわかりませんgen_x

コードを単純化する

gen_a(){ while true; do if [[ "$v" == "" ]]; then echo "Test"; v=1; fi; sleep 1; done }
gen_b(){ while true; do                             echo "Test";            sleep 1; done }

gen_a | rofi -dmenu # -> this outputs Test and does not end
gen_b | rofi -dmenu # -> this outputs Test and ends properly

whileループで条件を使用してプログラムを正しく終了させる方法はありますか?

答え1

rofiいいえ非同期モードに切り替えるデフォルトでは、25行の入力を読み取る前です。これは次のように変更できます。

-async-pre-read [number] 非同期モードに切り替える前に複数のブロック項目を読み込む

オプション。

だから:

cmd | rofi -async-pre-read 1 -dmenu

1行を読むとすぐにメニューが表示されるようにしますcmd

項目を選択するとrofi印刷され終了します。 cmdその後、通常どおりstdout(今は壊れたパイプ)に書き込むとSIGPIPEによって終了します。

すぐに殺すための一般的な方法は次のとおりです。

sh -c 'echo "$$"; exec cmd' | {
  IFS= read -r pid
  rofi -async-pre-read 1 -dmenu
  kill -s PIPE "$pid"
}

関連情報