モジュール内で関数を定義する
前回は、単純な宣言のみのモジュールの作り方について説明しました。今回は、モジュール内で定義した関数をオプションから呼び出す方法を紹介します。
入出力フィルター
greple の入出力フィルターについては以前の記事で紹介しました。
フィルターには --if
, --of
, --pf
の3種類があって、入力や出力に対して適用するフィルターコマンドを指定することができます。今回紹介するのは、コマンドではなく、モジュール内で定義した関数をフィルターとして利用する方法です。
-Mmsdoc モジュール
greple の msdoc
モジュールは、Microsoft Office のファイルからテキストを抜き出して検索対象にするものです。
オプション指定
まず、オプションの定義方法を見てみます。
__DATA__
option default --if '/\.(doc|ppt|xls)[xm]$/:&__PACKAGE__::extract_content'
ここでは、default オプションとして --if
を指定しています。つまり、このモジュールを指定すると、常にこのフィルターが適用されることになります。
まず、ファイル名が /\.(doc|ppt|xls)[xm]$/
にマッチするかどうかをチェックします。つまり docx, docm, pptx, pptm, xlsx, xlsm のいずれかの拡張子を持っているかをチェックして、この条件に当てはまると、その後で指定されている入力フィルターが適用されます。
以前コマンドを指定していた部分に &__PACKAGE__::extract_content
と書かれています。このようにコマンド部分が &
で始まると、コマンドではなく関数が実行されます。__PACKAGE__
は、モジュールのパッケージに展開されるので、この場合は App::Greple::msdoc
と書いたのと同じ意味です1。
結果として、docx 等のファイルを開くと App::Greple::msdoc::export_content
という関数が実行されるようになります。
関数定義
内容を簡略化すると、このようになります。
package App::Greple::msdoc;
use App::optex::textconv::msdoc qw(to_text get_list);
sub extract_content {
my %arg = @_;
my $file = $arg{&FILELABEL} or die;
my $pid = open(STDIN, '-|') // croak "process fork failed: $!";
binmode STDIN, ':encoding(utf8)';
if ($pid) {
return $pid;
}
print to_text($file);
exit;
}
1;
greple #17 関数インタフェースで説明したように、ファイル名は FILELABEL
という名前付きパラメータとして渡されます。
フィルター関数は、プロセス管理を行うことが期待されています。つまり、入力フィルタであれば、フィルター自体は別プロセスとして動作し、元のプロセスは標準入力からデータを読み込みます。これを行っているのが以下の部分です。親プロセスは、何もせずに return します。
my $pid = open(STDIN, '-|') // croak "process fork failed: $!";
if ($pid) {
return $pid;
}
子プロセスは、受け取ったファイルの内容をテキストに変換して、標準出力に書き出します。
実際の変換処理は App::optex::textconv::msdoc
という別モジュールを利用しています。このモジュールで定義される to_text
という関数を渡すと、その内容がテキストとして得られます。内容を書き出したら、子プロセスは exit
します。
まとめ
独自に実装した関数をモジュールから呼び出すことで、greple の持つ機能を自由に拡張することが可能です。そのため、greple は単なる検索ツールではなく、テキスト処理のフレームワークとして機能するようになります。
SEE ALSO
- https://qiita.com/kaz-utashiro/items/5b6bcbe54891b3bd9db5
- https://qiita.com/kaz-utashiro/items/eb8c7067e6de34842fe3
- https://qiita.com/kaz-utashiro/items/165e744d4250adedc4c1
- https://qiita.com/kaz-utashiro/items/439e6abcecf36c520703
- https://qiita.com/kaz-utashiro/items/24ac0b8fdd30b598e069
- https://qiita.com/kaz-utashiro/items/a1ba4e3d07cf37dc25e3
- https://qiita.com/kaz-utashiro/items/0c8c944c17a72724b771
- https://qiita.com/kaz-utashiro/items/8783c2fd0cc4315b9a3d
- https://qiita.com/kaz-utashiro/items/84f5a6be6bf996076c64
- https://qiita.com/kaz-utashiro/items/ebc7ea99f800cfc8c90c
- https://qiita.com/kaz-utashiro/items/25a14e75380c39b5e0af
- https://qiita.com/kaz-utashiro/items/ebbeb8a5538a15ff04fc
- https://qiita.com/kaz-utashiro/items/b265deef9c9b1953a414
- https://qiita.com/kaz-utashiro/items/2b20e0226cffde213ce0
- https://qiita.com/kaz-utashiro/items/16b5142ef7a89aa35380
- https://qiita.com/kaz-utashiro/items/d19fe5ee859f31ce172c
- https://qiita.com/kaz-utashiro/items/09a5f5cf08ce314e2add
- https://qiita.com/kaz-utashiro/items/6e4b1f51455e587ef743
- https://qiita.com/kaz-utashiro/items/010f141f17e855aab4fc
- https://qiita.com/kaz-utashiro/items/88a70cbdb9cc6c7a4520 ←イマココ
-
main パッケージに export すればパッケージを指定する必要はありません。 ↩