2019年2月9日土曜日

サクラエディタに改行をまたぐ検索・置換を実装する

●長いので結論だけ
サクラエディタに制限なしの「改行をまたぐ検索・置換」を実装してみた.
https://github.com/yoshinrt/SakuraVz

●技術的な話
サクラエディタの前は WZ Editor しか使ってなかったから (そして Wz では普通にできていたから) 知らなかったけど,多くのエディタでは改行をまたぐ検索・置換ができない,または行数に制限がある.

これは,大抵のエディタでは内部で行単位でデータ管理しており,次の行データと連結して検索しない限り例えば /\n\n+/ のようなパターンはマッチしない.じゃあらかじめ何行連結してから検索するの? というところで行数制限が発生し,例えば EmEditor では設定した行数以上にマッチする検索は出来ないし,サクラエディタでは 1行も連結しないので改行をまたぐ検索は一切できない.
自分は s/\n\n+/\n/g みたいな感じで空行を圧縮する置換をたまにするので,行数制限は不便.というわけで,行数制限がない改行をまたぐ検索・置換をサクラエディタに実装することにした.
(ちなみに最初から全部連結しとけば? というのは効率・処理速度の観点でやらない)

サクラエディタでこれをやるには,正規表現エンジン (RE エンジン) 側にとある機能が必須になる.それはパターンにマッチ・非マッチという結果以外にもう一つ「パターンの途中までマッチした」という結果を返す機能.
例えば,検索パターン /\n\n+/ で検索対象文字列 "aaa\n" を検索しても普通はマッチしないが,パターンの途中 (\n の一個目) まではマッチしているので,「途中までマッチした」という結果を RE エンジンが返す.呼び出し側はその結果を受けて,検索対象文字列に次の行を連結して再度検索を行うことを,完全にマッチ or マッチ失敗するまで繰り返すことで,行数制限がない検索することができる.

この機能を持っている RE エンジンは自分が探した限り PCRE2 (partial match) か Hyperscan (streaming mode) しか見つからなかった.今回はより使いやすそうな PCRE2 を使用することにした.bregonig (onigmo) の機能不足により,検索パターンをこねくり回したりしていた記述も PCRE2 のオプション一発で解決できるので,ソースコードもスッキリ出来て一石二鳥ヽ(´ー`)ノ

ただし,PCRE2 では partial match モードな置換は出来ないので,予め partial match モードで検索し必要な行数を連結した文字列に対して,置換を行う必要があった.