[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 メーリングリストの案内