An English version of this page is also available.
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
Firefoxにおける日本語でのページ内検索生活を快適かつ高速にする拡張機能です。いちいち漢字に変換しなくても、ローマ字で「kanzi」と入力するだけでそのまま「感じ」とか「幹事」とか「漢字」とかを検索できるようになります。いまいちピンとこない方は、実際に動いてる様子の動画をご覧下さい。 また、ラテン文字の発音記号などを無視する機能もあります。例えば「frederic」で「Frédéric」がヒットするようになります。検索モードを切り替えることで、任意の正規表現でページ内検索を実行することもできます。
また、おまけの機能として、検索ツールバーのカスタマイズ機能もあります。「すべて強調表示」「大文字/小文字を区別」を自動的に有効にしたり、検索で見つかった単語を画面の中央に表示したりといったことができます。
Safari 3風のハイライト機能も含んでいます。「すべて強調表示」の時、内容領域が暗く表示されて、フォーカスされた単語がアニメーションで表示されるようになります。また、検索された語句がページ内のどこにあるのかを示すマークがスクロールバーの横に表示されます。
XUL/Migemoが利用できる場面は以下の通りです。
※Ver.0.3.1から0.6.6までの間、本プロジェクトは本家XUL/Migemoとは別のプロジェクト「XUL/Migemo [Forked Edition]」として進行していました。0.7.0以降は本家の正式な後継「XUL/Migemo」プロジェクト(「[Forked Edition]」が付かない)として進行しています。詳しくはプロジェクトの経緯をご覧下さい。
不具合に遭遇した場合は、まずよくある質問をご覧下さい。それでも解決方法が見つからない場合の障害報告はGitHubのイシュートラッカーにお願いします。
とりあえずこのページを開いた状態で、「/」キーを押してから「nihongo」とローマ字で入力してみてください。検索バーが表示され、「日本語」という文字が検索されるはずです。このようにローマ字で入力するだけで日本語の単語を検索できるのが「Migemo検索」です。
また、このように検索バーが表示されていない状態から自動で検索が始まるモードを「クイックMigemo検索」と呼びます。
入力したローマ字に対応する日本語が辞書の中で複数見つかった場合は、その全てにヒットします。例えば「kanzi」と入力した場合は、「漢字」「感じ」「幹事」「かんじ」「カンジ」などのバリエーション全てが検索対象となります。
なお、コメント欄などの文字入力欄にフォーカスがある場合は、「/」キーではクイックMigemo検索を開始できません。このような時は代わりに「Ctrl-Shift-F」を押してください。
検索中、検索バーの右端に「Migemo」と表示され、そこのプログレスバーがだんだん短くなっていっているのが見えましたか? これはクイックMigemo検索モードを自動的に終了するまでの残り時間を示しています。一定時間が経過すると、Firefoxは自動的にMigemo検索を終了して、通常のWebブラウズの状態に戻ります。
なお、自動的に終了するのを待たなくても、クイックMigemo検索は「ESC」キーを押せばいつでも終了できます。
クイックMigemo検索を自動的に終了するまでの時間は、自由に設定できます(初期設定では4秒)。また、自動的に終了しないようにすることもできます。
今度は「nihongo deno pe-zi nai kensaku」と、スペースキーで言葉を句切りながらローマ字入力してみてください。「日本語でのページ内検索」という文章が検索されるはずです。このようにスペースキーで単語を区切ると、長い文章の検索を行うことができます。
また、大文字での文節区切り、いわゆるSKK方式での入力もサポートしています。「nihongoDenoPe-ziNaiKensaku」と、スペースキーを入力する代わりに文節区切りの位置で大文字で入力(Shiftキーを押しながら入力)してみてください。やはり先ほどと同様、長い文章を検索することができます。
通常のページ内検索中に、Migemo検索に切り替えることもできます。「Ctrl-F」で検索を始めた状態で、検索バー右端の「Migemo」と書かれたボタンをクリックしてください。次の入力から、入力内容がMigemo検索されます。もう一度「Migemo」をクリックするか「通常」をクリックすると、通常の検索に戻ります。
また、ツールバー右端のボタンをクリックせずとも、検索を実行中にもう一度「Ctrl-F」を入力すると、キーボード操作だけで検索モードを切り替えることができます。
Migemo検索は、辞書にある単語しか検索することができません。例えば「汎用人型決戦兵器」のような単語は辞書にないので、「hannyou hitogata kessen heiki」のように、文章として検索しないとヒットしません。また、そもそも辞書に読み方が登録されていない漢字は、いくら頑張っても検索できません。
辞書にない漢字や単語を検索できるようにするためには、ユーザ辞書に単語を登録してください。「Ctrl-Shift-F7」を押すか、XUL/Migemoの設定パネルの「辞書」タブで「辞書マネージャの起動」を選択すると、辞書を管理するためのダイアログが開かれます。
バージョン0.8.0から、任意の正規表現でページ内を検索できるようになりました。検索バー右端の「正規表現」と書かれたボタンをクリックすると、入力した内容が正規表現として解釈されるようになります。
また、通常の検索またはMigemo検索の実行中であっても、「/検索(語句|キーワード)?/」のように前後にスラッシュを付けて正規表現リテラルの形で入力すると正規表現として検索されます。
Firefox 3では、スマートロケーションバー、履歴サイドバー、ブックマークサイドバー、履歴とブックマークの管理ウィンドウでMigemo検索が有効になります。これらの箇所でのMigemo検索を無効にする場合は、XUL/Migemoの設定ダイアログで設定を変更してください。
Thunderbird 2では、スレッドペインのクイック検索でMigemo検索が有効になります。ただしメッセージ本文の検索は負荷が高いため、初期状態では無効になっています。クイック検索でメッセージ本文もMigemo検索したい場合は設定を変更する必要があります。
XUL/Migemoサービスは、英数字の入力に対して正規表現を生成します。生成する正規表現の内容はエンジンによって異なり、初期状態で組み込まれている日本語用エンジンは、ローマ字の入力に対応する日本語の語句の正規表現を生成します。英語用エンジンは、与えられた文字列から始まる英単語のリストの正規表現を生成します。
XUL/Migemoの機能は、JavaScriptのグローバルな名前空間のmigemo
オブジェクトから簡単に利用できます。このオブジェクトにはJavaScriptでいつでも・どこからでもアクセスすることができ、アドオンに限らずWebページ内のスクリプトからも利用できます。
migemo
オブジェクトはユーザが現在選択している言語のエンジンを利用するサービスへの参照になっており、以下のメソッドとプロパティを備えています。
migemo.provider
migemo.version
migemo.lang
migemo.query()
migemo.quieries()
migemo.queryFunctional()
migemo.quieriesFunctional()
migemo.provider
"XUL/Migemo 0.12.0 (ja)"
が返される。migemo.version
"0.12.0"
が返される。migemo.lang
"ja"
が返される。migemo.query(in String aInput)
input
で与えられた入力にマッチするかどうかを調べるメソッドをString
に追加する:
String.prototype.migemoMatches = function(input) {
return new RegExp(migemo.query(input), 'i').test(this);
};
alert('日本語'.migemoMatches('nihongo')) // => "true"
alert('英語'.migemoMatches('nihongo')) // => "false"
input
で与えられた入力にマッチする項目を抜き出す:
function getMatchedItems(list, input) {
var regexp = new RegExp(migemo.query(input));
return list.split('\n')
.filter(function(aTerm) {
return regexp.test(aTerm);
});
}
var list = <[CDATA[
コーヒー
紅茶
緑茶
水
]]>.toString();
alert(getMatchedItems(list, 'cha')); // => ["紅茶", "緑茶"]
migemo.queries(in String aInput)
String
に追加する:
String.prototype.migemoMatchesAll = function(input) {
return migemo.queries(input)
.map(function(aSource) {
return new RegExp(aSource, 'i');
})
.every(function(aRegExp) {
return aRegExp.test(this);
}, this);
};
alert('日本語と英語'.migemoMatchesAll('nihongo eigo')) // => "true"
alert('日本語とフランス語'.migemoMatchesAll('nihongo eigo')) // => "false"
migemo.queryFunctional(in String aInput)
regexp
、terms
、exceptions
の各プロパティを持ったオブジェクト。それぞれの内容は以下の通り。
regexp
プロパティの内容terms
プロパティの内容exceptions
プロパティの内容null
target
に列挙された内容から、input
で与えられた入力にマッチする項目を抽出する:
var target = [
'日本で英語を話す',
'英語を日本で話す',
'日本語fooooo!!',
'日本語hooooo!!'
];
var input = 'nihon go -foo';
var result = migemo.queryFunctional(input);
var regexp = new RegExp(result.regexp, 'i');
var terms = new RegExp(result.terms, 'gim');
var exceptions = result.exceptions ?
new RegExp(result.exceptions, 'gim') :
null ;
var matchedTerms = [];
var output = target.filter(function(aTarget) {
if (exceptions && exceptions.test(aTarget))
return false;
if (regexp.test(aTarget)) {
match = aTarget.match(terms);
matchedTerms = matchedTerms.concat(match);
return true;
}
});
alert(output.join('\n')+'\n---\n'+matchedTerms.join(', '));
// 結果:
// 日本で英語を話す
// 英語を日本で話す
// 日本語hooooo!!
// ---
// 日本, 語, 語, 日本, 日本, 語
migemo.queriesFunctional(in String aInput)
regexps
、terms
、exceptions
の各プロパティを持ったオブジェクト。それぞれの内容は以下の通り。
regexps
プロパティの内容terms
プロパティの内容exceptions
プロパティの内容null
target
に列挙された内容から、input
で与えられた入力にマッチする項目を抽出する:
var target = [
'日本で英語を話す',
'英語を日本で話す',
'日本語fooooo!!',
'日本語hooooo!!'
];
var input = 'nihon go -foo';
var result = migemo.queriesFunctional(input);
var regexps = result.regexps.map(function(aSource) {
return new RegExp(aSource, 'i');
});
var terms = new RegExp(result.terms, 'gim');
var exceptions = result.exceptions ?
new RegExp(result.exceptions, 'gim') :
null ;
var matchedTerms = [];
var output = target.filter(function(aTarget) {
if (exceptions && exceptions.test(aTarget))
return false;
if (regexps.every(function(aRegExp) {
return aRegExp.test(aTarget);
})) {
match = aTarget.match(terms);
matchedTerms = matchedTerms.concat(match);
return true;
}
});
alert(output.join('\n')+'\n---\n'+matchedTerms.join(', '));
// 結果:
// 日本で英語を話す
// 英語を日本で話す
// 日本語hooooo!!
// ---
// 日本, 語, 語, 日本, 日本, 語
また、アドオンからは以下のメソッドも利用できます。これらのメソッドは戻り値としてJavaScriptの正規表現オブジェクトを直接返します。
migemo.getRegExp(in String aInput, [in String aFlags])
"im"
として扱う。input
で与えられた入力にマッチするかどうかを調べるメソッドをString
に追加する:
String.prototype.migemoMatches = function(input) {
return migemo.getRegExp(input, 'i').test(this);
};
alert('日本語'.migemoMatches('nihongo')) // => "true"
alert('英語'.migemoMatches('nihongo')) // => "false"
input
で与えられた入力にマッチする項目を抜き出す:
function getMatchedItems(list, input) {
var regexp = migemo.getRegExp(input);
return list.split('\n')
.filter(function(aTerm) {
return regexp.test(aTerm);
});
}
var list = <[CDATA[
コーヒー
紅茶
緑茶
水
]]>.toString();
alert(getMatchedItems(list, 'cha')); // => ["紅茶", "緑茶"]
migemo.getRegExps(in String aInput, [in String aFlags])
"im"
として扱う。String
に追加する:
String.prototype.migemoMatchesAll = function(input) {
return migemo.getRegExps(input, 'i')
.every(function(aRegExp) {
return aRegExp.test(this);
}, this);
};
alert('日本語と英語'.migemoMatchesAll('nihongo eigo')) // => "true"
alert('日本語とフランス語'.migemoMatchesAll('nihongo eigo')) // => "false"
migemo.getRegExpFunctional(in String aInput, [in String aFlags])
"im"
として扱う。regexp
、terms
、exceptions
の各プロパティを持ったオブジェクト。それぞれの内容は以下の通り。
regexp
プロパティの内容terms
プロパティの内容"gim"
が指定された状態で返される)exceptions
プロパティの内容"gim"
が指定された状態で返される)、またはnull
target
に列挙された内容から、input
で与えられた入力にマッチする項目を抽出する:
var target = [
'日本で英語を話す',
'英語を日本で話す',
'日本語fooooo!!',
'日本語hooooo!!'
];
var input = 'nihon go -foo';
var result = migemo.getRegExpFunctional(input, 'i');
var matchedTerms = [];
var output = target.filter(function(aTarget) {
if (result.exceptions &&
result.exceptions.test(aTarget))
return false;
if (result.regexp.test(aTarget)) {
match = aTarget.match(result.terms);
matchedTerms = matchedTerms.concat(match);
return true;
}
});
alert(output.join('\n')+'\n---\n'+matchedTerms.join(', '));
// 結果:
// 日本で英語を話す
// 英語を日本で話す
// 日本語hooooo!!
// ---
// 日本, 語, 語, 日本, 日本, 語
migemo.getRegExpsFunctional(in String aInput, [in String aFlags])
"im"
として扱う。regexps
、terms
、exceptions
の各プロパティを持ったオブジェクト。それぞれの内容は以下の通り。
regexps
プロパティの内容terms
プロパティの内容"gim"
が指定された状態で返される)exceptions
プロパティの内容"gim"
が指定された状態で返される)、またはnull
target
に列挙された内容から、input
で与えられた入力にマッチする項目を抽出する:
var target = [
'日本で英語を話す',
'英語を日本で話す',
'日本語fooooo!!',
'日本語hooooo!!'
];
var input = 'nihon go -foo';
var result = migemo.getRegExpsFunctional(input, 'i');
var matchedTerms = [];
var output = target.filter(function(aTarget) {
if (result.exceptions &&
result.exceptions.test(aTarget))
return false;
if (result.regexps.every(function(aRegExp) {
return aRegExp.test(aTarget);
})) {
match = aTarget.match(result.terms);
matchedTerms = matchedTerms.concat(match);
return true;
}
});
alert(output.join('\n')+'\n---\n'+matchedTerms.join(', '));
// 結果:
// 日本で英語を話す
// 英語を日本で話す
// 日本語hooooo!!
// ---
// 日本, 語, 語, 日本, 日本, 語
XUL/Migemoの辞書アシスト検索機能は、辞書を作成するだけで、他の言語にも簡単に対応させる事ができます。
辞書の内容は、タブと改行で区切られた単語のリストです。以下に英語用辞書の一部を示します。
2 to too two
4 for
AA
AAA
Aachen
aardvark
Aaren
Aarhus
Aarika
Aaron
AB
aback
abacus
abaft
Abagael
Abagail
...
行頭にある単語がマッチングの対象となります。また、タブで区切ってその後に他の単語を記述すると、行頭にある単語が入力された際、その後に続く単語もマッチング対象になります。上記の例で言えば、「2」と入力した際には「to」や「too」もヒットするようになります。
このようにして作成した単語リストを「言語名.txt」という名前で、エンコーディングをUTF-8にして、辞書フォルダに設定されているフォルダの中に保存します。この状態で、文字列型の設定 xulmigemo.lang
の値としてその言語名を指定すると、それ以後、XUL/Migemoの辞書アシスト検索にその辞書が利用されるようになります。
設定名を xulmigemo.dictionary.download.uri.言語名
とした文字列型の設定を作成し、値に辞書ファイルのダウンロードURIを設定しておくと、XUL/Migemoは辞書ファイルがローカルに存在しない場合に、自動的にそれをダウンロードします。
Web上に置いておく辞書ファイルは、フォルダ等に入れずにそのままZIP形式で圧縮して下さい。
日本語のようにローマ字入力からひらがな・カタカナへの変換のような処理を行いたい場合は、エンジン部分そのものを再実装する必要があります。
XUL/Migemo用の他の言語のエンジンを追加する場合、xmIXMigemoEngine型のインターフェースを備えたエンジン部と、xmIXMigemoDictionary型のインターフェースを備えた辞書の両方を実装する必要があります。
簡単に開発したい場合は、以下のようにすると良いでしょう。
lang
プロパティの定義を言語名に書き換える。ここでは仮にMyLang
とする。classID
プロパティの定義の箇所のUUIDを、UUID Generator on the Webなどで作成した新しい物に書き換える。MyLang
とする。これで、XUL/Migemoのエンジンとして自作のエンジンを使えるようになります。
独自のエンジンを定義する際は、必ずコンポーネントのコントラクトIDを @piro.sakura.ne.jp/xmigemo/engine;1?lang=言語名
として下さい。例えば日本語なら言語名はja
です。xmIXMigemoEngine型は以下のメソッド・プロパティを実装する必要があります。
getRegExpFor(in String aInput)
var regexp = new RegExp(XMigemoCore.getRegExp('romaji'), 'ig');
などのように使う)gatherEntriesFor(in String aInput, in unsigned short aTargetDictionaryType)
xmIXMigemoEngine.SYSTEM_DIC
:システム辞書xmIXMigemoEngine.USER_DIC
:ユーザ登録単語の辞書xmIXMigemoEngine.ALL_DIC
:システム辞書とユーザ辞書の両方splitInput(in String aInput)
textTransform
Cc['@piro.sakura.ne.jp/xmigemo/text-transform;1?lang=*'].getService(Ci.xmIXMigemoTextTransform)
を使ってもいいですし、日本語エンジンのように独自のサービスを実装して使ってもいいです。dictionary
なお、xmIXMigemoはxmIXMigemoEngineのインターフェースを継承しています。
xmIXMigemoTextTransform型のインターフェースは、辞書が受け入れ可能な文字列であるかどうかのチェックや、文字列を辞書やエンジンが受け入れ可能な形式に変換する機能を提供します。
isValidInput(in String aInput)
normalizeInput(in String aInput)
normalizeKeyInput(in String aInput)
addLatinModifiers(in String aInput)
removeLatinModifiers(in String aInput)
日本語エンジン用の拡張インターフェース(xmIXMigemoTextTransformJa)では、ローマ字とひらがなの相互変換、ひらがなとカタカナの相互変換などの機能を実装しています。
xmIXMigemoDictionary型のインターフェースは、そのエンジン専用の辞書ファイルの読み書きを行います。
getDic()
getUserDic()
saveUserDic()
addTerm(in String aInput, in String aTerm)
xmIXMigemoDictionary.RESULT_OK
:正常終了。xmIXMigemoDictionary.RESULT_ERROR_INVALID_INPUT
:入力(読み)が不正。xmIXMigemoDictionary.RESULT_ERROR_ALREADY_EXIST
:登録しようとした語はすでに登録されている。xmIXMigemoDictionary.RESULT_ERROR_NO_TARGET
:登録するべき語が無い。xmIXMigemoDictionary.RESULT_ERROR_INVALID_OPERATION
:その他の無効な操作。removeTerm(in String aInput, in String aTerm)
xmIXMigemoDictionary.RESULT_OK
:正常終了。xmIXMigemoDictionary.RESULT_ERROR_INVALID_INPUT
:入力(読み)が不正。xmIXMigemoDictionary.RESULT_ERROR_NOT_EXIST
:削除しようとした語が登録されていない。xmIXMigemoDictionary.RESULT_ERROR_INVALID_OPERATION
:その他の無効な操作。load()
reload()
initialized
文字列型の設定 xulmigemo.lang
の値として独自に実装したエンジンの言語名を設定しておくと、起動時にXUL/Migemoはその言語用の辞書とエンジンを使用するようになります。
設定名を xulmigemo.dictionary.download.uri.言語名
とした文字列型の設定を作成し、値に辞書ファイルのダウンロードURIを設定しておくと、xmIXMigemoDicManagerは辞書ファイルがローカルに存在しない場合に、自動的にそれをダウンロードします。
Web上に置いておく辞書ファイルは、フォルダ等に入れずにそのままZIP形式で圧縮して下さい。
Firefoxでは、今までのブラウザでのページ内検索にありがちだった 「検索」機能を呼び出す→文字を入力する→「検索」ボタンを押す という操作がなくなり、その代わりに 文字を入力したらそのままそれが検索される というスムーズで快適な検索機能が実装されています。この機能は「インクリメンタル検索」「逐語検索」「Find As You Type」などと呼ばれています。
ただ、このような機能は、かな漢字変換が不要な英語圏での利用が前提になっています。例えば「firefox」と入力すればすぐにページ内で検索できてハッピーなのですが、日本語圏では、「にほんご」と入力する→「日本語」に変換する という風なステップが間に入るため(しかも漢字がどれが正しいか見て、候補を選んで変換しないといけない)に、検索実行までの間に入る手間が多くて、あんまりハッピーになれません。
この問題を解決するべく開発されたのが、plus7氏による本家XUL/Migemoです。これは、Emacsというテキストエディタ用の日本語文字列をローマ字入力で高速に検索するツールMigemo(Rubyによる実装)を、C/Migemo:MigemoのC言語による実装を使用したfub_netの動作を参考に、plus7氏がXULとJavaScriptでFirefox用に移植したものです。
本家XUL/Migemoは色々な事情から、バージョン0.3.0で更新が停止しています。しかしその間にも、Firefox 1.5が発表されたり、まだ残っていた問題が発覚したりと、事態は動いています。そこで、せめて本家の開発が再開されるまでの間くらいはなんとか使える状態を維持していきたいと考えて、ここでフォーク版として勝手改造版を公開するようになった次第です。
元々、本家XUL/Migemoが更新されこれらの問題が解消された暁には、このコンテンツは消去または更新を停止する予定でした。しかしバージョンアップの結果、既に中身は本家XUL/Migemoと全く異なるものになってしまっています。なので、開発はもうしばらく続きそうです。……というのが、XUL/Migemo [Forked Edition]の開発の経緯でした。
現在では、このプロジェクトはplus7氏の許可を得て、XUL/Migemoの正式な後継プロジェクトとして存続しています。
本家XUL/Migemo(0.3.0以前)誕生の経緯や内部的な動作の解説は、本家XUL/Migemoのページが詳しいので、そちらをご覧ください。
return
による警告が表示されないようにしたxulmigemo.scrollSelectionToCenter.smoothScroll.enabled
を false
に変更して下さい)xulmigemo.highlight.foundMarker.smoothScroll.enabled
を false
に変更して下さい)browser.urlbar.autoFill
が機能しない問題を修正