2020-4-19(Sun)
yad はシェルから GTK のダイアログを使うためのコマンドで、zenity のフォークである。これをシェル・スクリプト中で使うと「なんちゃって GUI」が作れる。オプションが豊富で、テキトーに使おうとすると「あ゛〜」ってなるからメモを作成。情報は、私の環境で man(1) yad から得たもの(いいかげんですまぬ)。使った yad のバージョンは 0.27.0。嘘書いてたら、ごめん。
目次
yad は起動されると GUI なダイアログを表示し、ユーザー入力を標準出力に書き出して終了する。どういうダイアログを表示するかは、すべてコマンド・ライン・オプションの形で yad に与えられる。そのオプションの種類がざっと 150 くらいある(ちゃんと数えてないけど)。
ときどき「メニューが複雑で店員に何をどういう順番で伝えたらいいかがわからん」て店があるけど、ちょっとそれに似ている。ベーコンを食べたいときに、ベーコン・サンドイッチを注文してもいいし、タマゴ・サンドにベーコンをトッピングしてもいいということが起こる。かと思えば、「こちらのサンドイッチにそのトッピングは載せられません」とか言われる。yad もまあそんな感じのとこがある。
注文の基本方針はこうだ。まず基本となるサンドイッチ(Dialog options)を一つを選んで、次にトッピングを注文する。どんなサンドイッチにも載せられるトッピング(General options)と、特定のサンドイッチにしか載せられないトッピング(Calendar options, Color selection options, etc.)とがある。
以下、こうした用語を整理しておく。
ダイアログ・オプションは一回 yad プロセスを起動するごとに一つずつしか指定できない。サンドイッチ店に入って、2 つも 3 つもサンドイッチを注文できない感じである。そのかわり、トッピングがおそろしく豊富な --form というサンドイッチダイアログがあるので、これを注文すればたらふく食べられる。
各ダイアログ・オプションと、それぞれのためのめぼしい専用オプションを見ていこう。いずれのダイアログもデフォルトで OK ボタンと Cancel ボタンがある。こうしたボタンは OK を押すと標準出力に何かを出力したあと yad が終了し、Cancel を押すと何も出力せずに終了するのが原則。なお OK の場合終了ステータスが 0 で、キャンセルの場合 1 である。
ダイアログで選んだ年月日を出力する。
yad --calendar \ --year=2020 --month 1 --day=31 \ --date-format="%Y:%m:%d"
デフォルトの年月日が指定できるところが zenity に比べてよいところ。この場合の出力は 2020:01:31 みたいになる。
色を選ぶいわゆるカラー・ピッカーである。
yad --color \ --init-color=#a32f2f
出力は #a32f2f のようになる。
ファイルをボックスにドラッグ&ドロップすると、そのファイルの URI を標準出力に吐き出す。それを引数として指定されたコマンドを起動することもできる。
yad --dnd\ --text="Drop your file here." \ --tooltip \ --command echo
ローカル・ディスク上のファイルをドロップすると file:///home/my/dir/abc.jpg のように出力されるし、ブラウザ上の画像などをドロップすると http://kabipan.com/densan/yad/dnd.png のように出力される。上の例の場合は --command-option で echo を指定しているのが、--command-option の省略時の動作も同様なものである。なお、出力のタイミングはファイルをドロップするごとである。OK ボタンは終了ステータスを 0 で、Cancel ボタンは終了ステータスを 1 で終わらせるが、なくてもかまわないかもしれない。これらがわずらわしければ、--no-buttons という共通オプションを使うとよい。
--tooltip オプションをつけると、ポインタがボックス上にきたとき、--text オプションで指定された文字列がヘルプとしてポップアップする。(--text オプションは共通オプションであるが、別の Dialog option で使われたときは異なる働きをする)
--command オプションを省略すると、URI が
yad --icons\ --read-dir=/usr/share/applications
GTK ではアプリケーションのアイコンとパスが書き込まれた xxx.desktop というファイルが使われている。--read-dir でそうした xxx.desktop ファイルたちのあるディレクトリを指定すると、アイコン画像がボックス内に並ぶ。これをダブルクリックするとアプリケーションが起動する。デフォルトで表示される OK ボタンには、積極的な意味はない。
下はデフォルト値を設定しただけの簡単な例。
yad --entry\ --entry-label="好きな将軍"\ --entry-text="源頼朝"
テキストボックス左側にアイコンを設置し、アイコンがクリックされたときのコマンドを設定するには次のようにする。そのコマンドの出力がテキストボックスに入力される。(アイコンを右側につける場合は --ricon と --ricon-action を使う)
yad --entry\ --entry-label="好きな将軍"\ --licon="${HOME}/Desktop/yoritomo.png"\ --licon-action="echo 源頼朝"
次のようにすると、補完リストをつけられる。
yad --entry\ --entry-label="好きな将軍"\ --completion "徳川家康" "徳川家光" "徳川吉宗" "徳川慶喜"
数の入力用。以下は、初期値 3.14、変域 3 以上 4 以下、ステップ 0.01、表示される小数点以下の桁数 2 である。
yad --entry\ --entry-label="好きな数"\ --numeric\ --entry-text=3.14\ 3 4 0.01 2
出力は勝手に小数点以下が 0 でパディングされて 3.140000 になるので、自力で処理する必要あり。
ファイルを選択する。
yad --file\ --filename="/tmp/henryVIII.png"\ --file-filter='png ファイル | *.png *.PNG *' \ --multiple \ --separator="," \ --add-preview \ --quoted-output
--filename はデフォルトとなるファイルを設定。
--multiple をつけると(私の環境では)Ctrl キーを押しながら複数のファイルを選択できる。--separator は出力のときファイルパスを区切る。
--file-filter オプションを加えるとダイアログで表示されるファイルの種類を制限できる。なお、このオプションはあくまでも --file ダイアログの専用オプションだから、--form ダイアログで FL や MFL タイプの --field を使ってファイルを選択する場合には使えない。
--add-preview をつけるとプレビューが現れる。
--quoted-output をつけると、パスがシングルクオートされる。
以下のように --save オプションをつけると、"Active save mode" になる。これは、ファイルの保存ダイアログを作るのに便利だ。この場合、--confirm-overwrite オプションを使うと上書きの警告してくれる。
yad --file\ --filename="henryVIII.png"\ --save\ --confirm-overwrite="上書きしちゃう?"
プレビューつきでフォントを選択できる。
yad --font\ --fontname="Sans Bold 10"\ --preview="The quick brown fox jumps over the lazy dog"
次の例は、ほとんどすべての種類の --field を並べた --form である。
yad --form\ --item-separator='!'\ --separator='|'\ --field="Hidden (H)":H "hidden" \ --field="Read Only(RO)":RO "read only" \ --field='Number(NUM)':NUM '3.14!3.00..4.00!0.01!2' \ --field="Checkbox(CHK)":CHK "true" \ --field="Combo Box(CB)":CB 'fox!bear!panda' \ --field="Editable Combo Box(CBE)":CBE 'fox!bear!panda' \ --field="SelectFile(FL)":FL "/tmp/01.txt" \ --field="Select Multiple Files(MFL)":MFL '/tmp/02.txt!/tmp/03.txt' \ --field="Create File(SFL)":SFL "/tmp/new.txt" \ --field="Select Directory(DIR)":DIR "/tmp/" \ --field="Select Multiple Directories(MDIR)":MDIR '/tmp/tmp1/!/tmp/tmp2/' \ --field="Create Directory(CDIR)":CDIR "/tmp/new_tmp/"\ --field="Select Font(FN)":FN "Sans Bold 10" \ --field="Date(DT)":DT '2020:01:31' \ --date-format="%Y:%m:%d"\ --field="Scale(SCL)":SCL "50" \ --field="Select Color(CLR)":CLR '#FF7700' \ --field='Button(BTN)!gtk-yes!popup':BTN "echo %1" \ --field='Button2(FBTN)!gtk-yes!popup':FBTN '@echo "16:#00FF77"' \ --field="Text Label(LBL)":LBL "" \ --field="Text(TXT)":TXT "text" \ --field="Simple Text(no type)" "simple text"
--item-separator は初期値を複数与えるときの区切文字。デフォルトは「!」
--separator は出力のときの区切文字。デフォルトは「|」(パイプ文字)
フォーム・ダイアログは、その中にボタンやらテキスト・ボックスやらを並べるのに使う。このボタンやらテキスト・ボックスやらはフィールドと呼ばれ --field で作成される。--field は --field=X:Y Z の形で書く。X はそのフィールドのラベル、Y はフィールドのタイプ、Z は「追加的な引数(extra argument)」と呼ばれるものである。追加的な引数が何を意味するかは、フィールドのタイプによって異なるが、フィールドの初期値のために使われることが多い。
ユーザーにファイルを選択させるとき、--file ダイアログを使うこともできるし、--form ダイアログに FL や MFL タイプの--field を書いて使うこともできる。--file-filter オプションは --file ダイアログの専用オプションなので、前者にはつけられるが後者にはつけられない。
※説明ラベル[!アイコン[!ポップアップヘルプ文字]]の形。アイコンは画像ファイルのパスか、GTK ストックの id。
※※ ボタン押下時に発行されるコマンド文字列。N 番目の --field の値を %N で取得。
(例)"echo %1" は最初の --field の値を標準出力に出す。
コマンドが@で始まり、その出力が N: で始まるならば、N: 以後の出力は N 番目の--field の値にセットされる。
(例)'@echo "1:abc"' は、最初の --field に abc をセット。
※ フィールド・タイプを省略するとシンプルなテキスト・ボックスになる
※※ 空にしておくとテキスト・ラベルの代わりに水平線が描かれる
※※※ ここは文字列を書く必要はないが、""のように空の文字列を入れておかないと、それ以後の --field と「追加的引数」の対応がズレてしまう。
フォーム・ダイアログ中にテキストを書きたい場合、共通オプションの --text="アイウエオ" を使うこともできるが、これは一つのダイアログ中で一度しか使えない。LBL タイプの --field は何度でも使える。
追加的(extra argument)な引数はコマンドの最後にまとめて書くことができる。たとえば
yad --form --field="苗字" "武田" \ --field="名前" "晴信" \ --field="法名" "信玄"
と
yad --form --field="苗字" \ --field="名前" \ --field="法名" \ "武田" \ "晴信" \ "信玄"
は同じことである。前者は --field と「追加的引数」の対応がわかりやすいという利点がある。後者は、「追加的引数」を動的に生成するような場合には便利である。じつのところ --field と「追加的引数」は、それぞれ順番に 1 対 1 対応していればいいので
yad --form --field="苗字" \ --field="名前" "武田"\ --field="法名" \ "晴信" \ "信玄"
としても、前の 2 つと同じである。これはおそろしく見づらい。やめてマジで。
リストというよりは、表を作るダイアログである。選択された行内容を --separator で区切って出力する。
「--column=ラベル:タイプ」でコラムの属性をセットする。表示される値は、「追加的な引数」(extra argument)として指定する。「追加的な引数」は「1 行 1 列、1 行 2 列、…、1 行最終列、2 行 1 列、…、最終行最終列」の順で書く。
コラムのタイプは次の通り。
yad --list\ --column=TEXT:TEXT\ --column=NUM:NUM\ --column=FLT:FLT\ --column=CHK:CHK\ --column=RD:RD\ --column=IMG:IMG\ --column=HD:HD\ --checklist\ --radiolist\ --separator="|"\ --multiple\ --editable\ --print-column=1\ --expand-column=0\ --search-column=1\ --limit=100\ --ellipsize=MIDDLE\ --dclick-action=\ --regex-search\ --width="400"\ --height="200"\ text1 1 1.1 true true gtk-ok hidden\ text2 1 2.2 false false gtk-cancel hidden
--list で活躍するのが、共通オプションの --rest FILENAME で、「追加的変数」を収めたファイルのファイル名を指定することができる。
デフォルトでは OK ボタンと Cancel ボタンが現れる。共通オプション --button でボタンを追加し、それぞれのボタンが押されたときの終了ステータスをセットしておくと色々使える。終了ステータスを捕えて標準出力(選択された行のテキスト)をどう処理するか分岐させるわけである。
プログレス・バーに与える値は、すべてのオプションのあとで与える。
yad --multi-progress\ --bar=twenty:NORM\ --bar=thirty:NORM\ --bar=forty:NORM\ "20"\ "30"\ "40"
NORM の代わりに RTL とすると、バーが右から進む。
ダイアログ・オプションは yad プロセスを一つ作るごとに一つしか使えない。しかし、あらかじめ複数の yad プロセスを作成し、それを新たに作成した yad プロセスからまとめて扱う仕組みがノートブックである。
yad --plug=12345 --tabnum=1 --text="first tab with text" &> res1 & yad --plug=12345 --tabnum=2 --text="second tab" --entry &> res2 & yad --notebook --key=12345 --tab="Tab 1" --tab="Tab 2"
1 番目のプロセスと 2 番目のプロセスが、出力をres1 ファイルと res2 ファイルに出力しているのは、両方とも標準入力に出力すると出力が混ざってしまうからだろう。
1、2番目のプロセスは共有メモリを使って 3 番目のプロセスと通信する。そのときの共有メモリのキーを --plug オプションと --key オプションで指定する。(使い終わったあと、何かの間違いで共有メモリが残ってしまった場合は、ipcrm -M 12345 のようにして手動で削除してやる必要があるかもしれない)
トレーの中にアイコンを出したりするらしいが、まだちゃんと確かめてない。
なにか。もう、めんどい。
標準入力から、0〜100 の数を受け取り、プログレス・バーを進める。ターミナルから
$ cat | yad --progress 10 20 30
のように打ってやると、
のような進捗バーを手動で伸ばせる。好き放題に進捗せよ。
ターミナルから
$ cat | yad --text-info --listen abc def
のようにすると、逐次テキストが追加表示される。
--listen でなく --file="ファイルのパス" を指定すると、その内容が表示される。--wrap でテキスト・ラップ。
つまみをスライドさせて数を入力する仕組み。
yad --scale --min-value=1 --max-value=100
のようにすると、OK を押して終了したときの数が標準出力に出る。
--print-partial オプションをつけると、変更された数が逐次出力される。次はその出力をパイプを使ってプログレス・バーに流し込んで遊んでいるところ。
yad --scale --print-partial | yad --progress
おわり