たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。
の動向はもえじら組ブログで。
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。
以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
昨年11月にエントリーして([1]、[2])たFirefox 2アドオンコンテストの結果がやっと発表されたよ。ずいぶん遅かったなあ……
結論から言うと、かすりもしませんでしたイヤッホー!
というわけでMozillaのえらい人にはやっぱりなれそうもないので今後はもえじらのエロイ人としてアイデンティティを確立していこうかなと思います。迷惑ですかそうですか。
しかしグランプリには選ばれなかったとはいえ、15人中3人は日本人か。国内シェアのわりには健闘してるよね。
Second Search更新した。Firefox 3(Beta3)とThunderbird 2に対応。
Thunderbird対応にあたって、全体的にコードに手を入れた。Firefoxだけでしか使わない部分とThunderbirdでしか使わない部分と両方で使う部分の3つにファイルを分割している。似たような構造の物に対してはこれで比較的楽に対応できるようになったんじゃないかと思う。
Firefox 3については、Placesへの対応がメイン。キーワードを設定されたブックマークを検索エンジンと同等に扱うという機能がSecond Searchにはあるんだけど、僕以外にどれだけの人が使ってるんだろう。
あと、「他の検索エンジン」サブメニューのあたりのコードもだいぶ書き直した。この辺はほんとは特に触る予定はなかったんだけど、Organize Search Enginesとの競合の解消も兼ねて、なるべく汎用的になるように変更している。っていうかテストしててなーんかうまく動かないなーと思って不思議だったんだけど、よく調べてみたらOSEの側にSecond Search用のハックが入っててそれが干渉していた。僕のアドオンのためにわざわざハック用のコードを書いてくれるなんて……よくあんなスパゲッティもスパゲッティなコードを解読してくれたもんだなぁ……と嬉しく思ったりもしたけど、このままだとせっかく修正したのがきちんと動いてくれないので、動くようにするパッチを作者の人に送りつけてみたり。
nsIMsgDBHdrとnsIMsgFolderからメールの本文を文字列として取得する方法をあれこれ試してみてこんな感じのところに辿り着きましたとさ。
あのBug 322367「Bring back the Firefox Plush Toy(Firefoxぬいぐるみ復活希望)」が、ついにFIXEDになりました!!! コメントによると、北米専用ショップではすでに購入可能で、海外発送可能なインターナショナルショップの方でもじきに注文できるようになるんだそーです。
イギリスから個人輸入したり、哀さんに協力してもらって共同購入したりと色々ありましたが、これで誰でも気軽に手に入れられるようになる……のかな?
mozIStorageConnectionのcreateFunctionメソッドを使うとユーザ定義関数を作れるそうなんだけど、Firefox 2だとユーザ定義関数から値を返せない(返り値が常にNULLになる)。値を返せるようになるのはFirefox 3からだそうな。
const DirectoryService = Components
.classes['@mozilla.org/file/directory_service;1']
.getService(Components.interfaces.nsIProperties);
var file = DirectoryService.get('ProfD', Components.interfaces.nsIFile);
file.append('mydatabase.sqlite');
var storageService = Components
.classes['@mozilla.org/storage/service;1']
.getService(Components.interfaces.mozIStorageService);
var dbcon = storageService.openDatabase(file);
// mozIStorageFunctionインターフェースを備えたオブジェクト
var func = {
onFunctionCall : function(aArgs) {
// 渡ってくるのはmozIStorageValueArrayのオブジェクト
var data = aArgs.getString(0);
var pattern = aArgs.getString(1);
return data.match(new RegExp(pattern)) ? true : false ;
}
};
// 引数の個数を「-1」にすると可変長引数の関数になる
dbcon.createFunction('match', -1, func);
var extracted = [];
var statement = dbcon.createStatement(
'SELECT * FROM mytable WHERE match(data_column, ?1)'
);
statement.bindStringParameter(0, '^foobar');
try {
while (statement.executeStep())
{
extracted.push(statement.getString(0));
}
}
catch(e) {
}
statement.reset();
alert(extracted.length); // 0
こんなの何に使えばいいんだ?
まあどうせPlacesはFirefox 3からだし、正規表現でのマッチングをやる必要が出てくるのはそれからだと思うんだけど。でもこのコードのようにJavaScript製ユーザ定義関数でマッチングするんだったら、結局は全ての行に対して処理が行われるわけで、それだったら先に全ての行を取り出してからループ回してマッチングするのと、処理速度的には全然変わらないよね……ほんと無意味。標準の関数で正規表現が使えればいいのになあ。
検索を開始したタイミングでヘッダ情報を一気に収集するという現状の仕様だと、フォルダ内に数千件とかメールが溜まってる人はまず間違いなく死亡するので、フォルダの内容を表示したタイミングでバックグラウンドでちまちまとヘッダ情報を収集するようにして、ついでに、その収集結果をMozStorageで保存するようにしてみてるんだけど。
今の所、一つのフォルダにつき一つのレコードとして、「Subjectだけ集めたもの」「Toだけ集めたもの」のような文字列をそれぞれフィールドに保存してるんだけど、これもあんまりでっかくなりすぎるとまずいですよねえ多分。仮にSubjectが10文字のメールが1000件あったとすると、20~40KBとかそれくらいになるのかな? 3000件もあれば100KBはいってもおかしくない。これって大丈夫なんだろうか。
えーと。SQLiteの制限事項によると、SQLiteデフォルトでの文字列の最大長は1ビリオン(1000000000)バイト……えーと、だいたい1GBくらい? Firefoxのソースツリーを検索してもSQLITE_MAX_LENGTHという文字列は登場しないようなので(というのは全然根拠にならんのだけど)、このデフォルト値のまんまなんだとしたら、パフォーマンスはさておきとりあえずこのままでも動くことは動くのかな?
というか別にSQLite使う必要は必ずしもないんですけどね。なんとなく最近無駄に多用する癖が……
Hello, thank you for your mail.
The only problem now is the new version, the old one for Firefox 1.5 is a lot better and right now I prefer having Firefox 1.5 with your old extension instead of using the new one.
Have you thought of making the same as for 1.5? If not, will you do it?
Currently I have no plan to develop an extension same as TBE on Fx 1.5. I suffered from too many bugs which are from options I didn't use, so, I decided to keep developing "TBE3" only on features I really need.
Because I was a student and I had a lot of off-time, I could develop huge software like old TBE. But now I'm one of working people. There is less time and motivation.
Now there are nice projects, Tab Mix Plus and Tab Kit, suites of tabbed browsing features. And, userChrome.js is also available to make people's small requirements reality. Lots of people develop user-scripts for the extension on MozillaZine forum. I hope communities of those extensions help you.
regards,
ということで、アップデートしました。余りに久しぶりの更新すぎて更新の手順を忘れてしまっていたのはここだけの秘密です。
やってることとしては、リンク先にも書いてるけど、まず検索対象のフォルダのメール全部を走査してヘッダ情報を収集。次に、それを文字列として連結して検索用のデータを作成。それに対してXUL/Migemoで生成した正規表現でマッチングを行い、ヒットした箇所を抜き出して、それを検索語句としてThunderbirdに渡す。という手順で、ローマ字入力でのメール検索を実現しています。今のところヘッダ情報しか収集していないので、本文内に含まれる単語は検索できません。要約とかをきちんとキャッシュするようにすればできるのかもしれないけど、そこまでやると大変そうなので今のところはここまで。
ハードディスクが逝ってしまった後に再構築した環境でテストしている都合上、大量のメールがある状況でどのくらい重くなるのかは未検証です。ヤバいくらい遅くなる場合は、設定ダイアログから「メールの検索でXUL/Migemoを使用する」のチェックを無効にしてください。
んぁ。意図したわけではなかったんだけど肉の日リリースになった……
XUL/Migemoでメールの検索をできるようにしてみたいな、と思って試してみた。
メールの検索はOR検索はできるようなので、キャラクタクラスやグルーピングを展開して単語のリストを生成してOR検索したらいけるかな?と思ってやってみたんだけど、ローマ字入力から単語のリストを作る所までで数百ミリ秒くらいの遅延というのはまあ許したとしても、そこから先の実際に検索にぶち込む所で重すぎてThunderbirdが落ちた。そりゃ9000ワードをOR検索とか、いくらC++で書かれた処理が速いといっても限度があるわ。
というわけで正攻法は無理なので別のやり方を考えないといかんですね。やっぱアレかな、検索対象のメールすべてのヘッダを一旦文字列に取り出してそこに検索をかけてから、ヒット箇所の単語を実際の検索に投げるという、いかにもXUL/Migemoらしい(plus7さんよくこんなやり方を思いついたもんだ)やり方で行くしかないのかな。
どーでもいいけどこの正規表現を単語のリストに変換する処理、自分で書いておきながら、どういう理屈で動いているのかさっぱり分からんです。
追記。前述したヘッダを一旦文字列に取り出して云々のやり方を実装してみたら、数十件程度ならわりとストレスなく動くようになった。1フォルダに数百件、数千件とかのメールが溜まってる環境だとやばいかもだけど。
UxUのことで悩み中。
テストケースを実行するとき、コンテキストオブジェクトを指定してスクリプトを実行しないといけないんだけど、色々問題があって悩ましい。
brazilさんが紹介されているとおり、ビルトイン関数のevalに第2引数を渡すか、Objectクラスのメソッドであるevalを使うと、コンテキストオブジェクトを指定してスクリプトを実行することができる。ただ、この両者は若干動作が異なる。
例えばこんなコードを考えよう。
var context = {};
context.eval('var val1 = true; this.val2 = false');
alert(context.val1); // => true
alert(context.val2); // => undefined
Objectクラスのメソッドだと、実行したスクリプトの中で変数として宣言した物がそのままそのオブジェクトのプロパティとなり、外部から後で参照することができる。でも、
var context = {};
eval('var val1 = true; this.val2 = false', context);
alert(context.val1); // => undefined
alert(context.val2); // => undefined
ビルトイン関数の方だと、そうはならない。また、どちらにしてもthisを明示した場合は外部からは参照できない。
言い換えると、「コンテキストオブジェクトを明示して実行したスクリプトの中でvarで宣言された値を外部から取得するには、Objectクラスのevalメソッドを使わないといけない」ということ。
ところが、Firefox 3ではObjectクラスのevalメソッドが存在しない。どうやらどこかの時点で削除されてしまったようだ。
元のMozLabではどうしていたかというと、evalを使う代わりにmozISubScriptLoaderを使っていた。
var context = {};
var loader = Components.classes['@mozilla.org/moz/jssubscript-loader;1']
.getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript(
'data:application/x-javascript,'+encodeURIComponent('var val1 = true; this.val2 = false'),
context
);
alert(context.val1); // => true
alert(context.val2); // => false
こちらは前二者のどっちとも結果が異なり、varで宣言した物もthisを明示した物も両方ともコンテキストオブジェクトのプロパティとして外部からアクセスできるようになる。
ところが。mozIJSSubScriptLoaderを使う方法だと、スクリプトの中に日本語などの非ASCII文字があると化けてしまう。
var script = 'alert("日本語")'; // Unicode
eval(script); // => "日本語"
({}).eval(script); // => "日本語"
loader.loadSubScript('data:application/x-javascript,'+encodeURIComponent(script), {}); // => 文字化けした文字列
encodeURIComponentによってUnicodeの文字列がUTF-8のバイト列に変換されてしまうのでこうなる、のか? とにかく、これではテストケースの説明を日本語で書けなくて(僕が)困る。UxUではこの処理の直前でUTF-8なりShift_JISなりで書かれたテストケースを読み込んで内部コードのUnicodeに変換しているのだけれども、せっかく変換したのに最後の最後で化けてしまうんじゃあしょうがない。
ということでああでもないこうでもないと試していて、以下のような方法に辿り着いた。
var script = 'alert("日本語")'; // Unicode
script = 'eval('+script.toSource().replace(/^\(new String\(|\)\)$/g, '')+')';
loader.loadSubScript('data:application/x-javascript,'+encodeURIComponent(script), {}); // => "日本語"
encodeURIComponentに放り込む前に、一旦全体を文字列リテラルとして評価可能な文に変換して(この時点で日本語などの非ASCII文字は「\uXXXX」のようなUnicodeエスケープに変換される)、encodeURIComponentを通過した後でevalで元に戻す、というトンネル抜けのようなやり方。これによって、日本語で書かれた説明もそのまま利用できるようになった。
でも、これにもまだ問題がある。この方法で実行したスクリプトの中でエラーが起こると、MozUnitテストランナーのUI上でソースを表示してもeval("(元のテストケースのスクリプト)")
という1行だけのソースになってしまって、エラー箇所がさっぱりわからない。これ、どうにかならんもんだろうか……
追記。エラーが発生した行の番号自体はこれでも正しく取れてるようなので、とりあえずやっつけ仕事で、MozUnitテストランナーのUI上でソースを表示する時にソースを元の文字列に復元するという方向で手を打とうと思う。
さらに追記。よく考えたら、わざわざ自分でソースを復元しなくても、変換前後で行数その他は変わってないんだから、ソース表示の時に元のファイルの方を読み込ませるようにしたらいいんだな……
さらにさらに追記。mozIJSSubScriptLoaderの仕様変更によってこの方法も使えなくなりました。現在何かいい手は無いか考え中。
さらにさらにさらに追記。上記内容と同じような結果になる代替案を考えてみた。
さらにさらにさらにさらに追記。evalの機能についてFirefox 3.1でまた変更があったようだ。