Migemo.query_grouping

概要

Migemoは文字列を受け取り、正規表現を返します。そこで、正規表現で表現できるものならなんでも返していいんじゃないかと、入力文字列を適当に解釈してAND検索やOR検索の正規表現を返す関数を作ってみました。(パーサ部分のソースとそのテスト)
括弧によるグルーピングと、空白によるAND、'|'によるORで表現します。ANDはORより優先されます。("abc def|ghi"という文字列は、(abc & (def | gh))ではなく((abc & def) | gh)と解釈される)。これにより、ほとんどの場合で括弧を使わずに特定ファイルの抽出、さらに別ファイルの追加、という作業をバックトラック無しに表現できます。


例: "c:\doc set|prog"と打つと、C:\Documents and SettingsとC:\Program Filesがリストに出力される。

メソッドの仕様

Migemo.query_groupingは引数を2つとります。1つ目は入力文字列、2つ目は「それ以下の場合Migemoを使わない文字数」です。戻り値は文字列です。下記の場合、abcはMigemo.query("abc")の戻り値に置き換えられますが、dはそのままです。


Migemo.query_grouping("abc|d" 1) //((?=^.*(abc|abc))|(?=^.*d))
パースエラーが発生した場合は空文字列を返します。例外等は発生しません。下記がエラーになる例です。

Migemo.query_grouping("abc|" 1) //ORで終わってる
Migemo.query_grouping("abc " 1) //ANDで終わってる

Migemo.query_grouping("(abc" 1) //括弧が閉じてない((Giraffe+ 0.5.57以前))
Migemo.query_grouping(")abc" 1) //唐突な閉じ括弧

既知の問題

Migemoの一部のように振る舞い、正規表現を返すわけですが、migemo_get_operatorでOR文字列を取得するとかいった作業を一切していません。
もうひとつ、Migemo.queryを通さない文字列を使う場合に、int2charを通さないといけないのですが、それをやってません。CMigemoクラスを少し書き換えてint2charを保持する形にする等、解決法は多くあるとは思いますが、どうでもいいと思っています。
この2つの問題は、「Migemo.query_groupingはMigemo.queryに生成される正規表現Perl式の場合にのみ使用可能」という制限を持って解決としています。

使用例

オートコンプリートにMigemo部分一致を使用してる場合、下記をsiteinit.giraffeに追加することでAND検索等が利用できます。


Giraffe:List:AutoComplete:MigemoPartialMatch@ `text[
s: Migemo.query_grouping(text.path_get_name 1)
s.empty.? [Giraffe:List:AutoComplete:PartialMatch(text).return]
regex: Regex.new(s "i")
Giraffe.AutoCompleteSetList(text [regex.search(param(0).path_get_name)] true)
]
ファイル検索にMigemoを使ってる場合

global.find_MakeSearchFactor: `file[
s: Migemo.query_grouping(file 1)
s.empty.? [s@ '.*']
Regex.new(s "i")
]