2007年 12月 23日

XUL/XPCOM のファイルのよみかき。

なんかすげーめんどくさいなぁ。Java 並のめんどくささ。しかも Java ほどセオリーっぽい書きかたがない…… (仕様変更がどうとか……)

実はラッパがあったりしないのかなぁ……

かるく書いてみたけど、こういうのが欲しい。ぜったい既にあると思うんだけど検索しにくくてみつからない……

function File () { this.initialize.apply(this, arguments) }
File.prototype = {
	initialize : function (path) {
		if (typeof path == "string") {
			this.file = Components.classes["@mozilla.org/file/local;1"]
			                      .createInstance(Components.interfaces.nsILocalFile);
			this.file.initWithPath(path);
		} else {
			this.file = path;
		}
		this.charset = "UTF-8";
	},

	read : function (cb) {
		if (!cb) cb = function (i) {
			var ret = [];
			var str = {};
			while (i.readString(4096, str) != 0) {
				ret.push(str.value);
			}
			return ret.join("");
		};
		var fistream = Components.classes["@mozilla.org/network/file-input-stream;1"]
		                         .createInstance(Components.interfaces.nsIFileInputStream);
		var cistream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
		                         .createInstance(Components.interfaces.nsIConverterInputStream);
		fistream.init(this.file, 0x01, 0444, 0);
		cistream.init(fistream, this.charset, 1024, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
		var ret = cb.call(this, cistream, fistream);
		cistream.close();
		fistream.close();
		return ret;
	},
	write : function (cb) {
		if (typeof cb == "string") {
			var _str = cb;
			cb = function (i) {
				i.writeString(_str);
				return this;
			};
		}
		var fostream = Components.classes["@mozilla.org/network/file-output-stream;1"]
		                         .createInstance(Components.interfaces.nsIFileOutputStream);
		var costream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
		                         .createInstance(Components.interfaces.nsIConverterOutputStream);
		fostream.init(this.file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
		costream.init(fostream, this.charset, 4096, 0x0000);
		var ret = cb.call(this, costream, fostream);
		costream.close();
		fostream.close();
		return ret;
	}
};
File.TempFile = function (prefix, suffix) {
	var name = [prefix, Math.floor(Math.random() * 0xffffff).toString(16), suffix].join(".");
	var file = Components.classes["@mozilla.org/file/directory_service;1"]
	                     .getService(Components.interfaces.nsIProperties)
	                     .get("TmpD", Components.interfaces.nsIFile);
	file.append(name);
	file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0664);

	Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
	          .getService(Components.interfaces.nsPIExternalAppLauncher)
	          .deleteTemporaryFileOnExit(file);

	return new File(file);
}

var tf = File.TempFile("foobar", "txt");
alert(tf);
tf.write("foobar");
alert(tf.read());

Opera での with の挙動

var foo = { 
    bar : "bar"
};
(function () {
    with (foo) {
        alert("normal+"+bar);
        function baz () {
            alert("function def."+bar); // opera だと reference error
        }
        baz();

        (function () {
            alert("function exp."+bar); // <del>opera だと reference error</del>
        })();
    }
})();

Fx と Safari では大丈夫。これは Opera のバグっぽい? (Opera 9.24, 9.50 Beta 4591)

同じくスコープチェインをいじる try/catch は大丈夫だ。with だけか

(function () {
    try {
        throw "hello";
    } catch (foo) {
        alert(foo);
        (function () {
            alert(foo);
        })();
    }
})();

(Opera, Safari, Fx でちゃんとできる)

関数式のほうは勘違いでした。関数宣言のほうだけだめです……

Safari の XPath

./div/div のつもりで div/div って書くと INVALID っていわれる。ひどい……

textarea を好きなエディタで編集する userChrome.js

XPCOM あたりを触っていたのはこれを書くため……

コメント欄で教えてもらった IO オブジェクトを使うようにしたので Fx3 でしか動かないです。

It's All Text とか使ってたんですが、Fx3 に対応していないのと、なんかいろいろ挙動がいまいちだったので短く書きなおした感じです。

ちゃんと設定を読むようにしたよ。
http://coderepos.org/share/changeset/3529

最初に Ctrl-E したときにエディタを訊くよ。もしリセットしたかったら about:config をひらいて extensions.userchromejs.EditOnFavorite.editor を検索してリセットすればいいよ。

キーバインドも設定を読むようにしたいけど、ちょっとめんどうなのでまだ放置だよ

キーバインドも設定可能にしたよ。
http://coderepos.org/share/changeset/3531

extensions.userchromejs.EditOnFavorite.key に C-e とか C-; とか入れればそっちを使うはずだよ。

設定画面をつけたよ……

Tools -> userChrome.js -> EditOnFavorite で画面がひらくよ。OS X でしか確認してないけど prefwindow をつかっているからたぶん別の環境でも大丈夫だよ