Zshell の補完の設定など


xanim 2.801

xanim の最新. 2.8 からは, 一部動画フォーマットで, モジュールを実行時に動的にロードす るようになった. モジュールは, まえもってコンパイルしたやつだ. たしかライセンスの関係で全 部は公開できない奴を, 昔はライブラリとして static link する形式で quick time とかを再生してたのだが, 今回は, 別ファイルになっていて, 実行時に動的にリンクするようになった.

これにしたがって, 昔は Imakefile で static link するオブジェクトファイル を指定して Makefile を生成していたのが, そういう設定を一切せんでも xmkmf && make でコンパイルできる, ようになってれば世話ないわいな. 全く Imake というのは底無しのアホタレじゃのう. Xlib.h すら見付けよらん. GNU/bash の configure からは想像も付かんほどのアホたれじゃ. 結局 Makefile の CFLAGS に自分で -I オプションを追加することとなった.

ダイナミックリンクモジュールは, xanim のサイトで配っている. これを

/usr/local/xanim/mods
というディレクトリに置いとけば, quicktime とかを再生するときは, 勝手に読み込まれて再生される. 新しい動画フォーマットが再生出来るようになったときも, 本体は コンパイルし直すことなく新しいモジュールをこのディレクトリに置くだけで, 対応できるようになるということだ. プラグインみたいなもんかのう.

Zshell その後 compctl について

zsh は具合が良い. これは久々に遊べるプログラムであり, しかも断然具合が良い. 使う喜びがある. ハデな GUI も良いが, なんつうか, こういうプログラムをうまく使ってこそ, コンピュータを使ってい るなあという気がするのは, 俺だけであろうか. これは, UNIX 的な計算機の使い方が到達した, 一つの極点であろう. 専ら shell から作業せねばならない root こそ, この恩恵を受けるべきである から, 今や root も zsh ユーザである. 特に, 今までいちいちしょうもない shell script を書いていたのが, for 文とかが対話的に使えてその場で実行できるのとかが, root の時に非常に嬉しい. コレがあれば, GUI を捨てても良い.

アホ的にいじくった結果, configure つまり, autoconf で生成される, パッ ケージの Makefile その他を設定してくれるあの configure に関しては, --help オプションを実行して得られるオプションのリストから動的に, つまり, 今いじくっている configure に応じて補完候補を取得するようにした.

というわけで, ここ数日 compctl をいじくっていたわけだ. まだ, 全部わかったわけではないが, 判った範囲では, 実は意外と単純なので, 要点を紹介しよう. 何がめんどくさいかというと, 制御コマンドが sendmail みたいに 1文字で, しかも引数にも使われそうな文字なので, compctl のステートメントが読みにくい. めんどくさいのはそれだけだ.

もっとも基本になるのは, どのプログラムはどういう補完をするか, という設定だ. 書き方は,

compctl 指示 コマンド名(のリスト)
である. 指示は, 引数を必要としないものもあれば, ファイル名のパターンなどの引数をとるものもある. 例えば,
compctl -/ cd chdir dirs pushd
とやると, cd と chdir と dir と pushd は ディレクトリだけを補完する. となる. 他にも, 例えば
compctl -g '*.(bz2)' bunzip2
とやると, bunzip2 に関しては, ファイル名のパターンが `*.bz2' のものだけ を補完対象に選ぶ. `-g' は引数をとるタイプの補完の指定ですな. ファイル名やら, キーワード(の配列)やら, ファイル名のパターンやら, 実行可能ファイルだけとか, いろんな指示が書けるので, 詳しくは, info の `Programable completion' の `Simple flags' を見てくれ.

コマンドによっては, 状況によって補完候補を変更したいものもある. そういう場合に備えて, 上で紹介した基本となる指示を組み合わせることで 条件分岐がかけられるようになっている. いちばん単純なのは, ある場合には, こういう補完をし, それがダメな場合は違うやりかたで補完しよ う, という指示だ. これは, こういう

compctl 指示1 + 指示2 + ..... コマンド名のリスト
この書式の意味するところは, リストに示されるコマンドに関しては, 指示1 の補完がダメだったら 指示2 を試す. 以下略. ということだ. だから,
compctl -k options + -f hogehoge
これで, コマンド hogehoge については, 最初にリスト `options' から補完し, これがダメだったら, (たとえば, オプションに無い文字列を入れたりしたら) ファイル名から補完するといわけだ. オプションの補完がうまく動くためには options にちゃんとそのコマンドのオ プションが入っている必要があるが, これについては後述.

