diff --git a/common/content/dactyl-overlay.js b/common/content/dactyl-overlay.js index e75d565e..d8a8c3ca 100644 --- a/common/content/dactyl-overlay.js +++ b/common/content/dactyl-overlay.js @@ -60,6 +60,7 @@ "prefs", "storage", "util", + "javascript", "dactyl", "modes", "abbreviations", @@ -76,7 +77,6 @@ "highlight", "hints", "io", - "javascript", "mappings", "marks", "options", diff --git a/common/content/dactyl.js b/common/content/dactyl.js index 1a0a137d..fc7f8bf0 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -538,19 +538,29 @@ const Dactyl = Module("dactyl", { return UTF8(xml.toXMLString()); }, - exportHelp: function (path) { + + exportHelp: JavaScript.setCompleter(function (path) { const FILE = io.File(path); const PATH = FILE.leafName.replace(/\..*/, "") + "/"; const TIME = Date.now(); + if (!FILE.exists() && (/\/$/.test(path) && !/\./.test(FILE.leafName))) + FILE.create(FILE.DIRECTORY_TYPE, octal(755)); + dactyl.initHelp(); - let zip = services.ZipWriter(); - zip.open(FILE, File.MODE_CREATE | File.MODE_WRONLY | File.MODE_TRUNCATE); - function addURIEntry(file, uri) - zip.addEntryChannel(PATH + file, TIME, 9, - services.io.newChannel(uri, null, null), false); - function addDataEntry(file, data) // Unideal to an extreme. - addURIEntry(file, "data:text/plain;charset=UTF-8," + encodeURI(data)); + if (FILE.isDirectory()) { + function addDataEntry(file, data) FILE.child(file).write(data); + function addURIEntry(file, uri) addDataEntry(file, util.httpGet(uri).responseText); + } + else { + var zip = services.ZipWriter(); + zip.open(FILE, File.MODE_CREATE | File.MODE_WRONLY | File.MODE_TRUNCATE); + function addURIEntry(file, uri) + zip.addEntryChannel(PATH + file, TIME, 9, + services.io.newChannel(uri, null, null), false); + function addDataEntry(file, data) // Unideal to an extreme. + addURIEntry(file, "data:text/plain;charset=UTF-8," + encodeURI(data)); + } let empty = set("area base basefont br col frame hr img input isindex link meta param" .split(" ")); @@ -619,9 +629,9 @@ const Dactyl = Module("dactyl", { } let data = [h for (h in highlight) if (set.has(styles, h.class) || /^Help/.test(h.class))] - .map(function (h) - h.selector.replace(/^\[.*?=(.*?)\]/, ".hl-$1").replace(/html\|/, "") + "\t" + - "{" + h.value + "}") + .map(function (h) h.selector + .replace(/^\[.*?=(.*?)\]/, ".hl-$1") + .replace(/html\|/, "") + "\t" + "{" + h.value + "}") .join("\n"); addDataEntry("help.css", data.replace(/chrome:[^ ")]+\//g, "")); @@ -632,8 +642,9 @@ const Dactyl = Module("dactyl", { for (let [uri, leaf] in Iterator(chrome)) addURIEntry(leaf, uri); - zip.close(); - }, + if (zip) + zip.close(); + }, [function (context, args) completion.file(context)]), /** * Generates a help entry and writes it to the clipboard. diff --git a/common/content/io.js b/common/content/io.js index b41e154c..de3b79a3 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -202,7 +202,7 @@ const IO = Module("io", { let file = services.directory.get("TmpD", Ci.nsIFile); file.append(config.tempFile); - file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt('0600', 8)); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, octal(600)); Cc["@mozilla.org/uriloader/external-helper-app-service;1"] .getService(Ci.nsPIExternalAppLauncher).deleteTemporaryFileOnExit(file); diff --git a/common/content/javascript.js b/common/content/javascript.js index 6becefa0..9e042607 100644 --- a/common/content/javascript.js +++ b/common/content/javascript.js @@ -655,6 +655,7 @@ const JavaScript = Module("javascript", { return completer.call(obj, context, obj, args); }; } + return arguments[0]; } }, { completion: function () { diff --git a/common/modules/base.jsm b/common/modules/base.jsm index 590ee4ec..7d9e03a6 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -177,7 +177,7 @@ defineModule("base", { "call", "callable", "ctypes", "curry", "debuggerProperties", "defineModule", "endModule", "forEach", "isArray", "isGenerator", "isinstance", "isObject", "isString", "isSubclass", "iter", "iterAll", "keys", - "memoize", "properties", "set", "update", "values", + "memoize", "octal", "properties", "set", "update", "values", "withCallerGlobal" ], use: ["services", "util"] @@ -1008,6 +1008,8 @@ function UTF8(str) { } } +function octal(decimal) parseInt(decimal, 8); + /** * Array utility methods. */ diff --git a/common/modules/storage.jsm b/common/modules/storage.jsm index 9a548508..fd6432db 100644 --- a/common/modules/storage.jsm +++ b/common/modules/storage.jsm @@ -16,16 +16,10 @@ defineModule("storage", { const win32 = /^win(32|nt)$/i.test(services.runtime.OS); -function getFile(name) { - let file = storage.infoPath.clone(); - file.append(name); - return File(file); -} - function loadData(name, store, type) { try { if (storage.infoPath) - var file = getFile(name).read(); + var file = storage.infoPath.child(name); if (file) var result = services.json.decode(file); if (result instanceof type) @@ -38,7 +32,7 @@ function saveData(obj) { if (obj.privateData && storage.privateMode) return; if (obj.store && storage.infoPath) - getFile(obj.name).write(obj.serial); + storage.infoPath.child(obj.name).write(obj.serial); } const StoreBase = Class("StoreBase", { @@ -246,12 +240,8 @@ const Storage = Module("Storage", { }, { }, { init: function (dactyl, modules) { - let infoPath = File(modules.IO.runtimePath.replace(/,.*/, "")); - if (infoPath) { - infoPath.append("info"); - infoPath.append(dactyl.profileName); - storage.infoPath = infoPath; - } + storage.infoPath = File(modules.IO.runtimePath.replace(/,.*/, "")) + .child("info").child(dactyl.profileName); } }); @@ -268,7 +258,7 @@ const File = Class("File", { let file = services.File(); if (path instanceof Ci.nsIFile) - file = path.QueryInterface(Ci.nsIFile); + file = path.QueryInterface(Ci.nsIFile).clone(); else if (/file:\/\//.test(path)) file = services["File:"]().getFileFromURLSpec(path); else { @@ -300,6 +290,15 @@ const File = Class("File", { yield File(file); }, + /** + * Returns a new file for the given child of this directory entry. + */ + child: function (name) { + let f = this.constructor(this); + f.append(name); + return f; + }, + /** * Reads this file's entire contents in "text" mode and returns the * content as a string. @@ -398,7 +397,7 @@ const File = Class("File", { mode = File.MODE_WRONLY | File.MODE_CREATE | File.MODE_TRUNCATE; if (!perms) - perms = parseInt('0644', 8); + perms = octal(644); if (!this.exists()) // OCREAT won't create the directory this.create(this.NORMAL_FILE_TYPE, perms);