= dmenuをいじって使いやすくする = 実験レポート風に書こうとして途中で面倒になったので文章の構成が変になったかもしれない。 == 概要 == dmenuはX上で動作するコマンドタイプのランチャである。元々はdwmのために開発されたものだが、他のウィンドウマネージャと合わせて使うことも可能。普通に使うとパスの通っている全てのコマンドが辞書順でメニューに表示されるが、膨大な量になる上、実際にランチャから起動したいものはその中のごく一部である。<>そこで、ランチャから起動して使いたいコマンドだけを表示することができないか試したらできてしまった。 == dmenuの動作 == `dmenu`単体では完全なランチャとしては動作せず、2つのシェルスクリプト`dmenu_run`と`dmenu_path`の補助により、ランチャとして動作する。 * `dmenu` - 標準入力から行区切りの文字列を入力し、それらを要素とするメニューを表示して、選択されたものを標準出力に出力する * `dmenu_run` - `dmenu_path`によって得られたプログラム一覧を使って`dmenu`を起動し、選択されたプログラムの起動を行う * `dmenu_path` - パスの通っている全てのプログラムを列挙し、行区切りで出力する。出力は`~/.dmenu_cache`にキャッシュする 以下にdmenuの動作概念図を示す。 {{attachment:dmenu.png}} == やったこと == 1. おもむろに`dmenu_run`を眺める。 {{{ cat `which dmenu_run` }}} 1. やっていることは非常にあっさりしていた。これはいける、と確信を得る。 {{{#!highlight sh #!/bin/sh exe=`dmenu_path | dmenu ${1+"$@"}` && exec $exe }}} * `$@`にはdwmから与えられるフォントや色の情報が入っており、dmenuはこれらを引数として受けとることでdwmのバーと同じ見た目を実現する * `dmenu`は何かが選択されたときに0を返すので`&&`でつないでいる 1. 今回は自分の使いたいコマンドだけをメニューに出したいので、`dmenu_path`は使わない。改行区切りであれば何でもいいので、とりあえず`~/.dmenu_list`という名前で一覧を書いて保存しておく。 {{{ firefox thunderbird libreoffice xlock nitrogen }}} * 最後に空行があるとメニューに空のエントリが出てしまうので空行は入れない * それぞれのエントリはそれだけでコマンドとして実行できる(パスが通っている)必要がある * 今回はやらなかったが、多分この辺は何とでもなる。少し余分にスクリプトを書けば、例えば短い名前とフルパスの表を作っておいてあれこれすることもできるだろう 1. あとは`~/.dmenu_list`を`dmenu`の標準入力に投げ込めば良いので、スクリプトをでっち上げる。ファイルは`~/bin/dmenu_personal`とした。 {{{#!highlight sh #!/bin/sh exe=$(dmenu < $HOME/.dmenu_list) && exec $exe }}} * ちなみに`-l`オプションでメニューを複数行表示(行数は`-l`の後で与える)に、`-b`で下にメニューを表示するようにできる。これら二つは併用できない。 1. とりあえず、単体で問題なく動作することを確認 {{{ dmenu_personal }}} 1. dwmの`config.h`を書き換える {{{ < static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; --- > static const char *dmenucmd[] = { "/home/clear/bin/dmenu_personal", "NULL" }; }}} * フォントや色はdwm側でなく、dmenu_personalの方で引数を与えて設定することにした。変更時再コンパイルする必要がなくなる * ランチャが使えるようになったのでショートカットキーを大幅削減 1. dwmを`make`、動作確認 1. 動いた == まとめ == 今回のようなことができたのはひとえにdmenuの設計のおかげ。いい感じに機能を分割してあるおかげで柔軟性が高い。