しかしながら, 条件分岐は, 「この場合にはこう, こっちはこれ, それ以外はこれ」というふうに書きたい場合も多い. if then else 方式だ. 無論, zshell はそういう書き方が出来るのであり, それゆえに, 俺などが はまっているわけだ.

その場合の compctl の書き方は, 次の通りである. もっとも単純なのは, これで,

compctl -x 条件 指示 -- コマンドリスト
その意味も自明だろう. このコマンドに関しては, ある条件の時は, この指 示で 補完しろ, ということだ. -x のあとの `--' に注目. これが -x の効力の及ぶ範囲を限定しているのだ. 次は, 「それ以外」を指示する場合. これは, さっきの `+' を組み合わせればできる.
compctl -x 条件 指示1 -- + 指示2 コマンドリスト
これで, 条件を満たしていれば 指示1 で, それ以外は 指示2を使う. 条件は, 現在入力中の語に関するものや, 他にもいろいろ, それこそ思い付く限 り書けるので, あとは info の Programable completion の Extended Completion のところを見てくれ. 「もう, ええわ」つうぐらい, わんさか載ってるぞ.

いろいろ条件を書けても, 補完リストをダイナミックに取得できなければしょう がないわけで, そのやりかたを紹介しよう. といっても, これは別に zshell に特殊なやりかたではなく, shell script における一種の関数や変数の定義みたいなものなのだ. たとえば変数 `urls' をzshell の設定ファイルで次のように定義してやると, zshell を起動すると, 変数 `urls' にはじぶんの navigator の bookmark から 取得した url が入る.

urls=( \
     `grep \<A ~/.netscape/bookmarks.html |\
      sed -e 's/.*HREF\=\"//' -e 's/\".*//'`\
      )
bookmarks.html から grep で A tag を取り出して, sed で url だけを切りだ し, 逆 quote を使って標準出力を変数に代入している. grep に A tag を読 ませるのに, リダイレクト記号 `<' をバックスラッシュでエスケープしてい るのに注目. このシェル変数を wget の補完候補に使うには,
compctl -k urls wget
である.

俺の場合は bookmark なんか, そうそう増えないので zshell を起動するときに 一回読み込めば十分だが, configure なんかは configure ごとにオプションが違うわけで, このやりかた では対応できない. そんなときは補完リストに shell function を実行した 結果を使うといい. とりあえず get_command-name_option 関数をこんなふうに定義しておこう

get_command-name_option (){
	reply=(
		hogehoge
		)
	}
シェル関数 get_command-name_option を引数無しで呼ぶと, その戻り値は get_command-name_option の局所変数 reply である. reply にコマンドのオプションがセットされるように, hogehoge を記述すれば 良い, たとえば, hogehoge はこんな感じ.
get_command-name_option (){
	reply=(
		`grep \<A ~/.netscape/bookmarks.html |\
		sed -e 's/.*HREF\=\"//' -e 's/\".*//'`\
		)
	}
さて, このシェル関数を補完候補に使うには, compctl の `-K' オプションだ. K は大文字だ.
compctl -K get_command-name_option command-name
これで, ユーザが command-name を実行したときは, zshell が get_command-name_option を実行して, その結果から補完候補を取得する. つまり, その都度いちいち bookmarks.html を grep して url を取得して, 補完 候補に使うというわけだ.

このテの補完の例には, おまけでついてくる compctl で man のあとには マニュアルの名前を補完するというやつがある. これはかなり超絶で, 俺もいまいち理解不能であるが, なるほどちゃんと動くのだ. それでは最後にわしがとりあえず作った configure のオプションを補完する compctl を紹介しよう.

configre_opts () {
	reply=( `./configure --help | awk '/--/{print $1}' |\
	sed -e 's/--//' -e 's/=.*/=/'` )
	}
compctl -x 'n[1,=]' -f -- + -P -- -K configre_opts configure
configure を実行すると, その configure を --help オプションで実行した結 果から sed と awk でオプションだけ切りだし, それを `--' のあとの補完リス トにしている. ただし, プロンプトが `=' のあとにあった場合は, ファイル名から補完する. これで, `--prefix=' とかはディレクトリパスを補完して指定できる. まあ, おそらくデキとしては最低の部類に入るのであろうが, とりあえずこれでも動くぞ. いちいち --help しなくても, オプションのリスト くらいは判るし, タイプミスも無くなるのだ.

だいたいこういう粗筋が判っていれば, もう info や man も読めるはず. すげえ compctl ができたら, ゼヒ俺にも教えてくれっす.