2008年2月18日月曜日

D言語でmigemoを使う

 [Migemo: ローマ字のまま日本語をインクリメンタル検索]なんていう仕組みが世の中にあります。これがとにかく便利でたまらないんです。なんで市販の日本語を扱うソフトがこの機能に対応しないのか不思議でしょうがないです。今のところ、対応しているソフトはフリーのものでしか見たことがありません。

 D言語で自作プロンプトをつくりたいな、と思いたち、一人でいろいろ試行錯誤しているのですが、もともとはMigemo対応のプロンプトが欲しいと考えたことに端を発してます。

 ということで、D言語からMigemoを利用できるようにしてみました。利用しているのは香り屋さんのCMigemoです。



main.d
// migemo テスト
import std.stdio;
import std.string;
import std.windows.charset;
import migemo;

void main(string[] args)
{

if(args.length < 3)
{
printf("There is not keyword.\n");
return;
}

cmigemo migemo = new cmigemo("D:\\migemo\\dict");

// mige.open(); // 自動で行われる。

// migemo dict
// dict は sjis だが、std.regexp を利用するために、
// 標準の戻り値は utf8 を返す。
// sjis が必要な場合は、 query_sjis を使う。
string ret;

// utf8
ret = migemo.query(args[1]);
printf("utf8: :%s\n",toStringz(ret));
printf("utf8:toMBSz:%s\n",toMBSz(ret));
writefln(migemo.find_sjis(args[2]));
writefln(migemo.find("テスト"));

// sjis
ret = migemo.query_sjis(args[1]);
printf("sjis: :%s\n",toStringz(ret));


// mige.release();// 自動で行われる。

}


migemo.d
import std.stdio;
import std.string;
import std.regexp;
import std.windows.charset;

pragma (lib, "migemo.lib");

const int MIGEMO_DICTID_INVALID =0;
const int MIGEMO_DICTID_MIGEMO =1;
const int MIGEMO_DICTID_ROMA2HIRA =2;
const int MIGEMO_DICTID_HIRA2KATA =3;
const int MIGEMO_DICTID_HAN2ZEN =4;

struct migemo {};
extern (C) {
export migemo* migemo_open(char* dict);
export void migemo_close(migemo* object);
export char* migemo_query(migemo* object, char* query);
export void migemo_release(migemo* object, char* string);

export int migemo_set_operator(migemo* object, int index, char* op);
export const char* migemo_get_operator(migemo* object, int index);

export int migemo_load(migemo* obj, int dict_id, char* dict_file);
export int migemo_is_enable(migemo* obj);
}


class cmigemo
{

private migemo *m;
private string migemo_path;
private bool open_flg = false;
private string prev_pattern;
public void path(string p){migemo_path = p;}


// コンストラクタ
public this(string path){migemo_path = path;}
public ~this(){if(open_flg)close();}

// migemo 開く
public void open()
{
open_flg = true;
m = migemo_open(null);
migemo_load(m, MIGEMO_DICTID_MIGEMO, toStringz(migemo_path ~ "\\migemo-dict"));
migemo_load(m, MIGEMO_DICTID_ROMA2HIRA, toStringz(migemo_path ~ "\\roma2hira.dat"));
migemo_load(m, MIGEMO_DICTID_HIRA2KATA, toStringz(migemo_path ~ "\\hira2kata.dat"));
migemo_load(m, MIGEMO_DICTID_HAN2ZEN, toStringz(migemo_path ~ "\\han2zen.dat"));
}

// migemo 閉じる
public void close()
{
migemo_close(m);
open_flg = false;
}


// 戻り値は utf8
public string query(string keyword)
{
return query_sub(keyword, false);
}


// 戻り値は sjis
public string query_sjis(string keyword)
{
return query_sub(keyword, true);
}


// migemo文字列取得用サブルーチン
public string query_sub(string keyword, bool sjis_flg)
{

if(!open_flg)open();

char* p;
string s;
p = migemo_query(m, toStringz(keyword));
if(sjis_flg)
s = std.string.toString(p);
else
s = fromMBSz(cast(invariant)(p));

migemo_release(m, p); /* queryの結果は必ずreleaseする */

prev_pattern = s.idup;
return s.idup;

}


// migemo 文字列比較
public bool find_sjis(string sjis)
{
return find(fromMBSz((sjis ~ "\00").ptr));
}
public bool find_sjis(string sjis, string pattern)
{
return find(fromMBSz((sjis ~ "\00").ptr), pattern);
}
public bool find(string text)
{
return find(text, prev_pattern);
}
public bool find(string text, string pattern)
{
// phobos ライブライリを利用しているため、
// text,patternともに utf8 の必要がある。
return (-1 != std.regexp.find(text, pattern, "i"));
}

}

0 件のコメント: