カレントバッファに対して、エディターedないしexの、g/RE/pと同じ ようなことをする。
コマンドの中で(作業用に)バッファを作ってみたいなあ、そうする といろいろ自由が利いてよさそうだなあ、第一面白いだろうなあ、今後 のためにも手がけておきたいなあ、というきわめて不純な動機で書いて みたものです。
grepモードってのが有名ですが、Mule for Windowsで試してみてどー
もうまく使えず、それ以来敬遠しています(かわいそう、なんでしょう
ね)。けっきょくシェルウィンドウからgrepを走らせる毎日。
ま、それはそれでいいんですが、ちょうどedのように、現在着目して
いるバッファに対して広域指令でパターン照合を行ない結果を印字する、
なんてことができるといいかもな、ということで、それらしいものを書
いてみました。
M-x g/re/p <RET>
と実行すると、
Pattern?:
と聞いてきます。探索したい文型を入力すると、結果が*g-re-p:result*
というバッファに表示されます。
例によってエラーや例外の処理は考えに入れてません。
バッファを作るためにcreate-file-buffer
という関数
を呼んでいます。このg/re/pコマンドを何回実行しても同じ結果バッファ
を使いたいので、もし同名のバッファがあればそれを使い、ない時だけ
新規作成、という風にしました。
delete-region
は結果バッファが既存の場合に、前回の
実行結果を消去するため。このときにset-buffer
でカレ
ントバッファを切り替えている(筈)ため、もとのカレントバッファに
戻します。こういうのはsave-excursion
を使うのがいい
のかも知れません。
それから、単に結果を別のバッファに表示するだけじゃつまらないの
で、パターンが出現する行を数え上げ、その行数をエコー領域に表示す
るようにしてみました。
数え上げ自体は簡単なことですが、せっかくだからマクロ(Emacs
Lispのマクロね)を作って使ってみました。incf
という
ヤツです。
文型が見つかった行を結果バッファに格納するために行内を動き回っ た挙げ句、次の行頭(きっと)に移動してそのままループを続けますが、 これは意図してのことです。g/RE/pとしては文型に合致する行があれば 目的は達成しているので、次の行からの探索に進んでもかまわないとい う考えです。
なお、次の行に進む時にnext-line
を使うと、行末に改
行文字がない場合にエラーとなってしまいます。ので、
forward-line
を使うようにしています。
(実は既に掲載済みのvi
風カットアンドペーストでは、next-line
を使ってい
ました。が、今回こっそり直してあります)
1: (defmacro incf (a) 2: `(setq ,a (1+ ,a)) 3: ) 4: 5: (defun g/re/p () 6: (interactive) 7: (let ((patter) 8: (npat 0) 9: (here) 10: (end (point-max)) 11: (bufname "*g-re-p:result*") ; name of result buffer 12: (momo) ; result buffer 13: (cur (current-buffer)) ; current buffer 14: ) 15: (if (setq momo (get-buffer bufname)) 16: () 17: (setq momo (create-file-buffer bufname))) 18: (set-buffer momo) 19: (delete-region (point-min) (point-max)) ; clean up result buffer 20: (set-buffer cur) 21: (setq pattern (read-input "Pattern?: ")) 22: (save-excursion 23: (let ((from) 24: (to) 25: ) 26: (beginning-of-buffer) 27: (while (and (setq here (search-forward-regexp pattern end t)) 28: (> end here)) 29: (beginning-of-line) (setq from (point)) 30: (forward-line 1) (setq to (point)) 31: (append-to-buffer momo from to) 32: (incf npat) 33: ) 34: ) 35: (switch-to-buffer momo) 36: (message (format "Pattern %s found in %d line(s)" pattern npat)) 37: )) 38: )
バッファを作って自分で表示させてみると、なんか、Emacs Lispプロ グラマーになったって感じがしますね(笑)。それに、けっこう長い。 ってもまだ直線的なフローでしかありませんが。
結果バッファに格納する各行の先頭に、行番号をつけられるといいな と思います。でもそこまでやるならgrepモードを使えるようにするんだ ろうなあ。
なお、結果バッファをしまっている変数のmomo
という
名前は、fooやbarと同じで、ぼくにとっての〈名称変数〉です。気にし
ないでください。
(2000.09.27)
(C) ©Copyright Noboru HIWAMATA (nulpleno). All rights reserved.