たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。
の動向はもえじら組ブログで。
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。
以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
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でメールの検索をできるようにしてみたいな、と思って試してみた。
メールの検索は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でまた変更があったようだ。
amachangの1000人スピーカプロジェクトの第1回でお披露目したUXU(うず)のこととか。書くのが遅くなったのは鴉見てたからです。
ニコ動に全プレゼンの映像が上がってて、僕の奴も見れるんですが、いやー、これはひどいプレゼンですね。
いや言い訳さしてもらうとですね、前日に仕事用マシン(Let's note W2)のHDDが逝ってしまいまして、前日夕方くらいからそれのせいであたふたして徹夜してて、あんまり頭働いてなかったんですよ。だからこの日はマシンは持参してたけどUbuntu 7.10のLive CDで起動してました。隣の人とか後ろの人とか多分CD-ROMドライブの音がぶんぶんうるさかったと思いますが、それはこのせいです。それにしてもUbuntuすごいね。CD起動なのに無線LAN使えちゃったよ。さすがにプロジェクターの認識は再起動が必要みたいだったからプレゼンの時だけamachangにマシンをお借りしましたが。
プレゼンでちゃんと言えてなかったことの補足。自分がテストという物の意義を理解したのがRailsのそれだったので、UXUを最終的にどういうものにしたいのかという目標も、今の所はRailsに置いてます。なので、今は実現できてないけどfixtureみたいな物もできるようにはしたいと思ってます。
それか、もっと根本的なところで、テスト専用のプロファイルにその時だけ切り替えて……みたいなこともできるようにしたいんですが、この辺になってくるとプラットフォーム用のバイナリを作らないといけないような気がしていて気が重いです。もしかしたらProfile Switcherが解決のヒントになるでしょうか?
yieldの読み方は「いーるど」でよかったんですね。でもそれ知ってもどうしても「いぇーるど」と読んでしまう……
昨年頭にごにょごにょしてたのはプレゼン中に書いたお蔵入りバージョンのUXU 0.1のことなんですが、その時は単にウェイトの秒数を指定するだけでした。つい最近になって奥さんのエントリを見て、そうか「復帰条件」と考えれば返り値は数値だけじゃなくてもっとなんでも渡してイイんだな、とインスパイアされて、フラグを保持するオブジェクトを渡すパターンをまず実装し、それから関数を渡すパターンも実装したという次第です。
UXUでやってることの工夫というか特徴的なところは、yieldの本来の用途であるところのジェネレータ・イテレータの生成という役割を隠蔽してしまって、「処理の一時停止」「再開」という部分だけに特化した見せ方をしているところではないでしょうか。内部的には昨年頭に書いた話にあるとおり、setUpとかテストケースとかの関数オブジェクトの返り値がジェネレータであればタイマーを使ってイテレーションを行う、というだけのことなんですが。
amachangが紹介していたJSDeferredの方がもっときっと便利でいろんな事ができるとは思うんですが、プレゼンでも言った通り僕はN88BASICの行番号の呪縛から未だに逃れられていないような人間ですので、これ以上の複雑なことは脳が拒否して受け入れてくれんのですよ……
第8回Mozilla拡張機能勉強会のプレゼン資料を公開した。
以下、内容を改めて整理してみる。
McCoyの改造を試みるために、XULRunnerアプリでもアドオンを使えるのかどうかという実験をしてみた。
これだけでいける。逆に、アドオンをアンインストールしたい時は、アドオンのID名が付いたフォルダをプロファイル内の「extensions」フォルダから削除する。
amachangさんはアプリやアドオンそのものの中身をガリガリ書き換えるやり方を紹介されてるけど、僕はこういうやり方はしない方がいいと思ってる。理由は以下の通り。
なので、これらの問題を回避するために、teramakoさんのようにそれ用のアドオンを作って使うか、userChrome.jsを使うかする方がいいと僕は思う。今回McCoy用の改造をアドオンという手法で行うことを試みているのも、そういう理由からだ。
第8回Mozilla拡張機能勉強会でFirefox 3で要求されるセキュアなアドオン提供方法について話すつもりですが、話すだけじゃ何なのでMcCoyを改造して何かできたらなぁと思ってますが、できるかどうか分からないのであんまり期待しないでください。と、宣伝になってるんだかなってないんだか分からない宣伝をしておきます。
とよく言われるんだけど自分の環境&自分の見てる範囲のWebサイトでは落ちないので原因が分からない、ということが多い。落ちるか落ちないかのギリギリの所をうまく突くようなコードを知らず知らずのうちに書いてしまっているのでしょうか。そんな能力いらなさすぎる。