[Mew-dist 04237] Re: mew-summary-search で漢字検索
Kazumasa Utashiro
utashiro at example.com
1998年 3月 19日 (木) 03:08:16 JST
From: SAKAI Kiyotaka <ksakai at example.com>
Subject: [Mew-dist 03257] Re: mew-summary-searchで漢字検索
Date: Wed, 24 Dec 1997 11:21:19 +0900
> >> そうです。imgrep が (まだ?) 漢字の検索に対応していないためです。
>
> > 正直いってどう実装すればいいかわかりません。日本語だけでいいのでしょうか。
> > ASCII JIS まじり文とかはどうするんでしょう。引数のコードとか、折り返しと
> > か、ヘッダは encode されていたりして。
>
> そういえば、歌代さんの作った perl script に mg というのがあって、漢字
> の検索や行の折り返しにも対応していますが、これを参考にする (コードを貰
> う?) のが手かもしれません。
今日 WIDE 合宿の BOF で話題になったので、次のミーティングの間 TSS しな
がら作ってみました。検索文字列の途中で改行していても見つけます。やって
いることは、そういう正規表現を作っているだけです。だから、長い文字列を
指定すると結構とんでもない結果になりますが、不思議とそれなりに動きます。
逆に短すぎる文字列を指定すると間違えます。
非常に adhoc な実装なので、普通の人はこのまま使わないで下さい。しかる
べき方から正式な patch としてリリースして欲しいです。問題点はこんなと
ころでしょうか。
+ 日本語しか考えていない。
+ 引数の文字列は何のコードかわからないので、とりあえず
jcode.pl で自動変換しちゃっている。ユーザが指定できるインタ
フェースもあった方がいいだろう。
+ IM::Japanese を使おうと思ったけど、X0201 仮名を考慮している
せいで EUC と SJIS の判定がうまくできない。
+ body しか対応していない。
+ encoding は考えてない
あと、この修正とは関係ありませんが、コードを眺めたところ、いくつかコメ
ントがあります。
+ いつもファイル全部を読み込んでいるけど、body の検索をしない
ときにはヘッダだけ読むようにした方がいいと思う。
+ 検索するときに eval しているが、これは最初に検索サブルーチン
の定義を eval して、後はそれを呼ぶだけにした方がいいと思う。
+ imgrep には、ファイル名を表示するだけではなく、grep みたいに
行番号と内容を表示する機能もあった方がいい。それで mew に
next-error みたいな機能をつけると、とても便利だと思う。まあ
mg を使っても、かなり近い目的が達成できるんですが。
*** IM/Grep.pm.old Fri Mar 6 17:54:36 1998
--- IM/Grep.pm Thu Mar 19 02:24:09 1998
***************
*** 23,28 ****
--- 23,29 ----
use IM::Config;
use IM::Util;
use IM::Folder qw(message_range);
+ use IM::Japanese;
use integer;
use strict;
use vars qw(@ISA @EXPORT);
***************
*** 290,296 ****
$field =~ s/([@\/])/\\$1/g;
$pattern =~ s/([@\/])/\\$1/g;
! if ($field =~ /^(all|head|body)$/) {
$string = "\$$field =~ /$pattern/om$case_flag";
} elsif ($field ne '') {
$string = "\$head =~ /^$field:.*$pattern/om$case_flag";
--- 291,300 ----
$field =~ s/([@\/])/\\$1/g;
$pattern =~ s/([@\/])/\\$1/g;
! if ($field eq 'body') {
! $pattern = mkpat($pattern);
! $string = "\$$field =~ /$pattern/om$case_flag";
! } elsif ($field =~ /^(all|head)$/) {
$string = "\$$field =~ /$pattern/om$case_flag";
} elsif ($field ne '') {
$string = "\$head =~ /^$field:.*$pattern/om$case_flag";
***************
*** 355,360 ****
--- 359,438 ----
@tmp{@target} = (undef) x @target;
return ( sort {$a <=> $b} keys %tmp );
+ }
+
+ ##################################################
+ ##
+ ## multi-line and multi-byte search
+ ##
+
+ my @in = ('\e\$\@', '\e\$B');
+ my @out = ('\e\(J', '\e\(B');
+ my $in = join('|', (@in));
+ my $out = join('|', (@out));
+ my $shiftcode = '(' . join('|', @in, @out) . ')';
+ my $chargap = '(' . join('|', @in, @out, '\s'). ')*';
+
+ sub mkpat {
+ my($pat, $p) = @_;
+ my $jis = 0;
+
+ # XXX
+ # XXX これは多分 imgrep に移した方がいいでしょう
+ # XXX 日本語以外のことは考えてません
+ # XXX IM::Japanese のコードは EUC と SJIS の判定が弱くて使えない
+ # XXX
+ if ($pat =~ /[\033\200-\377]/) {
+ require('jcode.pl');
+ $pat = jcode::jis($pat);
+ # $pat = IM::Japanese::conv_iso2022jp($pat);
+ }
+
+ for (split(/$shiftcode/, $pat)) {
+ if (/$in/o) {
+ $jis = 1;
+ $p .= $chargap if $p;
+ next;
+ }
+ if (/$out/o) {
+ $jis = 0;
+ next;
+ }
+ if ($jis) {
+ s/../&jis($&)/eg;
+ $p .= $_;
+ next;
+ }
+ # XXX
+ # XXX &mb の部分は EUC と SJIS の処理なんで必要ないんだけど、
+ # XXX とりあえず残してある
+ # XXX
+ s/([\200-\377])?./length($&) > 1 ? &mb($&) : &asc($&)/eg;
+ $p .= $_;
+ }
+ $p =~ s/\Q$chargap\E+$//;
+ length($p) ? $p : undef;
+ }
+
+ sub jis {
+ local($_) = shift;
+
+ s/\W/\\$&/g;
+ $_ . $chargap;
+ }
+
+ sub mb {
+ local($_, @_) = ($_[$[], split(//, shift));
+
+ $_ = sprintf("\\%03o\\%03o", ord(shift), ord(shift)) if @_ == 2;
+ $_ . '\\s*';
+ }
+
+ sub asc {
+ local($_) = @_;
+
+ s/\s/\\s*/ || s/\W/\Q$&/;
+ $_;
}
1;
--utashiro
Mew-dist メーリングリストの案内