今開いている秀丸に対して grep したい
コーディングしていて「今開いている秀丸に対してのみ grep したい」というケースがあります。
開いているソースコードのフォルダが分散していて、かつ根っこから grep するにはあまりにも量が多いような場合です。
ただ、現時点(v8.01)の秀丸には、このような機能はないため、自力で何とかしなければなりません。
秀丸のマクロは足掛け 15 年ですが、本当に便利になりました。
マクロが DLL と連携できるようになったときはかなり度肝を抜かれましたが、いまや、外部アプリへの標準入出力までサポートされているので、高度な処理がとても簡単になりました。
外部アプリは Windows ネイティブでなくてもかまわず、例えば Ruby、Python、Perl のようなスクリプト言語から、Java、C# などでも可能です。
今開いている秀丸に対して grep したい場合、HMJRE.DLL を使用して秀丸互換の正規表現で検索するのがもっともよいのはわかってはいるのですが、いくつかの理由により*1 *2 *3 *4 *5、外部アプリで実装しようと考えています。
Windows には findstr というコマンドがあって、これは実は地味に正規表現に対応しています。だけどサブセットのサブセットぐらい(1 日で実装できそうな感じ)の正規表現しかなくて、実用になりません。
Haskell は言語として正規表現に対応しています。Haskell の正規表現の表現力がどれぐらいあるのかは実はよくわかっていません。UTF-8 で使用できるので多言語環境でも問題ありません(UTF-16 ⇔ UTF-8 の変換は必要ですが)。
じゃあ Haskell で実装してみようかな、と思って findstr でちょこっと試してみた感じだと、秀丸の runex を使用して UTF-16 で標準入力に流し込むのがうまくいきません。
runex // "findstr /R /C:[a-z] /", "findstr /R /C:中 /", 1, 4, "", 7, "", 7, "", 0, "", 1, // 0 は非表示 0, // 1 はリダイレクト中再描画しない 0; // 0 だと ANSI、2 だと Unicode
上記は、現在秀丸で選択中の内容に対して、findstr を使用して検索します。このマクロを適当な名前で保存して、全選択して実行すれば、「中」が含まれる 2 行がヒットするはずです。だけど、runex の最後の引数を 2 にすると、処理が秀丸に戻ってきません。漢字をやめて ASCII の正規表現に変更したりすると処理が戻ってきます(ヒットしてはいけない行がヒットしますが、これは findstr のバグか仕様でしょう)。
この違いは何なんでしょうね。
というところでちょっと飽きちゃって、変換フィルタで実装していた続きを再開しました。
試行錯誤しながら、とりあえず検索対象から検索文字を見つけるコードを組み立てることができるようにはなりました。再開した理由として、HMJRE.DLL のヘルプを見ていて、Jre2SetCodePage という API を見つけて、どうやら Windows のコードページが指定できるので、「なるほど、API は JRE32.DLL と互換だから関数の引数には char * を渡すんだけど、実際には Jre2SetCodePage(&jre, 1200); re2Compile(&jre, (LPSTR)L"[あ-ん]+"); みたいにできるんだな」ということで、意欲がわいてきたわけです。
だけど実際には hmjre.dll関連で質問にあるとおり、UTF-16 を使用することはできないんです。
やる前にググれってこってす。夜が明けてしまいました。
メールで問い合わせをすれば、個別に秀丸内部の文字コード関係の情報を教えてもらえるかもしれないのですが、さてどうしましょう。
*1:HMJRE.DLL のドキュメントはちょっとわかりづらい
*2:マクロから使用可能な FindGeneral という関数は、やはりマクロから動作させなければならないらしく、変換フィルタとして実装した DLL ではあいまい検索のオプションを読み取ってくれない
*3:あいまい検索は個人的に使用したことが一度もないので、自分用に作る分にはサポートしなくてもよいんだけど、FindGeneral は単語の検索オプションがないので、これは運用上痛い
*4:FindGeneral は文字列の位置をインデックスで返すんだけど、それが何行目なのか、というのは自分で計算しなきゃならないので、地味に面倒くさい
*5:HMJRE.DLL を使用しないのなら、外部アプリで作るのが非常に簡単そうだ