nanoを手探ってみる#4:nanorcの読み込み

前回とはトピックが変わり、nanorcを起動時以外にも読み込める機能を実現したことについて書きます。

設定ファイルの読み込みについて

世の中に数多く存在しているLinux系のアプリケーションは、起動時に設定ファイルを読み込みます。設定ファイルはvimのであれば.vimrc、Emacsの場合は.emacs.d/init.el、bashなら.bashrcなどがあり、rcファイルと呼ばれることもあります。ほとんどのアプリケーションでは起動のときだけでなく、実行中のときも明示的に設定ファイルを読み込みなおすことができます。例えばVimなら

:source ~/.my_vimrc

とすれば改めて設定が読み込まれます。もちろんnanoにも.nanorcという設定ファイルがあるのですが、これは起動時にしか読み込めません。そこで、実行時にもファイルを読み込む機能をつけることにしました。

ソースからわかったこと

nanoではmain()内の無限ループwhile (TRUE) {...}でユーザーが打鍵するキーを受け取っていました。また、ユーザーが送ったキーに対応するコマンドを呼び出している関数も見つかったのでこの中身をいじれば新しいコマンドを定義できそうなことがわかりました。global.c内のadd_to_sclist()を使えばsclistにショートカットを登録できるようです。

add_to_sclist()とadd_to_func()

自分で定義した関数をadd_to_sclist()でショートカットに追加してみたところ、とくになにも起こりませんでした。add_to_sclist()で登録する前にadd_to_funcs()で関数を関数一覧に登録する必要があったようで、これをするとうまくいきました。なぜ、ショートカットを追加するのにわざわざ2段階処理を踏むのかは謎です。add_to_funcs()の引数にはint menusというものがあり、これは関数を実行するときのFLAGみたいです。このFLAGにはたくさんの種類がありnano.hの543行のところで定義されています。

#define MMAIN           (1<<0)
#define MWHEREIS       (1<<1)
#define MREPLACE       (1<<2)
#define MREPLACEWITH       (1<<3)
#define MGOTOLINE      (1<<4)
#define MWRITEFILE     (1<<5)
<略>

このFLAGの意味がいまいちよくわかりません。

FLAGの正体

今一度コードをしっかり読んでみると、FLAGはnanoのmodeを表していることがわかりました。MWHEREISなら文字列検索モード、MREPLACEなら文字列置換モード、MWRITEFILEならファイル書き込み(保存)モードといった感じです。Vimはmodeがあるエディタとして有名ですが、nanoはVimととの違いを強調するためにmodelessという言葉で紹介されることも多いです。そのようなエディタが内部でmodeの仕組みを採用していたのは意外でした。

成果

global.cのモード定義のところに

#define MREADRC         (1<<15)

という一文を追加して新たにrc読み込み専用のmodeを用意しました。このFLAGでadd_to_funcs()をした後でadd_to_sclist()をすると、ユーザーが入力したpathから設定ファイルを読み込むことに成功したので、当初の目的は達成です。適切にmodeを設定して、プロンプト表示を出す関数を呼ぶと、modeに対応したヘルプ(ショートカットキーの一覧)も表示されます。ついでに、あると便利な機能としてset autoindentなど設定コマンドを単独で実行できる機能もつけてみました。