repo: 373f1649c80dea9be7b5bc9c57e8395f94f93ab1
-node: 227d1399fe7c9d8de98fc6ab3222cf9e1d8ad38f
-branch: pentadactyl-1.0-branch
-tag: pentadactyl-1.0
+node: 6d61fc0f8f2757c919fb4bb29dfed28df23b5030
+branch: default
+latesttag: pentadactyl-1.0rc1
+latesttagdistance: 194
+++ /dev/null
-## To see if new rules exclude any existing files, run
-##
-## hg status -i
-##
-## after modifying this file.
-
-syntax: glob
-
-## Generated by the build process
-*.xpi
-*.o
-*.so
-*.xpt
-*/.depend
-*/config.local.mk
-*/locale/*/*.html
-*/chrome
-*/contrib/vim/*.vba
-*/bak/*
-downloads/*
-.git/*
-
-binary/src/*/*.h
-
-common/tests/functional/log
-
-*.py[co]
-
-## Editor backup and swap files
-*~
-.#*
-\#**\#
-.*.sw[op]
-.sw[op]
-
-## Generated by Mac filesystem
-.DS_Store
-
-syntax: regexp
-
-## For rejects
-\.(orig|rej|bak|diff)$
-
+++ /dev/null
-binary/components = https://code.google.com/p/dactyl.binary-modules/
+++ /dev/null
-9f8a25e7d9861892d8e6136764bb88139e0a7253 binary/components
+++ /dev/null
- A terse introduction to E4X
- Public Domain
-
-The inline XML literals in this code are part of E4X, a standard
-XML processing interface for ECMAScript. In addition to syntax
-for XML literals, E4X provides a new kind of native object,
-"xml", and a syntax, similar to XPath, for accessing and
-modifying the tree. Here is a brief synopsis of the kind of
-usage you'll see herein:
-
-> let xml =
- <foo bar="baz" baz="qux">
- <bar>
- <baz id="1"/>
- </bar>
- <baz id="2"/>
- </foo>;
-
- // Select all bar elements of the root foo element
-> xml.bar
- <bar><baz id="1"/></bar>
-
- // Select all baz elements anywhere beneath the root
-> xml..baz
- <baz id="1"/>
- <baz id="2"/>
-
- // Select all of the immediate children of the root
-> xml.*
- <bar><baz id="1"/></bar>
- <baz id="2"/>
-
- // Select the bar attribute of the root node
-> xml.@bar
- baz
-
- // Select all id attributes in the tree
-> xml..@id
- 1
- 2
-
- // Select all attributes of the root node
-> xml.@*
- baz
- quz
-
-// Add a quux elemend beneath the first baz
-> xml..baz[0] += <quux/>
- <baz id="1"/>
- <quux/>
-> xml
- <foo bar="baz" baz="qux">
- <bar>
- <baz id="1"/>
- <quux/>
- </bar>
- <baz id="2"/>
- </foo>
-
- // and beneath the second
-> xml.baz[1] = <quux id="1"/>
-> xml
- <foo bar="baz" baz="qux">
- <bar>
- <baz id="1"/>
- <quux/>
- </bar>
- <baz id="2"/>
- <quux id="1"/>
- </foo>
-
- // Replace bar's subtree with a foo element
-> xml.bar.* = <foo id="1"/>
-> xml
- <foo bar="baz" baz="qux">
- <bar>
- <foo id="1"/>
- </bar>
- <baz id="2"/>
- <quux id="1"/>
- </foo>
-
- // Add a bar below bar
-> xml.bar.* += <bar id="1"/>
- <foo id="1"/>
- <bar id="1"/>
-> xml
- <foo bar="baz" baz="qux">
- <bar>
- <foo id="1"/>
- <bar id="1"/>
- </bar>
- <baz id="2"/>
- <quux id="1"/>
- </foo>
-
- // Adding a quux attribute to the root
-> xml.@quux = "foo"
- foo
-> xml
- <foo bar="baz" baz="qux" quux="foo">
- <bar>
- <foo id="1"/>
- <bar id="1"/>
- </bar>
- <baz id="2"/>
- <quux id="1"/>
- </foo>
-
-> xml.bar.@id = "0"
-> xml..foo[0] = "Foo"
- Foo
-> xml..bar[1] = "Bar"
- Bar
-> xml
-js> xml
-<foo bar="baz" baz="qux" quux="foo" id="0">
- <bar id="0">
- <foo id="1">Foo</foo>
- <bar id="1">Bar</bar>
- </bar>
- <baz id="2"/>
- <quux id="1"/>
-</foo>
-
- // Selecting all bar elements where id="1"
-> xml..bar.(@id == 1)
- Bar
-
- // Literals:
- // XMLList literal. No root node.
-> <>Foo<br/>Baz</>
- Foo
- <br/>
- Baz
-
-// Interpolation.
-> let x = "<foo/>"
-> <foo bar={x}>{x + "<?>"}</foo>
- <foo/><?>
-> <foo bar={x}>{x + "<?>"}</foo>.toXMLString()
- <foo bar="<foo/>"><foo/><?></foo>
-
-> let x = <foo/>
-> <foo bar={x}>{x}</foo>.toXMLString()
- <foo bar="">
- <foo/>
- </foo>
-
//
// See https://wiki.mozilla.org/Extension_Manager:Bootstrapped_Extensions
// for details.
+"use strict";
-const NAME = "bootstrap";
const global = this;
var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
-function module(uri) {
- let obj = {};
- Cu.import(uri, obj);
- return obj;
-}
+function module(uri) Cu.import(uri, {});
+
+const DEBUG = true;
+
+__defineGetter__("BOOTSTRAP", function () "resource://" + moduleName + "/bootstrap.jsm");
-const { AddonManager } = module("resource://gre/modules/AddonManager.jsm");
-const { XPCOMUtils } = module("resource://gre/modules/XPCOMUtils.jsm");
-const { Services } = module("resource://gre/modules/Services.jsm");
+var { AddonManager } = module("resource://gre/modules/AddonManager.jsm");
+var { XPCOMUtils } = module("resource://gre/modules/XPCOMUtils.jsm");
+var { Services } = module("resource://gre/modules/Services.jsm");
const resourceProto = Services.io.getProtocolHandler("resource")
.QueryInterface(Ci.nsIResProtocolHandler);
const categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
const manager = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
-const DISABLE_ACR = "resource://dactyl-content/disable-acr.jsm";
-const BOOTSTRAP_JSM = "resource://dactyl/bootstrap.jsm";
const BOOTSTRAP_CONTRACT = "@dactyl.googlecode.com/base/bootstrap";
-var JSMLoader = BOOTSTRAP_CONTRACT in Cc && Cc[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader;
var name = "dactyl";
function reportError(e) {
- dump("\n" + name + ": bootstrap: " + e + "\n" + (e.stack || Error().stack) + "\n");
+ let stack = e.stack || Error().stack;
+ dump("\n" + name + ": bootstrap: " + e + "\n" + stack + "\n");
Cu.reportError(e);
+ Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
+ .logStringMessage(stack);
}
-function debug(msg) {
- dump(name + ": " + msg + "\n");
+function debug() {
+ if (DEBUG)
+ dump(name + ": " + Array.join(arguments, ", ") + "\n");
}
-function httpGet(url) {
+function httpGet(uri) {
let xmlhttp = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
xmlhttp.overrideMimeType("text/plain");
- xmlhttp.open("GET", url, false);
+ xmlhttp.open("GET", uri.spec || uri, false);
xmlhttp.send(null);
return xmlhttp;
}
+let moduleName;
let initialized = false;
let addon = null;
let addonData = null;
let basePath = null;
+let bootstrap;
+let bootstrap_jsm;
let categories = [];
let components = {};
let resources = [];
let getURI = null;
-function updateLoader() {
+let JSMLoader = {
+ SANDBOX: Cu.nukeSandbox && false,
+
+ get addon() addon,
+
+ currentModule: null,
+
+ factories: [],
+
+ get name() name,
+
+ get module() moduleName,
+
+ globals: {},
+ modules: {},
+
+ times: {
+ all: 0,
+ add: function add(major, minor, delta) {
+ this.all += delta;
+
+ this[major] = (this[major] || 0) + delta;
+ if (minor) {
+ minor = ":" + minor;
+ this[minor] = (this[minor] || 0) + delta;
+ this[major + minor] = (this[major + minor] || 0) + delta;
+ }
+ },
+ clear: function clear() {
+ for (let key in this)
+ if (typeof this[key] !== "number")
+ delete this[key];
+ }
+ },
+
+ getTarget: function getTarget(url) {
+ let uri = Services.io.newURI(url, null, null);
+ if (uri.schemeIs("resource"))
+ return resourceProto.resolveURI(uri);
+
+ let chan = Services.io.newChannelFromURI(uri);
+ try { chan.cancel(Cr.NS_BINDING_ABORTED) } catch (e) {}
+ return chan.name;
+ },
+
+ _atexit: [],
+
+ atexit: function atexit(arg, self) {
+ if (typeof arg !== "string")
+ this._atexit.push(arguments);
+ else
+ for each (let [fn, self] in this._atexit)
+ try {
+ fn.call(self, arg);
+ }
+ catch (e) {
+ reportError(e);
+ }
+ },
+
+ _load: function _load(name, target) {
+ let urls = [name];
+ if (name.indexOf(":") === -1)
+ urls = this.config["module-paths"].map(function (path) path + name + ".jsm");
+
+ for each (let url in urls)
+ try {
+ var uri = this.getTarget(url);
+ if (uri in this.globals)
+ return this.modules[name] = this.globals[uri];
+
+ this.globals[uri] = this.modules[name];
+ bootstrap_jsm.loadSubScript(url, this.modules[name]);
+ return;
+ }
+ catch (e) {
+ debug("Loading " + name + ": " + e);
+ delete this.globals[uri];
+
+ if (typeof e != "string")
+ throw e;
+ }
+
+ throw Error("No such module: " + name);
+ },
+
+ load: function load(name, target) {
+ if (!this.modules.hasOwnProperty(name)) {
+ this.modules[name] = this.modules.base ? bootstrap.create(this.modules.base)
+ : bootstrap.import({ JSMLoader: this, module: global.module });
+
+ let currentModule = this.currentModule;
+ this.currentModule = this.modules[name];
+
+ try {
+ this._load(name, this.modules[name]);
+ }
+ catch (e) {
+ delete this.modules[name];
+ reportError(e);
+ throw e;
+ }
+ finally {
+ this.currentModule = currentModule;
+ }
+ }
+
+ let module = this.modules[name];
+ if (target)
+ for each (let symbol in module.EXPORTED_SYMBOLS)
+ target[symbol] = module[symbol];
+
+ return module;
+ },
+
+ // Cuts down on stupid, fscking url mangling.
+ get loadSubScript() bootstrap_jsm.loadSubScript,
+
+ cleanup: function unregister() {
+ for each (let factory in this.factories.splice(0))
+ manager.unregisterFactory(factory.classID, factory);
+ },
+
+ Factory: function Factory(class_) ({
+ __proto__: class_.prototype,
+
+ createInstance: function (outer, iid) {
+ try {
+ if (outer != null)
+ throw Cr.NS_ERROR_NO_AGGREGATION;
+ if (!class_.instance)
+ class_.instance = new class_();
+ return class_.instance.QueryInterface(iid);
+ }
+ catch (e) {
+ Cu.reportError(e);
+ throw e;
+ }
+ }
+ }),
+
+ registerFactory: function registerFactory(factory) {
+ manager.registerFactory(factory.classID,
+ String(factory.classID),
+ factory.contractID,
+ factory);
+ this.factories.push(factory);
+ }
+};
+
+function init() {
+ debug("bootstrap: init");
+
+ let manifestURI = getURI("chrome.manifest");
+ let manifest = httpGet(manifestURI)
+ .responseText
+ .replace(/#(resource)#/g, "$1")
+ .replace(/^\s*|\s*$|#.*/g, "")
+ .replace(/^\s*\n/gm, "");
+
+ for each (let line in manifest.split("\n")) {
+ let fields = line.split(/\s+/);
+ switch(fields[0]) {
+ case "category":
+ categoryManager.addCategoryEntry(fields[1], fields[2], fields[3], false, true);
+ categories.push([fields[1], fields[2]]);
+ break;
+ case "component":
+ components[fields[1]] = new FactoryProxy(getURI(fields[2]).spec, fields[1]);
+ break;
+ case "contract":
+ components[fields[2]].contractID = fields[1];
+ break;
+
+ case "resource":
+ moduleName = moduleName || fields[1];
+ resources.push(fields[1]);
+ resourceProto.setSubstitution(fields[1], getURI(fields[2]));
+ }
+ }
+
+ JSMLoader.config = JSON.parse(httpGet("resource://dactyl-local/config.json").responseText);
+
+ bootstrap_jsm = module(BOOTSTRAP);
+ if (!JSMLoader.SANDBOX)
+ bootstrap = bootstrap_jsm;
+ else {
+ bootstrap = Cu.Sandbox(Cc["@mozilla.org/systemprincipal;1"].createInstance(),
+ { sandboxName: BOOTSTRAP });
+ Services.scriptloader.loadSubScript(BOOTSTRAP, bootstrap);
+ }
+ bootstrap.require = JSMLoader.load("base").require;
+
+ // Flush the cache if necessary, just to be paranoid
+ let pref = "extensions.dactyl.cacheFlushCheck";
+ let val = addon.version;
+ if (!Services.prefs.prefHasUserValue(pref) || Services.prefs.getCharPref(pref) != val) {
+ var cacheFlush = true;
+ Services.obs.notifyObservers(null, "startupcache-invalidate", "");
+ Services.prefs.setCharPref(pref, val);
+ }
+
try {
- JSMLoader.loader = Cc["@dactyl.googlecode.com/extra/utils"].getService(Ci.dactylIUtils);
+ //JSMLoader.load("disable-acr").init(addon.id);
+ }
+ catch (e) {
+ reportError(e);
}
- catch (e) {};
+
+ Services.obs.notifyObservers(null, "dactyl-rehash", null);
+
+ JSMLoader.bootstrap = global;
+
+ JSMLoader.load("config", global);
+ JSMLoader.load("main", global);
+
+ JSMLoader.cacheFlush = cacheFlush;
+ JSMLoader.load("base", global);
+
+ if (!(BOOTSTRAP_CONTRACT in Cc)) {
+ // Use Sandbox to prevent closures over this scope
+ let sandbox = Cu.Sandbox(Cc["@mozilla.org/systemprincipal;1"].createInstance());
+ let factory = Cu.evalInSandbox("({ createInstance: function () this })", sandbox);
+
+ factory.classID = Components.ID("{f541c8b0-fe26-4621-a30b-e77d21721fb5}");
+ factory.contractID = BOOTSTRAP_CONTRACT;
+ factory.QueryInterface = XPCOMUtils.generateQI([Ci.nsIFactory]);
+ factory.wrappedJSObject = factory;
+
+ manager.registerFactory(factory.classID, String(factory.classID),
+ BOOTSTRAP_CONTRACT, factory);
+ }
+
+ Cc[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader = !Cu.unload && JSMLoader;
+
+ for each (let component in components)
+ component.register();
+
+ updateVersion();
+
+ if (addon !== addonData)
+ require("main", global);
}
/**
* Performs necessary migrations after a version change.
*/
function updateVersion() {
+ function isDev(ver) /^hg|pre$/.test(ver);
try {
- function isDev(ver) /^hg|pre$/.test(ver);
if (typeof require === "undefined" || addon === addonData)
return;
- require(global, "config");
- require(global, "prefs");
+ JSMLoader.load("prefs", global);
config.lastVersion = localPrefs.get("lastVersion", null);
localPrefs.set("lastVersion", addon.version);
if (!initialized) {
initialized = true;
- debug("bootstrap: init" + " " + data.id);
+ debug("bootstrap: init " + data.id);
addonData = data;
addon = data;
AddonManager.getAddonByID(addon.id, function (a) {
addon = a;
- updateLoader();
updateVersion();
if (typeof require !== "undefined")
- require(global, "main");
+ require("main", global);
});
if (basePath.isDirectory())
}
}
-function init() {
- debug("bootstrap: init");
-
- let manifestURI = getURI("chrome.manifest");
- let manifest = httpGet(manifestURI.spec)
- .responseText
- .replace(/^\s*|\s*$|#.*/g, "")
- .replace(/^\s*\n/gm, "");
-
- let suffix = "-";
- let chars = "0123456789abcdefghijklmnopqrstuv";
- for (let n = Date.now(); n; n = Math.round(n / chars.length))
- suffix += chars[n % chars.length];
-
- for each (let line in manifest.split("\n")) {
- let fields = line.split(/\s+/);
- switch(fields[0]) {
- case "category":
- categoryManager.addCategoryEntry(fields[1], fields[2], fields[3], false, true);
- categories.push([fields[1], fields[2]]);
- break;
- case "component":
- components[fields[1]] = new FactoryProxy(getURI(fields[2]).spec, fields[1]);
- break;
- case "contract":
- components[fields[2]].contractID = fields[1];
- break;
-
- case "resource":
- resources.push(fields[1], fields[1] + suffix);
- resourceProto.setSubstitution(fields[1], getURI(fields[2]));
- resourceProto.setSubstitution(fields[1] + suffix, getURI(fields[2]));
- }
- }
-
- // Flush the cache if necessary, just to be paranoid
- let pref = "extensions.dactyl.cacheFlushCheck";
- let val = addon.version;
- if (!Services.prefs.prefHasUserValue(pref) || Services.prefs.getCharPref(pref) != val) {
- var cacheFlush = true;
- Services.obs.notifyObservers(null, "startupcache-invalidate", "");
- Services.prefs.setCharPref(pref, val);
- }
-
- try {
- module(DISABLE_ACR).init(addon.id);
- }
- catch (e) {
- reportError(e);
- }
-
- if (JSMLoader) {
- // Temporary hacks until platforms and dactyl releases that don't
- // support Cu.unload are phased out.
- if (Cu.unload) {
- // Upgrading from dactyl release without Cu.unload support.
- Cu.unload(BOOTSTRAP_JSM);
- for (let [name] in Iterator(JSMLoader.globals))
- Cu.unload(~name.indexOf(":") ? name : "resource://dactyl" + JSMLoader.suffix + "/" + name);
- }
- else if (JSMLoader.bump != 6) {
- // We're in a version without Cu.unload support and the
- // JSMLoader interface has changed. Bump off the old one.
- Services.scriptloader.loadSubScript("resource://dactyl" + suffix + "/bootstrap.jsm",
- Cu.import(BOOTSTRAP_JSM, global));
- }
- }
-
- if (!JSMLoader || JSMLoader.bump !== 6 || Cu.unload)
- Cu.import(BOOTSTRAP_JSM, global);
-
- JSMLoader.name = name;
- JSMLoader.bootstrap = this;
-
- JSMLoader.load(BOOTSTRAP_JSM, global);
-
- JSMLoader.init(suffix);
- JSMLoader.cacheFlush = cacheFlush;
- JSMLoader.load("base.jsm", global);
-
- if (!(BOOTSTRAP_CONTRACT in Cc)) {
- // Use Sandbox to prevent closures over this scope
- let sandbox = Cu.Sandbox(Cc["@mozilla.org/systemprincipal;1"].getService());
- let factory = Cu.evalInSandbox("({ createInstance: function () this })", sandbox);
-
- factory.classID = Components.ID("{f541c8b0-fe26-4621-a30b-e77d21721fb5}");
- factory.contractID = BOOTSTRAP_CONTRACT;
- factory.QueryInterface = XPCOMUtils.generateQI([Ci.nsIFactory]);
- factory.wrappedJSObject = factory;
-
- manager.registerFactory(factory.classID, String(factory.classID),
- BOOTSTRAP_CONTRACT, factory);
- }
-
- Cc[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader = !Cu.unload && JSMLoader;
-
- for each (let component in components)
- component.register();
-
- Services.obs.notifyObservers(null, "dactyl-rehash", null);
- updateVersion();
-
- updateLoader();
- if (addon !== addonData)
- require(global, "main");
-}
-
function shutdown(data, reason) {
- debug("bootstrap: shutdown " + reasonToString(reason));
+ let strReason = reasonToString(reason);
+ debug("bootstrap: shutdown " + strReason);
+
if (reason != APP_SHUTDOWN) {
try {
- module(DISABLE_ACR).cleanup();
- if (Cu.unload)
- Cu.unload(DISABLE_ACR);
+ //JSMLoader.load("disable-acr").cleanup(addon.id);
}
catch (e) {
reportError(e);
if (~[ADDON_UPGRADE, ADDON_DOWNGRADE, ADDON_UNINSTALL].indexOf(reason))
Services.obs.notifyObservers(null, "dactyl-purge", null);
- Services.obs.notifyObservers(null, "dactyl-cleanup", reasonToString(reason));
+ Services.obs.notifyObservers(null, "dactyl-cleanup", strReason);
Services.obs.notifyObservers(null, "dactyl-cleanup-modules", reasonToString(reason));
- JSMLoader.purge();
+ JSMLoader.atexit(strReason);
+ JSMLoader.cleanup(strReason);
+
+ if (JSMLoader.SANDBOX)
+ Cu.nukeSandbox(bootstrap);
+ bootstrap_jsm.require = null;
+ Cu.unload(BOOTSTRAP);
+ bootstrap = null;
+ bootstrap_jsm = null;
+
for each (let [category, entry] in categories)
categoryManager.deleteCategoryEntry(category, entry, false);
for each (let resource in resources)
-resource dactyl-local ./
-resource dactyl-local-content content/
-resource dactyl-local-skin skin/
-resource dactyl-local-locale locale/
-
-resource dactyl-common ../common/
resource dactyl ../common/modules/
+resource dactyl-common ../common/
resource dactyl-content ../common/content/
resource dactyl-skin ../common/skin/
resource dactyl-locale ../common/locale/
+resource dactyl-local ./
+resource dactyl-local-content content/
+resource dactyl-local-skin skin/
+resource dactyl-local-locale locale/
+
content dactyl ../common/content/
component {16dc34f7-6d22-4aa4-a67f-2921fb5dcb69} components/commandline-handler.js
function init() {
Cu.import("resource://dactyl/bootstrap.jsm");
- if (!JSMLoader.initialized)
- JSMLoader.init();
- JSMLoader.load("base.jsm", global);
- require(global, "config");
- require(global, "util");
+ require("config", global);
+ require("util", global);
}
function CommandLineHandler() {
// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2010 by anekos <anekos@snca.net>
-// Copyright (c) 2010-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2010-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
nonkeyword: /[ "']/
};
- this._match = util.regexp(<><![CDATA[
+ this._match = util.regexp(literal(/*
(^ | \s | <nonkeyword>) (<keyword>+ )$ | // full-id
(^ | \s | <keyword> ) (<nonkeyword>+ <keyword>)$ | // end-id
(^ | \s ) (\S* <nonkeyword> )$ // non-id
- ]]></>, "x", params);
- this._check = util.regexp(<><![CDATA[
+ */), "x", params);
+ this._check = util.regexp(literal(/*
^ (?:
<keyword>+ | // full-id
<nonkeyword>+ <keyword> | // end-id
\S* <nonkeyword> // non-id
) $
- ]]></>, "x", params);
+ */), "x", params);
},
get: deprecated("group.abbrevs.get", { get: function get() this.user.closure.get }),
function abbrevs(hive)
hive.merged.filter(function (abbr) (abbr.inModes(modes) && abbr.lhs.indexOf(lhs) == 0));
- let list = <table>
- <tr highlight="Title">
- <td/>
- <td style="padding-right: 1em;">{_("title.Mode")}</td>
- <td style="padding-right: 1em;">{_("title.Abbrev")}</td>
- <td style="padding-right: 1em;">{_("title.Replacement")}</td>
- </tr>
- <col style="min-width: 6em; padding-right: 1em;"/>
- {
- template.map(hives, function (hive) let (i = 0)
- <tr style="height: .5ex;"/> +
- template.map(abbrevs(hive), function (abbrev)
- <tr>
- <td highlight="Title">{!i++ ? hive.name : ""}</td>
- <td>{abbrev.modeChar}</td>
- <td>{abbrev.lhs}</td>
- <td>{abbrev.rhs}</td>
- </tr>) +
- <tr style="height: .5ex;"/>)
- }
- </table>;
-
- // TODO: Move this to an ItemList to show this automatically
- if (list.*.length() === list.text().length() + 2)
- dactyl.echomsg(_("abbreviation.none"));
- else
- commandline.commandOutput(list);
+ let list = ["table", {},
+ ["tr", { highlight: "Title" },
+ ["td"],
+ ["td", { style: "padding-right: 1em;" }, _("title.Mode")],
+ ["td", { style: "padding-right: 1em;" }, _("title.Abbrev")],
+ ["td", { style: "padding-right: 1em;" }, _("title.Replacement")]],
+ ["col", { style: "min-width: 6em; padding-right: 1em;" }],
+ hives.map(function (hive) let (i = 0) [
+ ["tr", { style: "height: .5ex;" }],
+ abbrevs(hive).map(function (abbrev)
+ ["tr", {},
+ ["td", { highlight: "Title" }, !i++ ? String(hive.name) : ""],
+ ["td", {}, abbrev.modeChar],
+ ["td", {}, abbrev.lhs],
+ ["td", {}, abbrev.rhs]]),
+ ["tr", { style: "height: .5ex;" }]])];
+
+ // FIXME?
+ // // TODO: Move this to an ItemList to show this automatically
+ // if (list.*.length() === list.text().length() + 2)
+ // dactyl.echomsg(_("abbreviation.none"));
+ // else
+ commandline.commandOutput(list);
}
}, {
user: contexts.hives.abbrevs.user
});
},
- completion: function () {
+ completion: function initCompletion() {
completion.abbreviation = function abbreviation(context, modes, group) {
group = group || abbreviations.user;
let fn = modes ? function (abbr) abbr.inModes(modes) : util.identity;
context.completions = group.merged.filter(fn);
};
},
- commands: function () {
+ commands: function initCommands() {
function addAbbreviationCommands(modes, ch, modeDescription) {
modes.sort();
modeDescription = modeDescription ? " in " + modeDescription + " mode" : "";
&dactyl.appName; is open source and freely distributable
type :q<<span class="key">Enter</span>> to exit <!---->
-type :help<<span class="key">Enter</span>> or <<span class="key">F1</span>> for on-line help
+type :help<<span class="key">Enter</span>> for on-line help
type :help faq<<span class="key">Enter</span>> for the FAQ page
type :help versions<<span class="key">Enter</span>> for version info
</div>
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
return cmds;
}
- XML.prettyPrinting = XML.ignoreWhitespace = false;
- commandline.commandOutput(
- <table>
- <tr highlight="Title">
- <td colspan="3">----- Auto Commands -----</td>
- </tr>
- {
- template.map(hives, function (hive)
- <tr>
- <td colspan="3"><span highlight="Title">{hive.name}</span>
- {hive.filter}</td>
- </tr> +
- <tr style="height: .5ex;"/> +
- template.map(cmds(hive), function ([event, items])
- <tr style="height: .5ex;"/> +
- template.map(items, function (item, i)
- <tr>
- <td highlight="Title" style="padding-left: 1em; padding-right: 1em;">{i == 0 ? event : ""}</td>
- <td>{item.filter.toXML ? item.filter.toXML() : item.filter}</td>
- <td>{item.command}</td>
- </tr>) +
- <tr style="height: .5ex;"/>) +
- <tr style="height: .5ex;"/>)
- }
- </table>);
+ let table = (
+ ["table", {},
+ ["tr", { highlight: "Title" },
+ ["td", { colspan: "3" }, "----- Auto Commands -----"]],
+ hives.map(function (hive) [
+ ["tr", {},
+ ["td", { colspan: "3" },
+ ["span", { highlight: "Title" }, hive.name],
+ " ", hive.filter.toJSONXML(modules)]],
+ ["tr", { style: "height: .5ex;" }],
+ iter(cmds(hive)).map(function ([event, items]) [
+ ["tr", { style: "height: .5ex;" }],
+ items.map(function (item, i)
+ ["tr", {},
+ ["td", { highlight: "Title", style: "padding-left: 1em; padding-right: 1em;" },
+ i == 0 ? event : ""],
+ ["td", {}, item.filter.toJSONXML ? item.filter.toJSONXML(modules) : String(item.filter)],
+ ["td", {}, String(item.command)]]),
+ ["tr", { style: "height: .5ex;" }]]).toArray(),
+ ["tr", { style: "height: .5ex;" }],
+ ])]);
+ commandline.commandOutput(table);
},
/**
}
}, {
}, {
- contexts: function () {
+ contexts: function initContexts() {
update(AutoCommands.prototype, {
hives: contexts.Hives("autocmd", AutoCmdHive),
user: contexts.hives.autocmd.user,
matchingHives: function matchingHives(uri, doc) contexts.matchingGroups(uri, doc).autocmd
});
},
- commands: function () {
+ commands: function initCommands() {
commands.add(["au[tocmd]"],
"Execute commands automatically on events",
function (args) {
});
});
},
- completion: function () {
+ completion: function initCompletion() {
completion.autocmdEvent = function autocmdEvent(context) {
context.completions = Iterator(config.autocommands);
};
},
- javascript: function () {
+ javascript: function initJavascript() {
JavaScript.setCompleter(AutoCmdHive.prototype.get, [function () Iterator(config.autocommands)]);
},
- options: function () {
+ options: function initOptions() {
options.add(["eventignore", "ei"],
"List of autocommand event names which should be ignored",
"stringlist", "",
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
// also includes methods for dealing with keywords and search engines
var Bookmarks = Module("bookmarks", {
checkBookmarked: function checkBookmarked(uri) {
if (PlacesUtils.asyncGetBookmarkIds)
- PlacesUtils.asyncGetBookmarkIds(uri, function (ids) {
+ PlacesUtils.asyncGetBookmarkIds(uri, function withBookmarkIDs(ids) {
statusline.bookmarked = ids.length;
});
else
}
}, {
}, {
- commands: function () {
+ commands: function initCommands() {
// TODO: Clean this up.
const tags = {
names: ["-tags", "-T"],
privateData: true
});
},
- mappings: function () {
+ mappings: function initMappings() {
var myModes = config.browserModes;
mappings.add(myModes, ["a"],
"Toggle bookmarked state of current URL",
function () { bookmarks.toggle(buffer.uri.spec); });
},
- options: function () {
+ options: function initOptions() {
options.add(["defsearch", "ds"],
"The default search engine",
"string", "google",
{ completer: function completer(context) completion.searchEngine(context, true), });
},
- completion: function () {
+ completion: function initCompletion() {
completion.bookmark = function bookmark(context, tags, extra) {
context.title = ["Bookmark", "Title"];
context.format = bookmarks.format;
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
commands.add(["redr[aw]"],
"Redraw the screen",
function () {
- window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils)
- .redraw();
statusline.overLink = null;
statusline.updateStatus();
commandline.clear();
+ window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils)
+ .redraw();
},
{ argCount: "0" });
},
mappings.add([modes.NORMAL], ["<open-homepage>", "gh"],
"Open homepage",
- function () { BrowserHome(); });
+ function () { window.BrowserHome(); });
mappings.add([modes.NORMAL], ["<tab-open-homepage>", "gH"],
"Open homepage in a new tab",
function () {
- let homepages = gHomeButton.getHomePage();
+ let homepages = window.gHomeButton.getHomePage();
dactyl.open(homepages, { from: "homepage", where: dactyl.NEW_TAB });
});
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
init: function init() {
let s = "dactyl-statusline-field-";
- XML.ignoreWhitespace = true;
overlay.overlayWindow(window, {
objects: {
eventTarget: commandline
},
- append: <e4x xmlns={XUL} xmlns:dactyl={NS}>
- <vbox id={config.ids.commandContainer}>
- <vbox class="dactyl-container" hidden="false" collapsed="true">
- <iframe class="dactyl-completions" id="dactyl-completions-dactyl-commandline" src="dactyl://content/buffer.xhtml"
- contextmenu="dactyl-contextmenu"
- flex="1" hidden="false" collapsed="false"
- highlight="Events" events="mowEvents" />
- </vbox>
-
- <stack orient="horizontal" align="stretch" class="dactyl-container" id="dactyl-container" highlight="CmdLine CmdCmdLine">
- <textbox class="plain" id="dactyl-strut" flex="1" crop="end" collapsed="true"/>
- <textbox class="plain" id="dactyl-mode" flex="1" crop="end"/>
- <textbox class="plain" id="dactyl-message" flex="1" readonly="true"/>
-
- <hbox id="dactyl-commandline" hidden="false" class="dactyl-container" highlight="Normal CmdNormal" collapsed="true">
- <label id="dactyl-commandline-prompt" class="dactyl-commandline-prompt plain" flex="0" crop="end" value="" collapsed="true"/>
- <textbox id="dactyl-commandline-command" class="dactyl-commandline-command plain" flex="1" type="input" timeout="100"
- highlight="Events" />
- </hbox>
- </stack>
-
- <vbox class="dactyl-container" hidden="false" collapsed="false" highlight="CmdLine">
- <textbox id="dactyl-multiline-input" class="plain" flex="1" rows="1" hidden="false" collapsed="true" multiline="true"
- highlight="Normal Events" events="multilineInputEvents" />
- </vbox>
- </vbox>
-
- <stack id="dactyl-statusline-stack">
- <hbox id={s + "commandline"} hidden="false" class="dactyl-container" highlight="Normal StatusNormal" collapsed="true">
- <label id={s + "commandline-prompt"} class="dactyl-commandline-prompt plain" flex="0" crop="end" value="" collapsed="true"/>
- <textbox id={s + "commandline-command"} class="dactyl-commandline-command plain" flex="1" type="text" timeout="100"
- highlight="Events" />
- </hbox>
- </stack>
- </e4x>.elements(),
-
- before: <e4x xmlns={XUL} xmlns:dactyl={NS}>
- <toolbar id={statusline.statusBar.id}>
- <vbox id={"dactyl-completions-" + s + "commandline-container"} class="dactyl-container" hidden="false" collapsed="true">
- <iframe class="dactyl-completions" id={"dactyl-completions-" + s + "commandline"} src="dactyl://content/buffer.xhtml"
- contextmenu="dactyl-contextmenu" flex="1" hidden="false" collapsed="false"
- highlight="Events" events="mowEvents" />
- </vbox>
- </toolbar>
- </e4x>.elements()
+ append: [
+ ["vbox", { id: config.ids.commandContainer, xmlns: "xul" },
+ ["vbox", { class: "dactyl-container", hidden: "false", collapsed: "true" },
+ ["iframe", { class: "dactyl-completions", id: "dactyl-completions-dactyl-commandline",
+ src: "dactyl://content/buffer.xhtml", contextmenu: "dactyl-contextmenu",
+ flex: "1", hidden: "false", collapsed: "false",
+ highlight: "Events", events: "mowEvents" }]],
+
+ ["stack", { orient: "horizontal", align: "stretch", class: "dactyl-container",
+ id: "dactyl-container", highlight: "CmdLine CmdCmdLine" },
+ ["textbox", { class: "plain", id: "dactyl-strut", flex: "1", crop: "end", collapsed: "true" }],
+ ["textbox", { class: "plain", id: "dactyl-mode", flex: "1", crop: "end" }],
+ ["hbox", { id: "dactyl-message-box" },
+ ["label", { class: "plain", id: "dactyl-message-pre", flex: "0", readonly: "true", highlight: "WarningMsg" }],
+ ["textbox", { class: "plain", id: "dactyl-message", flex: "1", readonly: "true" }]],
+
+ ["hbox", { id: "dactyl-commandline", hidden: "false", class: "dactyl-container", highlight: "Normal CmdNormal", collapsed: "true" },
+ ["label", { id: "dactyl-commandline-prompt", class: "dactyl-commandline-prompt plain", flex: "0", crop: "end", value: "", collapsed: "true" }],
+ ["textbox", { id: "dactyl-commandline-command", class: "dactyl-commandline-command plain", flex: "1", type: "input", timeout: "100",
+ highlight: "Events" }]]],
+
+ ["vbox", { class: "dactyl-container", hidden: "false", collapsed: "false", highlight: "CmdLine" },
+ ["textbox", { id: "dactyl-multiline-input", class: "plain", flex: "1", rows: "1", hidden: "false", collapsed: "true",
+ multiline: "true", highlight: "Normal Events", events: "multilineInputEvents" }]]],
+
+ ["stack", { id: "dactyl-statusline-stack", xmlns: "xul" },
+ ["hbox", { id: s + "commandline", hidden: "false", class: "dactyl-container", highlight: "Normal StatusNormal", collapsed: "true" },
+ ["label", { id: s + "commandline-prompt", class: "dactyl-commandline-prompt plain", flex: "0", crop: "end", value: "", collapsed: "true" }],
+ ["textbox", { id: s + "commandline-command", class: "dactyl-commandline-command plain", flex: "1", type: "text", timeout: "100",
+ highlight: "Events", }]]]],
+
+ before: [
+ ["toolbar", { id: statusline.statusBar.id, xmlns: "xul" },
+ ["vbox", { id: "dactyl-completions-" + s + "commandline-container", class: "dactyl-container", hidden: "false", collapsed: "true" },
+ ["iframe", { class: "dactyl-completions", id: "dactyl-completions-" + s + "commandline", src: "dactyl://content/buffer.xhtml",
+ contextmenu: "dactyl-contextmenu", flex: "1", hidden: "false", collapsed: "false", highlight: "Events",
+ events: "mowEvents" }]]]],
});
this.elements = {};
return this.statusbar;
let statusElem = this.statusbar.message;
- if (value && !value[2] && statusElem.editor && statusElem.editor.rootElement.scrollWidth > statusElem.scrollWidth)
+ // Currently doesn't work as expected with <hbox> parent.
+ if (false && value && !value[2] && statusElem.editor && statusElem.editor.rootElement.scrollWidth > statusElem.scrollWidth)
return this.commandbar;
return this.activeGroup.mode;
}
});
+ this.addElement({
+ name: "message-pre",
+ defaultGroup: "WarningMsg",
+ getGroup: function () this.activeGroup.message
+ });
+
+ this.addElement({
+ name: "message-box",
+ defaultGroup: "Normal",
+ getGroup: function () this.activeGroup.message,
+ getValue: function () this.message
+ });
+
this.addElement({
name: "mode",
defaultGroup: "ModeMsg",
},
updateVisibility: function updateVisibility() {
+ let changed = 0;
for (let elem in values(this.elements))
if (elem.getGroup) {
let value = elem.getValue ? elem.getValue.call(this)
let meth, node = group[elem.name];
let visible = (value && group === activeGroup);
if (node && !node.collapsed == !visible) {
+ changed++;
node.collapsed = !visible;
if (elem.onVisibility)
elem.onVisibility.call(this, node, visible);
function check(node) {
if (DOM(node).style.display === "-moz-stack") {
let nodes = Array.filter(node.children, function (n) !n.collapsed && n.boxObject.height);
- nodes.forEach(function (node, i) node.style.opacity = (i == nodes.length - 1) ? "" : "0");
+ nodes.forEach(function (node, i) { node.style.opacity = (i == nodes.length - 1) ? "" : "0" });
}
Array.forEach(node.children, check);
}
[this.commandbar.container, this.statusbar.container].forEach(check);
+ // Work around a redrawing bug.
+ if (changed && config.haveGecko("16", "20")) {
+ util.delay(function () {
+ // Urgh.
+ statusline.statusBar.style.paddingRight = "1px";
+ DOM(statusline.statusBar).rect; // Force reflow.
+ statusline.statusBar.style.paddingRight = "";
+ }, 0);
+ }
+
if (this.initialized && loaded.mow && mow.visible)
mow.resize(false);
},
if (!scroll || Date.now() - this._lastEchoTime > 5000)
this.clearMessage();
this._lastEchoTime = 0;
+ this.hiddenMessages = 0;
if (!this.commandSession) {
this.widgets.command = null;
},
clearMessage: function clearMessage() {
- if (this.widgets.message && this.widgets.message[1] === this._lastClearable)
+ if (this.widgets.message && this.widgets.message[1] === this._lastClearable) {
this.widgets.message = null;
+ this.hiddenMessages = 0;
+ }
},
/**
* @param {XML} xml The output as an E4X XML object.
*/
commandOutput: function commandOutput(xml) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- if (this.command)
- this.echo(<><div xmlns={XHTML}>:{this.command}</div>
{xml}</>, this.HIGHLIGHT_NORMAL, this.FORCE_MULTILINE);
- else
+ if (!this.command)
this.echo(xml, this.HIGHLIGHT_NORMAL, this.FORCE_MULTILINE);
+ else
+ this.echo([["div", { xmlns: "html" }, ":" + this.command], "\n", xml],
+ this.HIGHLIGHT_NORMAL, this.FORCE_MULTILINE);
this.command = null;
},
let field = this.widgets.active.message.inputField;
if (field.value && !forceSingle && field.editor.rootElement.scrollWidth > field.scrollWidth) {
this.widgets.message = null;
- mow.echo(<span highlight="Message">{str}</span>, highlightGroup, true);
+ mow.echo(["span", { highlight: "Message" }, str], highlightGroup, true);
}
},
+ _hiddenMessages: 0,
+ get hiddenMessages() this._hiddenMessages,
+ set hiddenMessages(val) {
+ this._hiddenMessages = val;
+ if (val)
+ this.widgets["message-pre"] = _("commandline.moreMessages", val) + " ";
+ else
+ this.widgets["message-pre"] = null
+ },
+
_lastEcho: null,
/**
highlightGroup = highlightGroup || this.HL_NORMAL;
- if (flags & this.APPEND_TO_MESSAGES) {
- let message = isObject(data) ? data : { message: data };
+ let self = this;
+ function appendToMessages(data) {
+ let message = isObject(data) && !DOM.isJSONXML(data) ? data : { message: data };
// Make sure the memoized message property is an instance property.
message.message;
- this._messageHistory.add(update({ highlight: highlightGroup }, message));
- data = message.message;
+ self._messageHistory.add(update({ highlight: highlightGroup }, message));
+ return message.message;
}
+ if (flags & this.APPEND_TO_MESSAGES)
+ data = appendToMessages(data);
+
if ((flags & this.ACTIVE_WINDOW) && window != overlay.activeWindow)
return;
if ((flags & this.DISALLOW_MULTILINE) && !this.widgets.mowContainer.collapsed)
return;
- let single = flags & (this.FORCE_SINGLELINE | this.DISALLOW_MULTILINE);
+ let forceSingle = flags & (this.FORCE_SINGLELINE | this.DISALLOW_MULTILINE);
let action = this._echoLine;
if ((flags & this.FORCE_MULTILINE) || (/\n/.test(data) || !isinstance(data, [_, "String"])) && !(flags & this.FORCE_SINGLELINE))
action = mow.closure.echo;
- if (single)
+ let single = function () action == self._echoLine;
+
+ if (forceSingle) {
this._lastEcho = null;
+ this.hiddenMessages = 0;
+ }
else {
- if (this.widgets.message && this.widgets.message[1] == this._lastEcho)
- mow.echo(<span highlight="Message">{this._lastEcho}</span>,
- this.widgets.message[0], true);
-
- if (action === this._echoLine && !(flags & this.FORCE_MULTILINE)
- && !(dactyl.fullyInitialized && this.widgets.mowContainer.collapsed)) {
+ // So complicated...
+ if (single() && !this.widgets.mowContainer.collapsed) {
highlightGroup += " Message";
action = mow.closure.echo;
}
- this._lastEcho = (action == this._echoLine) && data;
+ else if (!single() && this.widgets.mowContainer.collapsed) {
+ if (this._lastEcho && this.widgets.message && this.widgets.message[1] == this._lastEcho.msg) {
+ if (!(this._lastEcho.flags & this.APPEND_TO_MESSAGES))
+ appendToMessages(this._lastEcho.data);
+
+ mow.echo(
+ ["span", { highlight: "Message" },
+ ["span", { highlight: "WarningMsg" },
+ _("commandline.moreMessages", this.hiddenMessages + 1) + " "],
+ this._lastEcho.msg],
+ this.widgets.message[0], true);
+
+ this.hiddenMessages = 0;
+ }
+ }
+ else if (this._lastEcho && this.widgets.message && this.widgets.message[1] == this._lastEcho.msg) {
+ if (!(this._lastEcho.flags & this.APPEND_TO_MESSAGES))
+ appendToMessages(this._lastEcho.data);
+ if (single() && !(flags & this.APPEND_TO_MESSAGES))
+ appendToMessages(data);
+
+ flags |= this.APPEND_TO_MESSAGES;
+ this.hiddenMessages++;
+ }
+ this._lastEcho = single() && { flags: flags, msg: data, data: arguments[0] };
}
this._lastClearable = action === this._echoLine && String(data);
save: function save() {
if (events.feedingKeys)
return;
+
let str = this.input.value;
if (/^\s*$/.test(str))
return;
+
+ let privateData = this.checkPrivate(str);
+ if (privateData == "never-save")
+ return;
+
this.store = this.store.filter(function (line) (line.value || line) != str);
dactyl.trapErrors(function () {
- this.store.push({ value: str, timestamp: Date.now()*1000, privateData: this.checkPrivate(str) });
+ this.store.push({ value: str, timestamp: Date.now()*1000, privateData: privateData });
}, this);
this.store = this.store.slice(Math.max(0, this.store.length - options["history"]));
},
substring = substring.substr(value.length);
this.removeSubstring = substring;
- let node = DOM.fromXML(<span highlight="Preview">{substring}</span>,
- document);
+ let node = DOM.fromJSON(["span", { highlight: "Preview" }, substring],
+ document);
this.withSavedValues(["caret"], function () {
this.editor.insertNode(node, this.editor.rootElement, 1);
return arg;
}
}, {
- commands: function init_commands() {
+ commands: function initCommands() {
[
{
name: "ec[ho]",
commandline.echo(message.message, message.highlight, commandline.FORCE_SINGLELINE);
}
else if (commandline._messageHistory.length > 1) {
- XML.ignoreWhitespace = false;
commandline.commandOutput(
template.map(commandline._messageHistory.messages, function (message)
- <div highlight={message.highlight + " Message"}>{message.message}</div>));
+ ["div", { highlight: message.highlight + " Message" },
+ message.message]));
}
},
{ argCount: "0" });
bases: [modes.INSERT]
});
},
- mappings: function init_mappings() {
+ mappings: function initMappings() {
mappings.add([modes.COMMAND],
[":"], "Enter Command Line mode",
bind(["<C-]>", "<C-5>"], "Expand command line abbreviation",
function () { editor.expandAbbreviation(modes.COMMAND_LINE); });
},
- options: function init_options() {
+ options: function initOptions() {
options.add(["history", "hi"],
"Number of Ex commands and search patterns to store in the command-line history",
"number", 500,
"number", 100,
{ validator: function (value) value >= 0 });
},
- sanitizer: function init_sanitizer() {
+ sanitizer: function initSanitizer() {
sanitizer.addItem("commandline", {
description: "Command-line and search history",
persistent: true,
DOM(this.win).resize(this._onResize.closure.tell);
},
- get rootXML() <e4x>
- <div highlight="Normal" style="white-space: nowrap" key="root">
- <div key="wrapper">
- <div highlight="Completions" key="noCompletions"><span highlight="Title">{_("completion.noCompletions")}</span></div>
- <div key="completions"/>
- </div>
+ get rootXML()
+ ["div", { highlight: "Normal", style: "white-space: nowrap", key: "root" },
+ ["div", { key: "wrapper" },
+ ["div", { highlight: "Completions", key: "noCompletions" },
+ ["span", { highlight: "Title" },
+ _("completion.noCompletions")]],
+ ["div", { key: "completions" }]],
- <div highlight="Completions">{
- template.map(util.range(0, options["maxitems"] * 2), function (i)
- <div highlight="CompItem NonText"><li>~</li></div>)
- }</div>
- </div>
- </e4x>.elements(),
+ ["div", { highlight: "Completions" },
+ template.map(util.range(0, options["maxitems"] * 2), function (i)
+ ["div", { highlight: "CompItem NonText" },
+ "~"])]],
- get itemCount() this.context.contextList.reduce(function (acc, ctxt) acc + ctxt.items.length, 0),
+ get itemCount() this.context.contextList
+ .reduce(function (acc, ctxt) acc + ctxt.items.length, 0),
get visible() !this.container.collapsed,
set visible(val) this.container.collapsed = !val,
let off = group.getOffset(idx);
start = Math.constrain(start,
- off + Math.min(this.CONTEXT_LINES, group.itemCount - idx + group.offsets.end)
+ off + Math.min(this.CONTEXT_LINES,
+ group.itemCount - idx + group.offsets.end)
- this.maxItems + 1,
- off - Math.min(this.CONTEXT_LINES, idx + group.offsets.start));
+ off - Math.min(this.CONTEXT_LINES,
+ idx + group.offsets.start));
}
let count = this.maxItems;
},
get rootXML()
- <div key="root" highlight="CompGroup">
- <div highlight="Completions">
- { this.context.createRow(this.context.title || [], "CompTitle") }
- </div>
- <div highlight="CompTitleSep"/>
- <div key="contents">
- <div key="up" highlight="CompLess"/>
- <div key="message" highlight="CompMsg">{this.context.message}</div>
- <div key="itemsContainer" class="completion-items-container">
- <div key="items" highlight="Completions"/>
- </div>
- <div key="waiting" highlight="CompMsg">{ItemList.WAITING_MESSAGE}</div>
- <div key="down" highlight="CompMore"/>
- </div>
- </div>,
+ ["div", { key: "root", highlight: "CompGroup" },
+ ["div", { highlight: "Completions" },
+ this.context.createRow(this.context.title || [], "CompTitle")],
+ ["div", { highlight: "CompTitleSep" }],
+ ["div", { key: "contents" },
+ ["div", { key: "up", highlight: "CompLess" }],
+ ["div", { key: "message", highlight: "CompMsg" },
+ this.context.message || []],
+ ["div", { key: "itemsContainer", class: "completion-items-container" },
+ ["div", { key: "items", highlight: "Completions" }]],
+ ["div", { key: "waiting", highlight: "CompMsg" },
+ ItemList.WAITING_MESSAGE],
+ ["div", { key: "down", highlight: "CompMore" }]]],
get doc() this.parent.doc,
get win() this.parent.win,
this.nodes = {};
this.generatedRange = ItemList.Range(0, 0);
- DOM.fromXML(this.rootXML, this.doc, this.nodes);
+ DOM.fromJSON(this.rootXML, this.doc, this.nodes);
},
/**
DOM(this.nodes.items).empty();
if (this.context.message)
- DOM(this.nodes.message).empty().append(<>{this.context.message}</>);
+ DOM(this.nodes.message).empty()
+ .append(DOM.fromJSON(this.context.message, this.doc));
- if (!this.selectedIdx > this.itemCount)
+ if (this.selectedIdx > this.itemCount)
this.selectedIdx = null;
},
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
-default xml namespace = XHTML;
-XML.ignoreWhitespace = false;
-XML.prettyPrinting = false;
-
var EVAL_ERROR = "__dactyl_eval_error";
var EVAL_RESULT = "__dactyl_eval_result";
var EVAL_STRING = "__dactyl_eval_string";
init: function () {
window.dactyl = this;
// cheap attempt at compatibility
- let prop = { get: deprecated("dactyl", function liberator() dactyl) };
+ let prop = { get: deprecated("dactyl", function liberator() dactyl),
+ configurable: true };
Object.defineProperty(window, "liberator", prop);
Object.defineProperty(modules, "liberator", prop);
this.commands = {};
delete window.liberator;
// Prevents box ordering bugs after our stylesheet is removed.
- styles.system.add("cleanup-sheet", config.styleableChrome, <![CDATA[
+ styles.system.add("cleanup-sheet", config.styleableChrome, literal(/*
#TabsToolbar tab { display: none; }
- ]]>);
+ */));
styles.unregisterSheet("resource://dactyl-skin/dactyl.css");
DOM('#TabsToolbar tab', document).style.display;
},
signals: {
"io.source": function ioSource(context, file, modTime) {
- if (context.INFO)
+ if (contexts.getDocs(context))
help.flush("help/plugins.xml", modTime);
}
},
NEW_WINDOW: "window",
forceBackground: null,
+ forcePrivate: null,
forceTarget: null,
get forceOpen() ({ background: this.forceBackground,
for (let obj in values(results)) {
let res = dactyl.generateHelp(obj, null, null, true);
if (!haveTag(obj.helpTag))
- res[1].@tag = obj.helpTag;
+ res[0][1].tag = obj.helpTag;
yield res;
}
bell: document.getElementById("dactyl-bell"),
strut: document.getElementById("dactyl-bell-strut")
};
- XML.ignoreWhitespace = true;
if (!elems.bell)
overlay.overlayWindow(window, {
objects: elems,
- prepend: <>
- <window id={document.documentElement.id} xmlns={XUL}>
- <hbox style="display: none" highlight="Bell" id="dactyl-bell" key="bell"/>
- </window>
- </>,
- append: <>
- <window id={document.documentElement.id} xmlns={XUL}>
- <hbox style="display: none" highlight="Bell" id="dactyl-bell-strut" key="strut"/>
- </window>
- </>
+ prepend: [
+ ["window", { id: document.documentElement.id, xmlns: "xul" },
+ ["hbox", { style: "display: none", highlight: "Bell", id: "dactyl-bell", key: "bell" }]]],
+ append: [
+ ["window", { id: document.documentElement.id, xmlns: "xul" },
+ ["hbox", { style: "display: none", highlight: "Bell", id: "dactyl-bell-strut", key: "strut" }]]]
}, elems);
elems.bell.style.height = window.innerHeight + "px";
if (isObject(str) && "echoerr" in str)
str = str.echoerr;
else if (isinstance(str, ["Error", FailedAssertion]) && str.fileName)
- str = <>{str.fileName.replace(/^.* -> /, "")}: {str.lineNumber}: {str}</>;
+ str = [str.fileName.replace(/^.* -> /, ""), ": ", str.lineNumber, ": ", str].join("");
if (options["errorbells"])
dactyl.beep();
* @param {Object} context The context object into which the script
* should be loaded.
*/
- loadScript: function (uri, context) {
+ loadScript: function loadScript(uri, context) {
JSMLoader.loadSubScript(uri, context, File.defaultEncoding);
},
- userEval: function (str, context, fileName, lineNumber) {
+ userEval: function userEval(str, context, fileName, lineNumber) {
let ctxt;
if (jsmodules.__proto__ != window && jsmodules.__proto__ != XPCNativeWrapper(window) &&
jsmodules.isPrototypeOf(context))
* Acts like the Function builtin, but the code executes in the
* userContext global.
*/
- userFunc: function () {
+ userFunc: function userFunc() {
return this.userEval(
"(function userFunction(" + Array.slice(arguments, 0, -1).join(", ") + ")" +
" { " + arguments[arguments.length - 1] + " })");
* @param {boolean} silent Whether the command should be echoed on the
* command line.
*/
- execute: function (str, modifiers, silent) {
+ execute: function execute(str, modifiers, silent) {
// skip comments and blank lines
if (/^\s*("|$)/.test(str))
return;
* @param {string} feature The feature name.
* @returns {boolean}
*/
- has: function (feature) Set.has(config.features, feature),
+ has: function has(feature) Set.has(config.features, feature),
/**
* @private
*/
initHelp: function initHelp() {
if ("noscriptOverlay" in window)
- noscriptOverlay.safeAllow("dactyl:", true, false);
+ window.noscriptOverlay.safeAllow("dactyl:", true, false);
help.initialize();
},
- stringifyXML: function (xml) {
- XML.prettyPrinting = false;
- XML.ignoreWhitespace = false;
- return UTF8(xml.toXMLString());
- },
-
/**
* Generates a help entry and returns it as a string.
*
* @returns {string}
*/
generateHelp: function generateHelp(obj, extraHelp, str, specOnly) {
- default xml namespace = "";
-
let link, tag, spec;
link = tag = spec = util.identity;
let args = null;
if (obj instanceof Command) {
- link = function (cmd) <ex>{cmd}</ex>;
+ link = function (cmd) ["ex", {}, cmd];
args = obj.parseArgs("", CompletionContext(str || ""));
- tag = function (cmd) <>:{cmd}</>;
- spec = function (cmd) <>{
- obj.count ? <oa>count</oa> : <></>
- }{
- cmd
- }{
- obj.bang ? <oa>!</oa> : <></>
- }</>;
+ tag = function (cmd) DOM.DOMString(":" + cmd);
+ spec = function (cmd) [
+ obj.count ? ["oa", {}, "count"] : [],
+ cmd,
+ obj.bang ? ["oa", {}, "!"] : []
+ ];
}
else if (obj instanceof Map) {
- spec = function (map) obj.count ? <><oa>count</oa>{map}</> : <>{map}</>;
- tag = function (map) <>{
- let (c = obj.modes[0].char) c ? c + "_" : ""
- }{ map }</>;
+ spec = function (map) obj.count ? [["oa", {}, "count"], map] : DOM.DOMString(map);
+ tag = function (map) [
+ let (c = obj.modes[0].char) c ? c + "_" : "",
+ map
+ ]
link = function (map) {
let [, mode, name, extra] = /^(?:(.)_)?(?:<([^>]+)>)?(.*)$/.exec(map);
- let k = <k>{extra}</k>;
+ let k = ["k", {}, extra];
if (name)
- k.@name = name;
+ k[1].name = name;
if (mode)
- k.@mode = mode;
+ k[1].mode = mode;
return k;
};
}
else if (obj instanceof Option) {
spec = function () template.map(obj.names, tag, " ");
- tag = function (name) <>'{name}'</>;
- link = function (opt, name) <o>{name}</o>;
+ tag = function (name) DOM.DOMString("'" + name + "'");
+ link = function (opt, name) ["o", {}, name];
args = { value: "", values: [] };
}
- XML.prettyPrinting = false;
- XML.ignoreWhitespace = false;
- default xml namespace = NS;
-
- // E4X has its warts.
- let br = <>
- </>;
-
- let res = <res>
- <dt>{link(obj.helpTag || tag(obj.name), obj.name)}</dt> <dd>{
- template.linkifyHelp(obj.description ? obj.description.replace(/\.$/, "") : "", true)
- }</dd></res>;
+ let res = [
+ ["dt", {}, link(obj.helpTag || tag(obj.name), obj.name)],
+ ["dd", {},
+ template.linkifyHelp(obj.description ? obj.description.replace(/\.$/, "") : "", true)]];
if (specOnly)
- return res.elements();
+ return res;
- res.* += <>
- <item>
- <tags>{template.map(obj.names.slice().reverse(), tag, " ")}</tags>
- <spec>{let (name = (obj.specs || obj.names)[0])
+ let description = ["description", {},
+ obj.description ? ["p", {}, template.linkifyHelp(obj.description.replace(/\.?$/, "."), true)] : "",
+ extraHelp ? extraHelp : "",
+ !(extraHelp || obj.description) ? ["p", {}, /*L*/ "Sorry, no help available."] : ""]
+
+ res.push(
+ ["item", {},
+ ["tags", {}, template.map(obj.names.slice().reverse(),
+ tag,
+ " ").join("")],
+ ["spec", {},
+ let (name = (obj.specs || obj.names)[0])
spec(template.highlightRegexp(tag(name),
/\[(.*?)\]/g,
- function (m, n0) <oa>{n0}</oa>),
- name)
- }</spec>{
- !obj.type ? "" : <>
- <type>{obj.type}</type>
- <default>{obj.stringDefaultValue}</default></>}
- <description>{
- obj.description ? br + <p>{template.linkifyHelp(obj.description.replace(/\.?$/, "."), true)}</p> : "" }{
- extraHelp ? br + extraHelp : "" }{
- !(extraHelp || obj.description) ? br + <p><!--L-->Sorry, no help available.</p> : "" }
- </description>
- </item></>;
+ function (m, n0) ["oa", {}, n0]),
+ name)],
+ !obj.type ? "" : [
+ ["type", {}, obj.type],
+ ["default", {}, obj.stringDefaultValue]],
+ description]);
function add(ary) {
- res.item.description.* += br +
- let (br = br + <> </>)
- <><dl>{ br + template.map(ary, function ([a, b]) <><dt>{a}</dt> <dd>{b}</dd></>, br) }
- </dl>
- </>;
+ description.push(
+ ["dl", {}, template.map(ary,
+ function ([a, b]) [["dt", {}, a], " ",
+ ["dd", {}, b]])]);
}
- if (obj.completer)
+ if (obj.completer && false)
add(completion._runCompleter(obj.closure.completer, "", null, args).items
.map(function (i) [i.text, i.description]));
- if (obj.options && obj.options.some(function (o) o.description))
+ if (obj.options && obj.options.some(function (o) o.description) && false)
add(obj.options.filter(function (o) o.description)
.map(function (o) [
o.names[0],
- <>{o.description}{
- o.names.length == 1 ? "" :
- <> (short name: {
- template.map(o.names.slice(1), function (n) <em>{n}</em>, <>, </>)
- })</>
- }</>
+ [o.description,
+ o.names.length == 1 ? "" :
+ ["", " (short name: ",
+ template.map(o.names.slice(1), function (n) ["em", {}, n], ", "),
+ ")"]]
]));
- return res.*.toXMLString()
- .replace(' xmlns="' + NS + '"', "", "g")
- .replace(/^ {12}|[ \t]+$/gm, "")
- .replace(/^\s*\n|\n\s*$/g, "") + "\n";
+
+ return DOM.toPrettyXML(res, true, null, { "": String(NS) });
},
/**
get: function globalVariables() this._globalVariables
}),
- loadPlugins: function (args, force) {
+ loadPlugins: function loadPlugins(args, force) {
function sourceDirectory(dir) {
dactyl.assert(dir.isReadable(), _("io.notReadable", dir.path));
* @param {string|Object} msg The message to print.
* @param {number} level The logging level 0 - 15.
*/
- log: function (msg, level) {
+ log: function log(msg, level) {
let verbose = config.prefs.get("loglevel", 0);
if (!level || level <= verbose) {
* tabs.
* @returns {boolean}
*/
- open: function (urls, params, force) {
+ open: function open(urls, params, force) {
if (typeof urls == "string")
urls = dactyl.parseURLs(urls);
});
case dactyl.NEW_WINDOW:
- let win = window.openDialog(document.documentURI, "_blank", "chrome,all,dialog=no");
+ let options = ["chrome", "all", "dialog=no"];
+ if (dactyl.forcePrivate)
+ options.push("private");
+
+ let win = window.openDialog(document.documentURI, "_blank", options.join(","));
util.waitFor(function () win.document.readyState === "complete");
browser = win.dactyl && win.dactyl.modules.config.tabbrowser || win.getBrowser();
// FALLTHROUGH
// Try to find a matching file.
let file = io.File(url);
if (file.exists() && file.isReadable())
- return services.io.newFileURI(file).spec;
+ return file.URI.spec;
}
catch (e) {}
}
}, this);
},
stringToURLArray: deprecated("dactyl.parseURLs", "parseURLs"),
- urlish: Class.Memoize(function () util.regexp(<![CDATA[
+ urlish: Class.Memoize(function () util.regexp(literal(/*
^ (
<domain>+ (:\d+)? (/ .*) |
<domain>+ (:\d+) |
<domain>+ \. [a-z0-9]+ |
localhost
) $
- ]]>, "ix", {
- domain: util.regexp(String.replace(<![CDATA[
+ */), "ix", {
+ domain: util.regexp(String.replace(literal(/*
[^
U0000-U002c // U002d-U002e --.
U002f // /
U005b-U0060 // U0061-U007a A-Z
U007b-U007f
]
- ]]>, /U/g, "\\u"), "x")
+ */), /U/g, "\\u"), "x")
})),
pluginFiles: {},
* @param {boolean} force Forcibly quit irrespective of whether all
* windows could be closed individually.
*/
- quit: function (saveSession, force) {
+ quit: function quit(saveSession, force) {
if (!force && !this.confirmQuit())
return;
/**
* Restart the host application.
*/
- restart: function (args) {
+ restart: function restart(args) {
if (!this.confirmQuit())
return;
* @returns {Object}
* @see Commands#parseArgs
*/
- parseCommandLine: function (cmdline) {
+ parseCommandLine: function parseCommandLine(cmdline) {
try {
return commands.get("rehash").parseArgs(cmdline);
}
return [];
}
},
- wrapCallback: function (callback, self) {
+ wrapCallback: function wrapCallback(callback, self) {
self = self || this;
let save = ["forceOpen"];
let saved = save.map(function (p) dactyl[p]);
}, {
toolbarHidden: function hidden(elem) (elem.getAttribute("autohide") || elem.getAttribute("collapsed")) == "true"
}, {
- cache: function () {
+ cache: function initCache() {
cache.register("help/plugins.xml", function () {
// Process plugin help entries.
- XML.ignoreWhiteSpace = XML.prettyPrinting = false;
- let body = XML();
+ let body = [];
for (let [, context] in Iterator(plugins.contexts))
try {
let info = contexts.getDocs(context);
- if (info instanceof XML) {
- if (info.*.@lang.length()) {
- let lang = config.bestLocale(String(a) for each (a in info.*.@lang));
-
- info.* = info.*.(function::attribute("lang").length() == 0 || @lang == lang);
-
- for each (let elem in info.NS::info)
- for (let attr in values(["@name", "@summary", "@href"]))
- if (elem[attr].length())
- info[attr] = elem[attr];
+ if (DOM.isJSONXML(info)) {
+ let langs = info.slice(2).filter(function (e) isArray(e) && isObject(e[1]) && e[1].lang);
+ if (langs) {
+ let lang = config.bestLocale(l[1].lang for each (l in langs));
+
+ info = info.slice(0, 2).concat(
+ info.slice(2).filter(function (e) !isArray(e) || !isObject(e[1])
+ || e[1].lang == lang));
+
+ for each (let elem in info.slice(2).filter(function (e) isArray(e) && e[0] == "info" && isObject(e[1])))
+ for (let attr in values(["name", "summary", "href"]))
+ if (attr in elem[1])
+ info[attr] = elem[1][attr];
}
- body += <h2 xmlns={NS.uri} tag={info.@name + '-plugin'}>{info.@summary}</h2> +
- info;
+ body.push(["h2", { xmlns: "dactyl", tag: info[1].name + '-plugin' },
+ String(info[1].summary)]);
+ body.push(info);
}
}
catch (e) {
return '<?xml version="1.0"?>\n' +
'<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>\n' +
- '<!DOCTYPE document SYSTEM "resource://dactyl-content/dactyl.dtd">\n' +
- <document xmlns={NS}
- name="plugins" title={config.appName + " Plugins"}>
- <h1 tag="using-plugins">{_("help.title.Using Plugins")}</h1>
- <toc start="2"/>
-
- {body}
- </document>.toXMLString();
+ DOM.toXML(
+ ["document", { xmlns: "dactyl", name: "plugins",
+ title: config.appName + ", Plugins" },
+ ["h1", { tag: "using-plugins" }, _("help.title.Using Plugins")],
+ ["toc", { start: "2" }],
+
+ body]);
});
cache.register("help/index.xml", function () {
- default xml namespace = NS;
-
return '<?xml version="1.0"?>\n' +
- <overlay xmlns={NS}>{
- template.map(dactyl.indices, function ([name, iter])
- <dl insertafter={name + "-index"}>{
- template.map(iter(), util.identity)
- }</dl>, <>{"\n\n"}</>)
- }</overlay>;
+ DOM.toXML(["overlay", { xmlns: "dactyl" },
+ template.map(dactyl.indices, function ([name, iter])
+ ["dl", { insertafter: name + "-index" },
+ template.map(iter(), util.identity)],
+ "\n\n")]);
});
cache.register("help/gui.xml", function () {
- default xml namespace = NS;
-
return '<?xml version="1.0"?>\n' +
- <overlay xmlns={NS}>
- <dl insertafter="dialog-list">{
- template.map(config.dialogs, function ([name, val])
- (!val[2] || val[2]())
- ? <><dt>{name}</dt><dd>{val[0]}</dd></>
- : undefined,
- <>{"\n"}</>)
- }</dl>
- </overlay>;
+ DOM.toXML(["overlay", { xmlns: "dactyl" },
+ ["dl", { insertafter: "dialog-list" },
+ template.map(config.dialogs, function ([name, val])
+ (!val[2] || val[2]())
+ ? [["dt", {}, name],
+ ["dd", {}, val[0]]]
+ : undefined,
+ "\n")]]);
});
cache.register("help/privacy.xml", function () {
- default xml namespace = NS;
-
return '<?xml version="1.0"?>\n' +
- <overlay xmlns={NS}>
- <dl insertafter="sanitize-items">{
- template.map(options.get("sanitizeitems").values
- .sort(function (a, b) String.localeCompare(a.name, b.name)),
- function ({ name, description })
- <><dt>{name}</dt><dd>{template.linkifyHelp(description, true)}</dd></>,
- <>{"\n"}</>)
- }</dl>
- </overlay>;
+ DOM.toXML(["overlay", { xmlns: "dactyl" },
+ ["dl", { insertafter: "sanitize-items" },
+ template.map(options.get("sanitizeitems").values
+ .sort(function (a, b) String.localeCompare(a.name,
+ b.name)),
+ function ({ name, description })
+ [["dt", {}, name],
+ ["dd", {}, template.linkifyHelp(description, true)]],
+ "\n")]]);
});
},
- events: function () {
+ events: function initEvents() {
events.listen(window, dactyl, "events", true);
},
// Only general options are added here, which are valid for all Dactyl extensions
- options: function () {
+ options: function initOptions() {
options.add(["errorbells", "eb"],
"Ring the bell when an error message is displayed",
"boolean", false);
document.title = document.title.replace(RegExp("(.*)" + util.regexp.escape(old)), "$1" + current);
}
- if (services.has("privateBrowsing")) {
+ if (win.hasAttribute("titlemodifier_privatebrowsing")) {
let oldValue = win.getAttribute("titlemodifier_normal");
let suffix = win.getAttribute("titlemodifier_privatebrowsing").substr(oldValue.length);
win.setAttribute("titlemodifier_normal", value);
win.setAttribute("titlemodifier_privatebrowsing", value + suffix);
- if (services.privateBrowsing.privateBrowsingEnabled) {
+ if (storage.privateMode) {
updateTitle(oldValue + suffix, value + suffix);
+ win.setAttribute("titlemodifier", value + suffix);
return value;
}
}
});
},
- mappings: function () {
+ mappings: function initMappings() {
if (dactyl.has("session"))
mappings.add([modes.NORMAL], ["ZQ"],
"Quit and don't save the session",
function () { dactyl.quit(true); });
},
- commands: function () {
+ commands: function initCommands() {
commands.add(["dia[log]"],
"Open a " + config.appName + " dialog",
function (args) {
literal: 0
});
+ commands.add(["pr[ivate]", "pr0n", "porn"],
+ "Enable privacy features of a command, when applicable, and do not save the invocation in command history",
+ function (args) {
+ dactyl.withSavedValues(["forcePrivate"], function () {
+ this.forcePrivate = true;
+ dactyl.execute(args[0], null, true);
+ });
+ }, {
+ argCount: "1",
+ completer: function (context) completion.ex(context),
+ literal: 0,
+ privateData: "never-save",
+ subCommand: 0
+ });
+
commands.add(["exit", "x"],
"Quit " + config.appName,
function (args) {
"Reload the " + config.appName + " add-on",
function (args) {
if (args.trailing)
- storage.session.rehashCmd = args.trailing; // Hack.
+ storage.storeForSession("rehashCmd", args.trailing); // Hack.
args.break = true;
if (args["+purgecaches"])
cache.flush();
- util.rehash(args);
+ util.delay(function () { util.rehash(args) });
},
{
argCount: "0", // FIXME
totalUnits = "msec";
commandline.commandOutput(
- <table>
- <tr highlight="Title" align="left">
- <th colspan="3">{_("title.Code execution summary")}</th>
- </tr>
- <tr><td>  {_("title.Executed")}:</td><td align="right"><span class="times-executed">{count}</span></td><td><!--L-->times</td></tr>
- <tr><td>  {_("title.Average time")}:</td><td align="right"><span class="time-average">{each.toFixed(2)}</span></td><td>{eachUnits}</td></tr>
- <tr><td>  {_("title.Total time")}:</td><td align="right"><span class="time-total">{total.toFixed(2)}</span></td><td>{totalUnits}</td></tr>
- </table>);
+ ["table", {}
+ ["tr", { highlight: "Title", align: "left" },
+ ["th", { colspan: "3" }, _("title.Code execution summary")]],
+ ["tr", {},
+ ["td", {}, _("title.Executed"), ":"],
+ ["td", { align: "right" },
+ ["span", { class: "times-executed" }, count]],
+ ["td", {}, /*L*/"times"]],
+ ["tr", {},
+ ["td", {}, _("title.Average time"), ":"],
+ ["td", { align: "right" },
+ ["span", { class: "time-average" }, each.toFixed(2)]],
+ ["td", {}, eachUnits]],
+ ["tr", {},
+ ["td", {}, _("title.Total time"), ":"],
+ ["td", { align: "right" },
+ ["span", { class: "time-total" }, total.toFixed(2)]],
+ ["td", {}, totalUnits]]]);
}
else {
let beforeTime = Date.now();
let date = config.buildDate;
date = date ? " (" + date + ")" : "";
- commandline.commandOutput(
- <div>{config.appName} {config.version}{date} running on: </div> +
- <div>{navigator.userAgent}</div>)
+ commandline.commandOutput([
+ ["div", {}, [config.appName, " ", config.version, date, " running on: "].join("")],
+ ["div", {}, [window.navigator.userAgent].join("")]
+ ])
}
}, {
argCount: "0",
},
- completion: function () {
+ completion: function initCompletion() {
completion.dialog = function dialog(context) {
context.title = ["Dialog"];
context.filters.push(function ({ item }) !item[2] || item[2]());
context.completions = dactyl.windows;
};
},
- load: function () {
+ load: function initLoad() {
dactyl.triggerObserver("load");
dactyl.log(_("dactyl.modulesLoaded"), 3);
userContext.DOM = Class("DOM", DOM, { init: function DOM_(sel, ctxt) DOM(sel, ctxt || buffer.focusedFrame.document) });
userContext.$ = modules.userContext.DOM;
+ // Hack: disable disabling of Personas in private windows.
+ let root = document.documentElement;
+
+ if (PrivateBrowsingUtils && PrivateBrowsingUtils.isWindowPrivate(window)
+ && root._lightweightTheme
+ && root._lightweightTheme._lastScreenWidth == null) {
+
+ dactyl.withSavedValues.call(PrivateBrowsingUtils,
+ ["isWindowPrivate"], function () {
+ PrivateBrowsingUtils.isWindowPrivate = function () false;
+
+ Cu.import("resource://gre/modules/LightweightThemeConsumer.jsm", {})
+ .LightweightThemeConsumer.call(root._lightweightTheme, document);
+ });
+ }
+
dactyl.timeout(function () {
try {
var args = config.prefs.get("commandline-args")
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
this.setRegister(name, range);
},
- cut: function cut(range, name) {
+ cut: function cut(range, name, noStrip) {
if (range)
this.selectedRange = range;
if (!this.selection.isCollapsed)
this.setRegister(name, this.selection);
- this.editor.deleteSelection(0);
+ this.editor.deleteSelection(0, this.editor[noStrip ? "eNoStrip" : "eStrip"]);
},
paste: function paste(name) {
return DOM(elem).editor;
}
}, {
- modes: function init_modes() {
+ modes: function initModes() {
modes.addMode("OPERATOR", {
char: "o",
description: "Mappings which move the cursor",
bases: [modes.INSERT]
});
},
- commands: function init_commands() {
+ commands: function initCommands() {
commands.add(["reg[isters]"],
"List the contents of known registers",
function (args) {
},
{ argCount: "*" });
},
- completion: function init_completion() {
+ completion: function initCompletion() {
completion.register = function complete_register(context) {
context = context.fork("registers");
context.keys = { text: util.identity, description: editor.closure.getRegister };
});
};
},
- mappings: function init_mappings() {
+ mappings: function initMappings() {
Map.types["editor"] = {
preExecute: function preExecute(args) {
}
addMotionMap(["d", "x"], "Delete text", true, function (editor) { editor.cut(); });
- addMotionMap(["c"], "Change text", true, function (editor) { editor.cut(); }, modes.INSERT);
+ addMotionMap(["c"], "Change text", true, function (editor) { editor.cut(null, null, true); }, modes.INSERT);
addMotionMap(["y"], "Yank text", false, function (editor, range) { editor.copy(range); }, null, true);
addMotionMap(["gu"], "Lowercase text", false,
bind(["<C-n>"], "Select the next autocomplete result",
function () { events.feedkeys("<Down>", { skipmap: true }); });
},
- options: function init_options() {
+ options: function initOptions() {
options.add(["editor"],
"The external text editor",
"string", 'gvim -f +<line> +"sil! call cursor(0, <column>)" <file>', {
}
});
},
- sanitizer: function () {
+ sanitizer: function initSanitizer() {
sanitizer.addItem("registers", {
description: "Register values",
persistent: true,
// IMPORTANT: The eval statement *must* remain on the first line
// in order for line numbering in any errors to remain correct.
-// Copyright (c) 2008-2010 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
init: function () {
this.keyEvents = [];
- XML.ignoreWhitespace = true;
overlay.overlayWindow(window, {
- append: <e4x xmlns={XUL}>
- <window id={document.documentElement.id}>
- <!-- http://developer.mozilla.org/en/docs/XUL_Tutorial:Updating_Commands -->
- <commandset id="dactyl-onfocus" commandupdater="true" events="focus"
- oncommandupdate="dactyl.modules.events.onFocusChange(event);"/>
- <commandset id="dactyl-onselect" commandupdater="true" events="select"
- oncommandupdate="dactyl.modules.events.onSelectionChange(event);"/>
- </window>
- </e4x>.elements()
+ append: [
+ ["window", { id: document.documentElement.id, xmlns: "xul" },
+ // http://developer.mozilla.org/en/docs/XUL_Tutorial:Updating_Commands
+ ["commandset", { id: "dactyl-onfocus", commandupdater: "true", events: "focus",
+ commandupdate: this.closure.onFocusChange }],
+ ["commandset", { id: "dactyl-onselect", commandupdater: "true", events: "select",
+ commandupdate: this.closure.onSelectionChange }]]]
});
this._fullscreen = window.fullScreen;
let duringFeed = this.duringFeed || [];
this.duringFeed = [];
try {
- if (DOM.Event.feedingEvent)
- for (let [k, v] in Iterator(DOM.Event.feedingEvent))
+ let ourEvent = DOM.Event.feedingEvent;
+ DOM.Event.feedingEvent = null;
+ if (ourEvent)
+ for (let [k, v] in Iterator(ourEvent))
if (!(k in event))
event[k] = v;
- DOM.Event.feedingEvent = null;
- let key = DOM.Event.stringify(event);
+ let key = DOM.Event.stringify(ourEvent || event);
+ event.dactylString = key;
// Hack to deal with <BS> and so forth not dispatching input
// events
});
},
- commands: function () {
+ commands: function initCommands() {
commands.add(["delmac[ros]"],
"Delete macros",
function (args) {
completer: function (context) completion.macro(context)
});
},
- completion: function () {
+ completion: function initCompletion() {
completion.macro = function macro(context) {
context.title = ["Macro", "Keys"];
context.completions = [item for (item in events.getMacros())];
};
},
- mappings: function () {
+ mappings: function initMappings() {
mappings.add([modes.MAIN],
["<A-b>", "<pass-next-key-builtin>"], "Process the next key as a builtin mapping",
},
{ count: true });
},
- options: function () {
+ options: function initOptions() {
const Hive = Class("Hive", {
init: function init(values, map) {
this.name = "passkeys:" + map;
-// Copyright (c) 2009-2011 by Kris Maglione <kris@vimperator.org>
+// Copyright (c) 2009-2012 Kris Maglione <kris@vimperator.org>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
function checkFragment() {
document.title = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "title")[0].textContent;
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
/** @instance hints */
let body = doc.body || doc.querySelector("body");
if (body) {
- let fragment = DOM(<div highlight="hints"/>, doc).appendTo(body);
+ let fragment = DOM(["div", { highlight: "hints" }], doc).appendTo(body);
fragment.style.height; // Force application of binding.
let container = doc.getAnonymousElementByAttribute(fragment[0], "anonid", "hints") || fragment[0];
- let baseNode = DOM(<span highlight="Hint" style="display: none;"/>, doc)[0];
+ let baseNode = DOM(["span", { highlight: "Hint", style: "display: none;" }], doc)[0];
let mode = this.hintMode;
let res = mode.matcher(doc);
let n = 5;
(function next() {
+ if (Cu.isDeadWrapper && Cu.isDeadWrapper(elem))
+ // Hint document has been unloaded.
+ return;
+
let hinted = n || this.validHints.some(function (h) h.elem === elem);
if (!hinted)
hints.setClass(elem, null);
/**
* Display the hints in pageHints that are still valid.
*/
+ showCount: 0,
show: function _show() {
+ let count = ++this.showCount;
let hintnum = 1;
let validHint = hints.hintMatcher(this.hintString.toLowerCase());
let activeHint = this.hintNumber || 1;
inner:
for (let i in (util.interruptibleRange(start, end + 1, 500))) {
+ if (this.showCount != count)
+ return;
+
let hint = this.pageHints[i];
hint.valid = validHint(hint.text);
if (!rect)
continue;
- hint.imgSpan = DOM(<span highlight="Hint" dactyl:hl="HintImage" xmlns:dactyl={NS}/>, doc).css({
+ hint.imgSpan = DOM(["span", { highlight: "Hint", "dactyl:hl": "HintImage" }], doc).css({
display: "none",
left: (rect.left + offsetX) + "px",
top: (rect.top + offsetY) + "px",
this.modes = {};
this.addMode(";", "Focus hint", buffer.closure.focusElement);
this.addMode("?", "Show information for hint", function (elem) buffer.showElementInfo(elem));
+ // TODO: allow for ! override to overwrite existing paths -- where? --djk
this.addMode("s", "Save hint", function (elem) buffer.saveLink(elem, false));
this.addMode("f", "Focus frame", function (elem) dactyl.focus(elem.ownerDocument.defaultView));
this.addMode("F", "Focus frame or pseudo-frame", buffer.closure.focusElement, isScrollable);
}
else if (option == "label") {
if (elem.id) {
- let label = elem.ownerDocument.dactylLabels[elem.id];
+ let label = (elem.ownerDocument.dactylLabels || {})[elem.id];
+ // Urgh.
if (label)
return [label.textContent.toLowerCase(), true];
}
options.add(["hinttags", "ht"],
"XPath or CSS selector strings of hintable elements for Hints mode",
// Make sure to update the docs when you change this.
- "stringlist", ":-moz-any-link,area,button,iframe,input:not([type=hidden]),select,textarea," +
+ "stringlist", ":-moz-any-link,area,button,iframe,input:not([type=hidden]),label[for],select,textarea," +
"[onclick],[onmouseover],[onmousedown],[onmouseup],[oncommand]," +
"[tabindex],[role=link],[role=button],[contenteditable=true]",
{
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
var History = Module("history", {
SORT_DEFAULT: "-date",
}
}, {
}, {
- commands: function () {
+ commands: function initCommands() {
commands.add(["ba[ck]"],
"Go back in the browser history",
function (args) {
{ argCount: "0" });
},
- completion: function () {
+ completion: function initCompletion() {
completion.domain = function (context) {
context.anchored = false;
context.compare = function (a, b) String.localeCompare(a.key, b.key);
completion.addUrlCompleter("history", "History", completion.history);
},
- mappings: function () {
+ mappings: function initMappings() {
function bind() mappings.add.apply(mappings, [config.browserModes].concat(Array.slice(arguments)));
bind(["<C-o>"], "Go to an older position in the jump list",
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
if (this.timer)
this.timer.cancel();
- let key = DOM.Event.stringify(event);
+ let key = event.dactylString || DOM.Event.stringify(event);
this.events.push(event);
if (this.keyEvents)
this.keyEvents.push(event);
append: function append(event) {
this.events.push(event);
- let key = DOM.Event.stringify(event);
+ let key = event.dactylString || DOM.Event.stringify(event);
if (this.wantCount && !this.command &&
(this.countStr ? /^[0-9]$/ : /^[1-9]$/).test(key))
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
return maps;
}
- let list = <table>
- <tr highlight="Title">
- <td/>
- <td style="padding-right: 1em;">{_("title.Mode")}</td>
- <td style="padding-right: 1em;">{_("title.Command")}</td>
- <td style="padding-right: 1em;">{_("title.Action")}</td>
- </tr>
- <col style="min-width: 6em; padding-right: 1em;"/>
- {
- template.map(hives, function ([hive, maps]) let (i = 0)
- <tr style="height: .5ex;"/> +
- template.map(maps, function (map)
- template.map(map.names, function (name)
- <tr>
- <td highlight="Title">{!i++ ? hive.name : ""}</td>
- <td>{modeSign}</td>
- <td>{name}</td>
- <td>{map.rhs || map.action.toSource()}</td>
- </tr>)) +
- <tr style="height: .5ex;"/>)
- }
- </table>;
-
- // TODO: Move this to an ItemList to show this automatically
- if (list.*.length() === list.text().length() + 2)
- dactyl.echomsg(_("map.none"));
- else
- commandline.commandOutput(list);
+ let list = ["table", {},
+ ["tr", { highlight: "Title" },
+ ["td", {}],
+ ["td", { style: "padding-right: 1em;" }, _("title.Mode")],
+ ["td", { style: "padding-right: 1em;" }, _("title.Command")],
+ ["td", { style: "padding-right: 1em;" }, _("title.Action")]],
+ ["col", { style: "min-width: 6em; padding-right: 1em;" }],
+ hives.map(function ([hive, maps]) let (i = 0) [
+ ["tr", { style: "height: .5ex;" }],
+ maps.map(function (map)
+ map.names.map(function (name)
+ ["tr", {},
+ ["td", { highlight: "Title" }, !i++ ? hive.name : ""],
+ ["td", {}, modeSign],
+ ["td", {}, name],
+ ["td", {}, map.rhs || map.action.toSource()]])),
+ ["tr", { style: "height: .5ex;" }]])]
+
+ // E4X-FIXME
+ // // TODO: Move this to an ItemList to show this automatically
+ // if (list.*.length() === list.text().length() + 2)
+ // dactyl.echomsg(_("map.none"));
+ // else
+ commandline.commandOutput(list);
}
}, {
}, {
yield {
name: name,
columns: [
- i === 0 ? "" : <span highlight="Object" style="padding-right: 1em;">{mode.name}</span>,
- hive == mappings.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{hive.name}</span>
+ i === 0 ? "" : ["span", { highlight: "Object", style: "padding-right: 1em;" },
+ mode.name],
+ hive == mappings.builtin ? "" : ["span", { highlight: "Object", style: "padding-right: 1em;" },
+ hive.name]
],
__proto__: map
};
}
},
format: {
- description: function (map) (XML.ignoreWhitespace = false, XML.prettyPrinting = false, <>
- {options.get("passkeys").has(map.name)
- ? <span highlight="URLExtra">(passed by {template.helpLink("'passkeys'")})</span>
- : <></>}
- {template.linkifyHelp(map.description + (map.rhs ? ": " + map.rhs : ""))}
- </>),
+ description: function (map) [
+ options.get("passkeys").has(map.name)
+ ? ["span", { highlight: "URLExtra" },
+ "(", template.linkifyHelp(_("option.passkeys.passedBy")), ")"]
+ : [],
+ template.linkifyHelp(map.description + (map.rhs ? ": " + map.rhs : ""))
+ ],
help: function (map) let (char = array.compact(map.modes.map(function (m) m.char))[0])
char === "n" ? map.name : char ? char + "_" + map.name : "",
headings: ["Command", "Mode", "Group", "Description"]
}
- }
+ };
dactyl.addUsageCommand({
__proto__: args,
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/**
* @scope modules
{ arg: true });
},
- commands: function () {
+ commands: function initCommands() {
commands.add(["delm[arks]"],
"Delete the specified marks",
function (args) {
});
},
- completion: function () {
+ completion: function initCompletion() {
completion.mark = function mark(context) {
function percent(i) Math.round(i * 100);
context.completions = marks.all;
};
},
- sanitizer: function () {
+ sanitizer: function initSanitizer() {
sanitizer.addItem("marks", {
description: "Local and URL marks",
persistent: true,
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
onKeyPress: function (events) { if (modes.main == modes.QUOTE) modes.pop(); }
});
this.addMode("IGNORE", { hidden: true }, {
- onKeyPress: function (events) false,
+ onKeyPress: function (events_) {
+ if (events.isCancelKey(DOM.Event.stringify(events_[0])))
+ return true;
+ return false;
+ },
bases: [],
passthrough: true
});
update(StackElement.prototype, {
get toStringParams() !loaded.modes ? this.main.name : [
this.main.name,
- <>({ modes.all.filter(function (m) this.extended & m, this).map(function (m) m.name).join("|") })</>
+ ["(", modes.all.filter(function (m) this.extended & m, this)
+ .map(function (m) m.name).join("|"),
+ ")"].join("")
]
});
return StackElement;
for (let base in values(mode.bases))
tree[base.name][mode.name] = tree[mode.name];
- let roots = iter([m.name, tree[m.name]] for (m in values(list)) if (!m.bases.length)).toObject();
+ let roots = iter([m.name, tree[m.name]]
+ for (m in values(list))
+ if (!m.bases.length)).toObject();
- default xml namespace = NS;
function rec(obj) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
-
- let res = <ul dactyl:highlight="Dense" xmlns:dactyl={NS}/>;
+ let res = ["ul", { "dactyl:highlight": "Dense" }];
Object.keys(obj).sort().forEach(function (name) {
let mode = modes.getMode(name);
- res.* += <li><em>{mode.displayName}</em>: {mode.description}{
- rec(obj[name])
- }</li>;
+ res.push(["li", {},
+ ["em", {}, mode.displayName],
+ ": ", mode.description,
+ rec(obj[name])]);
});
- if (res.*.length())
+ if (res.length > 2)
return res;
- return <></>;
+ return [];
}
return rec(roots);
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
var MOW = Module("mow", {
init: function init() {
html|html > xul|scrollbar { visibility: collapse !important; }",
true);
- XML.ignoreWhitespace = true;
overlay.overlayWindow(window, {
objects: {
eventTarget: this
},
- append: <e4x xmlns={XUL} xmlns:dactyl={NS}>
- <window id={document.documentElement.id}>
- <popupset>
- <menupopup id="dactyl-contextmenu" highlight="Events" events="contextEvents">
- <menuitem id="dactyl-context-copylink"
- label={_("mow.contextMenu.copyLink")} dactyl:group="link"
- oncommand="goDoCommand('cmd_copyLink');"/>
- <menuitem id="dactyl-context-copypath"
- label={_("mow.contextMenu.copyPath")} dactyl:group="link path"
- oncommand="dactyl.clipboardWrite(document.popupNode.getAttribute('path'));"/>
- <menuitem id="dactyl-context-copy"
- label={_("mow.contextMenu.copy")} dactyl:group="selection"
- command="cmd_copy"/>
- <menuitem id="dactyl-context-selectall"
- label={_("mow.contextMenu.selectAll")}
- command="cmd_selectAll"/>
- </menupopup>
- </popupset>
- </window>
- <vbox id={config.ids.commandContainer}>
- <vbox class="dactyl-container" id="dactyl-multiline-output-container" hidden="false" collapsed="true">
- <iframe id="dactyl-multiline-output" src="dactyl://content/buffer.xhtml"
- flex="1" hidden="false" collapsed="false" contextmenu="dactyl-contextmenu"
- highlight="Events" />
- </vbox>
- </vbox>
- </e4x>
+ append: [
+ ["window", { id: document.documentElement.id, xmlns: "xul" },
+ ["popupset", {},
+ ["menupopup", { id: "dactyl-contextmenu", highlight: "Events", events: "contextEvents" },
+ ["menuitem", { id: "dactyl-context-copylink", label: _("mow.contextMenu.copyLink"),
+ "dactyl:group": "link", oncommand: "goDoCommand('cmd_copyLink');" }],
+ ["menuitem", { id: "dactyl-context-copypath", label: _("mow.contextMenu.copyPath"),
+ "dactyl:group": "link path", oncommand: "dactyl.clipboardWrite(document.popupNode.getAttribute('path'));" }],
+ ["menuitem", { id: "dactyl-context-copy", label: _("mow.contextMenu.copy"),
+ "dactyl:group": "selection", command: "cmd_copy" }],
+ ["menuitem", { id: "dactyl-context-selectall", label: _("mow.contextMenu.selectAll"),
+ command: "cmd_selectAll" }]]]],
+
+ ["vbox", { id: config.ids.commandContainer, xmlns: "xul" },
+ ["vbox", { class: "dactyl-container", id: "dactyl-multiline-output-container", hidden: "false", collapsed: "true" },
+ ["iframe", { id: "dactyl-multiline-output", src: "dactyl://content/buffer.xhtml",
+ flex: "1", hidden: "false", collapsed: "false",
+ contextmenu: "dactyl-contextmenu", highlight: "Events" }]]]]
});
},
this.messages = [];
}
- // If it's already XML, assume it knows what it's doing.
- // Otherwise, white space is significant.
- // The problem elsewhere is that E4X tends to insert new lines
- // after interpolated data.
- XML.ignoreWhitespace = XML.prettyPrinting = false;
-
highlightGroup = "CommandOutput " + (highlightGroup || "");
- if (isObject(data) && !isinstance(data, _)) {
+ if (isObject(data) && !isinstance(data, _) && !DOM.isJSONXML(data)) {
this.lastOutput = null;
- var output = DOM(<div style="white-space: nowrap" highlight={highlightGroup}/>,
+ var output = DOM(["div", { style: "white-space: nowrap", highlight: highlightGroup }],
this.document);
data.document = this.document;
try {
}
else {
let style = isString(data) ? "pre-wrap" : "nowrap";
- this.lastOutput = <div style={"white-space: " + style} highlight={highlightGroup}>{data}</div>;
+ this.lastOutput = ["div", { style: "white-space: " + style, highlight: highlightGroup },
+ data];
var output = DOM(this.lastOutput, this.document);
}
// copy text to clipboard
bind(["<C-y>"], "Yank selection to clipboard",
- function () { dactyl.clipboardWrite(buffer.getCurrentWord(mow.window)); });
+ function () { dactyl.clipboardWrite(Buffer.currentWord(mow.window)); });
// close the window
bind(["q"], "Close the output window",
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
}
}, {
}, {
- commands: function () {
+ commands: function initCommands() {
commands.add(["delqm[arks]"],
"Delete the specified QuickMarks",
function (args) {
completer: function (context) completion.quickmark(context),
});
},
- completion: function () {
+ completion: function initCompletion() {
completion.quickmark = function (context) {
context.title = ["QuickMark", "URL"];
context.generate = function () Iterator(quickmarks._qmarks);
};
},
- mappings: function () {
+ mappings: function initMappings() {
var myModes = config.browserModes;
mappings.add(myModes,
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
this.baseGroup = this.statusBar == this._statusLine ? "StatusLine " : "";
if (this.statusBar.localName == "toolbar") {
- styles.system.add("addon-bar", config.styleableChrome, <css><![CDATA[
+ styles.system.add("addon-bar", config.styleableChrome, literal(/*
#status-bar { margin-top: 0 !important; }
#addon-bar > statusbar { -moz-box-flex: 1 }
#addon-bar > #addonbar-closebutton { visibility: collapse; }
#addon-bar > xul|toolbarspring { visibility: collapse; }
- ]]></css>);
+ */));
- overlay.overlayWindow(window, { append: <><statusbar id="status-bar" ordinal="0"/></> });
+ overlay.overlayWindow(window, {
+ append: [
+ ["statusbar", { id: "status-bar", ordinal: "0" }]]
+ });
- highlight.loadCSS(util.compileMacro(<![CDATA[
+ highlight.loadCSS(util.compileMacro(literal(/*
!AddonBar;#addon-bar {
- /* The Add-on Bar */
padding-left: 0 !important;
min-height: 18px !important;
-moz-appearance: none !important;
<padding>
}
!AddonButton;#addon-bar xul|toolbarbutton {
- /* An Add-on Bar button */
-moz-appearance: none !important;
padding: 0 !important;
border-width: 0px !important;
color: inherit !important;
}
AddonButton:not(:hover) background: transparent;
- ]]>)({ padding: config.OS.isMacOSX ? "padding-right: 10px !important;" : "" }));
+ */))({ padding: config.OS.isMacOSX ? "padding-right: 10px !important;" : "" }));
if (document.getElementById("appmenu-button"))
- highlight.loadCSS(<![CDATA[
- AppmenuButton /* The app-menu button */ \
- min-width: 0 !important; padding: 0 .5em !important;
- ]]>);
+ highlight.loadCSS(literal(/*
+ AppmenuButton min-width: 0 !important; padding: 0 .5em !important;
+ */));
}
- XML.ignoreWhitespace = true;
let _commandline = "if (window.dactyl) return dactyl.modules.commandline";
- let prepend = <e4x xmlns={XUL} xmlns:dactyl={NS}>
- <button id="appmenu-button" label="" image="chrome://branding/content/icon16.png" highlight="AppmenuButton" />
- <toolbarbutton id="appmenu-toolbar-button" label="" image="chrome://branding/content/icon16.png" />
- <statusbar id="status-bar" highlight="StatusLine">
- <!-- insertbefore="dactyl.statusBefore;" insertafter="dactyl.statusAfter;" -->
- <hbox key="container" hidden="false" align="center" flex="1">
- <stack orient="horizontal" align="stretch" flex="1" highlight="CmdLine StatusCmdLine" class="dactyl-container">
- <hbox highlight="CmdLine StatusCmdLine" class="dactyl-container">
- <label key="mode" crop="end" class="plain" collapsed="true"/>
- <stack id="dactyl-statusline-stack" flex="1" highlight="CmdLine StatusCmdLine" class="dactyl-container">
- <textbox key="url" crop="end" flex="1" style="background: transparent;" class="plain dactyl-status-field-url" readonly="true"/>
- <textbox key="message" crop="end" flex="1" highlight="Normal StatusNormal" class="plain" readonly="true"/>
- </stack>
- </hbox>
- </stack>
- <label class="plain" key="inputbuffer" flex="0"/>
- <label class="plain" key="progress" flex="0"/>
- <label class="plain" key="tabcount" flex="0"/>
- <label class="plain" key="bufferposition" flex="0"/>
- <label class="plain" key="zoomlevel" flex="0"/>
- </hbox>
- <!-- just hide them since other elements expect them -->
- <statusbarpanel id="statusbar-display" hidden="true"/>
- <statusbarpanel id="statusbar-progresspanel" hidden="true"/>
- </statusbar>
- </e4x>;
-
- for each (let attr in prepend..@key)
- attr.parent().@id = "dactyl-statusline-field-" + attr;
+ let prepend = [
+ ["button", { id: "appmenu-button", label: "", image: "chrome://branding/content/icon16.png", highlight: "AppmenuButton", xmlns: "xul" }],
+ ["toolbarbutton", { id: "appmenu-toolbar-button", label: "", image: "chrome://branding/content/icon16.png" }],
+ ["statusbar", { id: "status-bar", highlight: "StatusLine", xmlns: "xul" },
+ // <!-- insertbefore="dactyl.statusBefore;" insertafter="dactyl.statusAfter;" -->
+ ["hbox", { key: "container", hidden: "false", align: "center", flex: "1" },
+ ["stack", { orient: "horizontal", align: "stretch", flex: "1", highlight: "CmdLine StatusCmdLine", class: "dactyl-container" },
+ ["hbox", { highlight: "CmdLine StatusCmdLine", class: "dactyl-container" },
+ ["label", { key: "mode", crop: "end", class: "plain", collapsed: "true" }],
+ ["stack", { id: "dactyl-statusline-stack", flex: "1", highlight: "CmdLine StatusCmdLine", class: "dactyl-container" },
+ ["textbox", { key: "url", crop: "end", flex: "1", style: "background: transparent;", class: "plain dactyl-status-field-url",
+ readonly: "true" }],
+ ["hbox", { key: "message-box" },
+ ["label", { key: "message-pre", highlight: "WarningMsg StatusWarningMsg", class: "plain", readonly: "true" }],
+ ["textbox", { key: "message", crop: "end", flex: "1", highlight: "Normal StatusNormal", class: "plain",
+ readonly: "true" }]]]]],
+ ["label", { class: "plain", key: "inputbuffer", flex: "0" }],
+ ["label", { class: "plain", key: "progress", flex: "0" }],
+ ["label", { class: "plain", key: "tabcount", flex: "0" }],
+ ["label", { class: "plain", key: "bufferposition", flex: "0" }],
+ ["label", { class: "plain", key: "zoomlevel", flex: "0" }]],
+ // just hide them since other elements expect them
+ ["statusbarpanel", { id: "statusbar-display", hidden: "true" }],
+ ["statusbarpanel", { id: "statusbar-progresspanel", hidden: "true" }]]];
+
+ (function rec(ary) {
+ ary.forEach(function (elem) {
+ if ("key" in elem[1])
+ elem[1].id = "dactyl-statusline-field-" + elem[1].key;
+ if (elem.length > 2)
+ rec(elem.slice(2));
+ });
+ })(prepend);
overlay.overlayWindow(window, {
objects: this.widgets = { get status() this.container },
- prepend: prepend.elements()
+ prepend: prepend
});
try {
this.timeout(function () {
this.status = message || buffer.uri;
});
+ },
+ "fullscreen": function onFullscreen(fullscreen) {
+ let go = options.get("guioptions");
+ if (fullscreen) {
+ this.wasVisible = go.has("s");
+ go.op("-", "s");
+ }
+ else if (this.wasVisible) {
+ go.op("+", "s");
+ }
}
},
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
tabs.switchTo(event.originalTarget.getAttribute("identifier"));
};
- this.tabBinding = styles.system.add("tab-binding", "chrome://browser/content/browser.xul", String.replace(<><![CDATA[
+ this.tabBinding = styles.system.add("tab-binding", "chrome://browser/content/browser.xul", literal(/*
xul|tab { -moz-binding: url(chrome://dactyl/content/bindings.xml#tab) !important; }
- ]]></>, /tab-./g, function (m) config.OS.isMacOSX ? "tab-mac" : m),
+ */).replace(/tab-./g, function (m) config.OS.isMacOSX ? "tab-mac" : m),
false, true);
this.timeout(function () {
if (!node("dactyl-tab-number")) {
let img = node("tab-icon-image");
if (img) {
- let dom = DOM(<xul xmlns:xul={XUL} xmlns:html={XHTML}>
- <xul:hbox highlight="tab-number"><xul:label key="icon" align="center" highlight="TabIconNumber" class="dactyl-tab-icon-number"/></xul:hbox>
- <xul:hbox highlight="tab-number"><html:div key="label" highlight="TabNumber" class="dactyl-tab-number"/></xul:hbox>
- </xul>.elements(), document).appendTo(img.parentNode);
+ let dom = DOM([
+ ["xul:hbox", { highlight: "tab-number" },
+ ["xul:label", { key: "icon", align: "center", highlight: "TabIconNumber",
+ class: "dactyl-tab-icon-number" }]],
+ ["xul:hbox", { highlight: "tab-number" },
+ ["html:div", { key: "label", highlight: "TabNumber",
+ class: "dactyl-tab-number" }]]],
+ document).appendTo(img.parentNode);
update(tab, {
get dactylOrdinal() Number(dom.nodes.icon.value),
if (func)
func = bind(function (func) { func(this._groups) }, this, func);
- if (window.TabView && TabView._initFrame)
- TabView._initFrame(func);
+ if (window.TabView && window.TabView._initFrame)
+ window.TabView._initFrame(func);
this._groups = iframe ? iframe.contentWindow : null;
if (this._groups && !func)
services.sessionStore.setTabState(to, tabState);
}
}, {
- load: function init_load() {
+ load: function initLoad() {
tabs.updateTabCount();
},
- commands: function init_commands() {
+ commands: function initCommands() {
[
{
name: ["bd[elete]"],
{ argCount: "0" });
}
},
- completion: function init_completion() {
+ completion: function initCompletion() {
completion.buffer = function buffer(context, visible) {
let { tabs } = modules;
group[1].push([i, tab.linkedBrowser]);
});
- context.pushProcessor(0, function (item, text, next) <>
- <span highlight="Indicator" style="display: inline-block;">{item.indicator}</span>
- { next.call(this, item, text) }
- </>);
+ context.pushProcessor(0, function (item, text, next) [
+ ["span", { highlight: "Indicator", style: "display: inline-block;" },
+ item.indicator],
+ next.call(this, item, text)
+ ]);
context.process[1] = function (item, text) template.bookmarkDescription(item, template.highlightFilter(text, this.filter));
context.anchored = false;
};
};
},
- events: function init_events() {
+ events: function initEvents() {
let tabContainer = config.tabbrowser.mTabContainer;
function callback() {
tabs.timeout(function () { this.updateTabCount(); });
events.listen(tabContainer, event, callback, false);
events.listen(tabContainer, "TabSelect", tabs.closure._onTabSelect, false);
},
- mappings: function init_mappings() {
+ mappings: function initMappings() {
mappings.add([modes.COMMAND], ["<C-t>", "<new-tab-next>"],
"Execute the next mapping in a new tab",
{ count: true });
}
},
- options: function init_options() {
+ options: function initOptions() {
options.add(["showtabline", "stal"],
"Define when the tab bar is visible",
"string", true,
Like <ex>:tabopen</ex>, but all arguments are opened in
a single new window.
</p>
+ <p>
+ When called via <ex>:private</ex>, the new window is a
+ private browsing window.
+ </p>
</description>
</item>
</p>
<xml-block><item>
- <tags><F1> :help :h help</tags>
+ <tags>:help :h help</tags>
<spec>:h<oa>elp</oa> <oa>subject</oa></spec>
- <spec><F1></spec>
<description>
<p>
Open the help page. The default page, as specified by <o>helpfile</o> is shown
</item></xml-block>
<p>
- creates a new help section for the command <ex>:help</ex> and for
- the related key binding, <k name="F1"/>. It also creates help tags
- for the command, its shortcuts, the key binding, and the general
- topic, ‘help’. These tags enable linking to this section from
- other mentions of the topic and from the <ex>:help</ex> command.
+ creates a new help section for the command <ex>:help</ex>. It
+ also creates help tags for the command, its shortcuts, the key
+ binding, and the general topic, ‘help’. These tags enable
+ linking to this section from other mentions of the topic and
+ from the <ex>:help</ex> command.
</p>
<h3 tag="help-tags help-xml">Help tags</h3>
</p>
</description>
</item>
- <escape><oa>...</oa>
+ <escape><oa>…</oa>
<hl key="HelpXMLTagEnd"></plugin></hl></escape>;</xml-block>
<p>
<spec>:javas<oa>cript</oa> <a>cmd</a></spec>
<spec style="white-space: pre; height: 1.6em; overflow: visible;">:javascript <<<a>endpattern</a>
<a>cmd</a>
- ...
+ …
<a>endpattern</a></spec>
<description>
<p>
command.yank.yankedLine-1 = Yanked %S line
command.yank.yankedLines-1 = Yanked %S lines
+commandline.moreMessages = [%S more. Type :messages to read]
+
completion.additional = (additional)
completion.generating = Generating results...
completion.noCompletions = No Completions
# TODO: merge with addon.*?
download.unknownCommand = Unknown command
download.commandNotAllowed = Command not allowed
+download.givingUpAfter = Giving up loading downloads after %S seconds
download.prompt.launchExecutable = This will launch an executable download. Would you like to continue? (yes/[no]/always):
download.nActive-1 = %S active
io.definedAt = Defined at
io.downloadFinished-2 = Download of %S to %S finished
io.eNotDir = Not a directory
+io.eNotDir-1 = Not a directory %S
io.exists = File exists (add ! to override)
io.exists-1 = File %S exists (add ! to override)
+# XXX
+io.existsNoOverride-1 = File %S exists
io.noCommand-1 = Command not found: %S
io.noPrevDir = E186: No previous directory
io.noSuchDir-1 = E344: Can't find directory %S
io.sourcing-1 = sourcing %S
io.sourcingEnd-1 = finished sourcing %S
io.sourcingError-1 = Sourcing file: %S
+io.writing-1 = writing %S
macro.canceled-1 = Canceled playback of macro '%S'
macro.recorded-1 = Recorded macro '%S'
</item>
<item>
- <spec>:se<oa>t</oa> <a>option</a> <oa>...</oa></spec>
+ <spec>:se<oa>t</oa> <a>option</a> <oa>…</oa></spec>
<description>
<p>
For boolean options, turn them on. For all other types,
</item>
<item>
- <spec>:se<oa>t</oa> no<a>option</a> <oa>...</oa></spec>
+ <spec>:se<oa>t</oa> no<a>option</a> <oa>…</oa></spec>
<description>
<p>
For boolean options, turn them off. For all other types,
</item>
<item>
- <spec>:se<oa>t</oa> <a>option</a>! <oa>...</oa></spec>
- <spec>:se<oa>t</oa> inv<a>option</a> <oa>...</oa></spec>
+ <spec>:se<oa>t</oa> <a>option</a>! <oa>…</oa></spec>
+ <spec>:se<oa>t</oa> inv<a>option</a> <oa>…</oa></spec>
<description>
<p>
For boolean options, invert their value. For all other types,
<item>
<tags>:set!=</tags>
- <spec>:se<oa>t</oa> inv<a>option</a>=<a>value</a> <oa>...</oa></spec>
- <spec>:se<oa>t</oa> <a>option</a>!=<a>value</a> <oa>...</oa></spec>
+ <spec>:se<oa>t</oa> inv<a>option</a>=<a>value</a> <oa>…</oa></spec>
+ <spec>:se<oa>t</oa> <a>option</a>!=<a>value</a> <oa>…</oa></spec>
<description>
<p>For list options, toggle the specified values.</p>
<item>
<tags>:set-default</tags>
- <spec>:se<oa>t</oa> <a>option</a>& <oa>...</oa></spec>
+ <spec>:se<oa>t</oa> <a>option</a>& <oa>…</oa></spec>
<description>
<p>Reset option to its default value.</p>
</description>
<item>
<tags>:set-args E487 E521</tags>
- <spec>:se<oa>t</oa> <a>option</a>=<a>value</a> <oa>...</oa></spec>
+ <spec>:se<oa>t</oa> <a>option</a>=<a>value</a> <oa>…</oa></spec>
<description>
<p>
Set string or number option to <a>value</a>.
<item>
<tags>:set+=</tags>
- <spec>:se<oa>t</oa> <a>option</a>+=<a>value</a> <oa>...</oa></spec>
+ <spec>:se<oa>t</oa> <a>option</a>+=<a>value</a> <oa>…</oa></spec>
<description>
<p>
Add the <a>value</a> to a number option, or append the <a>value</a>
<item>
<tags>:set^=</tags>
- <spec>:se<oa>t</oa> <a>option</a>^=<a>value</a> <oa>...</oa></spec>
+ <spec>:se<oa>t</oa> <a>option</a>^=<a>value</a> <oa>…</oa></spec>
<description>
<p>
Multiply the <a>value</a> to a number option, or prepend the
<item>
<tags>:set-=</tags>
- <spec>:se<oa>t</oa> <a>option</a>-=<a>value</a> <oa>...</oa></spec>
+ <spec>:se<oa>t</oa> <a>option</a>-=<a>value</a> <oa>…</oa></spec>
<description>
<p>
Subtract the <a>value</a> from a number option, or remove the
<strut/>
<spec>'hinttags' 'ht'</spec>
<type>&option.hinttags.type;</type>
- <default>:-moz-any-link,area,button,iframe,input:not([type=hidden]),select,textarea,
+ <default>:-moz-any-link,area,button,iframe,input:not([type=hidden]),
+ label[for],select,textarea,
[onclick],[onmouseover],[onmousedown],[onmouseup],[oncommand],
[tabindex],[role=link],[role=button],[contenteditable=true]</default>
<description>
<item>
<tags>'pu' 'passunknown'</tags>
<spec>'passunknown' 'pu'</spec>
- <type>&option.showmode.type;</type>
- <default>&option.showmode.default;</default>
+ <type>&option.passunknown.type;</type>
+ <default>&option.passunknown.default;</default>
<description>
<p>
Pass unknown keys through to &dactyl.host; in these
</description>
</item>
+<item>
+ <tags>:private :pr</tags>
+ <tags>:pr0n :porn</tags>
+ <strut/>
+ <spec>:pr<oa>ivate</oa> <a>cmd</a></spec>
+ <description>
+ <p>
+ Execute <a>cmd</a> with privacy features enabled, and
+ do not save the invocation in command history.
+ </p>
+ </description>
+</item>
+
<h2 tag="cookie-settings">Cookie settings</h2>
<item>
<tags>:cookies :ck</tags>
<item>
<tags>:lpl :loadplugins</tags>
<strut/>
- <spec>:loadplugins <oa>pattern</oa> …</spec>
+ <spec>:loadplugins[!] <oa>pattern</oa> …</spec>
<description>
<p>
Immediately load all plugins which have yet to be loaded. Because
If <oa>pattern</oa>s are provided, the given regular expressions are
used as filters rather than those in <o>loadplugins</o>.
</p>
+ <p>
+ If <oa>!</oa> is given the plugins are forcibly loaded.
+ </p>
</description>
</item>
</item>
<item>
- <tags>:mks :mksyntax</tags>
- <spec>:mks<oa>yntax</oa><oa>!</oa> <oa>path</oa></spec>
+ <tags>:mkv :mkvimruntime</tags>
+ <spec>:mkv<oa>imruntime</oa><oa>!</oa> <oa>dir</oa></spec>
<description>
<p>
- Generate a Vim syntax file. If <oa>path</oa> is not given, the local
- Vim runtime path is guessed. If <oa>path</oa> is a directory, the
- file <str delim="">&dactyl.name;.vim</str> in that directory is
- used. An existing file will never be overwritten unless
- <oa>bang</oa> is given.
+ Creates and installs Vim ftdetect, ftplugin and syntax files. If
+ <oa>dir</oa> is not given, the local Vim runtime path is guessed.
+ An existing file will never be overwritten unless <oa>!</oa> is
+ given.
+ </p>
+ <p>
+ See <em>:help 'runtimepath'</em> and <em>:help after-directory</em>
+ in Vim for an explanation of how best to manage personal changes to
+ these files.
</p>
</description>
</item>
<p>
What is the meaning of life, the universe and everything? Douglas Adams,
the only person who knew what this question really was about is now dead,
- unfortunately. So now you might wonder what the meaning of death is...
+ unfortunately. So now you might wonder what the meaning of death is…
</p>
<h2 tag="uncategorized">Uncategorized help</h2>
}
fi
+mungeliterals=$(cat <<'!'
+ local $/;
+ $_ = <>;
+ s{(?<!function )\bliteral\(/\*(.*?)\*/\)}{
+ my $s = $1;
+ $s =~ s/[\\']/\\$&/g;
+ $s =~ s/\n/\\n\\$&/g;
+ "/* Preprocessors FTW. */ '$s'";
+ }ges;
+ print;
+!
+)
+
+mungeliterals() {
+ if which perl >/dev/null 2>&1
+ then perl -e "$mungeliterals"
+ else cat
+ fi
+}
+
getfiles() {
filter="\.($(echo $1 | tr ' ' '|'))$"; shift
find "$@" -not -path '*\.hg*' 2>/dev/null | grep -E "$filter" || true
}
copytext() {
+ mungeliterals <"$1" |
sed -e "s,@VERSION@,$VERSION,g" \
-e "s,@DATE@,$BUILD_DATE,g" \
- <"$1" >"$2"
+ >"$2"
cmp -s -- "$1" "$2" ||
( echo "modified: $1"; diff -u -- "$1" "$2" | grep '^[-+][^-+]' )
}
for f in $(getfiles "$bin" "$dir")
do
mkdir -p "$stage/${f%/*}"
- cp -- $f "$stage/$f"
+ cp -- "$f" "$stage/$f"
done
for f in $(getfiles "$text" "$dir")
do
done
for f in $files
do
- [ -f "$f" ] && copytext "$f" "$stage/$f"
+ if [ -f "$f" ]
+ then
+ case "$f" in
+ *.js|*.jsm|*.css|*.dtd|*.xml|*.xul|*.html|*.xhtml|*.xsl|*.properties|*.json)
+ copytext "$f" "$stage/$f";;
+ *)
+ cp -- "$f" "$stage/$f";;
+ esac
+ fi
done
true
) || exit 1
-// Copyright (c) 2009-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2009-2012 Kris Maglione <maglione.k@gmail.com>
// Copyright (c) 2009-2010 by Doug Kearns <dougkearns@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("addons", {
exports: ["AddonManager", "Addons", "Addon", "addons"],
- require: ["services"]
-}, this);
+ require: ["services", "util"]
+});
+
+this.lazyRequire("completion", ["completion"]);
+lazyRequire("template", ["template"]);
var callResult = function callResult(method) {
let args = Array.slice(arguments, 1);
this.nodes = {
commandTarget: this
};
- XML.ignoreWhitespace = true;
- util.xmlToDom(
- <tr highlight="Addon" key="row" xmlns:dactyl={NS} xmlns={XHTML}>
- <td highlight="AddonName" key="name"/>
- <td highlight="AddonVersion" key="version"/>
- <td highlight="AddonButtons Buttons">
- <a highlight="Button" href="javascript:0" key="enable">{_("addon.action.On")}</a>
- <a highlight="Button" href="javascript:0" key="disable">{_("addon.action.Off")}</a>
- <a highlight="Button" href="javascript:0" key="delete">{_("addon.action.Delete")}</a>
- <a highlight="Button" href="javascript:0" key="update">{_("addon.action.Update")}</a>
- <a highlight="Button" href="javascript:0" key="options">{_("addon.action.Options")}</a>
- </td>
- <td highlight="AddonStatus" key="status"/>
- <td highlight="AddonDescription" key="description"/>
- </tr>,
+ DOM.fromJSON(
+ ["tr", { highlight: "Addon", key: "row" },
+ ["td", { highlight: "AddonName", key: "name" }],
+ ["td", { highlight: "AddonVersion", key: "version" }],
+ ["td", { highlight: "AddonButtons Buttons" },
+ ["a", { highlight: "Button", href: "javascript:0", key: "enable" }, _("addon.action.On")],
+ ["a", { highlight: "Button", href: "javascript:0", key: "disable" }, _("addon.action.Off")],
+ ["a", { highlight: "Button", href: "javascript:0", key: "delete" }, _("addon.action.Delete")],
+ ["a", { highlight: "Button", href: "javascript:0", key: "update" }, _("addon.action.Update")],
+ ["a", { highlight: "Button", href: "javascript:0", key: "options" }, _("addon.action.Options")]],
+ ["td", { highlight: "AddonStatus", key: "status" }],
+ ["td", { highlight: "AddonDescription", key: "description" }]],
this.list.document, this.nodes);
this.update();
compare: function compare(other) String.localeCompare(this.name, other.name),
get statusInfo() {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- default xml namespace = XHTML;
-
- let info = this.isActive ? <span highlight="Enabled">enabled</span>
- : <span highlight="Disabled">disabled</span>;
+ let info = this.isActive ? ["span", { highlight: "Enabled" }, "enabled"]
+ : ["span", { highlight: "Disabled" }, "disabled"];
let pending;
if (this.pendingOperations & AddonManager.PENDING_UNINSTALL)
else if (this.pendingOperations & AddonManager.PENDING_UPGRADE)
pending = ["Enabled", "upgraded"];
if (pending)
- return <>{info} (<span highlight={pending[0]}>{pending[1]}</span>
-  on <a href="#" dactyl:command="dactyl.restart" xmlns:dactyl={NS}>restart</a>)</>;
+ return [info, " (",
+ ["span", { highlight: pending[0] }, pending[1]],
+ " on ",
+ ["a", { href: "#", "dactyl:command": "dactyl.restart" }, "restart"],
+ ")"]
return info;
},
let node = self.nodes[key];
while (node.firstChild)
node.removeChild(node.firstChild);
- node.appendChild(util.xmlToDom(<>{xml}</>, self.list.document));
+
+ DOM(node).append(isArray(xml) ? xml : DOM.DOMString(xml));
}
update("name", template.icon({ icon: this.iconURL }, this.name));
},
message: Class.Memoize(function () {
-
- XML.ignoreWhitespace = true;
- util.xmlToDom(<table highlight="Addons" key="list" xmlns={XHTML}>
- <tr highlight="AddonHead">
- <td>{_("title.Name")}</td>
- <td>{_("title.Version")}</td>
- <td/>
- <td>{_("title.Status")}</td>
- <td>{_("title.Description")}</td>
- </tr>
- </table>, this.document, this.nodes);
+ DOM.fromJSON(["table", { highlight: "Addons", key: "list" },
+ ["tr", { highlight: "AddonHead" },
+ ["td", {}, _("title.Name")],
+ ["td", {}, _("title.Version")],
+ ["td"],
+ ["td", {}, _("title.Status")],
+ ["td", {}, _("title.Description")]]],
+ this.document, this.nodes);
if (this._addons)
this._init();
.toObject())
}, {
}, {
- commands: function (dactyl, modules, window) {
+ commands: function initCommands(dactyl, modules, window) {
const { CommandOption, commands, completion, io } = modules;
commands.add(["addo[ns]", "ao"],
});
});
},
- completion: function (dactyl, modules, window) {
+ completion: function initCompletion(dactyl, modules, window) {
completion.addonType = function addonType(context) {
let base = ["extension", "theme"];
function update(types) {
}
});
-if (!services.has("extensionManager"))
- Components.utils.import("resource://gre/modules/AddonManager.jsm");
-else
- var AddonManager = {
- PERM_CAN_UNINSTALL: 1,
- PERM_CAN_ENABLE: 2,
- PERM_CAN_DISABLE: 4,
- PERM_CAN_UPGRADE: 8,
-
- getAddonByID: function (id, callback) {
- callback = callback || util.identity;
- addon = services.extensionManager.getItemForID(id);
- if (addon)
- addon = this.wrapAddon(addon);
- return callback(addon);
- },
-
- wrapAddon: function wrapAddon(addon) {
- addon = Object.create(addon.QueryInterface(Ci.nsIUpdateItem));
-
- ["aboutURL", "creator", "description", "developers",
- "homepageURL", "installDate", "optionsURL",
- "releaseNotesURI", "updateDate"].forEach(function (item) {
- memoize(addon, item, function (item) this.getProperty(item));
- });
-
- update(addon, {
-
- get permissions() 1 | (this.userDisabled ? 2 : 4),
-
- appDisabled: false,
-
- getProperty: function getProperty(property) {
- let resource = services.rdf.GetResource("urn:mozilla:item:" + this.id);
-
- if (resource) {
- let target = services.extensionManager.datasource.GetTarget(resource,
- services.rdf.GetResource("http://www.mozilla.org/2004/em-rdf#" + property), true);
-
- if (target && target instanceof Ci.nsIRDFLiteral)
- return target.Value;
- }
-
- return "";
- },
-
- installLocation: Class.Memoize(function () services.extensionManager.getInstallLocation(this.id)),
- getResourceURI: function getResourceURI(path) {
- let file = this.installLocation.getItemFile(this.id, path);
- return services.io.newFileURI(file);
- },
-
- get isActive() this.getProperty("isDisabled") != "true",
-
- uninstall: function uninstall() {
- services.extensionManager.uninstallItem(this.id);
- },
-
- get userDisabled() this.getProperty("userDisabled") === "true",
- set userDisabled(val) {
- services.extensionManager[val ? "disableItem" : "enableItem"](this.id);
- }
- });
-
- return addon;
- },
-
- getAddonsByTypes: function (types, callback) {
- let res = [];
- for (let [, type] in Iterator(types))
- for (let [, item] in Iterator(services.extensionManager
- .getItemList(Ci.nsIUpdateItem["TYPE_" + type.toUpperCase()], {})))
- res.push(this.wrapAddon(item));
-
- if (callback)
- util.timeout(function () { callback(res); });
- return res;
- },
-
- getInstallForFile: function (file, callback, mimetype) {
- callback({
- addListener: function () {},
- install: function () {
- services.extensionManager.installItemFromFile(file, "app-profile");
- }
- });
- },
-
- getInstallForURL: function (url, callback, mimetype) {
- util.assert(false, _("error.unavailable", config.host, services.runtime.version));
- },
-
- observers: [],
- addAddonListener: function (listener) {
- observer.listener = listener;
- function observer(subject, topic, data) {
- if (subject instanceof Ci.nsIUpdateItem)
- subject = AddonManager.wrapAddon(subject);
-
- if (data === "item-installed")
- listener.onInstalling(subject, true);
- else if (data === "item-uninstalled")
- listener.onUnistalling(subject, true);
- else if (data === "item-upgraded")
- listener.onInstalling(subject, true);
- else if (data === "item-enabled")
- listener.onEnabling(subject, true);
- else if (data === "item-disabled")
- listener.onDisabling(subject, true);
- }
- services.observer.addObserver(observer, "em-action-requested", false);
- this.observers.push(observer);
- },
- removeAddonListener: function (listener) {
- this.observers = this.observers.filter(function (observer) {
- if (observer.listener !== listener)
- return true;
- services.observer.removeObserver(observer, "em-action-requested");
- });
- }
- };
+Components.utils.import("resource://gre/modules/AddonManager.jsm", this);
endModule();
-// Copyright (c) 2009-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2009-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
-Cu.import("resource://dactyl/bootstrap.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
try {
var ctypes;
Cu.import("resource://gre/modules/ctypes.jsm");
if (typeof XPCSafeJSObjectWrapper === "undefined")
this.XPCSafeJSObjectWrapper = XPCNativeWrapper;
-if (!XPCNativeWrapper.unwrap)
- XPCNativeWrapper.unwrap = function unwrap(obj) {
- if (hasOwnProperty.call(obj, "wrappedJSObject"))
- return obj.wrappedJSObject;
- return obj;
- };
-if (!Object.create)
- Object.create = function create(proto, props) {
- let obj = { __proto__: proto };
- for (let k in properties(props || {}))
- Object.defineProperty(obj, k, props[k]);
- return obj;
- };
-if (!Object.defineProperty)
- Object.defineProperty = function defineProperty(obj, prop, desc) {
- try {
- let value = desc.value;
- if ("value" in desc)
- if (desc.writable && !__lookupGetter__.call(obj, prop)
- && !__lookupSetter__.call(obj, prop))
- try {
- obj[prop] = value;
- }
- catch (e if e instanceof TypeError) {}
- else {
- __defineGetter__.call(obj, prop, function () value);
- if (desc.writable)
- __defineSetter__.call(obj, prop, function (val) { value = val; });
- }
+let getGlobalForObject = Cu.getGlobalForObject || function (obj) obj.__parent__;
- if ("get" in desc)
- __defineGetter__.call(obj, prop, desc.get);
- if ("set" in desc)
- __defineSetter__.call(obj, prop, desc.set);
- }
- catch (e) {
- throw e.stack ? e : Error(e);
- }
- };
-if (!Object.defineProperties)
- Object.defineProperties = function defineProperties(obj, props) {
- for (let [k, v] in Iterator(props))
- Object.defineProperty(obj, k, v);
- };
-if (!Object.freeze)
- Object.freeze = function freeze(obj) {};
-if (!Object.getPropertyDescriptor)
- Object.getPropertyDescriptor = function getPropertyDescriptor(obj, prop) {
- try {
- let desc = {
- configurable: true,
- enumerable: propertyIsEnumerable.call(obj, prop)
- };
- var get = __lookupGetter__.call(obj, prop),
- set = __lookupSetter__.call(obj, prop);
- if (!get && !set) {
- desc.value = obj[prop];
- desc.writable = true;
- }
- if (get)
- desc.get = get;
- if (set)
- desc.set = set;
- return desc;
- }
- catch (e) {
- throw e.stack ? e : Error(e);
- }
- };
-if (!Object.getOwnPropertyDescriptor)
- Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(obj, prop) {
- if (hasOwnProperty.call(obj, prop))
- return Object.getPropertyDescriptor(obj, prop);
- };
-if (!Object.getOwnPropertyNames)
- Object.getOwnPropertyNames = function getOwnPropertyNames(obj, _debugger) {
- try {
- // This is an ugly and unfortunately necessary hack.
- if (hasOwnProperty.call(obj, "__iterator__")) {
- var oldIter = obj.__iterator__;
- delete obj.__iterator__;
- }
- let res = [k for (k in obj) if (hasOwnProperty.call(obj, k))];
- if (oldIter !== undefined) {
- obj.__iterator__ = oldIter;
- res.push("__iterator__");
- }
- return res;
- }
- catch (e) {
- throw e.stack ? e : Error(e);
- }
- };
-if (!Object.getPrototypeOf)
- Object.getPrototypeOf = function getPrototypeOf(obj) obj.__proto__;
-if (!Object.keys)
- Object.keys = function keys(obj)
- Object.getOwnPropertyNames(obj).filter(function (k) propertyIsEnumerable.call(obj, k));
+function require(module, target) JSMLoader.load(module, target);
-let getGlobalForObject = Cu.getGlobalForObject || function (obj) obj.__parent__;
+function lazyRequire(module, names, target) {
+ for each (let name in names)
+ memoize(target || this, name, function (name) require(module)[name]);
+}
-let jsmodules = {
- lazyRequire: function lazyRequire(module, names, target) {
- for each (let name in names)
- memoize(target || this, name, function (name) require(module)[name]);
- }
-};
+let jsmodules = { lazyRequire: lazyRequire };
jsmodules.jsmodules = jsmodules;
+function toString() "[module-global " + this.NAME + "]";
+
let use = {};
let loaded = {};
let currentModule;
let global = this;
function defineModule(name, params, module) {
if (!module)
- module = getGlobalForObject(params);
+ module = this;
module.NAME = name;
module.EXPORTED_SYMBOLS = params.exports || [];
defineModule.prefix += " ";
for (let [, mod] in Iterator(params.require || []))
- require(module, mod, null, name);
- module.__proto__ = jsmodules;
+ require(mod, module);
module._lastModule = currentModule;
currentModule = module;
Object.defineProperty(defineModule.loadLog, "push", {
value: function (val) {
val = defineModule.prefix + val;
- if (false)
+ if (true)
defineModule.dump(val + "\n");
this[this.length] = Date.now() + " " + val;
}
defineModule.loadLog.push("(End " + currentModule.NAME + ")");
loaded[currentModule.NAME] = 1;
- require(jsmodules, currentModule.NAME);
+ require(currentModule.NAME, jsmodules);
currentModule = currentModule._lastModule;
}
-function require(obj, name, from, targetName) {
+function require_(obj, name, from, targetName) {
try {
if (arguments.length === 1)
[obj, name] = [{}, obj];
defineModule("base", {
// sed -n 's/^(const|var|function) ([a-zA-Z0-9_]+).*/ "\2",/p' base.jsm | sort | fmt
exports: [
- "ErrorBase", "Cc", "Ci", "Class", "Cr", "Cu", "Module", "JSMLoader", "Object",
+ "ErrorBase", "Cc", "Ci", "Class", "Cr", "Cu", "Finished", "Module", "JSMLoader",
"Set", "Struct", "StructBase", "Timer", "UTF8", "XPCOM", "XPCOMShim", "XPCOMUtils",
"XPCSafeJSObjectWrapper", "array", "bind", "call", "callable", "ctypes", "curry",
"debuggerProperties", "defineModule", "deprecated", "endModule", "forEach", "isArray",
- "isGenerator", "isinstance", "isObject", "isString", "isSubclass", "iter", "iterAll",
- "iterOwnProperties", "keys", "memoize", "octal", "properties", "require", "set", "update",
- "values", "withCallerGlobal"
+ "isGenerator", "isinstance", "isObject", "isString", "isSubclass", "isXML", "iter",
+ "iterAll", "iterOwnProperties", "keys", "literal", "memoize", "octal", "properties",
+ "require", "set", "update", "values", "update_"
]
-}, this);
+});
+this.lazyRequire("cache", ["cache"]);
+this.lazyRequire("config", ["config"]);
this.lazyRequire("messages", ["_", "Messages"]);
-this.lazyRequire("util", ["util"]);
+this.lazyRequire("services", ["services"]);
+this.lazyRequire("storage", ["File"]);
+this.lazyRequire("util", ["FailedAssertion", "util"]);
+
+function literal(/* comment */) {
+ let { caller } = Components.stack;
+ while (caller && caller.language != 2)
+ caller = caller.caller;
+
+ let file = caller.filename.replace(/.* -> /, "");
+ let key = "literal:" + file + ":" + caller.line;
+
+ let source = File.readURL(file);
+
+ let match = RegExp("(?:.*\\n){" + (caller.lineNumber - 1) + "}" +
+ ".*literal\\(/\\*([^]*?)\\*/\\)").exec(source);
+ return match[1];
+
+ // Later...
+ return cache.get(key, function () {
+ let source = cache.get("literal:" + file,
+ function () util.httpGet(file).responseText);
+
+ let match = RegExp("(?:.*\\n){" + (caller.lineNumber - 1) + "}" +
+ ".*literal\\(/\\*([^]*?)\\*/\\)").exec(source);
+ return match[1];
+ });
+}
/**
* Returns a list of all of the top-level properties of an object, by
* @returns {Generator}
*/
function prototype(obj)
- /* Temporary hack: */ typeof obj === "xml" || obj.__proto__ !== obj.__proto__ ? null :
obj.__proto__ || Object.getPrototypeOf(obj) ||
XPCNativeWrapper.unwrap(obj).__proto__ ||
Object.getPrototypeOf(XPCNativeWrapper.unwrap(obj));
}
catch (e) {}
+ function props(obj) {
+ // Grr.
+ try {
+ return Object.getOwnPropertyNames(obj);
+ }
+ catch (e) {
+ if (e.result === Cr.NS_ERROR_FAILURE) {
+ // This is being thrown for PDF.js content windows,
+ // currently.
+ let filter = function filter(prop) {
+ try {
+ return prop in obj;
+ }
+ catch (e) {
+ util.reportError("Filtering properties for " +
+ String.quote(obj) + ", " +
+ "error checking presence of " +
+ String.quote(prop) + ": " + e);
+ }
+ return false;
+ };
+ return array.uniq([k for (k in obj)].concat(
+ Object.getOwnPropertyNames(
+ XPCNativeWrapper.unwrap(obj))
+ .filter(filter)))
+ }
+ else if (!e.stack) {
+ throw Error(e);
+ }
+ }
+ }
+
for (; obj; obj = prototypes && prototype(obj)) {
try {
- if (sandbox.Object.getOwnPropertyNames || !debugger_ || !services.debugger.isOn)
- var iter = (v for each (v in Object.getOwnPropertyNames(obj)));
+ if (!debugger_ || !services.debugger.isOn)
+ var iter = (v for each (v in props(obj)));
}
catch (e) {}
if (!iter)
deprecated.warn = function warn(func, name, alternative, frame) {
if (!func.seenCaller)
func.seenCaller = Set([
- "resource://dactyl" + JSMLoader.suffix + "/javascript.jsm",
- "resource://dactyl" + JSMLoader.suffix + "/util.jsm"
+ "resource://dactyl/javascript.jsm",
+ "resource://dactyl/util.jsm"
]);
frame = frame || Components.stack.caller.caller;
*/
function isObject(obj) typeof obj === "object" && obj != null || obj instanceof Ci.nsISupports;
+/**
+ * Returns true if obje is an E4X XML object.
+ * @deprecated
+ */
+function isXML(obj) typeof obj === "xml";
+
/**
* Returns true if and only if its sole argument is an
* instance of the builtin Array type. The array may come from
}
}
-let sandbox = Cu.Sandbox(this);
+let sandbox = Cu.Sandbox(Cc["@mozilla.org/systemprincipal;1"].createInstance());
sandbox.__proto__ = this;
-/**
- * Wraps a function so that when called, the global object of the caller
- * is prepended to its arguments.
- */
-// Hack to get around lack of access to caller in strict mode.
-var withCallerGlobal = Cu.evalInSandbox(<![CDATA[
- (function withCallerGlobal(fn)
- function withCallerGlobal_wrapped()
- fn.apply(this,
- [Class.objectGlobal(withCallerGlobal_wrapped.caller)]
- .concat(Array.slice(arguments))))
-]]>, Cu.Sandbox(this), "1.8");
/**
* Updates an object with the properties of another object. Getters
if (typeof desc.value === "function" && target.__proto__ && !(desc.value instanceof Ci.nsIDOMElement /* wtf? */)) {
let func = desc.value.wrapped || desc.value;
if (!func.superapply) {
- func.__defineGetter__("super", function () Object.getPrototypeOf(target)[k]);
+ func.__defineGetter__("super", function get_super() Object.getPrototypeOf(target)[k]);
func.superapply = function superapply(self, args)
let (meth = Object.getPrototypeOf(target)[k])
meth && meth.apply(self, args);
}
return target;
}
+function update_(target) {
+ for (let i = 1; i < arguments.length; i++) {
+ let src = arguments[i];
+ Object.getOwnPropertyNames(src || {}).forEach(function (k) {
+ let desc = Object.getOwnPropertyDescriptor(src, k);
+ if (desc.value instanceof Class.Property)
+ desc = desc.value.init(k, target) || desc.value;
+
+ try {
+ if (typeof desc.value === "function" && target.__proto__ && !(desc.value instanceof Ci.nsIDOMElement /* wtf? */)) {
+ let func = desc.value.wrapped || desc.value;
+ if (!func.superapply) {
+ func.__defineGetter__("super", function get_super_() Object.getPrototypeOf(target)[k]);
+ func.superapply = function super_apply(self, args)
+ let (meth = Object.getPrototypeOf(target)[k])
+ meth && meth.apply(self, args);
+ func.supercall = function super_call(self)
+ func.superapply(self, Array.slice(arguments, 1));
+ }
+ }
+ Object.defineProperty(target, k, desc);
+ }
+ catch (e) {}
+ });
+ }
+ return target;
+}
/**
* @constructor Class
var Constructor = function Constructor() {
var self = Object.create(Constructor.prototype);
self.instance = self;
+ self.globalInstance = self;
if ("_metaInit_" in self && self._metaInit_)
self._metaInit_.apply(self, arguments);
return res !== undefined ? res : self;
};
else
- var Constructor = eval(String.replace(<![CDATA[
- (function constructor(PARAMS) {
- var self = Object.create(Constructor.prototype);
- self.instance = self;
-
- if ("_metaInit_" in self && self._metaInit_)
- self._metaInit_.apply(self, arguments);
-
- var res = self.init.apply(self, arguments);
- return res !== undefined ? res : self;
- })]]>,
+ var Constructor = eval(String.replace('\n\
+ (function constructor(PARAMS) { \n\
+ var self = Object.create(Constructor.prototype); \n\
+ self.instance = self; \n\
+ self.globalInstance = self; \n\
+ \n\
+ if ("_metaInit_" in self && self._metaInit_) \n\
+ self._metaInit_.apply(self, arguments); \n\
+ \n\
+ var res = self.init.apply(self, arguments); \n\
+ return res !== undefined ? res : self; \n\
+ })',
"constructor", (name || superclass.className).replace(/\W/g, "_"))
.replace("PARAMS", /^function .*?\((.*?)\)/.exec(args[0] && args[0].init || Class.prototype.init)[1]
.replace(/\b(self|res|Constructor)\b/g, "$1_")));
toString: function () String(this.message)
});
+/**
+ * An Error subclass to throw in order to stop sourcing a plugin without
+ * printing a stack trace.
+ */
+var Finished = Class("Finished", ErrorBase);
+
/**
* Constructs a new Module class and instantiates an instance into the current
* module global object.
}
else if (isinstance(obj, [Ci.nsIDOMHTMLCollection, Ci.nsIDOMNodeList]))
res = array.iterItems(obj);
- else if (obj instanceof Ci.nsIDOMNamedNodeMap)
+ else if (Ci.nsIDOMNamedNodeMap && obj instanceof Ci.nsIDOMNamedNodeMap ||
+ Ci.nsIDOMMozNamedAttrMap && obj instanceof Ci.nsIDOMMozNamedAttrMap)
res = (function () {
for (let i = 0; i < obj.length; i++)
yield [obj.name, obj];
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("bookmarkcache", {
exports: ["Bookmark", "BookmarkCache", "Keyword", "bookmarkcache"],
require: ["services", "util"]
-}, this);
+});
this.lazyRequire("storage", ["storage"]);
-// Copyright (c) 2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2011-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-try {
+var EXPORTED_SYMBOLS = ["require"];
-let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
+// Deal with cross-compartment XML passing issues.
+function create(proto) Object.create(proto);
+this["import"] = function import_(obj) {
+ let res = {};
+ for each (let key in Object.getOwnPropertyNames(obj))
+ Object.defineProperty(res, key, Object.getOwnPropertyDescriptor(obj, key));
+ return res;
+}
-var EXPORTED_SYMBOLS = ["JSMLoader"];
+// Deal with subScriptLoader prepending crap to loaded URLs
+Components.utils.import("resource://gre/modules/Services.jsm");
+function loadSubScript() Services.scriptloader.loadSubScript.apply(null, arguments);
-var BOOTSTRAP_CONTRACT = "@dactyl.googlecode.com/base/bootstrap";
-var JSMLoader = BOOTSTRAP_CONTRACT in Components.classes &&
- Components.classes[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader;
-
-if (JSMLoader && JSMLoader.bump === 6)
- JSMLoader.global = this;
-else
- JSMLoader = {
- bump: 6,
-
- builtin: Cu.Sandbox(this),
-
- canonical: {},
-
- factories: [],
-
- name: "dactyl",
-
- global: this,
-
- globals: JSMLoader ? JSMLoader.globals : {},
-
- io: Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService),
-
- loader: Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader),
-
- manager: Components.manager.QueryInterface(Ci.nsIComponentRegistrar),
-
- modules: JSMLoader && JSMLoader.modules || {},
-
- stale: JSMLoader ? JSMLoader.stale : {},
-
- suffix: "",
-
- times: {
- all: 0,
- add: function add(major, minor, delta) {
- this.all += delta;
-
- this[major] = (this[major] || 0) + delta;
- if (minor) {
- minor = ":" + minor;
- this[minor] = (this[minor] || 0) + delta;
- this[major + minor] = (this[major + minor] || 0) + delta;
- }
- },
- clear: function clear() {
- for (let key in this)
- if (typeof this[key] !== "number")
- delete this[key];
- }
- },
-
- init: function init(suffix) {
- this.initialized = true;
- this.suffix = suffix || "";
-
- let base = this.load("base.jsm", this.global);
- this.global.EXPORTED_SYMBOLS = base.EXPORTED_SYMBOLS;
- this.global.JSMLoader = this;
- base.JSMLoader = this;
- },
-
- getTarget: function getTarget(url) {
- if (url.indexOf(":") === -1)
- url = "resource://dactyl" + this.suffix + "/" + url;
-
- let chan = this.io.newChannel(url, null, null);
- chan.cancel(Cr.NS_BINDING_ABORTED);
- return chan.name;
- },
-
- load: function load(name, target) {
- let url = name;
- if (url.indexOf(":") === -1)
- url = "resource://dactyl" + this.suffix + "/" + url;
- let targetURL = this.getTarget(url);
-
- let stale = this.stale[name] || this.stale[targetURL];
- if (stale) {
- delete this.stale[name];
- delete this.stale[targetURL];
-
- let loadURL = url.replace(RegExp("^(resource://dactyl)/"), "$1" + this.suffix + "/");
-
- let global = this.globals[name];
- if (stale === targetURL)
- this.loadSubScript(loadURL, global.global || global);
- }
-
- try {
- let now = Date.now();
- this.modules[url] = true;
- let global = Cu.import(url, target);
-
- if (!(name in this.globals))
- this.times.add("require", name, Date.now() - now);
-
- return this.globals[name] = global;
- }
- catch (e) {
- dump("Importing " + url + ": " + e + "\n" + (e.stack || Error().stack));
- throw e;
- }
- },
-
- loadSubScript: function loadSubScript(script) {
- let now = Date.now();
- this.loader.loadSubScript.apply(this.loader, arguments);
- this.times.add("loadSubScript", script, Date.now() - now);
- },
-
- cleanup: function unregister() {
- for each (let factory in this.factories)
- this.manager.unregisterFactory(factory.classID, factory);
- this.factories = {};
- },
-
- purge: function purge() {
- dump("dactyl: JSMLoader: purge\n");
-
- this.bootstrap = null;
-
- if (Cu.unload) {
- Object.keys(this.modules).reverse().forEach(function (url) {
- try {
- Cu.unload(url);
- }
- catch (e) {
- Cu.reportError(e);
- }
- });
- }
- else {
- for (let [url, global] in Iterator(this.globals)) {
- if (url === "bootstrap.jsm" || url === "resource://dactyl/bootstrap.jsm")
- continue;
-
- let target = this.getTarget(url);
- this.stale[url] = target;
- this.stale[target] = target;
-
- for each (let prop in Object.getOwnPropertyNames(global))
- try {
- if (!(prop in this.builtin) &&
- ["JSMLoader", "Set", "set", "EXPORTED_SYMBOLS"].indexOf(prop) < 0 &&
- !global.__lookupGetter__(prop))
- global[prop] = undefined;
- }
- catch (e) {
- dump("Deleting property " + prop + " on " + url + ":\n " + e + "\n");
- Cu.reportError(e);
- }
- }
- }
- },
-
- Factory: function Factory(clas) ({
- __proto__: clas.prototype,
-
- createInstance: function (outer, iid) {
- try {
- if (outer != null)
- throw Cr.NS_ERROR_NO_AGGREGATION;
- if (!clas.instance)
- clas.instance = new clas();
- return clas.instance.QueryInterface(iid);
- }
- catch (e) {
- Cu.reportError(e);
- throw e;
- }
- }
- }),
-
- registerFactory: function registerFactory(factory) {
- if (Set.has(this.factories, factory.contractID))
- this.manager.unregisterFactory(this.factories[factory.contractID].classID,
- this.factories[factory.contractID]);
-
- this.manager.registerFactory(factory.classID,
- String(factory.classID),
- factory.contractID,
- factory);
- this.factories[factory.contractID] = factory;
- }
- };
-
-}catch(e){ dump(e + "\n" + (e.stack || Error().stack)); Components.utils.reportError(e) }
-
-// vim: set fdm=marker sw=4 sts=4 et ft=javascript:
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2013 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-try {"use strict";
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("buffer", {
exports: ["Buffer", "buffer"],
require: ["prefs", "services", "util"]
-}, this);
+});
-this.lazyRequire("finder", ["RangeFind"]);
-this.lazyRequire("io", ["io"]);
-this.lazyRequire("overlay", ["overlay"]);
-this.lazyRequire("storage", ["File", "storage"]);
-this.lazyRequire("template", ["template"]);
+lazyRequire("bookmarkcache", ["bookmarkcache"]);
+lazyRequire("contexts", ["Group"]);
+lazyRequire("io", ["io"]);
+lazyRequire("finder", ["RangeFind"]);
+lazyRequire("overlay", ["overlay"]);
+lazyRequire("sanitizer", ["sanitizer"]);
+lazyRequire("storage", ["File", "storage"]);
+lazyRequire("template", ["template"]);
/**
* A class to manage the primary web content buffer. The name comes
);
},
+ /**
+ * Gets a content preference for the given buffer.
+ *
+ * @param {string} pref The preference to get.
+ * @param {function(string|number|boolean)} callback The callback to
+ * call with the preference value. @optional
+ * @returns {string|number|boolean} The value of the preference, if
+ * callback is not provided.
+ */
+ getPref: function getPref(pref, callback) {
+ // God damn it.
+ if (config.haveGecko("19.0a1"))
+ services.contentPrefs.getPref(this.uri, pref,
+ sanitizer.getContext(this.win), callback);
+ else
+ services.contentPrefs.getPref(uri, pref, callback);
+ },
+
+ /**
+ * Sets a content preference for the given buffer.
+ *
+ * @param {string} pref The preference to set.
+ * @param {string} value The value to store.
+ */
+ setPref: function setPref(pref, value) {
+ services.contentPrefs.setPref(
+ this.uri, pref, value, sanitizer.getContext(this.win));
+ },
+
+ /**
+ * Clear a content preference for the given buffer.
+ *
+ * @param {string} pref The preference to clear.
+ */
+ clearPref: function clearPref(pref) {
+ services.contentPrefs.removePref(
+ this.uri, pref, sanitizer.getContext(this.win));
+ },
+
climbUrlPath: function climbUrlPath(count) {
let { dactyl } = this.modules;
})(win || this.win);
if (focusedFirst)
- return frames.filter(function (f) f === this.focusedFrame).concat(
- frames.filter(function (f) f !== this.focusedFrame));
+ return frames.filter(function (f) f === this.focusedFrame, this).concat(
+ frames.filter(function (f) f !== this.focusedFrame, this));
return frames;
},
*/
get selectionController() util.selectionController(this.focusedFrame),
+ /**
+ * @property {string|null} The canonical short URL for the current
+ * document.
+ */
+ get shortURL() {
+ let { uri, doc } = this;
+
+ for each (let shortener in Buffer.uriShorteners)
+ try {
+ let shortened = shortener(uri, doc);
+ if (shortened)
+ return shortened.spec;
+ }
+ catch (e) {
+ util.reportError(e);
+ }
+
+ let link = DOM("link[href][rev=canonical], \
+ link[href][rel=shortlink]", doc);
+ if (link)
+ return link.attr("href");
+
+ return null;
+ },
+
/**
* Opens the appropriate context menu for *elem*.
*
* Saves a page link to disk.
*
* @param {HTMLAnchorElement} elem The page link to save.
+ * @param {boolean} overwrite If true, overwrite any existing file.
*/
- saveLink: function saveLink(elem) {
+ saveLink: function saveLink(elem, overwrite) {
let { completion, dactyl, io } = this.modules;
let self = this;
if (file.exists() && file.isDirectory())
file.append(Buffer.getDefaultNames(elem)[0][0]);
+ util.assert(!file.exists() || overwrite, _("io.existsNoOverride", file.path));
+
try {
if (!file.exists())
file.create(File.NORMAL_FILE_TYPE, octal(644));
util.assert(false, _("save.invalidDestination", e.name));
}
- self.saveURI(uri, file);
+ self.saveURI({ uri: uri, file: file, context: elem });
},
completer: function (context) completion.savePage(context, elem)
* @param {nsIURI} uri The URI to save
* @param {nsIFile} file The file into which to write the result.
*/
- saveURI: function saveURI(uri, file, callback, self) {
+ saveURI: function saveURI(params) {
+ if (params instanceof Ci.nsIURI)
+ // Deprecated?
+ params = { uri: arguments[0], file: arguments[1],
+ callback: arguments[2], self: arguments[3] };
+
var persist = services.Persist();
persist.persistFlags = persist.PERSIST_FLAGS_FROM_CACHE
| persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
let window = this.topWindow;
+ let privacy = sanitizer.getContext(params.context || this.win);
+ let file = File(params.file);
if (!file.exists())
file.create(Ci.nsIFile.NORMAL_FILE_TYPE, octal(666));
let downloadListener = new window.DownloadListener(window,
- services.Transfer(uri, File(file).URI, "",
- null, null, null, persist));
+ services.Transfer(params.uri, file.URI, "", null, null, null,
+ persist, privacy && privacy.usePrivateBrowsing));
+ var { callback, self } = params;
if (callback)
persist.progressListener = update(Object.create(downloadListener), {
onStateChange: util.wrapCallback(function onStateChange(progress, request, flags, status) {
if (callback && (flags & Ci.nsIWebProgressListener.STATE_STOP) && status == 0)
- util.trapErrors(callback, self, uri, file, progress, request, flags, status);
+ util.trapErrors(callback, self, params.uri, file.file,
+ progress, request, flags, status);
return onStateChange.superapply(this, arguments);
})
else
persist.progressListener = downloadListener;
- persist.saveURI(uri, null, null, null, null, file);
+ persist.saveURI(params.uri, null, null, null, null,
+ file.file, privacy);
},
/**
var sel = this.focusedFrame.getSelection();
}
catch (e) {}
+
if (!elem && sel && sel.rangeCount)
elem = sel.getRangeAt(0).startContainer;
+
+ if (!elem) {
+ let area = -1;
+ for (let e in DOM(Buffer.SCROLLABLE_SEARCH_SELECTOR,
+ this.focusedFrame.document)) {
+ if (Buffer.isScrollable(e, dir, horizontal)) {
+ let r = DOM(e).rect;
+ let a = r.width * r.height;
+ if (a > area) {
+ area = a;
+ elem = e;
+ }
+ }
+ }
+ if (elem)
+ util.trapErrors("focus", elem);
+ }
if (elem)
elem = find(elem);
// add the frame indicator
let doc = frames[next].document;
- let indicator = DOM(<div highlight="FrameIndicator"/>, doc)
+ let indicator = DOM(["div", { highlight: "FrameIndicator" }], doc)
.appendTo(doc.body || doc.documentElement || doc);
util.timeout(function () { indicator.remove(); }, 500);
// Doesn't unattach
- //doc.body.setAttributeNS(NS.uri, "activeframe", "true");
- //util.timeout(function () { doc.body.removeAttributeNS(NS.uri, "activeframe"); }, 500);
+ //doc.body.setAttributeNS(NS, "activeframe", "true");
+ //util.timeout(function () { doc.body.removeAttributeNS(NS, "activeframe"); }, 500);
},
// similar to pageInfo
showElementInfo: function showElementInfo(elem) {
let { dactyl } = this.modules;
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- dactyl.echo(<><!--L-->Element:<br/>{util.objectToString(elem, true)}</>);
+ dactyl.echo(["", /*L*/"Element:", ["br"], util.objectToString(elem, true)]);
},
/**
(sections || options["pageinfo"])
.map(function (opt) Buffer.pageInfo[opt].action.call(self)),
function (res) res && iter(res).join(", ") || undefined,
- ", ");
+ ", ").join("");
if (bookmarkcache.isBookmarked(this.URL))
info += ", " + _("buffer.bookmarked");
- let pageInfoText = <>{file.quote()} [{info}] {title}</>;
+ let pageInfoText = [file.quote(), " [", info, "] ", title].join("");
dactyl.echo(pageInfoText, commandline.FORCE_SINGLELINE);
return;
}
let list = template.map(sections || options["pageinfo"], function (option) {
let { action, title } = Buffer.pageInfo[option];
return template.table(title, action.call(self, true));
- }, <br/>);
+ }, ["br"]);
commandline.commandOutput(list);
},
return true;
};
- let uri = isString(doc) ? util.newURI(doc) : util.newURI(doc.location.href);
+ if (isString(doc)) {
+ var privacyContext = null;
+ var uri = util.newURI(doc);
+ }
+ else {
+ privacyContext = sanitizer.getContext(doc);
+ uri = util.newURI(doc.location.href);
+ }
+
let ext = uri.fileExtension || "txt";
if (doc.contentType)
ext = services.mime.getPrimaryExtension(doc.contentType, ext);
var persist = services.Persist();
persist.persistFlags = persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
persist.progressListener = this;
- persist.saveURI(uri, null, null, null, null, this.file);
+ persist.saveURI(uri, null, null, null, null, this.file,
+ privacyContext);
}
return null;
},
* closed range [Buffer.ZOOM_MIN, Buffer.ZOOM_MAX].
*/
setZoom: function setZoom(value, fullZoom) {
- let { dactyl, statusline } = this.modules;
+ let { dactyl, statusline, storage } = this.modules;
let { ZoomManager } = this;
if (fullZoom === undefined)
return dactyl.echoerr(_("zoom.illegal"));
}
- if (services.has("contentPrefs") && !storage.privateMode
- && prefs.get("browser.zoom.siteSpecific")) {
- services.contentPrefs[value != 1 ? "setPref" : "removePref"]
- (this.uri, "browser.content.full-zoom", value);
- services.contentPrefs[value != 1 ? "setPref" : "removePref"]
- (this.uri, "dactyl.content.full-zoom", fullZoom);
+ if (prefs.get("browser.zoom.siteSpecific")) {
+ var privacy = sanitizer.getContext(this.win);
+ if (value == 1) {
+ this.clearPref("browser.content.full-zoom");
+ this.clearPref("dactyl.content.full-zoom");
+ }
+ else {
+ this.setPref("browser.content.full-zoom", value);
+ this.setPref("dactyl.content.full-zoom", fullZoom);
+ }
}
statusline.updateZoomLevel();
let self = this;
let uri = this.uri;
- if (services.has("contentPrefs") && prefs.get("browser.zoom.siteSpecific"))
- services.contentPrefs.getPref(uri, "dactyl.content.full-zoom", function (val) {
+ if (prefs.get("browser.zoom.siteSpecific")) {
+ this.getPref("dactyl.content.full-zoom", function (val) {
if (val != null && uri.equals(self.uri) && val != prefs.get("browser.zoom.full"))
[self.contentViewer.textZoom, self.contentViewer.fullZoom] =
[self.contentViewer.fullZoom, self.contentViewer.textZoom];
});
+ }
}),
/**
scrollTo: deprecated("Buffer.scrollTo", function scrollTo(x, y) this.win.scrollTo(x, y)),
textZoom: deprecated("buffer.zoomValue/buffer.fullZoom", function textZoom() this.contentViewer.markupDocumentViewer.textZoom * 100)
}, {
+ /**
+ * The pattern used to search for a scrollable element when we have
+ * no starting point.
+ */
+ SCROLLABLE_SEARCH_SELECTOR: "html, body, div",
+
PageInfo: Struct("PageInfo", "name", "title", "action")
.localize("title"),
this.pageInfo[option] = Buffer.PageInfo(option, title, func);
},
+ uriShorteners: [],
+
+ /**
+ * Adds a new URI shortener for documents matching the given filter.
+ *
+ * @param {string|function(URI, Document):boolean} filter A site filter
+ * string or a function which accepts a URI and a document and
+ * returns true if it can shorten the document's URI.
+ * @param {function(URI, Document):URI} shortener Returns a shortened
+ * URL for the given URI and document.
+ */
+ addURIShortener: function addURIShortener(filter, shortener) {
+ if (isString(filter))
+ filter = Group.compileFilter(filter);
+
+ this.uriShorteners.push(function uriShortener(uri, doc) {
+ if (filter(uri, doc))
+ return shortener(uri, doc);
+ });
+ },
+
Scrollable: function Scrollable(elem) {
if (elem instanceof Ci.nsIDOMElement)
return elem;
get scrollWidth() this.win.scrollMaxX + this.win.innerWidth,
get scrollHeight() this.win.scrollMaxY + this.win.innerHeight,
+ get scrollLeftMax() this.win.scrollMaxX,
+ get scrollRightMax() this.win.scrollMaxY,
+
get scrollLeft() this.win.scrollX,
set scrollLeft(val) { this.win.scrollTo(val, this.win.scrollY) },
},
canScroll: function canScroll(elem, dir, horizontal) {
- let pos = "scrollTop", size = "clientHeight", max = "scrollHeight", layoutSize = "offsetHeight",
+ let pos = "scrollTop", size = "clientHeight", end = "scrollHeight", layoutSize = "offsetHeight",
overflow = "overflowX", border1 = "borderTopWidth", border2 = "borderBottomWidth";
if (horizontal)
- pos = "scrollLeft", size = "clientWidth", max = "scrollWidth", layoutSize = "offsetWidth",
+ pos = "scrollLeft", size = "clientWidth", end = "scrollWidth", layoutSize = "offsetWidth",
overflow = "overflowX", border1 = "borderLeftWidth", border2 = "borderRightWidth";
+ if (dir < 0)
+ return elem[pos] > 0;
+
+ let max = pos + "Max";
+ if (max in elem && pos > 0)
+ return elem[pos] < elem[max];
+
let style = DOM(elem).style;
let borderSize = Math.round(parseFloat(style[border1]) + parseFloat(style[border2]));
let realSize = elem[size];
// Stupid Gecko eccentricities. May fail for quirks mode documents.
- if (elem[size] + borderSize == elem[max] || elem[size] == 0) // Stupid, fallible heuristic.
+ if (elem[size] + borderSize >= elem[end] || elem[size] == 0) // Stupid, fallible heuristic.
return false;
if (style[overflow] == "hidden")
realSize += borderSize;
- return dir < 0 && elem[pos] > 0 || dir > 0 && elem[pos] + realSize < elem[max] || !dir && realSize < elem[max];
+ return dir > 0 && elem[pos] + realSize < elem[end] || !dir && realSize < elem[end];
},
/**
/**
* Scrolls the given element vertically.
*
- * @param {Element} elem The element to scroll.
+ * @param {Node} node The node to scroll.
* @param {string} unit The increment by which to scroll.
* Possible values are: "lines", "pages"
* @param {number} number The possibly fractional number of
_exWidth: function _exWidth(elem) {
try {
- let div = DOM(<elem style="width: 1ex !important; position: absolute !important; padding: 0 !important; display: block;"/>,
+ let div = DOM(["elem", { style: "width: 1ex !important; position: absolute !important; padding: 0 !important; display: block;" }],
elem.ownerDocument).appendTo(elem.body || elem);
try {
return parseFloat(div.style.width);
function (file) {
let output = io.system(filename.substr(1), file);
commandline.command = command;
- commandline.commandOutput(<span highlight="CmdOutput">{output}</span>);
+ commandline.commandOutput(["span", { highlight: "CmdOutput" }, output]);
});
if (/^>>/.test(filename)) {
dactyl.assert(args.bang || !file.exists(), _("io.exists"));
- chosenData = { file: file, uri: util.newURI(doc.location.href) };
+ chosenData = { file: file.file, uri: util.newURI(doc.location.href) };
}
// if browser.download.useDownloadDir = false then the "Save As"
window.internalSave(doc.location.href, doc, null, contentDisposition,
doc.contentType, false, null, chosenData,
doc.referrer ? window.makeURI(doc.referrer) : null,
- true);
+ doc, true);
},
{
argCount: "?",
uri.query = uri.query.replace(/(?:^|&)utm_[^&]+/g, "")
.replace(/^&/, "");
- let link = DOM("link[href][rev=canonical], link[href][rel=shortlink]", doc);
- let url = link.length && options.get("yankshort").getKey(uri) ? link.attr("href") : uri.spec;
+ let url = options.get("yankshort").getKey(uri) && buffer.shortURL || uri.spec;
dactyl.clipboardWrite(url, true);
});
function (args) { buffer.scrollVertical("lines", -Math.max(args.count, 1)); },
{ count: true });
- mappings.add([modes.COMMAND], dactyl.has("mail") ? ["h", "<scroll-left-column>"] : ["h", "<Left>", "<scroll-left-column>"],
+ mappings.add([modes.NORMAL], dactyl.has("mail") ? ["h", "<scroll-left-column>"] : ["h", "<Left>", "<scroll-left-column>"],
"Scroll document to the left",
function (args) { buffer.scrollHorizontal("columns", -Math.max(args.count, 1)); },
{ count: true });
if (verbose)
for (let link in engines)
yield [link.title || /*L*/ "Engine " + n++,
- <a xmlns={XHTML} href={link.href}
- onclick="if (event.button == 0) { window.external.AddSearchProvider(this.href); return false; }"
- highlight="URL">{link.href}</a>];
+ ["a", { href: link.href, highlight: "URL",
+ onclick: "if (event.button == 0) { window.external.AddSearchProvider(this.href); return false; }" },
+ link.href]];
}
if (!verbose && nEngines)
nFeed++;
let type = feedTypes[feed.type] || "RSS";
if (verbose)
- yield [feed.title, template.highlightURL(feed.href, true) + <span class="extra-info"> ({type})</span>];
+ yield [feed.title, [template.highlightURL(feed.href, true),
+ ["span", { class: "extra-info" }, " (" + type + ")"]]];
}
}
yield ["Title", doc.title];
yield ["URL", template.highlightURL(doc.location.href, true)];
+ let { shortURL } = this;
+ if (shortURL)
+ yield ["Short URL", template.highlightURL(shortURL, true)];
+
let ref = "referrer" in doc && doc.referrer;
if (ref)
yield ["Referrer", template.highlightURL(ref, true)];
// get meta tag data, sort and put into pageMeta[]
let metaNodes = this.focusedFrame.document.getElementsByTagName("meta");
- return Array.map(metaNodes, function (node) [(node.name || node.httpEquiv), template.highlightURL(node.content)])
+ return Array.map(metaNodes, function (node) [(node.name || node.httpEquiv),
+ template.highlightURL(node.content)])
.sort(function (a, b) util.compareIgnoreCase(a[0], b[0]));
});
}
});
-} catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
+// catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
endModule();
-// Copyright (c) 2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2011-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("cache", {
exports: ["Cache", "cache"],
require: ["config", "services", "util"]
-}, this);
+});
+
+lazyRequire("overlay", ["overlay"]);
+lazyRequire("storage", ["File"]);
var Cache = Module("Cache", XPCOM(Ci.nsIRequestObserver), {
init: function init() {
if (!this._cacheReader && this.cacheFile.exists()
&& !this.inQueue)
try {
- this._cacheReader = services.ZipReader(this.cacheFile);
+ this._cacheReader = services.ZipReader(this.cacheFile.file);
}
catch (e if e.result == Cr.NS_ERROR_FILE_CORRUPTED) {
util.reportError(e);
if (!this.cacheFile.exists())
mode |= File.MODE_CREATE;
- cache._cacheWriter = services.ZipWriter(this.cacheFile, mode);
+ cache._cacheWriter = services.ZipWriter(this.cacheFile.file, mode);
}
catch (e if e.result == Cr.NS_ERROR_FILE_CORRUPTED) {
util.reportError(e);
this.cacheFile.remove(false);
mode |= File.MODE_CREATE;
- cache._cacheWriter = services.ZipWriter(this.cacheFile, mode);
+ cache._cacheWriter = services.ZipWriter(this.cacheFile.file, mode);
}
return this._cacheWriter;
},
}
},
- closeWriter: function closeWriter() {
+ closeWriter: util.wrapCallback(function closeWriter() {
this.closeReader();
if (this._cacheWriter) {
if (this.cacheFile.fileSize <= 22)
this.cacheFile.remove(false);
}
- },
+ }),
flush: function flush() {
cache.cache = {};
},
flushJAR: function flushJAR(file) {
- services.observer.notifyObservers(file, "flush-cache-entry", "");
+ services.observer.notifyObservers(File(file).file, "flush-cache-entry", "");
},
flushStartup: function flushStartup() {
return cache.force(name);
},
- get: function get(name) {
+ get: function get(name, callback, self) {
if (!Set.has(this.cache, name)) {
+ if (callback && !(Set.has(this.providers, name) ||
+ Set.has(this.localProviders, name)))
+ this.register(name, callback, self);
+
this.cache[name] = this.force(name);
util.assert(this.cache[name] !== undefined,
"No such cache key", false);
if (this.queue.length && !this.inQueue) {
// removeEntry does not work properly with queues.
+ let removed = 0;
for each (let [, entry] in this.queue)
if (this.getCacheWriter().hasEntry(entry)) {
this.getCacheWriter().removeEntry(entry, false);
- this.closeWriter();
+ removed++;
}
+ if (removed)
+ this.closeWriter();
this.queue.splice(0).forEach(function ([time, entry]) {
if (time && Set.has(this.cache, entry)) {
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("commands", {
exports: ["ArgType", "Command", "Commands", "CommandOption", "Ex", "commands"],
require: ["contexts", "messages", "util"]
-}, this);
+});
+
+lazyRequire("help", ["help"]);
+lazyRequire("options", ["Option"]);
+lazyRequire("template", ["template"]);
/**
* A structure representing the options available for a command.
* @param {function} action The action invoked by this command when executed.
* @param {Object} extraInfo An optional extra configuration hash. The
* following properties are supported.
+ * always - see {@link Command#always}
* argCount - see {@link Command#argCount}
* bang - see {@link Command#bang}
* completer - see {@link Command#completer}
* @property {function (Args)} The function called to execute this command.
*/
action: null,
+
+ /**
+ * @property {function (Args)} A function which is called when this
+ * command is encountered, even if we are ignoring commands. Used to
+ * implement control structures.
+ */
+ always: null,
+
/**
* @property {string} This command's argument count spec.
* @see Commands#parseArguments
*/
argCount: 0,
+
/**
* @property {function (CompletionContext, Args)} This command's completer.
* @see CompletionContext
*/
completer: null,
+
/** @property {boolean} Whether this command accepts a here document. */
hereDoc: false,
+
/**
* @property {boolean} Whether this command may be called with a bang,
* e.g., :com!
*/
bang: false,
+
/**
* @property {boolean} Whether this command may be called with a count,
* e.g., :12bdel
*/
count: false,
+
/**
* @property {function(args)} A function which should return a list
* of domains referenced in the given args. Used in determining
* private data.
*/
domains: function (args) [],
+
/**
* @property {boolean} At what index this command's literal arguments
* begin. For instance, with a value of 2, all arguments starting with
* key mappings or Ex command lines as arguments.
*/
literal: null,
+
/**
* @property {Array} The options this command takes.
* @see Commands@parseArguments
let { cache } = this.modules;
this.cached = true;
- cache.register(this.cacheKey, function () {
+ let cached = cache.get(this.cacheKey, function () {
self.cached = false;
this.modules.moduleManager.initDependencies("commands");
let hives = (hives || this.userHives).map(function (h) [h, cmds(h)]).filter(function ([h, c]) c.length);
- let list = <table>
- <tr highlight="Title">
- <td/>
- <td style="padding-right: 1em;"></td>
- <td style="padding-right: 1ex;">{_("title.Name")}</td>
- <td style="padding-right: 1ex;">{_("title.Args")}</td>
- <td style="padding-right: 1ex;">{_("title.Range")}</td>
- <td style="padding-right: 1ex;">{_("title.Complete")}</td>
- <td style="padding-right: 1ex;">{_("title.Definition")}</td>
- </tr>
- <col style="min-width: 6em; padding-right: 1em;"/>
- {
- template.map(hives, function ([hive, cmds]) let (i = 0)
- <tr style="height: .5ex;"/> +
- template.map(cmds, function (cmd)
- <tr>
- <td highlight="Title">{!i++ ? hive.name : ""}</td>
- <td>{cmd.bang ? "!" : " "}</td>
- <td>{cmd.name}</td>
- <td>{cmd.argCount}</td>
- <td>{cmd.count ? "0c" : ""}</td>
- <td>{completerToString(cmd.completer)}</td>
- <td>{cmd.replacementText || "function () { ... }"}</td>
- </tr>) +
- <tr style="height: .5ex;"/>)
- }
- </table>;
-
- if (list.*.length() === list.text().length() + 2)
- dactyl.echomsg(_("command.none"));
- else
- commandline.commandOutput(list);
+ let list = ["table", {},
+ ["tr", { highlight: "Title" },
+ ["td"],
+ ["td", { style: "padding-right: 1em;" }],
+ ["td", { style: "padding-right: 1ex;" }, _("title.Name")],
+ ["td", { style: "padding-right: 1ex;" }, _("title.Args")],
+ ["td", { style: "padding-right: 1ex;" }, _("title.Range")],
+ ["td", { style: "padding-right: 1ex;" }, _("title.Complete")],
+ ["td", { style: "padding-right: 1ex;" }, _("title.Definition")]],
+ ["col", { style: "min-width: 6em; padding-right: 1em;" }],
+ hives.map(function ([hive, cmds]) let (i = 0) [
+ ["tr", { style: "height: .5ex;" }],
+ cmds.map(function (cmd)
+ ["tr", {},
+ ["td", { highlight: "Title" }, !i++ ? hive.name : ""],
+ ["td", {}, cmd.bang ? "!" : " "],
+ ["td", {}, cmd.name],
+ ["td", {}, cmd.argCount],
+ ["td", {}, cmd.count ? "0c" : ""],
+ ["td", {}, completerToString(cmd.completer)],
+ ["td", {}, cmd.replacementText || "function () { ... }"]]),
+ ["tr", { style: "height: .5ex;" }]])];
+
+ // E4X-FIXME
+ // if (list.*.length() === list.text().length() + 2)
+ // dactyl.echomsg(_("command.none"));
+ // else
+ commandline.commandOutput(list);
}
}),
hasPrivateData: function hasPrivateData(command) {
for (let [cmd, args] in this.subCommands(command))
if (cmd.privateData)
- return !callable(cmd.privateData) || cmd.privateData(args);
+ return !callable(cmd.privateData) ? cmd.privateData
+ : cmd.privateData(args);
return false;
},
}
},
- nameRegexp: util.regexp(<![CDATA[
+ nameRegexp: util.regexp(literal(/*
[^
0-9
<forbid>
]
[^ <forbid> ]*
- ]]>, "gx", {
- forbid: util.regexp(String.replace(<![CDATA[
+ */), "gx", {
+ forbid: util.regexp(String.replace(literal(/*
U0000-U002c // U002d -
U002e-U002f
U003a-U0040 // U0041-U005a a-z
Ufe70-Ufeff // Arabic Presentation Forms-B
Uff00-Uffef // Halfwidth and Fullwidth Forms
Ufff0-Uffff // Specials
- ]]>, /U/g, "\\u"), "x")
+ */), /U/g, "\\u"), "x")
}),
validName: Class.Memoize(function validName() util.regexp("^" + this.nameRegexp.source + "$")),
- commandRegexp: Class.Memoize(function commandRegexp() util.regexp(<![CDATA[
+ commandRegexp: Class.Memoize(function commandRegexp() util.regexp(literal(/*
^
(?P<spec>
(?P<prespace> [:\s]*)
(?:. | \n)*?
)?
$
- ]]>, "x", {
+ */), "x", {
name: this.nameRegexp
})),
iterate: function (args) commands.iterator().map(function (cmd) ({
__proto__: cmd,
columns: [
- cmd.hive == commands.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{cmd.hive.name}</span>
+ cmd.hive == commands.builtin ? "" : ["span", { highlight: "Object", style: "padding-right: 1em;" },
+ cmd.hive.name]
]
})),
iterateIndex: function (args) let (tags = help.tags)
}
});
-(function () {
-
- Commands.quoteMap = {
- "\n": "\\n",
- "\t": "\\t",
- };
- function quote(q, list, map) {
- map = map || Commands.quoteMap;
- let re = RegExp("[" + list + "]", "g");
- function quote(str) q + String.replace(str, re, function ($0) $0 in map ? map[$0] : ("\\" + $0)) + q;
- quote.list = list;
- return quote;
- };
-
- Commands.quoteArg = {
- '"': quote('"', '\n\t"\\\\'),
- "'": quote("'", "'", { "'": "''" }),
- "": quote("", "|\\\\\\s'\"")
- };
- Commands.complQuote = {
- '"': ['"', quote("", Commands.quoteArg['"'].list), '"'],
- "'": ["'", quote("", Commands.quoteArg["'"].list), "'"],
- "": ["", Commands.quoteArg[""], ""]
- };
-
- Commands.parseBool = function (arg) {
- if (/^(true|1|on)$/i.test(arg))
- return true;
- if (/^(false|0|off)$/i.test(arg))
- return false;
- return NaN;
- };
-})();
+let quote = function quote(q, list, map) {
+ map = map || Commands.quoteMap;
+ let re = RegExp("[" + list + "]", "g");
+ function quote(str) q + String.replace(str, re, function ($0) $0 in map ? map[$0] : ("\\" + $0)) + q;
+ quote.list = list;
+ return quote;
+};
+
+Commands.quoteMap = {
+ "\n": "\\n",
+ "\t": "\\t",
+};
+
+Commands.quoteArg = {
+ '"': quote('"', '\n\t"\\\\'),
+ "'": quote("'", "'", { "'": "''" }),
+ "": quote("", "|\\\\\\s'\"")
+};
+Commands.complQuote = {
+ '"': ['"', quote("", Commands.quoteArg['"'].list), '"'],
+ "'": ["'", quote("", Commands.quoteArg["'"].list), "'"],
+ "": ["", Commands.quoteArg[""], ""]
+};
+
+Commands.parseBool = function (arg) {
+ if (/^(true|1|on)$/i.test(arg))
+ return true;
+ if (/^(false|0|off)$/i.test(arg))
+ return false;
+ return NaN;
+};
endModule();
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("completion", {
exports: ["CompletionContext", "Completion", "completion"]
}, this);
+lazyRequire("dom", ["DOM"]);
+lazyRequire("messages", ["_", "messages"]);
+lazyRequire("template", ["template"]);
+
/**
* Creates a new completion context.
*
* @constructor
*/
var CompletionContext = Class("CompletionContext", {
- init: function (editor, name, offset) {
+ init: function cc_init(editor, name, offset) {
if (!name)
name = "";
*/
self.parent = parent;
- ["filters", "keys", "process", "title", "quote"].forEach(function (key)
+ ["filters", "keys", "process", "title", "quote"].forEach(function fe(key)
self[key] = parent[key] && util.cloneObject(parent[key]));
["anchored", "compare", "editor", "_filter", "filterFunc", "forceAnchored", "top"].forEach(function (key)
self[key] = parent[key]);
- self.__defineGetter__("value", function () this.top.value);
+ self.__defineGetter__("value", function get_value() this.top.value);
self.offset = parent.offset;
self.advance(offset || 0);
delete self.ignoreCase;
if (self != this)
return self;
- ["_caret", "contextList", "maxItems", "onUpdate", "selectionTypes", "tabPressed", "updateAsync", "value"].forEach(function (key) {
+ ["_caret", "contextList", "maxItems", "onUpdate", "selectionTypes", "tabPressed", "updateAsync", "value"].forEach(function fe(key) {
self.__defineGetter__(key, function () this.top[key]);
self.__defineSetter__(key, function (val) this.top[key] = val);
});
this.anchored = true;
this.forceAnchored = null;
- this.compare = function (a, b) String.localeCompare(a.text, b.text);
+ this.compare = function compare(a, b) String.localeCompare(a.text, b.text);
/**
* @property {function} This function is called when we close
* a completion window with Esc or Ctrl-c. Usually this callback
* @default Selects all results which match every predicate in the
* {@link #filters} array.
*/
- this.filterFunc = function (items) {
+ this.filterFunc = function filterFunc(items) {
let self = this;
return this.filters.
- reduce(function (res, filter) res.filter(function (item) filter.call(self, item)),
+ reduce(function r(res, filter) res.filter(function f(item) filter.call(self, item)),
items);
};
/**
* changes its completion list. Only called when
* {@link #updateAsync} is true.
*/
- this.onUpdate = function () true;
+ this.onUpdate = function onUpdate() true;
this.runCount = 0;
* @property {CompletionContext} The top-level completion context.
*/
this.top = this;
- this.__defineGetter__("incomplete", function () this._incomplete || this.contextList.some(function (c) c.parent && c.incomplete));
- this.__defineGetter__("waitingForTab", function () this._waitingForTab || this.contextList.some(function (c) c.parent && c.waitingForTab));
- this.__defineSetter__("incomplete", function (val) { this._incomplete = val; });
- this.__defineSetter__("waitingForTab", function (val) { this._waitingForTab = val; });
+ this.__defineGetter__("incomplete", function get_incomplete() this._incomplete
+ || this.contextList.some(function (c) c.parent && c.incomplete));
+ this.__defineGetter__("waitingForTab", function get_waitingForTab() this._waitingForTab
+ || this.contextList.some(function (c) c.parent && c.waitingForTab));
+ this.__defineSetter__("incomplete", function get_incomplete(val) { this._incomplete = val; });
+ this.__defineSetter__("waitingForTab", function get_waitingForTab(val) { this._waitingForTab = val; });
this.reset();
}
/**
* Returns a key, as detailed in {@link #keys}.
* @function
*/
- this.getKey = function (item, key) (typeof self.keys[key] == "function") ? self.keys[key].call(this, item.item) :
+ this.getKey = function getKey(item, key) (typeof self.keys[key] == "function") ? self.keys[key].call(this, item.item) :
key in self.keys ? item.item[self.keys[key]]
: item.item[key];
return this;
},
- __title: Class.Memoize(function () this._title.map(function (s)
+ __title: Class.Memoize(function __title() this._title.map(function (s)
typeof s == "string" ? messages.get("completion.title." + s, s)
: s)),
},
get title() this.__title,
- get activeContexts() this.contextList.filter(function (c) c.items.length),
+ get activeContexts() this.contextList.filter(function f(c) c.items.length),
// Temporary
/**
let self = this;
try {
- let allItems = this.contextList.map(function (context) context.hasItems && context.items.length);
+ let allItems = this.contextList.map(function m(context) context.hasItems && context.items.length);
if (this.cache.allItems && array.equals(this.cache.allItems, allItems))
return this.cache.allItemsResult;
this.cache.allItems = allItems;
- let minStart = Math.min.apply(Math, this.activeContexts.map(function (c) c.offset));
+ let minStart = Math.min.apply(Math, this.activeContexts.map(function m(c) c.offset));
if (minStart == Infinity)
minStart = 0;
get longestSubstring() self.longestAllSubstring,
- get items() array.flatten(self.activeContexts.map(function (context) {
+ get items() array.flatten(self.activeContexts.map(function m(context) {
let prefix = self.value.substring(minStart, context.offset);
- return context.items.map(function (item) ({
+ return context.items.map(function m(item) ({
text: prefix + item.text,
result: prefix + item.result,
__proto__: item
// Temporary
get allSubstrings() {
let contexts = this.activeContexts;
- let minStart = Math.min.apply(Math, contexts.map(function (c) c.offset));
- let lists = contexts.map(function (context) {
+ let minStart = Math.min.apply(Math, contexts.map(function m(c) c.offset));
+ let lists = contexts.map(function m(context) {
let prefix = context.value.substring(minStart, context.offset);
- return context.substrings.map(function (s) prefix + s);
+ return context.substrings.map(function m(s) prefix + s);
});
/* TODO: Deal with sub-substrings for multiple contexts again.
* Possibly.
*/
let substrings = lists.reduce(
- function (res, list) res.filter(function (str) list.some(function (s) s.substr(0, str.length) == str)),
+ function r(res, list) res.filter(function f(str) list.some(function s_(s) s.substr(0, str.length) == str)),
lists.pop());
if (!substrings) // FIXME: How is this undefined?
return [];
},
// Temporary
get longestAllSubstring() {
- return this.allSubstrings.reduce(function (a, b) a.length > b.length ? a : b, "");
+ return this.allSubstrings.reduce(function r(a, b) a.length > b.length ? a : b, "");
},
get caret() this._caret - this.offset,
set caret(val) this._caret = val + this.offset,
- get compare() this._compare || function () 0,
+ get compare() this._compare || function compare() 0,
set compare(val) this._compare = val,
get completions() this._completions || [],
let res = { highlight: "" };
function result(quote) {
- yield ["context", function () self];
- yield ["result", quote ? function () quote[0] + util.trapErrors(1, quote, this.text) + quote[2]
- : function () this.text];
- yield ["texts", function () Array.concat(this.text)];
+ yield ["context", function p_context() self];
+ yield ["result", quote ? function p_result() quote[0] + util.trapErrors(1, quote, this.text) + quote[2]
+ : function p_result() this.text];
+ yield ["texts", function p_texts() Array.concat(this.text)];
};
for (let i in iter(this.keys, result(this.quote))) {
// reference any variables. Don't bother with eval context.
v = Function("i", "return i" + v);
if (typeof v == "function")
- res.__defineGetter__(k, function () Class.replaceProperty(this, k, v.call(this, this.item, self)));
+ res.__defineGetter__(k, function p_gf() Class.replaceProperty(this, k, v.call(this, this.item, self)));
else
- res.__defineGetter__(k, function () Class.replaceProperty(this, k, this.item[v]));
- res.__defineSetter__(k, function (val) Class.replaceProperty(this, k, val));
+ res.__defineGetter__(k, function p_gp() Class.replaceProperty(this, k, this.item[v]));
+ res.__defineSetter__(k, function p_s(val) Class.replaceProperty(this, k, val));
}
return res;
},
this.noUpdate = false;
},
- ignoreCase: Class.Memoize(function () {
+ ignoreCase: Class.Memoize(function M() {
let mode = this.wildcase;
if (mode == "match")
return false;
// Item matchers
if (this.ignoreCase)
this.matchString = this.anchored ?
- function (filter, str) String.toLowerCase(str).indexOf(filter.toLowerCase()) == 0 :
- function (filter, str) String.toLowerCase(str).indexOf(filter.toLowerCase()) >= 0;
+ function matchString(filter, str) String.toLowerCase(str).indexOf(filter.toLowerCase()) == 0 :
+ function matchString(filter, str) String.toLowerCase(str).indexOf(filter.toLowerCase()) >= 0;
else
this.matchString = this.anchored ?
- function (filter, str) String.indexOf(str, filter) == 0 :
- function (filter, str) String.indexOf(str, filter) >= 0;
+ function matchString(filter, str) String.indexOf(str, filter) == 0 :
+ function matchString(filter, str) String.indexOf(str, filter) >= 0;
// Item formatters
this.processor = Array.slice(this.process);
if (!this.anchored)
- this.processor[0] = function (item, text) self.process[0].call(self, item,
+ this.processor[0] = function processor_0(item, text) self.process[0].call(self, item,
template.highlightFilter(item.text, self.filter, null, item.isURI));
try {
// Item prototypes
if (!this._cache.constructed) {
let proto = this.itemPrototype;
- this._cache.constructed = items.map(function (item) ({ __proto__: proto, item: item }));
+ this._cache.constructed = items.map(function m(item) ({ __proto__: proto, item: item }));
}
// Filters
filtered.sort(this.compare);
if (!this.anchored) {
let filter = this.filter;
- filtered.sort(function (a, b) (b.text.indexOf(filter) == 0) - (a.text.indexOf(filter) == 0));
+ filtered.sort(function s(a, b) (b.text.indexOf(filter) == 0) - (a.text.indexOf(filter) == 0));
}
}
}
}
- substrings = items.reduce(function (res, item)
- res.map(function (substring) {
+ substrings = items.reduce(function r(res, item)
+ res.map(function m(substring) {
// A simple binary search to find the longest substring
// of the given string which also matches the current
// item's text.
let quote = this.quote;
if (quote)
- substrings = substrings.map(function (str) quote[0] + quote[1](str));
+ substrings = substrings.map(function m(str) quote[0] + quote[1](str));
return this._substrings = substrings;
},
* Calls the {@link #cancel} method of all currently active
* sub-contexts.
*/
- cancelAll: function () {
+ cancelAll: function cancelAll() {
for (let [, context] in Iterator(this.contextList)) {
if (context.cancel)
context.cancel();
* @param {string} key
* @param defVal
*/
- getCache: function (key, defVal) {
+ getCache: function getCache(key, defVal) {
if (!(key in this.cache))
this.cache[key] = defVal();
return this.cache[key];
let step = start > end ? -1 : 1;
start = Math.max(0, start || 0);
end = Math.min(items.length, end ? end : items.length);
- return iter.map(util.range(start, end, step), function (i) items[i]);
+ return iter.map(util.range(start, end, step), function m(i) items[i]);
},
getRow: function getRow(idx, doc) {
if (cache) {
if (idx in this.items && !(idx in this.cache.rows))
try {
- cache[idx] = util.xmlToDom(this.createRow(this.items[idx]),
- doc || this.doc);
+ cache[idx] = DOM.fromJSON(this.createRow(this.items[idx]),
+ doc || this.doc);
}
catch (e) {
util.reportError(e);
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- cache[idx] = util.xmlToDom(
- <div highlight="CompItem" style="white-space: nowrap">
- <li highlight="CompResult">{this.text} </li>
- <li highlight="CompDesc ErrorMsg">{e} </li>
- </div>, doc || this.doc);
+ util.dump(util.prettifyJSON(this.createRow(this.items[idx]), null, true));
+ cache[idx] = DOM.fromJSON(
+ ["div", { highlight: "CompItem", style: "white-space: nowrap" },
+ ["li", { highlight: "CompResult" }, this.text + "\u00a0"],
+ ["li", { highlight: "CompDesc ErrorMsg" }, e + "\u00a0"]],
+ doc || this.doc);
}
return cache[idx];
}
let context = this.fork(name);
function alias(prop) {
- context.__defineGetter__(prop, function () self[prop]);
- context.__defineSetter__(prop, function (val) self[prop] = val);
+ context.__defineGetter__(prop, function get_() self[prop]);
+ context.__defineSetter__(prop, function set_(val) self[prop] = val);
}
alias("_cache");
alias("_completions");
*/
pushProcessor: function pushProcess(index, func) {
let next = this.process[index];
- this.process[index] = function (item, text) func(item, text, next);
+ this.process[index] = function process_(item, text) func(item, text, next);
},
/**
throw Error();
this.offset = 0;
- this.process = [template.icon, function (item, k) k];
+ this.process = [template.icon, function process_1(item, k) k];
this.filters = [CompletionContext.Filter.text];
this.tabPressed = false;
this.title = ["Completions"];
*/
wait: function wait(timeout, interruptable) {
this.allItems;
- return util.waitFor(function () !this.incomplete, this, timeout, interruptable);
+ return util.waitFor(function wf() !this.incomplete, this, timeout, interruptable);
}
}, {
Sort: {
- number: function (a, b) parseInt(a.text) - parseInt(b.text) || String.localeCompare(a.text, b.text),
+ number: function S_number(a, b) parseInt(a.text) - parseInt(b.text)
+ || String.localeCompare(a.text, b.text),
unsorted: null
},
Filter: {
- text: function (item) {
+ text: function F_text(item) {
let text = item.texts;
for (let [i, str] in Iterator(text)) {
if (this.match(String(str))) {
}
return false;
},
- textDescription: function (item) {
+ textDescription: function F_textDescription(item) {
return CompletionContext.Filter.text.call(this, item) || this.match(item.description);
}
}
* @instance completion
*/
var Completion = Module("completion", {
- init: function () {
+ init: function init() {
},
get setFunctionCompleter() JavaScript.setCompleter, // Backward compatibility
- Local: function (dactyl, modules, window) ({
+ Local: function Local(dactyl, modules, window) ({
urlCompleters: {},
get modules() modules,
let res = context.fork.apply(context, ["run", 0, this, name].concat(Array.slice(arguments, 3)));
if (res) {
if (Components.stack.caller.name === "runCompleter") // FIXME
- return { items: res.map(function (i) ({ item: i })) };
+ return { items: res.map(function m(i) ({ item: i })) };
context.contexts["/run"].completions = res;
}
context.wait(null, true);
runCompleter: function runCompleter(name, filter, maxItems) {
return this._runCompleter.apply(this, Array.slice(arguments))
- .items.map(function (i) i.item);
+ .items.map(function m(i) i.item);
},
listCompleter: function listCompleter(name, filter, maxItems) {
let contexts = context.activeContexts;
if (!contexts.length)
- contexts = context.contextList.filter(function (c) c.hasItems).slice(0, 1);
+ contexts = context.contextList.filter(function f(c) c.hasItems).slice(0, 1);
if (!contexts.length)
contexts = context.contextList.slice(-1);
modules.commandline.commandOutput(
- <div highlight="Completions">
- { template.map(contexts, function (context)
- template.completionRow(context.title, "CompTitle") +
- template.map(context.items, function (item) context.createRow(item), null, 100)) }
- </div>);
+ ["div", { highlight: "Completions" },
+ template.map(contexts, function m(context)
+ [template.completionRow(context.title, "CompTitle"),
+ template.map(context.items, function m(item) context.createRow(item), null, 100)])]);
},
}),
context.quote = context.quote || ["", util.identity, ""];
let quote = context.quote[1];
- context.quote[1] = function (str) quote(str.replace(/!/g, escape));
+ context.quote[1] = function quote_1(str) quote(str.replace(/!/g, escape));
}
if (this.options["urlseparator"])
context.advance(skip[0].length);
if (/^about:/.test(context.filter))
- context.fork("about", 6, this, function (context) {
+ context.fork("about", 6, this, function fork_(context) {
context.title = ["about:"];
- context.generate = function () {
+ context.generate = function generate_() {
return [[k.substr(services.ABOUT.length), ""]
for (k in Cc)
if (k.indexOf(services.ABOUT) == 0)];
complete = this.options["complete"];
// Will, and should, throw an error if !(c in opts)
- Array.forEach(complete, function (c) {
+ Array.forEach(complete, function fe(c) {
let completer = this.urlCompleters[c] || { args: [], completer: this.autocomplete(c.replace(/^native:/, "")) };
context.forkapply(c, 0, this, completer.completer, completer.args);
}, this);
let words = context.filter.toLowerCase().split(/\s+/g);
context.hasItems = true;
- context.completions = context.completions.filter(function ({ url, title })
- words.every(function (w) (url + " " + title).toLowerCase().indexOf(w) >= 0))
+ context.completions = context.completions.filter(function f({ url, title })
+ words.every(function e(w) (url + " " + title).toLowerCase().indexOf(w) >= 0))
context.format = this.modules.bookmarks.format;
- context.keys.extra = function (item) {
+ context.keys.extra = function k_extra(item) {
try {
return bookmarkcache.get(item.url).extra;
}
};
context.title = [_("autocomplete.title", provider)];
- context.cancel = function () {
+ context.cancel = function cancel_() {
this.incomplete = false;
if (running[provider])
service.stopSearch();
}
}),
- urls: function (context, tags) {
+ urls: function urls(context, tags) {
let compare = String.localeCompare;
let contains = String.indexOf;
if (context.ignoreCase) {
compare = util.compareIgnoreCase;
- contains = function (a, b) a && a.toLowerCase().indexOf(b.toLowerCase()) > -1;
+ contains = function contains_(a, b) a && a.toLowerCase().indexOf(b.toLowerCase()) > -1;
}
if (tags)
- context.filters.push(function (item) tags.
- every(function (tag) (item.tags || []).
- some(function (t) !compare(tag, t))));
+ context.filters.push(function filter_(item) tags.
+ every(function e(tag) (item.tags || []).
+ some(function s(t) !compare(tag, t))));
context.anchored = false;
if (!context.title)
context.title = ["URL", "Title"];
- context.fork("additional", 0, this, function (context) {
+ context.fork("additional", 0, this, function fork_(context) {
context.title[0] += " " + _("completion.additional");
context.filter = context.parent.filter; // FIXME
context.completions = context.parent.completions;
// accept them if all tokens match either the URL or the title.
// Filter out all directly matching strings.
let match = context.filters[0];
- context.filters[0] = function (item) !match.call(this, item);
+ context.filters[0] = function filters_0(item) !match.call(this, item);
// and all that don't match the tokens.
let tokens = context.filter.split(/\s+/);
- context.filters.push(function (item) tokens.every(
- function (tok) contains(item.url, tok) ||
+ context.filters.push(function filter_(item) tokens.every(
+ function e(tok) contains(item.url, tok) ||
contains(item.title, tok)));
let re = RegExp(tokens.filter(util.identity).map(util.regexp.escape).join("|"), "g");
function highlight(item, text, i) process[i].call(this, item, template.highlightRegexp(text, re));
let process = context.process;
context.process = [
- function (item, text) highlight.call(this, item, item.text, 0),
- function (item, text) highlight.call(this, item, text, 1)
+ function process_0(item, text) highlight.call(this, item, item.text, 0),
+ function process_1(item, text) highlight.call(this, item, text, 1)
];
});
}
get options() this.modules.options
});
},
- commands: function (dactyl, modules, window) {
+ commands: function initCommands(dactyl, modules, window) {
const { commands, completion } = modules;
commands.add(["contexts"],
"List the completion contexts used during completion of an Ex command",
function (args) {
modules.commandline.commandOutput(
- <div highlight="Completions">
- { template.completionRow(["Context", "Title"], "CompTitle") }
- { template.map(completion.contextList || [], function (item) template.completionRow(item, "CompItem")) }
- </div>);
+ ["div", { highlight: "Completions" },
+ template.completionRow(["Context", "Title"], "CompTitle"),
+ template.map(completion.contextList || [],
+ function m(item) template.completionRow(item, "CompItem"))]);
},
{
argCount: "*",
literal: 0
});
},
- options: function (dactyl, modules, window) {
+ options: function initOptions(dactyl, modules, window) {
const { completion, options } = modules;
let wildmode = {
values: {
return first == val || second == val;
},
has: function () {
- test = function (val) this.value.some(function (value) this.checkHas(value, val), this);
+ let test = function test(val) this.value.some(function s(value) this.checkHas(value, val), this);
return Array.some(arguments, test, this);
}
};
setter: function setter(values) {
if (values.length == 1 && !Set.has(values[0], this.values)
&& Array.every(values[0], Set.has(this.valueMap)))
- return Array.map(values[0], function (v) this[v], this.valueMap);
+ return Array.map(values[0], function m(v) this[v], this.valueMap);
return values;
},
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
let global = this;
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("config", {
exports: ["ConfigBase", "Config", "config"],
require: ["dom", "io", "protocol", "services", "util", "template"]
-}, this);
+});
-this.lazyRequire("addons", ["AddonManager"]);
-this.lazyRequire("cache", ["cache"]);
-this.lazyRequire("highlight", ["highlight"]);
-this.lazyRequire("messages", ["_"]);
-this.lazyRequire("prefs", ["localPrefs", "prefs"]);
-this.lazyRequire("storage", ["storage", "File"]);
-this.lazyRequire("styles", ["Styles"]);
+lazyRequire("addons", ["AddonManager"]);
+lazyRequire("cache", ["cache"]);
+lazyRequire("highlight", ["highlight"]);
+lazyRequire("messages", ["_"]);
+lazyRequire("prefs", ["localPrefs", "prefs"]);
+lazyRequire("storage", ["storage", "File"]);
+lazyRequire("styles", ["Styles"]);
function AboutHandler() {}
AboutHandler.prototype = {
global: ["addons",
"base",
"io",
+ ["bookmarkcache", "bookmarkcache"],
"buffer",
"cache",
"commands",
highlight.loadCSS(this.helpCSS.replace(/__MSG_(.*?)__/g, function (m0, m1) _(m1)));
if (!this.haveGecko("2b"))
- highlight.loadCSS(<![CDATA[
+ highlight.loadCSS(literal(/*
!TabNumber font-weight: bold; margin: 0px; padding-right: .8ex;
!TabIconNumber {
font-weight: bold;
text-align: center;
text-shadow: black -1px 0 1px, black 0 1px 1px, black 1px 0 1px, black 0 -1px 1px;
}
- ]]>);
+ */));
let hl = highlight.set("Find", "");
hl.onChange = function () {
}
}
function processJar(file) {
- let jar = services.ZipReader(file);
+ let jar = services.ZipReader(file.file);
if (jar)
try {
if (jar.hasEntry("chrome.manifest"))
"xmlns.html": "http://www.w3.org/1999/xhtml",
"xmlns.xul": "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
- "tag.command-line": <link topic="command-line">command line</link>,
- "tag.status-line": <link topic="status-line">status line</link>,
- "mode.command-line": <link topic="command-line-mode">Command Line</link>,
+ "tag.command-line": ["link", { xmlns: "dactyl", topic: "command-line" }, "command line"],
+ "tag.status-line": ["link", { xmlns: "dactyl", topic: "status-line" }, "status line"],
+ "mode.command-line": ["link", { xmlns: "dactyl", topic: "command-line-mode" }, "Command Line"]
},
dtdStrings: [
init: function init() {
this.loadConfig(document.documentURI);
- let append = <e4x xmlns={XUL} xmlns:dactyl={NS}>
- <menupopup id="viewSidebarMenu"/>
- <broadcasterset id="mainBroadcasterSet"/>
- </e4x>;
+ let append = [
+ ["menupopup", { id: "viewSidebarMenu", xmlns: "xul" }],
+ ["broadcasterset", { id: "mainBroadcasterSet", xmlns: "xul" }]];
+
for each (let [id, [name, key, uri]] in Iterator(this.sidebars)) {
- append.XUL::menupopup[0].* +=
- <menuitem observes={"pentadactyl-" + id + "Sidebar"} label={name} accesskey={key} xmlns={XUL}/>;
- append.XUL::broadcasterset[0].* +=
- <broadcaster id={"pentadactyl-" + id + "Sidebar"}
- autoCheck="false" type="checkbox" group="sidebar"
- sidebartitle={name} sidebarurl={uri}
- oncommand="toggleSidebar(this.id || this.observes);" xmlns={XUL}/>;
+ append[0].push(
+ ["menuitem", { observes: "pentadactyl-" + id + "Sidebar", label: name,
+ accesskey: key }]);
+ append[1].push(
+ ["broadcaster", { id: "pentadactyl-" + id + "Sidebar", autoCheck: "false",
+ type: "checkbox", group: "sidebar", sidebartitle: name,
+ sidebarurl: uri,
+ oncommand: "toggleSidebar(this.id || this.observes);" }]);
}
- util.overlayWindow(window, { append: append.elements() });
+ util.overlayWindow(window, { append: append });
},
get window() window,
let img = window.Image();
img.src = this.logo || "resource://dactyl-local-content/logo.png";
img.onload = util.wrapCallback(function () {
- highlight.loadCSS(<>{"!Logo {"}
+ highlight.loadCSS(literal(/*
+ !Logo {
display: inline-block;
- background: url({img.src});
- width: {img.width}px;
- height: {img.height}px;
- {"}"}</>);
+ background: url({src});
+ width: {width}px;
+ height: {height}px;
+ }
+ */).replace(/\{(.*?)\}/g, function (m, m1) img[m1]));
img = null;
});
},
-// Copyright (c) 2010-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2010-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("contexts", {
exports: ["Contexts", "Group", "contexts"],
require: ["services", "util"]
-}, this);
+});
-this.lazyRequire("overlay", ["overlay"]);
+lazyRequire("commands", ["ArgType", "CommandOption", "commands"]);
+lazyRequire("options", ["Option"]);
+lazyRequire("overlay", ["overlay"]);
+lazyRequire("storage", ["File"]);
+lazyRequire("template", ["template"]);
var Const = function Const(val) Class.Property({ enumerable: true, value: val });
return update(siteFilter, {
toString: function () this.filters.join(","),
- toXML: function (modules) let (uri = modules && modules.buffer.uri)
+ toJSONXML: function (modules) let (uri = modules && modules.buffer.uri)
template.map(this.filters,
- function (f) <span highlight={uri && f(uri) ? "Filter" : ""}>{f}</span>,
- <>,</>),
+ function (f) ["span", { highlight: uri && f(uri) ? "Filter" : "" },
+ "toJSONXML" in f ? f.toJSONXML() : String(f)],
+ ","),
filters: Option.parse.sitelist(patterns)
});
return {
__proto__: frame,
filename: this.context.file[0] == "[" ? this.context.file
- : services.io.newFileURI(File(this.context.file)).spec,
+ : File(this.context.file).URI.spec,
lineNumber: this.context.line
};
return frame;
getDocs: function getDocs(context) {
try {
if (isinstance(context, ["Sandbox"])) {
- let info = "INFO" in context && Cu.evalInSandbox("this.INFO instanceof XML && INFO.toXMLString()", context);
- return info && XML(info);
+ let info = "INFO" in context && Cu.evalInSandbox("this.INFO instanceof XML ? INFO.toXMLString() : this.INFO", context);
+ return /^</.test(info) ? XML(info) : info;
}
- if (typeof context.INFO == "xml")
+ if (DOM.isJSONXML(context.INFO))
+ return context.INFO;
+ if (typeof context.INFO == "xml" && config.haveGecko(null, "14.*"))
return context.INFO;
}
catch (e) {}
{
names: ["-description", "-desc", "-d"],
description: "A description of this group",
- default: ["User-defined group"],
+ default: "User-defined group",
type: CommandOption.STRING
},
{
names: ["-locations", "-locs", "-loc", "-l"],
- description: ["The URLs for which this group should be active"],
+ description: "The URLs for which this group should be active",
default: ["*"],
type: CommandOption.LIST
},
context.keys = {
active: function (group) group.filter(uri),
text: "name",
- description: function (g) <>{g.filter.toXML ? g.filter.toXML(modules) + <> </> : ""}{g.description || ""}</>
+ description: function (g) ["", g.filter.toJSONXML ? g.filter.toJSONXML(modules).concat("\u00a0") : "", g.description || ""]
};
context.completions = (active === undefined ? contexts.groupList : contexts.initializedGroups(active))
.slice(0, -1);
--- /dev/null
+// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
+//
+// This work is licensed for reuse under an MIT license. Details are
+// given in the LICENSE.txt file included with this file.
+/* use strict */
+
+defineModule("dom", {
+ exports: ["fromXML"]
+});
+
+lazyRequire("highlight", ["highlight"]);
+
+var XBL = Namespace("xbl", "http://www.mozilla.org/xbl");
+var XHTML = Namespace("html", "http://www.w3.org/1999/xhtml");
+var XUL = Namespace("xul", "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+var NS = Namespace("dactyl", "http://vimperator.org/namespaces/liberator");
+
+function fromXML(node, doc, nodes) {
+ XML.ignoreWhitespace = XML.prettyPrinting = false;
+ if (typeof node === "string") // Sandboxes can't currently pass us XML objects.
+ node = XML(node);
+
+ if (node.length() != 1) {
+ let domnode = doc.createDocumentFragment();
+ for each (let child in node)
+ domnode.appendChild(fromXML(child, doc, nodes));
+ return domnode;
+ }
+
+ switch (node.nodeKind()) {
+ case "text":
+ return doc.createTextNode(String(node));
+ case "element":
+ let domnode = doc.createElementNS(node.namespace(), node.localName());
+
+ for each (let attr in node.@*::*)
+ if (attr.name() != "highlight")
+ domnode.setAttributeNS(attr.namespace(), attr.localName(), String(attr));
+
+ for each (let child in node.*::*)
+ domnode.appendChild(fromXML(child, doc, nodes));
+ if (nodes && node.@key)
+ nodes[node.@key] = domnode;
+
+ if ("@highlight" in node)
+ highlight.highlightNode(domnode, String(node.@highlight), nodes || true);
+ return domnode;
+ default:
+ return null;
+ }
+}
+
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("dom", {
exports: ["$", "DOM", "NS", "XBL", "XHTML", "XUL"]
-}, this);
+});
-this.lazyRequire("highlight", ["highlight"]);
-this.lazyRequire("template", ["template"]);
+lazyRequire("highlight", ["highlight"]);
+lazyRequire("messages", ["_"]);
+lazyRequire("prefs", ["prefs"]);
+lazyRequire("template", ["template"]);
-var XBL = Namespace("xbl", "http://www.mozilla.org/xbl");
-var XHTML = Namespace("html", "http://www.w3.org/1999/xhtml");
-var XUL = Namespace("xul", "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-var NS = Namespace("dactyl", "http://vimperator.org/namespaces/liberator");
-default xml namespace = XHTML;
+var XBL = "http://www.mozilla.org/xbl";
+var XHTML = "http://www.w3.org/1999/xhtml";
+var XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+var NS = "http://vimperator.org/namespaces/liberator";
function BooleanAttribute(attr) ({
get: function (elem) elem.getAttribute(attr) == "true",
;
else if (typeof val == "xml" && context instanceof Ci.nsIDOMDocument)
this[length++] = DOM.fromXML(val, context, this.nodes);
+ else if (DOM.isJSONXML(val)) {
+ if (context instanceof Ci.nsIDOMDocument)
+ this[length++] = DOM.fromJSON(val, context, this.nodes);
+ else
+ this[length++] = val;
+ }
else if (val instanceof Ci.nsIDOMNode || val instanceof Ci.nsIDOMWindow)
this[length++] = val;
else if ("__iterator__" in val || isinstance(val, ["Iterator", "Generator"]))
},
eachDOM: function eachDOM(val, fn, self) {
- XML.prettyPrinting = XML.ignoreWhitespace = false;
- if (isString(val))
- val = XML(val);
-
- if (typeof val == "xml")
- return this.each(function (elem, i) {
- fn.call(this, DOM.fromXML(val, elem.ownerDocument), elem, i);
- }, self || this);
-
let dom = this;
function munge(val, container, idx) {
if (val instanceof Ci.nsIDOMRange)
if (val instanceof Ci.nsIDOMNode)
return val;
- if (typeof val == "xml") {
+ if (typeof val == "xml" || DOM.isJSONXML(val)) {
val = dom.constructor(val, dom.document);
if (container)
container[idx] = val[0];
if (DOM(elem).isInput
|| /^(?:hidden|textarea)$/.test(elem.type)
|| elem.type == "submit" && elem == field
- || elem.checked && /^(?:checkbox|radio)$/.test(elem.type))
- elems.push(encode(elem.name, elem.value, elem === field));
+ || elem.checked && /^(?:checkbox|radio)$/.test(elem.type)) {
+
+ if (elem !== field)
+ elems.push(encode(elem.name, elem.value));
+ else if (overlay.getData(elem, "had-focus"))
+ elems.push(encode(elem.name, elem.value, true));
+ else
+ elems.push(encode(elem.name, "", true));
+ }
else if (elem instanceof Ci.nsIDOMHTMLSelectElement) {
for (let [, opt] in Iterator(elem.options))
if (opt.selected)
* representation of this node.
*/
repr: function repr(color) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
-
function namespaced(node) {
- var ns = DOM.namespaceNames[node.namespaceURI] || /^(?:(.*?):)?/.exec(node.name)[0];
+ var ns = DOM.namespaceNames[node.namespaceURI] || /^(?:(.*?):)?/.exec(node.name)[1];
if (!ns)
return node.localName;
if (color)
- return <><span highlight="HelpXMLNamespace">{ns}</span>{node.localName}</>
+ return [["span", { highlight: "HelpXMLNamespace" }, ns],
+ node.localName];
return ns + ":" + node.localName;
}
try {
let hasChildren = elem.firstChild && (!/^\s*$/.test(elem.firstChild) || elem.firstChild.nextSibling)
if (color)
- res.push(<span highlight="HelpXML"><span highlight="HelpXMLTagStart"><{
- namespaced(elem)} {
- template.map(array.iterValues(elem.attributes),
- function (attr)
- <span highlight="HelpXMLAttribute">{namespaced(attr)}</span> +
- <span highlight="HelpXMLString">{attr.value}</span>,
- <> </>)
- }{ !hasChildren ? "/>" : ">"
- }</span>{ !hasChildren ? "" : <>...</> +
- <span highlight="HtmlTagEnd"><{namespaced(elem)}></span>
- }</span>);
+ res.push(["span", { highlight: "HelpXML" },
+ ["span", { highlight: "HelpXMLTagStart" },
+ "<", namespaced(elem), " ",
+ template.map(array.iterValues(elem.attributes),
+ function (attr) [
+ ["span", { highlight: "HelpXMLAttribute" }, namespaced(attr)],
+ ["span", { highlight: "HelpXMLString" }, attr.value]
+ ],
+ " "),
+ !hasChildren ? "/>" : ">",
+ ],
+ !hasChildren ? "" :
+ ["", "...",
+ ["span", { highlight: "HtmlTagEnd" },"<", namespaced(elem), ">"]]
+ ]);
else {
let tag = "<" + [namespaced(elem)].concat(
- [namespaced(a) + "=" + template.highlight(a.value, true)
+ [namespaced(a) + '="' + String.replace(a.value, /["<]/, DOM.escapeHTML) + '"'
for ([i, a] in array.iterItems(elem.attributes))]).join(" ");
res.push(tag + (!hasChildren ? "/>" : ">...</" + namespaced(elem) + ">"));
res.push({}.toString.call(elem));
}
}, this);
- return template.map(res, util.identity, <>,</>);
+ res = template.map(res, util.identity, ",");
+ return color ? res : res.join("");
},
attr: function attr(key, val) {
}, this);
},
+ fragment: function fragment() {
+ let frag = this.document.createDocumentFragment();
+ this.appendTo(frag);
+ return this;
+ },
+
+ clone: function clone(deep)
+ this.map(function (elem) elem.cloneNode(deep)),
+
toggle: function toggle(val, self) {
if (callable(val))
return this.each(function (elem, i) {
html: function html(txt, self) {
return this.getSet(arguments,
function (elem) elem.innerHTML,
- function (elem, val) { elem.innerHTML = val });
+ util.wrapCallback(function (elem, val) { elem.innerHTML = val }));
},
text: function text(txt, self) {
}
for (let [k, v] in Iterator(Ci.nsIDOMKeyEvent)) {
+ if (!/^DOM_VK_/.test(k))
+ continue;
+
this.code_nativeKey[v] = k.substr(4);
k = k.substr(7).toLowerCase();
? function (elem, dir) services.dactyl.getScrollable(elem) & (dir ? services.dactyl["DIRECTION_" + dir.toUpperCase()] : ~0)
: function (elem, dir) true),
+ isJSONXML: function isJSONXML(val) isArray(val) && isinstance(val[0], ["String", "Array", "XML", DOM.DOMString])
+ || isObject(val) && "toDOM" in val,
+
+ DOMString: function DOMString(val) ({
+ __proto__: DOMString.prototype,
+
+ toDOM: function toDOM(doc) doc.createTextNode(val),
+
+ toString: function () val
+ }),
+
/**
* The set of input element type attribute values that mark the element as
* an editable field.
* entities.
*
* @param {string} str
+ * @param {boolean} simple If true, only escape for the simple case
+ * of text nodes.
* @returns {string}
*/
- escapeHTML: function escapeHTML(str) {
+ escapeHTML: function escapeHTML(str, simple) {
let map = { "'": "'", '"': """, "%": "%", "&": "&", "<": "<", ">": ">" };
- return str.replace(/['"&<>]/g, function (m) map[m]);
+ let regexp = simple ? /[<>]/g : /['"&<>]/g;
+ return str.replace(regexp, function (m) map[m]);
},
/**
* stored here, keyed to the value thereof.
* @returns {Node}
*/
- fromXML: function fromXML(node, doc, nodes) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- if (typeof node === "string") // Sandboxes can't currently pass us XML objects.
- node = XML(node);
-
- if (node.length() != 1) {
- let domnode = doc.createDocumentFragment();
- for each (let child in node)
- domnode.appendChild(fromXML(child, doc, nodes));
- return domnode;
+ fromXML: deprecated("DOM.fromJSON", { get: function fromXML()
+ prefs.get("javascript.options.xml.chrome") !== false
+ && require("dom-e4x").fromXML }),
+
+ fromJSON: update(function fromJSON(xml, doc, nodes, namespaces) {
+ if (!doc)
+ doc = document;
+
+ function tag(args, namespaces) {
+ let _namespaces = namespaces;
+
+ // Deal with common error case
+ if (args == null) {
+ util.reportError(Error("Unexpected null when processing XML."));
+ args = ["html:i", {}, "[NULL]"];
+ }
+
+ if (isinstance(args, ["String", "Number", "Boolean", _]))
+ return doc.createTextNode(args);
+ if (isXML(args))
+ return DOM.fromXML(args, doc, nodes);
+ if (isObject(args) && "toDOM" in args)
+ return args.toDOM(doc, namespaces, nodes);
+ if (args instanceof Ci.nsIDOMNode)
+ return args;
+ if (args instanceof DOM)
+ return args.fragment();
+ if ("toJSONXML" in args)
+ args = args.toJSONXML();
+
+ let [name, attr] = args;
+
+ if (!isString(name) || args.length == 0 || name === "") {
+ var frag = doc.createDocumentFragment();
+ Array.forEach(args, function (arg) {
+ if (!isArray(arg[0]))
+ arg = [arg];
+ arg.forEach(function (arg) {
+ frag.appendChild(tag(arg, namespaces));
+ });
+ });
+ return frag;
+ }
+
+ attr = attr || {};
+
+ function parseNamespace(name) DOM.parseNamespace(name, namespaces);
+
+ // FIXME: Surely we can do better.
+ for (var key in attr) {
+ if (/^xmlns(?:$|:)/.test(key)) {
+ if (_namespaces === namespaces)
+ namespaces = Object.create(namespaces);
+
+ namespaces[key.substr(6)] = namespaces[attr[key]] || attr[key];
+ }}
+
+ var args = Array.slice(args, 2);
+ var vals = parseNamespace(name);
+ var elem = doc.createElementNS(vals[0] || namespaces[""],
+ name);
+
+ for (var key in attr)
+ if (!/^xmlns(?:$|:)/.test(key)) {
+ var val = attr[key];
+ if (nodes && key == "key")
+ nodes[val] = elem;
+
+ vals = parseNamespace(key);
+ if (key == "highlight")
+ ;
+ else if (typeof val == "function")
+ elem.addEventListener(key.replace(/^on/, ""), val, false);
+ else
+ elem.setAttributeNS(vals[0] || "", key, val);
+ }
+ args.forEach(function(e) {
+ elem.appendChild(tag(e, namespaces));
+ });
+
+ if ("highlight" in attr)
+ highlight.highlightNode(elem, attr.highlight, nodes || true);
+ return elem;
}
- switch (node.nodeKind()) {
- case "text":
- return doc.createTextNode(String(node));
- case "element":
- let domnode = doc.createElementNS(node.namespace(), node.localName());
-
- for each (let attr in node.@*::*)
- if (attr.name() != "highlight")
- domnode.setAttributeNS(attr.namespace(), attr.localName(), String(attr));
-
- for each (let child in node.*::*)
- domnode.appendChild(fromXML(child, doc, nodes));
- if (nodes && node.@key)
- nodes[node.@key] = domnode;
-
- if ("@highlight" in node)
- highlight.highlightNode(domnode, String(node.@highlight), nodes || true);
- return domnode;
- default:
- return null;
+ if (namespaces)
+ namespaces = update({}, fromJSON.namespaces, namespaces);
+ else
+ namespaces = fromJSON.namespaces;
+
+ return tag(xml, namespaces)
+ }, {
+ namespaces: {
+ "": "http://www.w3.org/1999/xhtml",
+ dactyl: String(NS),
+ html: "http://www.w3.org/1999/xhtml",
+ xmlns: "http://www.w3.org/2000/xmlns/",
+ xul: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
}
+ }),
+
+ toXML: function toXML(xml) {
+ // Meh. For now.
+ let doc = services.XMLDocument();
+ let node = this.fromJSON(xml, doc);
+ return services.XMLSerializer()
+ .serializeToString(node);
+ },
+
+ toPrettyXML: function toPrettyXML(xml, asXML, indent, namespaces) {
+ const INDENT = indent || " ";
+
+ const EMPTY = Set("area base basefont br col frame hr img input isindex link meta param"
+ .split(" "));
+
+ function namespaced(namespaces, namespace, localName) {
+ for (let [k, v] in Iterator(namespaces))
+ if (v == namespace)
+ return (k ? k + ":" + localName : localName);
+
+ throw Error("No such namespace");
+ }
+
+ function isFragment(args) !isString(args[0]) || args.length == 0 || args[0] === "";
+
+ function hasString(args) {
+ return args.some(function (a) isString(a) || isFragment(a) && hasString(a))
+ }
+
+ function isStrings(args) {
+ if (!isArray(args))
+ return util.dump("ARGS: " + {}.toString.call(args) + " " + args), false;
+ return args.every(function (a) isinstance(a, ["String", DOM.DOMString]) || isFragment(a) && isStrings(a))
+ }
+
+ function tag(args, namespaces, indent) {
+ let _namespaces = namespaces;
+
+ if (args == "")
+ return "";
+
+ if (isinstance(args, ["String", "Number", "Boolean", _, DOM.DOMString]))
+ return indent +
+ DOM.escapeHTML(String(args), true);
+
+ if (isXML(args))
+ return indent +
+ args.toXMLString()
+ .replace(/^/m, indent);
+
+ if (isObject(args) && "toDOM" in args)
+ return indent +
+ services.XMLSerializer()
+ .serializeToString(args.toDOM(services.XMLDocument()))
+ .replace(/^/m, indent);
+
+ if (args instanceof Ci.nsIDOMNode)
+ return indent +
+ services.XMLSerializer()
+ .serializeToString(args)
+ .replace(/^/m, indent);
+
+ if ("toJSONXML" in args)
+ args = args.toJSONXML();
+
+ // Deal with common error case
+ if (args == null) {
+ util.reportError(Error("Unexpected null when processing XML."));
+ return "[NULL]";
+ }
+
+ let [name, attr] = args;
+
+ if (isFragment(args)) {
+ let res = [];
+ let join = isArray(args) && isStrings(args) ? "" : "\n";
+ Array.forEach(args, function (arg) {
+ if (!isArray(arg[0]))
+ arg = [arg];
+
+ let contents = [];
+ arg.forEach(function (arg) {
+ let string = tag(arg, namespaces, indent);
+ if (string)
+ contents.push(string);
+ });
+ if (contents.length)
+ res.push(contents.join("\n"), join)
+ });
+ if (res[res.length - 1] == join)
+ res.pop();
+ return res.join("");
+ }
+
+ attr = attr || {};
+
+ function parseNamespace(name) {
+ var m = /^(?:(.*):)?(.*)$/.exec(name);
+ return [namespaces[m[1]], m[2]];
+ }
+
+ // FIXME: Surely we can do better.
+ let skipAttr = {};
+ for (var key in attr) {
+ if (/^xmlns(?:$|:)/.test(key)) {
+ if (_namespaces === namespaces)
+ namespaces = update({}, namespaces);
+
+ let ns = namespaces[attr[key]] || attr[key];
+ if (ns == namespaces[key.substr(6)])
+ skipAttr[key] = true;
+
+ attr[key] = namespaces[key.substr(6)] = ns;
+ }}
+
+ var args = Array.slice(args, 2);
+ var vals = parseNamespace(name);
+
+ let res = [indent, "<", name];
+
+ for (let [key, val] in Iterator(attr)) {
+ if (Set.has(skipAttr, key))
+ continue;
+
+ let vals = parseNamespace(key);
+ if (typeof val == "function") {
+ key = key.replace(/^(?:on)?/, "on");
+ val = val.toSource() + "(event)";
+ }
+
+ if (key != "highlight" || vals[0] == String(NS))
+ res.push(" ", key, '="', DOM.escapeHTML(val), '"');
+ else
+ res.push(" ", namespaced(namespaces, String(NS), "highlight"),
+ '="', DOM.escapeHTML(val), '"');
+ }
+
+ if ((vals[0] || namespaces[""]) == String(XHTML) && Set.has(EMPTY, vals[1])
+ || asXML && !args.length)
+ res.push("/>");
+ else {
+ res.push(">");
+
+ if (isStrings(args))
+ res.push(args.map(function (e) tag(e, namespaces, "")).join(""),
+ "</", name, ">");
+ else {
+ let contents = [];
+ args.forEach(function(e) {
+ let string = tag(e, namespaces, indent + INDENT);
+ if (string)
+ contents.push(string);
+ });
+
+ res.push("\n", contents.join("\n"), "\n", indent, "</", name, ">");
+ }
+ }
+
+ return res.join("");
+ }
+
+ if (namespaces)
+ namespaces = update({}, DOM.fromJSON.namespaces, namespaces);
+ else
+ namespaces = DOM.fromJSON.namespaces;
+
+ return tag(xml, namespaces, "")
+ },
+
+ parseNamespace: function parseNamespace(name, namespaces) {
+ if (name == "xmlns")
+ return [DOM.fromJSON.namespaces.xmlns, "xmlns"];
+
+ var m = /^(?:(.*):)?(.*)$/.exec(name);
+ return [(namespaces || DOM.fromJSON.namespaces)[m[1]],
+ m[2]];
},
/**
},
namespaces: {
- xul: XUL.uri,
- xhtml: XHTML.uri,
- html: XHTML.uri,
+ xul: XUL,
+ xhtml: XHTML,
+ html: XHTML,
xhtml2: "http://www.w3.org/2002/06/xhtml2",
- dactyl: NS.uri
+ dactyl: NS
},
namespaceNames: Class.Memoize(function ()
-// Copyright (c) 2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2011-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("downloads", {
- exports: ["Download", "Downloads", "downloads"]
-}, this);
+ exports: ["Download", "Downloads", "downloads"],
+ require: ["util"]
+});
-this.lazyRequire("overlay", ["overlay"]);
+lazyRequire("overlay", ["overlay"]);
Cu.import("resource://gre/modules/DownloadUtils.jsm", this);
+var MAX_LOAD_TIME = 10 * 1000;
+
let prefix = "DOWNLOAD_";
var states = iter([v, k.slice(prefix.length).toLowerCase()]
for ([k, v] in Iterator(Ci.nsIDownloadManager))
this.nodes = {
commandTarget: self
};
- XML.ignoreWhitespace = true;
- XML.prettyPrinting = false;
- util.xmlToDom(
- <tr highlight="Download" key="row" xmlns:dactyl={NS} xmlns={XHTML}>
- <td highlight="DownloadTitle">
- <span highlight="Link">
- <a key="launch"
- href={self.target.spec} path={self.targetFile.path}>{self.displayName}</a>
- <span highlight="LinkInfo">{self.targetFile.path}</span>
- </span>
- </td>
- <td highlight="DownloadState" key="state"/>
- <td highlight="DownloadButtons Buttons">
- <a highlight="Button" href="javascript:0" key="pause">{_("download.action.Pause")}</a>
- <a highlight="Button" href="javascript:0" key="remove">{_("download.action.Remove")}</a>
- <a highlight="Button" href="javascript:0" key="resume">{_("download.action.Resume")}</a>
- <a highlight="Button" href="javascript:0" key="retry">{_("download.action.Retry")}</a>
- <a highlight="Button" href="javascript:0" key="cancel">{_("download.action.Cancel")}</a>
- <a highlight="Button" href="javascript:0" key="delete">{_("download.action.Delete")}</a>
- </td>
- <td highlight="DownloadProgress" key="progress">
- <span highlight="DownloadProgressHave" key="progressHave"
- />/<span highlight="DownloadProgressTotal" key="progressTotal"/>
- </td>
- <td highlight="DownloadPercent" key="percent"/>
- <td highlight="DownloadSpeed" key="speed"/>
- <td highlight="DownloadTime" key="time"/>
- <td><a highlight="DownloadSource" key="source" href={self.source.spec}>{self.source.spec}</a></td>
- </tr>,
+ DOM.fromJSON(
+ ["tr", { highlight: "Download", key: "row" },
+ ["td", { highlight: "DownloadTitle" },
+ ["span", { highlight: "Link" },
+ ["a", { key: "launch", href: self.target.spec, path: self.targetFile.path },
+ self.displayName],
+ ["span", { highlight: "LinkInfo" },
+ self.targetFile.path]]],
+ ["td", { highlight: "DownloadState", key: "state" }],
+ ["td", { highlight: "DownloadButtons Buttons" },
+ ["a", { highlight: "Button", href: "javascript:0", key: "pause" }, _("download.action.Pause")],
+ ["a", { highlight: "Button", href: "javascript:0", key: "remove" }, _("download.action.Remove")],
+ ["a", { highlight: "Button", href: "javascript:0", key: "resume" }, _("download.action.Resume")],
+ ["a", { highlight: "Button", href: "javascript:0", key: "retry" }, _("download.action.Retry")],
+ ["a", { highlight: "Button", href: "javascript:0", key: "cancel" }, _("download.action.Cancel")],
+ ["a", { highlight: "Button", href: "javascript:0", key: "delete" }, _("download.action.Delete")]],
+ ["td", { highlight: "DownloadProgress", key: "progress" },
+ ["span", { highlight: "DownloadProgressHave", key: "progressHave" }],
+ "/",
+ ["span", { highlight: "DownloadProgressTotal", key: "progressTotal" }]],,
+ ["td", { highlight: "DownloadPercent", key: "percent" }],
+ ["td", { highlight: "DownloadSpeed", key: "speed" }],
+ ["td", { highlight: "DownloadTime", key: "time" }],
+ ["td", {},
+ ["a", { highlight: "DownloadSource", key: "source", href: self.source.spec },
+ self.source.spec]]],
this.list.document, this.nodes);
this.nodes.launch.addEventListener("click", function (event) {
function action() {
try {
if (this.MIMEInfo && this.MIMEInfo.preferredAction == this.MIMEInfo.useHelperApp)
- this.MIMEInfo.launchWithFile(file);
+ this.MIMEInfo.launchWithFile(file.file);
else
file.launch();
}
message: Class.Memoize(function () {
- XML.ignoreWhitespace = true;
- XML.prettyPrinting = false;
- util.xmlToDom(<table highlight="Downloads" key="list" xmlns={XHTML}>
- <tr highlight="DownloadHead" key="head">
- <span>{_("title.Title")}</span>
- <span>{_("title.Status")}</span>
- <span/>
- <span>{_("title.Progress")}</span>
- <span/>
- <span>{_("title.Speed")}</span>
- <span>{_("title.Time remaining")}</span>
- <span>{_("title.Source")}</span>
- </tr>
- <tr highlight="Download"><span><div style="min-height: 1ex; /* FIXME */"/></span></tr>
- <tr highlight="Download" key="totals" active="true">
- <td><span highlight="Title">{_("title.Totals")}:</span> <span key="total"/></td>
- <td/>
- <td highlight="DownloadButtons">
- <a highlight="Button" href="javascript:0" key="clear">{_("download.action.Clear")}</a>
- </td>
- <td highlight="DownloadProgress" key="progress">
- <span highlight="DownloadProgressHave" key="progressHave"
- />/<span highlight="DownloadProgressTotal" key="progressTotal"/>
- </td>
- <td highlight="DownloadPercent" key="percent"/>
- <td highlight="DownloadSpeed" key="speed"/>
- <td highlight="DownloadTime" key="time"/>
- <td/>
- </tr>
- </table>, this.document, this.nodes);
+ DOM.fromJSON(["table", { highlight: "Downloads", key: "list" },
+ ["tr", { highlight: "DownloadHead", key: "head" },
+ ["span", {}, _("title.Title")],
+ ["span", {}, _("title.Status")],
+ ["span"],
+ ["span", {}, _("title.Progress")],
+ ["span"],
+ ["span", {}, _("title.Speed")],
+ ["span", {}, _("title.Time remaining")],
+ ["span", {}, _("title.Source")]],
+ ["tr", { highlight: "Download" },
+ ["span", {},
+ ["div", { style: "min-height: 1ex; /* FIXME */" }]]],
+ ["tr", { highlight: "Download", key: "totals", active: "true" },
+ ["td", {},
+ ["span", { highlight: "Title" },
+ _("title.Totals") + ":"],
+ " ",
+ ["span", { key: "total" }]],
+ ["td"],
+ ["td", { highlight: "DownloadButtons" },
+ ["a", { highlight: "Button", href: "javascript:0", key: "clear" }, _("download.action.Clear")]],
+ ["td", { highlight: "DownloadProgress", key: "progress" },
+ ["span", { highlight: "DownloadProgressHave", key: "progressHave" }],
+ "/",
+ ["span", { highlight: "DownloadProgressTotal", key: "progressTotal" }]],
+ ["td", { highlight: "DownloadPercent", key: "percent" }],
+ ["td", { highlight: "DownloadSpeed", key: "speed" }],
+ ["td", { highlight: "DownloadTime", key: "time" }],
+ ["td"]]],
+ this.document, this.nodes);
this.index = Array.indexOf(this.nodes.list.childNodes,
this.nodes.head);
+ let start = Date.now();
for (let row in iter(services.downloadManager.DBConnection
- .createStatement("SELECT id FROM moz_downloads")))
+ .createStatement("SELECT id FROM moz_downloads"))) {
+ if (Date.now() - start > MAX_LOAD_TIME) {
+ util.dactyl.warn(_("download.givingUpAfter", (Date.now() - start) / 1000));
+ break;
+ }
this.addDownload(row.id);
+ }
this.update();
util.addObserver(this);
services.downloadManager.addListener(this);
},
- destroy: function destroy() {
+ cleanup: function destroy() {
services.downloadManager.removeListener(this);
},
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("finder", {
exports: ["RangeFind", "RangeFinder", "rangefinder"],
- require: ["prefs"]
-}, this);
+ require: ["prefs", "util"]
+});
-this.lazyRequire("buffer", ["Buffer"]);
-this.lazyRequire("overlay", ["overlay"]);
+lazyRequire("buffer", ["Buffer"]);
+lazyRequire("overlay", ["overlay"]);
-function equals(a, b) XPCNativeWrapper(a) == XPCNativeWrapper(b);
+function id(w) w.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils)
+ .outerWindowID;
+function equals(a, b) id(a) == id(b);
/** @instance rangefinder */
var RangeFinder = Module("rangefinder", {
get onSubmit() modules.rangefinder.closure.onSubmit
});
},
- mappings: function (dactyl, modules, window) {
+ mappings: function initMappings(dactyl, modules, window) {
const { Buffer, buffer, config, mappings, modes, rangefinder } = modules;
var myModes = config.browserModes.concat([modes.CARET]);
});
},
- options: function (dactyl, modules, window) {
+ options: function initOptions(dactyl, modules, window) {
const { options, rangefinder } = modules;
options.add(["hlfind", "hlf"],
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("help", {
exports: ["help"],
require: ["cache", "dom", "protocol", "services", "util"]
-}, this);
+});
-this.lazyRequire("completion", ["completion"]);
-this.lazyRequire("overlay", ["overlay"]);
+lazyRequire("completion", ["completion"]);
+lazyRequire("overlay", ["overlay"]);
+lazyRequire("template", ["template"]);
var HelpBuilder = Class("HelpBuilder", {
init: function init() {
{ mimeType: "text/plain;charset=UTF-8" })
.responseText;
- let re = util.regexp(UTF8(<![CDATA[
+ let re = util.regexp(UTF8(literal(/*
^ (?P<comment> \s* # .*\n)
| ^ (?P<space> \s*)
)
| (?: ^ [^\S\n]* \n) +
- ]]>), "gmxy");
+ */)), "gmxy");
let betas = util.regexp(/\[((?:b|rc)\d)\]/, "gx");
.map(function (m) m[1]).uniq().slice(-1)[0];
- default xml namespace = NS;
function rec(text, level, li) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
-
- let res = <></>;
+ let res = [];
let list, space, i = 0;
continue;
else if (match.char) {
if (!list)
- res += list = <ul/>;
- let li = <li/>;
- li.* += rec(match.content.replace(RegExp("^" + match.space, "gm"), ""), level + 1, li);
- list.* += li;
+ res.push(list = ["ul", {}]);
+ let li = ["li", {}];
+ li.push(rec(match.content
+ .replace(RegExp("^" + match.space, "gm"), ""),
+ level + 1,
+ li));
+ list.push(li);
}
else if (match.par) {
let [, par, tags] = /([^]*?)\s*((?:\[[^\]]+\])*)\n*$/.exec(match.par);
let group = !tags.length ? "" :
!tags.some(function (t) t == beta) ? "HelpNewsOld" : "HelpNewsNew";
if (i === 0 && li) {
- li.@highlight = group;
+ li[1]["dactyl:highlight"] = group;
group = "";
}
list = null;
if (level == 0 && /^.*:\n$/.test(match.par)) {
let text = par.slice(0, -1);
- res += <h2 tag={"news-" + text}>{template.linkifyHelp(text, true)}</h2>;
+ res.push(["h2", { tag: "news-" + text },
+ template.linkifyHelp(text, true)]);
}
else {
let [, a, b] = /^(IMPORTANT:?)?([^]*)/.exec(par);
- res += <p highlight={group + " HelpNews"}>{
- !tags.length ? "" :
- <hl key="HelpNewsTag">{tags.join(" ")}</hl>
- }{
- a ? <hl key="HelpWarning">{a}</hl> : ""
- }{
- template.linkifyHelp(b, true)
- }</p>;
+
+ res.push(["p", { "dactyl:highlight": group + " HelpNews" },
+ !tags.length ? "" : ["hl", { key: "HelpNewsTag" }, tags.join(" ")],
+ a ? ["hl", { key: "HelpWarning" }, a] : "",
+ template.linkifyHelp(b, true)]);
}
}
i++;
}
- for each (let attr in res..@highlight) {
- attr.parent().@NS::highlight = attr;
- delete attr.parent().@highlight;
- }
+
return res;
}
- XML.ignoreWhitespace = XML.prettyPrinting = false;
let body = rec(NEWS, 0);
- for each (let li in body..li) {
- let list = li..li.(@NS::highlight == "HelpNewsOld");
- if (list.length() && list.length() == li..li.(@NS::highlight != "").length()) {
- for each (let li in list)
- li.@NS::highlight = "";
- li.@NS::highlight = "HelpNewsOld";
- }
- }
+
+ // E4X-FIXME
+ // for each (let li in body..li) {
+ // let list = li..li.(@NS::highlight == "HelpNewsOld");
+ // if (list.length() && list.length() == li..li.(@NS::highlight != "").length()) {
+ // for each (let li in list)
+ // li.@NS::highlight = "";
+ // li.@NS::highlight = "HelpNewsOld";
+ // }
+ // }
return '<?xml version="1.0"?>\n' +
'<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>\n' +
- '<!DOCTYPE document SYSTEM "resource://dactyl-content/dactyl.dtd">\n' +
- <document xmlns={NS} xmlns:dactyl={NS}
- name="versions" title={config.appName + " Versions"}>
- <h1 tag="versions news NEWS">{config.appName} Versions</h1>
- <toc start="2"/>
-
- {body}
- </document>.toXMLString()
+ DOM.toXML(["document", { xmlns: "dactyl", name: "versions",
+ title: config.appName + " Versions" },
+ ["h1", { tag: "versions news NEWS" }, config.appName + " Versions"],
+ ["toc", { start: "2" }],
+
+ body]);
});
},
init: function init() {
dactyl.commands["dactyl.help"] = function (event) {
let elem = event.originalTarget;
- help.help(elem.getAttribute("tag") || elem.textContent);
+ modules.help.help(elem.getAttribute("tag") || elem.textContent);
};
},
var addURIEntry = function addURIEntry(file, uri) addDataEntry(file, util.httpGet(uri).responseText);
}
else {
- var zip = services.ZipWriter(FILE, File.MODE_CREATE | File.MODE_WRONLY | File.MODE_TRUNCATE);
+ var zip = services.ZipWriter(FILE.file, File.MODE_CREATE | File.MODE_WRONLY | File.MODE_TRUNCATE);
addURIEntry = function addURIEntry(file, uri)
zip.addEntryChannel(PATH + file, TIME, 9,
if (isinstance(node, [Ci.nsIDOMHTMLBaseElement]))
return;
- data.push("<"); data.push(node.localName);
+ data.push("<", node.localName);
if (node instanceof Ci.nsIDOMHTMLHtmlElement)
- data.push(" xmlns=" + XHTML.uri.quote(),
- " xmlns:dactyl=" + NS.uri.quote());
+ data.push(" xmlns=" + XHTML.quote(),
+ " xmlns:dactyl=" + NS.quote());
for (let { name, value } in array.iterValues(node.attributes)) {
if (name == "dactyl:highlight") {
value = value.replace(/.*\//, "");
}
- data.push(" ", name, '="',
- <>{value}</>.toXMLString().replace(/"/g, """),
- '"');
+ data.push(" ", name, '="', DOM.escapeHTML(value), '"');
}
if (node.localName in empty)
data.push(" />");
else {
data.push(">");
if (node instanceof Ci.nsIDOMHTMLHeadElement)
- data.push(<link rel="stylesheet" type="text/css" href="help.css"/>.toXMLString());
+ data.push('<link rel="stylesheet" type="text/css" href="help.css"/>');
Array.map(node.childNodes, fix);
data.push("</", node.localName, ">");
}
break;
case Ci.nsIDOMNode.TEXT_NODE:
- data.push(<>{node.textContent}</>.toXMLString());
+ data.push(DOM.escapeHTML(node.textContent, true));
}
}
})
}, {
}, {
- commands: function init_commands(dactyl, modules, window) {
+ commands: function initCommands(dactyl, modules, window) {
const { commands, completion, help } = modules;
[
});
});
},
- completion: function init_completion(dactyl, modules, window) {
+ completion: function initCompletion(dactyl, modules, window) {
const { completion } = modules;
completion.help = function completion_help(context, consolidated) {
context.keys = { text: 0, description: function () "all" };
};
},
- mappings: function init_mappings(dactyl, modules, window) {
- const { help, mappings, modes } = modules;
-
- mappings.add([modes.MAIN], ["<open-help>", "<F1>"],
- "Open the introductory help page",
- function () { help.help(); });
-
- mappings.add([modes.MAIN], ["<open-single-help>", "<A-F1>"],
- "Open the single, consolidated help page",
- function () { modules.ex.helpall(); });
- },
- javascript: function init_javascript(dactyl, modules, window) {
+ javascript: function initJavascript(dactyl, modules, window) {
modules.JavaScript.setCompleter([modules.help.exportHelp],
[function (context, args) overlay.activeModules.completion.file(context)]);
}
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("highlight", {
exports: ["Highlight", "Highlights", "highlight"],
require: ["services", "util"]
-}, this);
+});
-this.lazyRequire("styles", ["Styles", "styles"]);
+lazyRequire("styles", ["Styles", "styles"]);
+lazyRequire("template", ["template"]);
var Highlight = Struct("class", "selector", "sites",
"defaultExtends", "defaultValue",
* @param {string} group
*/
highlightNode: function highlightNode(node, group, applyBindings) {
- node.setAttributeNS(NS.uri, "highlight", group);
+ node.setAttributeNS(NS, "highlight", group);
let groups = group.split(" ");
for each (let group in groups)
(self.highlight[hl] && self.highlight[hl].class != class_
? self.highlight[hl].selector : "[dactyl|highlight~=" + hl + "]")),
- groupRegexp: util.regexp(<![CDATA[
+ groupRegexp: util.regexp(literal(/*
^
(\s* (?:\S|\s\S)+ \s+)
\{ ([^}]*) \}
\s*
$
- ]]>, "gmx"),
- sheetRegexp: util.regexp(<![CDATA[
+ */), "gmx"),
+ sheetRegexp: util.regexp(literal(/*
^\s*
!? \*?
(?P<group> (?:[^;\s]|\s[^;\s])+ )
(?:; (?P<extends> (?:[^;\s]|\s[^;\s])+ )? )?
\s* (?P<css> .*)
$
- ]]>, "x"),
+ */), "x"),
+ // </css>
/**
* Bulk loads new CSS rules, in the format of,
commands.add(["hi[ghlight]"],
"Set the style of certain display elements",
function (args) {
- let style = <![CDATA[
+ let style = literal(/*
;
display: inline-block !important;
position: static !important;
width: 3em !important; min-width: 3em !important; max-width: 3em !important;
height: 1em !important; min-height: 1em !important; max-height: 1em !important;
overflow: hidden !important;
- ]]>;
+ */);
let clear = args[0] == "clear";
if (clear)
args.shift();
["padding: 0 1em 0 0; vertical-align: top; max-width: 16em; overflow: hidden;",
"text-align: center"],
([h.class,
- <span style={"text-align: center; line-height: 1em;" + h.value + style}>XXX</span>,
- template.map(h.extends, function (s) template.highlight(s), <>,</>),
+ ["span", { style: "text-align: center; line-height: 1em;" + h.value + style }, "XXX"],
+ template.map(h.extends, function (s) template.highlight(s), ","),
template.highlightRegexp(h.value, /\b[-\w]+(?=:)|\/\*.*?\*\//g,
- function (match) <span highlight={match[0] == "/" ? "Comment" : "Key"}>{match}</span>)
+ function (match) ["span", { highlight: match[0] == "/" ? "Comment" : "Key" }, match])
]
for (h in highlight)
if (!key || h.class.indexOf(key) > -1))));
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
-// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2007-2012 by Doug Kearns <dougkearns@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
// Some code based on Venkman
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("io", {
exports: ["IO", "io"],
require: ["services"]
-}, this);
+});
-this.lazyRequire("config", ["config"]);
-this.lazyRequire("contexts", ["Contexts", "contexts"]);
+lazyRequire("config", ["config"]);
+lazyRequire("contexts", ["Contexts", "contexts"]);
+lazyRequire("storage", ["File", "storage"]);
+lazyRequire("styles", ["styles"]);
+lazyRequire("template", ["template"]);
// TODO: why are we passing around strings rather than file objects?
/**
dactyl.triggerObserver("io.source", context, file, file.lastModifiedTime);
}
- if (/\.js,$/.test(filename))
+ if (/\.jsm$/.test(filename))
sourceJSM();
else if (/\.js$/.test(filename)) {
try {
sourceJSM();
}
else {
+ if (e instanceof Finished)
+ return;
if (e.fileName && !(e instanceof FailedAssertion))
try {
e.fileName = util.fixURI(e.fileName);
if (e.fileName == uri.spec)
e.fileName = filename;
- e.echoerr = <>{e.fileName}:{e.lineNumber}: {e}</>;
+ e.echoerr = [e.fileName, ":", e.lineNumber, ": ", e].join("");
}
catch (e) {}
throw e;
file = util.getFile(file);
if (file && file.exists() && file.isFile() && file.isReadable()) {
// let jar = services.zipReader.getZip(file); Crashes.
- let jar = services.ZipReader(file);
+ let jar = services.ZipReader(file.file);
try {
let filter = RegExp("^" + util.regexp.escape(decodeURI(path))
+ "[^/]*/?$");
return -1;
}
- let process = services.Process(file);
+ let process = services.Process(file.file);
process.run(false, args.map(String), args.length);
try {
if (callable(blocking))
*/
PATH_SEP: deprecated("File.PATH_SEP", { get: function PATH_SEP() File.PATH_SEP })
}, {
- commands: function init_commands(dactyl, modules, window) {
+ commands: function initCommands(dactyl, modules, window) {
const { commands, completion, io } = modules;
commands.add(["cd", "chd[ir]"],
try {
file.write(lines.join("\n"));
+ dactyl.echomsg(_("io.writing", file.path.quote()), 2);
}
catch (e) {
dactyl.echoerr(_("io.notWriteable", file.path.quote()));
completer: function (context) completion.file(context, true)
});
- commands.add(["mks[yntax]"],
- "Generate a Vim syntax file",
+ commands.add(["mkv[imruntime]"],
+ "Create and install Vim runtime files for " + config.appName,
function (args) {
- let runtime = config.OS.isWindows ? "~/vimfiles/" : "~/.vim/";
- let file = io.File(runtime + "syntax/" + config.name + ".vim");
- if (args.length)
- file = io.File(args[0]);
+ dactyl.assert(args.length <= 1, _("io.oneFileAllowed"));
+
+ if (args.length) {
+ var rtDir = io.File(args[0]);
+ dactyl.assert(rtDir.exists(), _("io.noSuchDir", rtDir.path.quote()));
+ }
+ else
+ rtDir = io.File(config.OS.isWindows ? "~/vimfiles/" : "~/.vim/");
+
+ dactyl.assert(!rtDir.exists() || rtDir.isDirectory(), _("io.eNotDir", rtDir.path.quote()));
+
+ let rtItems = { ftdetect: {}, ftplugin: {}, syntax: {} };
+
+ // require bang if any of the paths exist
+ for (let [type, item] in iter(rtItems)) {
+ let file = io.File(rtDir).child(type, config.name + ".vim");
+ dactyl.assert(!file.exists() || args.bang, _("io.exists", file.path.quote()));
+ item.file = file;
+ }
+
+ rtItems.ftdetect.template = // {{{
+literal(/*" Vim filetype detection file
+<header>
+
+au BufNewFile,BufRead *<name>rc*,*.<fileext> set filetype=<name>
+*/);//}}}
+ rtItems.ftplugin.template = // {{{
+literal(/*" Vim filetype plugin file
+<header>
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
- if (file.exists() && file.isDirectory() || args[0] && /\/$/.test(args[0]))
- file.append(config.name + ".vim");
- dactyl.assert(!file.exists() || args.bang, _("io.exists"));
+let b:undo_ftplugin = "setl com< cms< fo< ofu< | unlet! b:browsefilter"
- let template = util.compileMacro(<![CDATA[
-" Vim syntax file
-" Language: Pentadactyl configuration file
-" Maintainer: Doug Kearns <dougkearns@gmail.com>
+setlocal comments=:\"
+setlocal commentstring=\"%s
+setlocal formatoptions-=t formatoptions+=croql
+setlocal omnifunc=syntaxcomplete#Complete
+
+if has("gui_win32") && !exists("b:browsefilter")
+ let b:browsefilter = "<appname> Config Files (*.<fileext>)\t*.<fileext>\n" .
+ \ "All Files (*.*)\t*.*\n"
+endif
-" TODO: make this <name> specific - shared dactyl config?
+let &cpo = s:cpo_save
+unlet s:cpo_save
+*/);//}}}
+ rtItems.syntax.template = // {{{
+literal(/*" Vim syntax file
+<header>
if exists("b:current_syntax")
finish
let &cpo = s:cpo_save
unlet s:cpo_save
-" vim: tw=130 et ts=4 sw=4:
-]]>, true);
+" vim: tw=130 et ts=8 sts=4 sw=4:
+*/);//}}}
+
+ const { options } = modules;
const WIDTH = 80;
- function wrap(prefix, items, sep) {
+ function wrap(prefix, items, sep) {//{{{
sep = sep || " ";
let width = 0;
let lines = [];
}
lines.last.pop();
return lines.map(function (l) l.join("")).join("\n").replace(/\s+\n/gm, "\n");
- }
+ }//}}}
- const { commands, options } = modules;
- file.write(template({
+ let params = { // {{{
+ header: ['" Language: ' + config.appName + ' configuration file',
+ '" Maintainer: Doug Kearns <dougkearns@gmail.com>',
+ '" Version: ' + config.version].join("\n"),
name: config.name,
+ appname: config.appName,
+ fileext: config.fileExtension,
+ maintainer: "Doug Kearns <dougkearns@gmail.com>",
autocommands: wrap("syn keyword " + config.name + "AutoEvent ",
keys(config.autocommands)),
commands: wrap("syn keyword " + config.name + "Command ",
array(o.realNames for (o in options) if (o.type == "boolean"))
.flatten().map(String.quote),
", ") + "]"
- }));
+ }; // }}}
+
+ for (let { file, template } in values(rtItems)) {
+ try {
+ file.write(util.compileMacro(template, true)(params));
+ dactyl.echomsg(_("io.writing", file.path.quote()), 2);
+ }
+ catch (e) {
+ dactyl.echoerr(_("io.notWriteable", file.path.quote()));
+ dactyl.log(_("error.notWriteable", file.path, e.message));
+ }
+ }
}, {
argCount: "?",
bang: true,
- completer: function (context) completion.file(context, true),
+ completer: function (context) completion.directory(context, true),
literal: 1
});
result.output += "\n" + _("io.shellReturn", result.returnValue);
modules.commandline.command = args.commandName.replace("run", "$& ") + arg;
- modules.commandline.commandOutput(<span highlight="CmdOutput">{result.output}</span>);
+ modules.commandline.commandOutput(["span", { highlight: "CmdOutput" }, result.output]);
modules.autocommands.trigger("ShellCmdPost", {});
}, {
literal: 0
});
},
- completion: function init_completion(dactyl, modules, window) {
+ completion: function initCompletion(dactyl, modules, window) {
const { completion, io } = modules;
completion.charset = function (context) {
};
completion.addUrlCompleter("file", "Local files", function (context, full) {
- let match = util.regexp(<![CDATA[
+ let match = util.regexp(literal(/*
^
(?P<prefix>
(?P<proto>
)
(?P<path> \/[^\/]* )?
$
- ]]>, "x").exec(context.filter);
+ */), "x").exec(context.filter);
if (match) {
if (!match.path) {
context.key = match.proto;
completion.file(context, full);
});
},
- javascript: function init_javascript(dactyl, modules, window) {
+ javascript: function initJavascript(dactyl, modules, window) {
modules.JavaScript.setCompleter([File, File.expandPath],
[function (context, obj, args) {
context.quote[2] = "";
input: true
});
},
- options: function init_options(dactyl, modules, window) {
+ options: function initOptions(dactyl, modules, window) {
const { completion, options } = modules;
var shell, shellcmdflag;
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
let { getOwnPropertyNames } = Object;
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("javascript", {
exports: ["JavaScript", "javascript"],
require: ["util"]
-}, this);
+});
+
+lazyRequire("template", ["template"]);
let isPrototypeOf = Object.prototype.isPrototypeOf;
context[JavaScript.EVAL_TMP] = tmp;
try {
- cache[key] = this.modules.dactyl.userEval(arg, context, /*L*/"[Command Line Completion]", 1);
+ cache[key] = this.modules.dactyl.userEval(arg, context,
+ /*L*/"[Command Line Completion]", 1);
return cache[key];
}
let [, prefix, args] = /^(function .*?)\((.*?)\)/.exec(Function.prototype.toString.call(func));
let n = this._get(i).comma.length;
args = template.map(Iterator(args.split(", ")),
- function ([i, arg]) <span highlight={i == n ? "Filter" : ""}>{arg}</span>,
- <>, </>);
- this.context.message = <>{prefix}({args})</>;
+ function ([i, arg]) ["span", { highlight: i == n ? "Filter" : "" }, arg],
+ ",\u00a0");
+ this.context.message = ["", prefix + "(", args, ")"];
}
}
}
if (!this.context.tabPressed && key == "" && obj.length > 1) {
let message = this.context.message || "";
this.context.waitingForTab = true;
- this.context.message = <>{message}
- {_("completion.waitingForKeyPress")}</>;
+ this.context.message = ["", message, "\n",
+ _("completion.waitingForKeyPress")];
return null;
}
},
addOutput: function addOutput(js) {
- default xml namespace = XHTML;
this.count++;
try {
if (e.fileName)
e = util.fixURI(e.fileName) + ":" + e.lineNumber + ": " + e;
- xml = <span highlight="ErrorMsg">{e}</span>;
+ xml = ["span", { highlight: "ErrorMsg" }, e];
}
let prompt = "js" + this.count;
Class.replaceProperty(this.context, prompt, result);
- XML.ignoreWhitespace = XML.prettyPrinting = false;
let nodes = {};
this.rootNode.appendChild(
- util.xmlToDom(<e4x>
- <div highlight="REPL-E" key="e"><span highlight="REPL-R">{prompt}></span> {js}</div>
- <div highlight="REPL-P" key="p">{xml}</div>
- </e4x>.elements(), this.document, nodes));
+ DOM.fromJSON(
+ [["div", { highlight: "REPL-E", key: "e" },
+ ["span", { highlight: "REPL-R" },
+ prompt, ">"], " ", js],
+ ["div", { highlight: "REPL-P", key: "p" },
+ xml]],
+ this.document, nodes));
this.rootNode.scrollTop += nodes.e.getBoundingClientRect().top
- this.rootNode.getBoundingClientRect().top;
count: 0,
message: Class.Memoize(function () {
- default xml namespace = XHTML;
- util.xmlToDom(<div highlight="REPL" key="rootNode"/>,
+ DOM.fromJSON(["div", { highlight: "REPL", key: "rootNode" }],
this.document, this);
return this.rootNode;
bind(["<C-b>", "<PageUp>"], "Scroll up half a page",
function ({ self }) { self.repl.scrollVertical("pages", -1); });
},
- options: function (dactyl, modules, window) {
+ options: function initOptions(dactyl, modules, window) {
modules.options.add(["jsdebugger", "jsd"],
"Enable the JavaScript debugger service for use in JavaScript completion",
"boolean", false, {
-// Copyright (c) 2009-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2009-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("main", {
exports: ["ModuleBase"],
require: ["config", "overlay", "services", "util"]
-}, this);
+});
var BASE = "resource://dactyl-content/";
Module.list = [];
Module.constructors = {};
- const create = window.Object.create || (function () {
- window.__dactyl_eval_string = "(function (proto) ({ __proto__: proto }))";
- JSMLoader.loadSubScript(BASE + "eval.js", window);
-
- let res = window.__dactyl_eval_result;
- delete window.__dactyl_eval_string;
- delete window.__dactyl_eval_result;
- return res;
- })();
+ const create = window.Object.create.bind(window.Object);
const BASES = [BASE, "resource://dactyl-local-content/"];
- const jsmodules = { NAME: "jsmodules" };
+ jsmodules = Cu.createObjectIn(window);
+ jsmodules.NAME = "jsmodules";
const modules = update(create(jsmodules), {
yes_i_know_i_should_not_report_errors_in_these_branches_thanks: [],
}
}
try {
- require(jsmodules, script);
+ require(script, jsmodules);
}
catch (e) {
util.dump("Loading script " + script + ":");
wantXrays: false });
// Hack:
- sandbox.Object = jsmodules.Object;
+ // sandbox.Object = jsmodules.Object;
sandbox.File = jsmodules.File;
sandbox.Math = jsmodules.Math;
sandbox.__proto__ = proto || modules;
defineModule.time("load", null, function _load() {
config.modules.global
- .forEach(function (name) defineModule.time("load", name, require, null, modules.jsmodules, name));
+ .forEach(function (name) {
+ if (!isArray(name))
+ defineModule.time("load", name, require, null, name, modules.jsmodules);
+ else
+ lazyRequire(name[0], name.slice(1), modules.jsmodules);
+ });
config.modules.window
.forEach(function (name) defineModule.time("load", name, modules.load, modules, name));
-// Copyright (c) 2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2011-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-try {
-
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("messages", {
exports: ["Messages", "messages", "_"],
require: ["services", "util"]
-}, this);
+});
var Messages = Module("messages", {
endModule();
-} catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
+// catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
// vim: set fdm=marker sw=4 ts=4 et ft=javascript:
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("options", {
exports: ["Option", "Options", "ValueError", "options"],
require: ["contexts", "messages", "storage"]
-}, this);
+});
-this.lazyRequire("config", ["config"]);
+lazyRequire("cache", ["cache"]);
+lazyRequire("config", ["config"]);
+lazyRequire("commands", ["Commands"]);
+lazyRequire("completion", ["CompletionContext"]);
+lazyRequire("prefs", ["prefs"]);
+lazyRequire("styles", ["Styles"]);
+lazyRequire("template", ["template"]);
/** @scope modules */
function opts(opt) {
for (let opt in Iterator(this)) {
+ if (filter && !filter(opt))
+ continue;
+ if (!(opt.scope & scope))
+ continue;
+
let option = {
__proto__: opt,
isDefault: opt.isDefault,
default: opt.stringDefaultValue,
pre: "\u00a0\u00a0", // Unicode nonbreaking space.
- value: <></>
+ value: []
};
- if (filter && !filter(opt))
- continue;
- if (!(opt.scope & scope))
- continue;
-
if (opt.type == "boolean") {
if (!opt.value)
option.pre = "no";
option.default = (opt.defaultValue ? "" : "no") + opt.name;
}
else if (isArray(opt.value) && opt.type != "charlist")
- option.value = <>={template.map(opt.value,
- function (v) template.highlight(String(v)),
- <>,<span style="width: 0; display: inline-block"> </span></>)}</>;
+ option.value = ["", "=",
+ template.map(opt.value,
+ function (v) template.highlight(String(v)),
+ ["", ",",
+ ["span", { style: "width: 0; display: inline-block" }, " "]])];
else
- option.value = <>={template.highlight(opt.stringValue)}</>;
+ option.value = ["", "=", template.highlight(opt.stringValue)];
yield option;
}
};
- modules.commandline.commandOutput(template.options("Options", opts.call(this), this["verbose"] > 0));
+ modules.commandline.commandOutput(
+ template.options("Options", opts.call(this), this["verbose"] > 0));
},
cleanup: function cleanup() {
commands: function initCommands(dactyl, modules, window) {
const { commands, contexts, options } = modules;
- let args = {
- getMode: function (args) findMode(args["-mode"]),
- iterate: function (args) {
- for (let map in mappings.iterate(this.getMode(args)))
- for (let name in values(map.names))
- yield { name: name, __proto__: map };
- },
- format: {
- description: function (map) (XML.ignoreWhitespace = false, XML.prettyPrinting = false, <>
- {options.get("passkeys").has(map.name)
- ? <span highlight="URLExtra">({
- tempate.linkifyHelp(_("option.passkeys.passedBy"))
- })</span>
- : <></>}
- {template.linkifyHelp(map.description)}
- </>)
- }
- };
-
dactyl.addUsageCommand({
name: ["listo[ptions]", "lo"],
description: "List all options along with their short descriptions",
index: "option",
iterate: function (args) options,
format: {
- description: function (opt) (XML.ignoreWhitespace = false, XML.prettyPrinting = false, <>
- {opt.scope == Option.SCOPE_LOCAL
- ? <span highlight="URLExtra">({_("option.bufferLocal")})</span> : ""}
- {template.linkifyHelp(opt.description)}
- </>),
+ description: function (opt) [
+ opt.scope == Option.SCOPE_LOCAL
+ ? ["span", { highlight: "URLExtra" },
+ "(" + _("option.bufferLocal") + ")"]
+ : "",
+ template.linkifyHelp(opt.description)
+ ],
help: function (opt) "'" + opt.name + "'"
}
});
function fmt(value) (typeof value == "number" ? "#" :
typeof value == "function" ? "*" :
" ") + value;
- if (!args || args == "g:") {
- let str =
- <table>
- {
- template.map(globalVariables, function ([i, value]) {
- return <tr>
- <td style="width: 200px;">{i}</td>
- <td>{fmt(value)}</td>
- </tr>;
- })
- }
- </table>;
- if (str.text().length() == str.*.length())
- dactyl.echomsg(_("variable.none"));
- else
- dactyl.echo(str, modules.commandline.FORCE_MULTILINE);
- return;
- }
+ util.assert(!(!args || args == "g:"));
let matches = args.match(/^([a-z]:)?([\w]+)(?:\s*([-+.])?=\s*(.*)?)?$/);
if (matches) {
-// Copyright (c) 2009-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2009-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("overlay", {
exports: ["overlay"],
require: ["util"]
-}, this);
+});
+
+lazyRequire("highlight", ["highlight"]);
var getAttr = function getAttr(elem, ns, name)
elem.hasAttributeNS(ns, name) ? elem.getAttributeNS(ns, name) : null;
util.addObserver(this);
this.overlays = {};
+ this.weakMap = WeakMap();
+
this.onWindowVisible = [];
},
},
getData: function getData(obj, key, constructor) {
- let { id } = this;
- if (!(id in obj && obj[id]))
- obj[id] = {};
+ if (!this.weakMap.has(obj))
+ try {
+ this.weakMap.set(obj, {});
+ }
+ catch (e if e instanceof TypeError) {
+ // util.dump("Bad WeakMap key: " + obj + " " + Components.stack.caller);
+ let { id } = this;
+
+ if (!(id in obj && obj[id]))
+ obj[id] = {};
+
+ var data = obj[id];
+ }
+
+ data = data || this.weakMap.get(obj);
if (arguments.length == 1)
- return obj[id];
+ return data;
- if (obj[id][key] === undefined)
+ if (data[key] === undefined)
if (constructor === undefined || callable(constructor))
- obj[id][key] = (constructor || Array)();
+ data[key] = (constructor || Array)();
else
- obj[id][key] = constructor;
+ data[key] = constructor;
- return obj[id][key];
+ return data[key];
},
setData: function setData(obj, key, val) {
- let { id } = this;
-
- if (!(id in obj))
- obj[id] = {};
+ let data = this.getData(obj);
- return obj[id][key] = val;
+ return data[key] = val;
},
overlayWindow: function (url, fn) {
_loadOverlay: function _loadOverlay(window, obj) {
let doc = window.document;
- let elems = this.getData(doc, "overlayElements");
- let attrs = this.getData(doc, "overlayAttributes");
+ let savedElems = this.getData(doc, "overlayElements");
+ let savedAttrs = this.getData(doc, "overlayAttributes");
function insert(key, fn) {
if (obj[key]) {
let iterator = Iterator(obj[key]);
- if (!isObject(obj[key]))
- iterator = ([elem.@id, elem.elements(), elem.@*::*.(function::name() != "id")] for each (elem in obj[key]));
+ if (isArray(obj[key])) {
+ iterator = ([elem[1].id, elem.slice(2), elem[1]]
+ for each (elem in obj[key]))
+ }
+
+ for (let [elem, xml, attrs] in iterator) {
+ if (elem = doc.getElementById(String(elem))) {
+ // Urgh. Hack.
+ let namespaces;
+ if (attrs && !isXML(attrs))
+ namespaces = iter([k.slice(6), DOM.fromJSON.namespaces[v] || v]
+ for ([k, v] in Iterator(attrs))
+ if (/^xmlns(?:$|:)/.test(k))).toObject();
+
+ let node;
+ if (isXML(xml))
+ node = DOM.fromXML(xml, doc, obj.objects);
+ else
+ node = DOM.fromJSON(xml, doc, obj.objects, namespaces);
- for (let [elem, xml, attr] in iterator) {
- if (elem = doc.getElementById(elem)) {
- let node = DOM.fromXML(xml, doc, obj.objects);
if (!(node instanceof Ci.nsIDOMDocumentFragment))
- elems.push(node);
+ savedElems.push(node);
else
for (let n in array.iterValues(node.childNodes))
- elems.push(n);
+ savedElems.push(n);
fn(elem, node);
- for each (let attr in attr || []) {
- let ns = attr.namespace(), name = attr.localName();
- attrs.push([elem, ns, name, getAttr(elem, ns, name), String(attr)]);
- if (attr.name() != "highlight")
- elem.setAttributeNS(ns, name, String(attr));
+
+ if (isXML(attrs))
+ // Evilness and such.
+ let (oldAttrs = attrs) {
+ attrs = (attr for each (attr in oldAttrs));
+ }
+
+ for (let attr in attrs || []) {
+ let [ns, localName] = DOM.parseNamespace(attr);
+ let name = attr;
+ let val = attrs[attr];
+
+ savedAttrs.push([elem, ns, name, getAttr(elem, ns, name), val]);
+ if (name === "highlight")
+ highlight.highlightNode(elem, val);
else
- highlight.highlightNode(elem, String(attr));
+ elem.setAttributeNS(ns || "", name, val);
}
}
}
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("prefs", {
exports: ["Prefs", "localPrefs", "prefs"],
require: ["services", "util"]
-}, this);
+});
-this.lazyRequire("messages", ["_"]);
+lazyRequire("messages", ["_"]);
+lazyRequire("template", ["template"]);
var Prefs = Module("prefs", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), {
ORIGINAL: "extensions.dactyl.original.",
switch (type) {
case Ci.nsIPrefBranch.PREF_STRING:
let value = this.branch.getComplexValue(name, Ci.nsISupportsString).data;
- // try in case it's a localized string (will throw an exception if not)
- if (!this.branch.prefIsLocked(name) && !this.branch.prefHasUserValue(name) &&
- RegExp("chrome://.+/locale/.+\\.properties").test(value))
- value = this.branch.getComplexValue(name, Ci.nsIPrefLocalizedString).data;
+ try {
+ if (/^[a-z0-9-]+:/i.test(value))
+ value = this.branch.getComplexValue(name, Ci.nsIPrefLocalizedString).data;
+ }
+ catch (e) {}
return value;
case Ci.nsIPrefBranch.PREF_INT:
return this.branch.getIntPref(name);
let option = {
isDefault: !userValue,
default: this.defaults.get(pref, null),
- value: <>={template.highlight(value, true, 100)}</>,
+ value: ["", "=", template.highlight(value, true, 100)],
name: pref,
pre: "\u00a0\u00a0" // Unicode nonbreaking space.
};
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("protocol", {
exports: ["LocaleChannel", "Protocol", "RedirectChannel", "StringChannel", "XMLChannel"],
require: ["services", "util"]
-}, this);
+});
var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].getService(Ci.nsIPrincipal);
}).data.QueryInterface(Ci.nsIChannel);
}
function RedirectChannel(to, orig, time, message) {
- let html = <html><head><meta http-equiv="Refresh" content={(time || 0) + ";" + to}/></head>
- <body><h2 style="text-align: center">{message || ""}</h2></body></html>.toXMLString();
+ let html = DOM.toXML(
+ ["html", {},
+ ["head", {},
+ ["meta", { "http-equiv": "Refresh", content: (time || 0) + ";" + to }]],
+ ["body", {},
+ ["h2", { style: "text-align: center" }, message || ""]]]);
return StringChannel(html, "text/html", services.io.newURI(to, null, null));
}
let type = this.channel.contentType;
if (/^text\/|[\/+]xml$/.test(type)) {
let stream = services.InputStream(channelStream);
- let [, pre, doctype, url, extra, open, post] = util.regexp(<![CDATA[
+ let [, pre, doctype, url, extra, open, post] = util.regexp(literal(/*
^ ([^]*?)
(?:
(<!DOCTYPE \s+ \S+ \s+) (?:SYSTEM \s+ "([^"]*)" | ((?:[^[>\s]|\s[^[])*))
([^]*)
)?
$
- ]]>, "x").exec(stream.read(4096));
+ */), "x").exec(stream.read(4096));
this.writes.push(pre);
if (doctype) {
this.writes.push(doctype + (extra || "") + " [\n");
this.writes.push(services.io.newChannel(url, null, this.uri).open());
}
catch (e) {
+ util.dump("addChannel('" + url + "'):");
util.reportError(e);
}
},
// Copyright (c) 2009 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2009-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2009-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
// TODO:
// - fix Sanitize autocommand
// FIXME:
// - finish 1.9.0 support if we're going to support sanitizing in Melodactyl
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("sanitizer", {
exports: ["Range", "Sanitizer", "sanitizer"],
require: ["config", "prefs", "services", "util"]
-}, this);
+});
-this.lazyRequire("messages", ["_"]);
-this.lazyRequire("overlay", ["overlay"]);
-this.lazyRequire("storage", ["storage"]);
-this.lazyRequire("template", ["teplate"]);
+lazyRequire("messages", ["_"]);
+lazyRequire("overlay", ["overlay"]);
+lazyRequire("storage", ["storage"]);
+lazyRequire("template", ["template"]);
let tmp = Object.create(this);
JSMLoader.loadSubScript("chrome://browser/content/sanitize.js", tmp);
},
override: true
});
- if (services.has("privateBrowsing"))
+ try {
+ var { ForgetAboutSite } = Cu.import("resource://gre/modules/ForgetAboutSite.jsm", {});
+ }
+ catch (e) {}
+ if (ForgetAboutSite)
this.addItem("host", {
description: "All data from the given host",
action: function (range, host) {
if (host)
- services.privateBrowsing.removeDataFromDomain(host);
+ ForgetAboutSite.removeDataFromDomain(host);
}
});
this.addItem("sitesettings", {
];
function prefOverlay(branch, persistent, local) update(Object.create(local), {
- before: array.toObject([
- [branch.substr(Item.PREFIX.length) + "history",
- <preferences xmlns={XUL}>{
- template.map(ourItems(persistent), function (item)
- <preference type="bool" id={branch + item.name} name={branch + item.name}/>)
- }</preferences>.*::*]
- ]),
+ before: [
+ ["preferences", { id: branch.substr(Item.PREFIX.length) + "history",
+ xmlns: "xul" },
+ template.map(ourItems(persistent), function (item)
+ ["preference", { type: "bool", id: branch + item.name, name: branch + item.name }])]
+ ],
init: function init(win) {
let pane = win.document.getElementById("SanitizeDialogPane");
for (let [, pref] in iter(pane.preferences))
function (win) prefOverlay(branch, true, {
append: {
SanitizeDialogPane:
- <groupbox orient="horizontal" xmlns={XUL}>
- <caption label={config.appName + /*L*/" (see :help privacy)"}/>
- <grid flex="1">
- <columns><column flex="1"/><column flex="1"/></columns>
- <rows>{
+ ["groupbox", { orient: "horizontal", xmlns: "xul" },
+ ["caption", { label: config.appName + /*L*/" (see :help privacy)" }],
+ ["grid", { flex: "1" },
+ ["columns", {},
+ ["column", { flex: "1" }],
+ ["column", { flex: "1" }]],
+ ["rows", {},
let (items = ourItems(true))
template.map(util.range(0, Math.ceil(items.length / 2)), function (i)
- <row xmlns={XUL}>{
- template.map(items.slice(i * 2, i * 2 + 2), function (item)
- <checkbox xmlns={XUL} label={item.description} preference={branch + item.name}/>)
- }</row>)
- }</rows>
- </grid>
- </groupbox>
+ ["row", {},
+ template.map(items.slice(i * 2, i * 2 + 2), function (item)
+ ["checkbox", { xmlns: XUL, label: item.description, preference: branch + item.name }])])]]],
}
}));
}
overlay.overlayWindow("chrome://browser/content/sanitize.xul",
function (win) prefOverlay(branch, false, {
append: {
- itemList: <>
- <listitem xmlns={XUL} label={/*L*/"See :help privacy for the following:"} disabled="true" style="font-style: italic; font-weight: bold;"/>
- {
- template.map(ourItems(), function ([item, desc])
- <listitem xmlns={XUL} type="checkbox"
- label={config.appName + " " + desc}
- preference={branch + item}
- onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/>)
- }
- </>
+ itemList: [
+ ["listitem", { xmlns: "xul", label: /*L*/"See :help privacy for the following:",
+ disabled: "true", style: "font-style: italic; font-weight: bold;" }],
+ template.map(ourItems(), function ([item, desc])
+ ["listitem", { xmlns: "xul", preference: branch + item,
+ type: "checkbox", label: config.appName + ", " + desc,
+ onsyncfrompreference: "return gSanitizePromptDialog.onReadGeneric();" }]),
+ ]
},
ready: function ready(win) {
let elem = win.document.getElementById("itemList");
}
},
+ /**
+ * Returns a load context for the given thing, to be used with
+ * interfaces needing one for per-window private browsing support.
+ *
+ * @param {Window|Document|Node} thing The thing for which to return
+ * a load context.
+ */
+ getContext: function getContext(thing) {
+ if (!Ci.nsILoadContext)
+ return null;
+
+ if (thing instanceof Ci.nsIDOMNode && thing.ownerDocument)
+ thing = thing.ownerDocument;
+ if (thing instanceof Ci.nsIDOMDocument)
+ thing = thing.defaultView;
+ if (thing instanceof Ci.nsIInterfaceRequestor)
+ thing = thing.getInterface(Ci.nsIWebNavigation);
+ return thing.QueryInterface(Ci.nsILoadContext);
+ },
+
get ranAtShutdown() config.prefs.get("didSanitizeOnShutdown"),
set ranAtShutdown(val) config.prefs.set("didSanitizeOnShutdown", Boolean(val)),
get runAtShutdown() prefs.get("privacy.sanitize.sanitizeOnShutdown"),
set runAtShutdown(val) prefs.set("privacy.sanitize.sanitizeOnShutdown", Boolean(val)),
- sanitize: function (items, range)
+ sanitize: function sanitize(items, range)
this.withSavedValues(["sanitizing"], function () {
this.sanitizing = true;
let errors = this.sanitizeItems(items, range, null);
return errors;
}),
- sanitizeItems: function (items, range, host, key)
+ sanitizeItems: function sanitizeItems(items, range, host, key)
this.withSavedValues(["sanitizing"], function () {
this.sanitizing = true;
if (items == null)
yield p;
}
}, {
- load: function (dactyl, modules, window) {
+ load: function initLoad(dactyl, modules, window) {
if (!sanitizer.firstRun++ && sanitizer.runAtShutdown && !sanitizer.ranAtShutdown)
sanitizer.sanitizeItems(null, Range(), null, "shutdown");
sanitizer.ranAtShutdown = false;
},
- autocommands: function (dactyl, modules, window) {
+ autocommands: function initAutocommands(dactyl, modules, window) {
const { autocommands } = modules;
storage.addObserver("private-mode",
autocommands.trigger("Sanitize", { name: event.substr("clear-".length), domain: value[1] });
}, window);
},
- commands: function (dactyl, modules, window) {
+ commands: function initCommands(dactyl, modules, window) {
const { commands } = modules;
commands.add(["sa[nitize]"],
"Clear private data",
}
function setPerms(host, perm) {
let uri = util.createURI(host);
- services.permissions.remove(uri, "cookie");
+ services.permissions.remove(uri.host, "cookie");
services.permissions.add(uri, "cookie", Sanitizer.PERMS[perm]);
}
commands.add(["cookies", "ck"],
["Host", "Expiry (UTC)", "Path", "Name", "Value"],
["padding-right: 1em", "padding-right: 1em", "padding-right: 1em", "max-width: 12em; overflow: hidden;", "padding-left: 1ex;"],
([c.host,
- c.isSession ? <span highlight="Enabled">session</span>
+ c.isSession ? ["span", { highlight: "Enabled" }, "session"]
: (new Date(c.expiry * 1000).toJSON() || "Never").replace(/:\d\d\.000Z/, "").replace("T", " ").replace(/-/g, "/"),
c.path,
c.name,
let count = [0, 0];
for (let c in Sanitizer.iterCookies(host))
count[c.isSession + 0]++;
- return <>{Sanitizer.COMMANDS[getPerms(host)]} (session: {count[1]} persistent: {count[0]})</>;
+ return [Sanitizer.COMMANDS[getPerms(host)], " (session: ", count[1], " persistent: ", count[0], ")"].join("");
};
break;
case 1:
},
});
},
- completion: function (dactyl, modules, window) {
+ completion: function initCompletion(dactyl, modules, window) {
modules.completion.visibleHosts = function completeHosts(context) {
let res = util.visibleHosts(window.content);
if (context.filter && !res.some(function (host) host.indexOf(context.filter) >= 0))
context.completions = res;
};
},
- options: function (dactyl, modules) {
+ options: function initOptions(dactyl, modules) {
const options = modules.options;
- if (services.has("privateBrowsing"))
+ if (services.has("privateBrowsing") && "privateBrowsingEnabled" in services.privateBrowsing)
options.add(["private", "pornmode"],
"Set the 'private browsing' option",
"boolean", false,
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
var global = this;
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("services", {
- exports: ["services"]
-}, this);
+ exports: ["PrivateBrowsingUtils", "services"]
+});
+
+try {
+ var { PrivateBrowsingUtils } = Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
+}
+catch (e) {}
/**
* A lazily-instantiated XPCOM class and service cache.
this.add("appShell", "@mozilla.org/appshell/appShellService;1", "nsIAppShellService");
this.add("appStartup", "@mozilla.org/toolkit/app-startup;1", "nsIAppStartup");
this.add("bookmarks", "@mozilla.org/browser/nav-bookmarks-service;1", "nsINavBookmarksService");
- this.add("bootstrap", "@dactyl.googlecode.com/base/bootstrap");
this.add("browserSearch", "@mozilla.org/browser/search-service;1", "nsIBrowserSearchService");
this.add("cache", "@mozilla.org/network/cache-service;1", "nsICacheService");
this.add("charset", "@mozilla.org/charset-converter-manager;1", "nsICharsetConverterManager");
this.addClass("Xmlhttp", "@mozilla.org/xmlextras/xmlhttprequest;1", [], "open");
this.addClass("XPathEvaluator", "@mozilla.org/dom/xpath-evaluator;1", "nsIDOMXPathEvaluator");
this.addClass("XMLDocument", "@mozilla.org/xml/xml-document;1", ["nsIDOMXMLDocument", "nsIDOMNodeSelector"]);
+ this.addClass("XMLSerializer","@mozilla.org/xmlextras/xmlserializer;1", ["nsIDOMSerializer"]);
this.addClass("ZipReader", "@mozilla.org/libjar/zip-reader;1", "nsIZipReader", "open", false);
this.addClass("ZipWriter", "@mozilla.org/zipwriter;1", "nsIZipWriter", "open", false);
},
reinit: function () {},
- _create: function (name, args) {
+ _create: function _create(name, args) {
try {
var service = this.services[name];
}
return res;
}
- catch (e if service.quiet !== false) {
+ catch (e) {
+ if (service.quiet === false)
+ throw e.stack ? e : Error(e);
+
if (typeof util !== "undefined")
util.reportError(e);
else
* @param {string} meth The name of the function used to instantiate
* the service.
*/
- add: function (name, class_, ifaces, meth) {
+ add: function add(name, class_, ifaces, meth) {
const self = this;
this.services[name] = { method: meth, class: class_, interfaces: Array.concat(ifaces || []) };
if (name in this && ifaces && !this.__lookupGetter__(name) && !(this[name] instanceof Ci.nsISupports))
* @param {string} init Name of a property or method used to initialize the
* class.
*/
- addClass: function (name, class_, ifaces, init, quiet) {
+ addClass: function addClass(name, class_, ifaces, init, quiet) {
const self = this;
this.services[name] = { class: class_, interfaces: Array.concat(ifaces || []), method: "createInstance", init: init, quiet: quiet };
if (init)
memoize(this.services[name], "callable",
function () callable(XPCOMShim(this.interfaces)[this.init]));
- this[name] = function () self._create(name, arguments);
+ this[name] = function Create() self._create(name, arguments);
update.apply(null, [this[name]].concat([Ci[i] for each (i in Array.concat(ifaces))]));
return this[name];
},
*
* @param {string} name The service's cache key.
*/
- has: function (name) Set.has(this.services, name) && this.services[name].class in Cc &&
+ has: function has(name) Set.has(this.services, name) && this.services[name].class in Cc &&
this.services[name].interfaces.every(function (iface) iface in Ci)
});
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("storage", {
exports: ["File", "Storage", "storage"],
require: ["services", "util"]
-}, this);
+});
-this.lazyRequire("config", ["config"]);
-this.lazyRequire("io", ["IO"]);
+lazyRequire("config", ["config"]);
+lazyRequire("io", ["IO"]);
+lazyRequire("overlay", ["overlay"]);
var win32 = /^win(32|nt)$/i.test(services.runtime.OS);
var myObject = JSON.parse("{}").constructor;
-function loadData(name, store, type) {
- try {
- let file = storage.infoPath.child(name);
- if (file.exists()) {
- let data = file.read();
- let result = JSON.parse(data);
- if (result instanceof type)
- return result;
- }
- }
- catch (e) {
- util.reportError(e);
- }
-}
-
-function saveData(obj) {
- if (obj.privateData && storage.privateMode)
- return;
- if (obj.store && storage.infoPath)
- storage.infoPath.child(obj.name).write(obj.serial);
-}
-
var StoreBase = Class("StoreBase", {
OPTIONS: ["privateData", "replacer"],
init: function (name, store, load, options) {
this._load = load;
+ this._options = options;
this.__defineGetter__("store", function () store);
this.__defineGetter__("name", function () name);
this.reload();
},
- changed: function () { this.timer.tell(); },
+ clone: function (storage) {
+ let store = storage.privateMode ? false : this.store;
+ let res = this.constructor(this.name, store, this._load, this._options);
+ res.storage = storage;
+ return res;
+ },
+
+ changed: function () { this.timer && this.timer.tell(); },
reload: function reload() {
this._object = this._load() || this._constructor();
storage.infoPath.child(this.name).remove(false);
},
- save: function () { saveData(this); },
+ save: function () { (self.storage || storage)._saveData(this); },
__iterator__: function () Iterator(this._object)
});
}
});
+var sessionGlobal = Cu.import("resource://gre/modules/Services.jsm", {})
+
var Storage = Module("Storage", {
+ Local: function Local(dactyl, modules, window) ({
+ init: function init() {
+ this.privateMode = PrivateBrowsingUtils.isWindowPrivate(window);
+ }
+ }),
+
alwaysReload: {},
- init: function () {
+ init: function init() {
this.cleanup();
- if (services.bootstrap && !services.bootstrap.session)
- services.bootstrap.session = {};
- this.session = services.bootstrap ? services.bootstrap.session : {};
+ let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
+ if (!Services.dactylSession)
+ Services.dactylSession = Cu.createObjectIn(sessionGlobal);
+ this.session = Services.dactylSession;
},
cleanup: function () {
this.observers = {};
},
+ _loadData: function loadData(name, store, type) {
+ try {
+ let file = storage.infoPath.child(name);
+ if (file.exists()) {
+ let data = file.read();
+ let result = JSON.parse(data);
+ if (result instanceof type)
+ return result;
+ }
+ }
+ catch (e) {
+ util.reportError(e);
+ }
+ },
+
+ _saveData: function saveData(obj) {
+ if (obj.privateData && storage.privateMode)
+ return;
+ if (obj.store && storage.infoPath)
+ storage.infoPath.child(obj.name).write(obj.serial);
+ },
+
+ storeForSession: function storeForSession(key, val) {
+ if (val)
+ this.session[key] = sessionGlobal.JSON.parse(JSON.stringify(val));
+ else
+ delete this.dactylSession[key];
+ },
+
infoPath: Class.Memoize(function ()
File(IO.runtimePath.replace(/,.*/, ""))
.child("info").child(config.profileName)),
},
newObject: function newObject(key, constructor, params) {
+ let self = this;
if (params == null || !isObject(params))
throw Error("Invalid argument type");
- if (!(key in this.keys) || params.reload || this.alwaysReload[key]) {
- if (key in this && !(params.reload || this.alwaysReload[key]))
- throw Error();
- let load = function () loadData(key, params.store, params.type || myObject);
+ if (this.isLocalModule) {
+ this.globalInstance.newObject.apply(this.globalInstance, arguments);
+
+ if (!(key in this.keys) && this.privateMode && key in this.globalInstance.keys) {
+ let obj = this.globalInstance.keys[key];
+ this.keys[key] = this._privatize(obj);
+ }
+
+ return this.keys[key];
+ }
+
+ let reload = params.reload || this.alwaysReload[key];
+ if (!(key in this.keys) || reload) {
+ if (key in this && !reload)
+ throw Error("Cannot add storage key with that name.");
+
+ let load = function () self._loadData(key, params.store, params.type || myObject);
this.keys[key] = new constructor(key, params.store, load, params);
- this.keys[key].timer = new Timer(1000, 10000, function () storage.save(key));
+ this.keys[key].timer = new Timer(1000, 10000, function () self.save(key));
this.__defineGetter__(key, function () this.keys[key]);
}
return this.keys[key];
else {
callbackRef = { get: function () callback };
}
+
this.removeDeadObservers();
+
if (!(key in this.observers))
this.observers[key] = [];
+
if (!this.observers[key].some(function (o) o.callback.get() == callback))
this.observers[key].push({ ref: ref && Cu.getWeakReference(ref), callback: callbackRef });
},
removeObserver: function (key, callback) {
this.removeDeadObservers();
+
if (!(key in this.observers))
return;
+
this.observers[key] = this.observers[key].filter(function (elem) elem.callback.get() != callback);
if (this.observers[key].length == 0)
delete obsevers[key];
},
removeDeadObservers: function () {
+ function filter(o) {
+ if (!o.callback.get())
+ return false;
+
+ let ref = o.ref && o.ref.get();
+ return ref && !ref.closed && overlay.getData(ref, "storage-refs", null);
+ }
+
for (let [key, ary] in Iterator(this.observers)) {
- this.observers[key] = ary = ary.filter(function (o) o.callback.get()
- && (!o.ref || o.ref.get()
- && overlay.getData(o.ref.get(), "storage-refs", null)));
+ this.observers[key] = ary = ary.filter(filter);
if (!ary.length)
delete this.observers[key];
}
fireEvent: function fireEvent(key, event, arg) {
this.removeDeadObservers();
+
if (key in this.observers)
// Safe, since we have our own Array object here.
for each (let observer in this.observers[key])
observer.callback.get()(key, event, arg);
- if (key in this.keys)
+
+ if (key in this.keys && this.keys[key].timer)
this[key].timer.tell();
},
save: function save(key) {
if (this[key])
- saveData(this.keys[key]);
+ this._saveData(this.keys[key]);
},
saveAll: function storeAll() {
for each (let obj in this.keys)
- saveData(obj);
+ this._saveData(obj);
},
_privateMode: false,
get privateMode() this._privateMode,
- set privateMode(val) {
- if (val && !this._privateMode)
+ set privateMode(enabled) {
+ this._privateMode = Boolean(enabled);
+
+ if (this.isLocalModule) {
this.saveAll();
- if (!val && this._privateMode)
- for (let key in this.keys)
- this.load(key);
- return this._privateMode = Boolean(val);
- }
+
+ if (!enabled)
+ delete this.keys;
+ else {
+ let { keys } = this;
+ this.keys = {};
+ for (let [k, v] in Iterator(keys))
+ this.keys[k] = this._privatize(v);
+ }
+ }
+ return this._privateMode;
+ },
+
+ _privatize: function privatize(obj) {
+ if (obj.privateData && obj.clone)
+ return obj.clone(this);
+ return obj;
+ },
}, {
Replacer: {
skipXpcom: function skipXpcom(key, val) val instanceof Ci.nsISupports ? null : val
if (path instanceof Ci.nsIFileURL)
path = path.file;
- if (path instanceof Ci.nsIFile)
+ if (path instanceof Ci.nsIFile || path instanceof File)
file = path.clone();
else if (/file:\/\//.test(path))
file = services["file:"].getFileFromURLSpec(path);
return File.DoesNotExist(path, e);
}
}
- let self = XPCSafeJSObjectWrapper(file.QueryInterface(Ci.nsILocalFile));
- self.__proto__ = this;
- return self;
+ this.file = file.QueryInterface(Ci.nsILocalFile);
+ return this;
},
charset: Class.Memoize(function () File.defaultEncoding),
* @property {nsIFileURL} Returns the nsIFileURL object for this file.
*/
URI: Class.Memoize(function () {
- let uri = services.io.newFileURI(this).QueryInterface(Ci.nsIFileURL);
+ let uri = services.io.newFileURI(this.file)
+ .QueryInterface(Ci.nsIFileURL);
uri.QueryInterface(Ci.nsIMutable).mutable = false;
return uri;
}),
/**
* Iterates over the objects in this directory.
*/
- iterDirectory: function () {
+ iterDirectory: function iterDirectory() {
if (!this.exists())
throw Error(_("io.noSuchFile"));
if (!this.isDirectory())
/**
* Returns a new file for the given child of this directory entry.
*/
- child: function (name) {
+ child: function child() {
let f = this.constructor(this);
- for each (let elem in name.split(File.pathSplit))
- f.append(elem);
+ for (let [, name] in Iterator(arguments))
+ for each (let elem in name.split(File.pathSplit))
+ f.append(elem);
return f;
},
/**
* Returns an iterator for all lines in a file.
*/
- get lines() File.readLines(services.FileInStream(this, -1, 0, 0),
+ get lines() File.readLines(services.FileInStream(this.file, -1, 0, 0),
this.charset),
/**
* @default #charset
* @returns {string}
*/
- read: function (encoding) {
- let ifstream = services.FileInStream(this, -1, 0, 0);
+ read: function read(encoding) {
+ let ifstream = services.FileInStream(this.file, -1, 0, 0);
return File.readStream(ifstream, encoding || this.charset);
},
* entries.
* @returns {[nsIFile]}
*/
- readDirectory: function (sort) {
+ readDirectory: function readDirectory(sort) {
if (!this.isDirectory())
throw Error(_("io.eNotDir"));
*
* @returns {nsIFileURL}
*/
- toURI: function toURI() services.io.newFileURI(this),
+ toURI: function toURI() services.io.newFileURI(this.file),
/**
* Writes the string *buf* to this file.
* @param {string} encoding The encoding to used to write the file.
* @default #charset
*/
- write: function (buf, mode, perms, encoding) {
+ write: function write(buf, mode, perms, encoding) {
function getStream(defaultChar) {
return services.ConvOutStream(ofstream, encoding, 0, defaultChar);
}
if (!this.exists()) // OCREAT won't create the directory
this.create(this.NORMAL_FILE_TYPE, perms);
- let ofstream = services.FileOutStream(this, mode, perms, 0);
+ let ofstream = services.FileOutStream(this.file, mode, perms, 0);
try {
var ocstream = getStream(0);
ocstream.writeString(buf);
ofstream.close();
}
return true;
- }
+ },
+
+ // Wrapped native methods:
+ copyTo: function copyTo(dir, name)
+ this.file.copyTo(this.constructor(dir).file,
+ name),
+
+ copyToFollowingLinks: function copyToFollowingLinks(dir, name)
+ this.file.copyToFollowingLinks(this.constructor(dir).file,
+ name),
+
+ moveTo: function moveTo(dir, name)
+ this.file.moveTo(this.constructor(dir).file,
+ name),
+
+ equals: function equals(file)
+ this.file.equals(this.constructor(file).file),
+
+ contains: function contains(dir, recur)
+ this.file.contains(this.constructor(dir).file,
+ recur),
+
+ getRelativeDescriptor: function getRelativeDescriptor(file)
+ this.file.getRelativeDescriptor(this.constructor(file).file),
+
+ setRelativeDescriptor: function setRelativeDescriptor(file, path)
+ this.file.setRelativeDescriptor(this.constructor(file).file,
+ path)
}, {
/**
* @property {number} Open for reading only.
replacePathSep: function (path) path.replace("/", File.PATH_SEP, "g")
});
+let (file = services.directory.get("ProfD", Ci.nsIFile)) {
+ Object.keys(file).forEach(function (prop) {
+ if (!(prop in File.prototype)) {
+ let isFunction;
+ try {
+ isFunction = callable(file[prop])
+ }
+ catch (e) {}
+
+ if (isFunction)
+ File.prototype[prop] = util.wrapCallback(function wrapper() this.file[prop].apply(this.file, arguments));
+ else
+ Object.defineProperty(File.prototype, prop, {
+ configurable: true,
+ get: function wrap_get() this.file[prop],
+ set: function wrap_set(val) { this.file[prop] = val; }
+ });
+ }
+ });
+ file = null;
+}
+
endModule();
// catch(e){ dump(e + "\n" + (e.stack || Error().stack)); Components.utils.reportError(e) }
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("styles", {
exports: ["Style", "Styles", "styles"],
require: ["services", "util"]
-}, this);
+});
+
+lazyRequire("contexts", ["Contexts"]);
+lazyRequire("template", ["template"]);
function cssUri(css) "chrome-data:text/css," + encodeURI(css);
-var namespace = "@namespace html " + XHTML.uri.quote() + ";\n" +
- "@namespace xul " + XUL.uri.quote() + ";\n" +
- "@namespace dactyl " + NS.uri.quote() + ";\n";
+var namespace = "@namespace html " + XHTML.quote() + ";\n" +
+ "@namespace xul " + XUL.quote() + ";\n" +
+ "@namespace dactyl " + NS.quote() + ";\n";
var Sheet = Struct("name", "id", "sites", "css", "hive", "agent");
Sheet.liveProperty = function (name) {
update(Sheet.prototype, {
formatSites: function (uris)
template.map(this.sites,
- function (filter) <span highlight={uris.some(Styles.matchFilter(filter)) ? "Filter" : ""}>{filter}</span>,
- <>,</>),
+ function (filter) ["span", { highlight: uris.some(Styles.matchFilter(filter)) ? "Filter" : "" }, filter],
+ ","),
remove: function () { this.hive.remove(this); },
let uris = util.visibleURIs(content);
- let list = <table>
- <tr highlight="Title">
- <td/>
- <td/>
- <td style="padding-right: 1em;">{_("title.Name")}</td>
- <td style="padding-right: 1em;">{_("title.Filter")}</td>
- <td style="padding-right: 1em;">{_("title.CSS")}</td>
- </tr>
- <col style="min-width: 4em; padding-right: 1em;"/>
- <col style="min-width: 1em; text-align: center; color: red; font-weight: bold;"/>
- <col style="padding: 0 1em 0 1ex; vertical-align: top;"/>
- <col style="padding: 0 1em 0 0; vertical-align: top;"/>
- {
- template.map(hives, function (hive) let (i = 0)
- <tr style="height: .5ex;"/> +
- template.map(sheets(hive), function (sheet)
- <tr>
- <td highlight="Title">{!i++ ? hive.name : ""}</td>
- <td>{sheet.enabled ? "" : UTF8("×")}</td>
- <td>{sheet.name || hive.sheets.indexOf(sheet)}</td>
- <td>{sheet.formatSites(uris)}</td>
- <td>{sheet.css}</td>
- </tr>) +
- <tr style="height: .5ex;"/>)
- }
- </table>;
-
- // TODO: Move this to an ItemList to show this automatically
- if (list.*.length() === list.text().length() + 5)
- dactyl.echomsg(_("style.none"));
- else
- commandline.commandOutput(list);
+ let list = ["table", {},
+ ["tr", { highlight: "Title" },
+ ["td"],
+ ["td"],
+ ["td", { style: "padding-right: 1em;" }, _("title.Name")],
+ ["td", { style: "padding-right: 1em;" }, _("title.Filter")],
+ ["td", { style: "padding-right: 1em;" }, _("title.CSS")]],
+ ["col", { style: "min-width: 4em; padding-right: 1em;" }],
+ ["col", { style: "min-width: 1em; text-align: center; color: red; font-weight: bold;" }],
+ ["col", { style: "padding: 0 1em 0 1ex; vertical-align: top;" }],
+ ["col", { style: "padding: 0 1em 0 0; vertical-align: top;" }],
+ template.map(hives, function (hive) let (i = 0) [
+ ["tr", { style: "height: .5ex;" }],
+ template.map(sheets(hive), function (sheet)
+ ["tr", {},
+ ["td", { highlight: "Title" }, !i++ ? hive.name : ""],
+ ["td", {}, sheet.enabled ? "" : UTF8("×")],
+ ["td", {}, sheet.name || hive.sheets.indexOf(sheet)],
+ ["td", {}, sheet.formatSites(uris)],
+ ["td", {}, sheet.css]]),
+ ["tr", { style: "height: .5ex;" }]])];
+
+ // E4X-FIXME
+ // // TODO: Move this to an ItemList to show this automatically
+ // if (list.*.length() === list.text().length() + 5)
+ // dactyl.echomsg(_("style.none"));
+ // else
+ commandline.commandOutput(list);
},
registerSheet: function registerSheet(url, agent, reload) {
}
},
- propertyPattern: util.regexp(<![CDATA[
+ propertyPattern: util.regexp(literal(/*
(?:
(?P<preSpace> <space>*)
(?P<name> [-a-z]*)
)?
)
(?P<postSpace> <space>* (?: ; | $) )
- ]]>, "gix",
+ */), "gix",
{
space: /(?: \s | \/\* .*? \*\/ )/,
string: /(?:" (?:[^\\"]|\\.)* (?:"|$) | '(?:[^\\']|\\.)* (?:'|$) )/
}),
patterns: memoize({
- get property() util.regexp(<![CDATA[
+ get property() util.regexp(literal(/*
(?:
(?P<preSpace> <space>*)
(?P<name> [-a-z]*)
)?
)
(?P<postSpace> <space>* (?: ; | $) )
- ]]>, "gix", this),
+ */), "gix", this),
- get function() util.regexp(<![CDATA[
+ get function() util.regexp(literal(/*
(?P<function>
\s* \( \s*
(?: <string> | [^)]* )
\s* (?: \) | $)
)
- ]]>, "gx", this),
+ */), "gx", this),
space: /(?: \s | \/\* .*? \*\/ )/,
- get string() util.regexp(<![CDATA[
+ get string() util.regexp(literal(/*
(?P<string>
" (?:[^\\"]|\\.)* (?:"|$) |
' (?:[^\\']|\\.)* (?:'|$)
)
- ]]>, "gx", this),
+ */), "gx", this),
- get token() util.regexp(<![CDATA[
+ get token() util.regexp(literal(/*
(?P<token>
(?P<word> [-\w]+)
<function>?
| <space>+
| [^;}\s]+
)
- ]]>, "gix", this)
+ */), "gix", this)
}),
/**
return '"' + str.replace(/([\\"])/g, "\\$1").replace(/\n/g, "\\00000a") + '"';
},
}, {
- commands: function (dactyl, modules, window) {
+ commands: function initCommands(dactyl, modules, window) {
const { commands, contexts, styles } = modules;
function sheets(context, args, filter) {
context.compare = modules.CompletionContext.Sort.number;
context.generate = function () args["-group"].sheets;
context.keys.active = function (sheet) uris.some(sheet.closure.match);
- context.keys.description = function (sheet) <>{sheet.formatSites(uris)}: {sheet.css.replace("\n", "\\n")}</>
+ context.keys.description = function (sheet) [sheet.formatSites(uris), ": ", sheet.css.replace("\n", "\\n")];
if (filter)
context.filters.push(function ({ item }) filter(item));
Styles.splitContext(context);
});
});
},
- contexts: function (dactyl, modules, window) {
+ contexts: function initContexts(dactyl, modules, window) {
modules.contexts.Hives("styles",
Class("LocalHive", Contexts.Hive, {
init: function init(group) {
}
}));
},
- completion: function (dactyl, modules, window) {
- const names = Array.slice(DOM(<div/>, window.document).style);
+ completion: function initCompletion(dactyl, modules, window) {
+ const names = Array.slice(DOM(["div"], window.document).style);
modules.completion.css = function (context) {
context.title = ["CSS Property"];
context.keys = { text: function (p) p + ":", description: function () "" };
}
};
},
- javascript: function (dactyl, modules, window) {
+ javascript: function initJavascript(dactyl, modules, window) {
modules.JavaScript.setCompleter(["get", "add", "remove", "find"].map(function (m) Hive.prototype[m]),
[ // Prototype: (name, filter, css, index)
function (context, obj, args) this.names,
function (context, obj, args) this.sheets
]);
},
- template: function () {
+ template: function initTemplate() {
let patterns = Styles.patterns;
template.highlightCSS = function highlightCSS(css) {
- XML.prettyPrinting = XML.ignoreWhitespace = false;
-
return this.highlightRegexp(css, patterns.property, function (match) {
if (!match.length)
- return <></>;
- return <>{match.preSpace}{template.filter(match.name)}: {
+ return [];
+ return ["", match.preSpace, template.filter(match.name), ": ",
template.highlightRegexp(match.value, patterns.token, function (match) {
if (match.function)
- return <>{template.filter(match.word)}{
+ return ["", template.filter(match.word),
template.highlightRegexp(match.function, patterns.string,
- function (match) <span highlight="String">{match.string}</span>)
- }</>;
+ function (match) ["span", { highlight: "String" }, match.string])
+ ];
if (match.important == "!important")
- return <span highlight="String">{match.important}</span>;
+ return ["span", { highlight: "String" }, match.important];
if (match.string)
- return <span highlight="String">{match.string}</span>;
- return template.highlightRegexp(match.wholeMatch, /^(\d+)(em|ex|px|in|cm|mm|pt|pc)?/g,
- function (m, n, u) <><span highlight="Number">{n}</span><span highlight="Object">{u || ""}</span></>);
- })
-
- }{ match.postSpace }</>
+ return ["span", { highlight: "String" }, match.string];
+ return template._highlightRegexp(match.wholeMatch, /^(\d+)(em|ex|px|in|cm|mm|pt|pc)?/g,
+ function (m, n, u) [
+ ["span", { highlight: "Number" }, n],
+ ["span", { highlight: "Object" }, u || ""]
+ ]);
+ }),
+ match.postSpace
+ ]
})
}
- },
+ }
});
endModule();
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
let global = this;
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("template", {
exports: ["Binding", "Template", "template"],
require: ["util"]
-}, this);
+});
-default xml namespace = XHTML;
+lazyRequire("help", ["help"]);
var Binding = Class("Binding", {
init: function (node, nodes) {
});
var Template = Module("Template", {
- add: function add(a, b) a + b,
- join: function join(c) function (a, b) a + c + b,
-
- map: function map(iter, func, sep, interruptable) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- if (typeof iter.length == "number") // FIXME: Kludge?
- iter = array.iterValues(iter);
- let res = <></>;
- let n = 0;
- for each (let i in Iterator(iter)) {
- let val = func(i, n);
- if (val == undefined)
- continue;
- if (n++ && sep)
- res += sep;
- if (interruptable && n % interruptable == 0)
- util.threadYield(true, true);
- res += val;
- }
- return res;
- },
bindings: {
Button: Class("Button", Binding, {
})
},
- bookmarkDescription: function (item, text)
- <>
- {
- !(item.extra && item.extra.length) ? "" :
- <span highlight="URLExtra">
- ({
- template.map(item.extra, function (e)
- <>{e[0]}: <span highlight={e[2]}>{e[1]}</span></>,
- <> </>)
- }) </span>
+ map: function map(iter, func, sep, interruptable) {
+ if (typeof iter.length == "number") // FIXME: Kludge?
+ iter = array.iterValues(iter);
+
+ let res = [];
+ let n = 0;
+ for each (let i in Iterator(iter)) {
+ let val = func(i, n);
+ if (val == undefined)
+ continue;
+ if (n++ && sep)
+ res.push(sep);
+ if (interruptable && n % interruptable == 0)
+ util.threadYield(true, true);
+ res.push(val);
}
- <a xmlns:dactyl={NS} identifier={item.id == null ? "" : item.id} dactyl:command={item.command || ""}
- href={item.item.url} highlight="URL">{text || ""}</a>
- </>,
+ return res;
+ },
+
+
+ bookmarkDescription: function (item, text) [
+ !(item.extra && item.extra.length) ? [] :
+ ["span", { highlight: "URLExtra" },
+ " (",
+ template.map(item.extra, function (e)
+ ["", e[0], ": ",
+ ["span", { highlight: e[2] }, e[1]]],
+ "\u00a0"),
+ ")\u00a0"],
+ ["a", { identifier: item.id == null ? "" : item.id,
+ "dactyl:command": item.command || "",
+ href: item.item.url, highlight: "URL" },
+ text || ""]
+ ],
- filter: function (str) <span highlight="Filter">{str}</span>,
+ filter: function (str) ["span", { highlight: "Filter" }, str],
completionRow: function completionRow(item, highlightGroup) {
if (typeof icon == "function")
var desc = this.processor[1].call(this, item, item.description);
}
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- // <e4x>
- return <div highlight={highlightGroup || "CompItem"} style="white-space: nowrap">
- <!-- The non-breaking spaces prevent empty elements
- - from pushing the baseline down and enlarging
- - the row.
- -->
- <li highlight={"CompResult " + item.highlight}>{text} </li>
- <li highlight="CompDesc">{desc} </li>
- </div>;
- // </e4x>
+ return ["div", { highlight: highlightGroup || "CompItem", style: "white-space: nowrap" },
+ /* The non-breaking spaces prevent empty elements
+ * from pushing the baseline down and enlarging
+ * the row.
+ */
+ ["li", { highlight: "CompResult " + item.highlight },
+ text, "\u00a0"],
+ ["li", { highlight: "CompDesc" },
+ desc, "\u00a0"]];
},
helpLink: function (token, text, type) {
topic = topic.slice(2);
if (help.initialized && !Set.has(help.tags, topic))
- return <span highlight={type || ""}>{text || token}</span>;
+ return ["span", { highlight: type || ""}, text || token];
- XML.ignoreWhitespace = XML.prettyPrinting = false;
type = type || (/^'.*'$/.test(token) ? "HelpOpt" :
/^\[.*\]$|^E\d{3}$/.test(token) ? "HelpTopic" :
/^:\w/.test(token) ? "HelpEx" : "HelpKey");
- return <a highlight={"InlineHelpLink " + type} tag={topic} href={"dactyl://help-tag/" + topic} dactyl:command="dactyl.help" xmlns:dactyl={NS}>{text || topic}</a>;
+ return ["a", { highlight: "InlineHelpLink " + type, tag: topic,
+ href: "dactyl://help-tag/" + topic,
+ "dactyl:command": "dactyl.help" },
+ text || topic];
},
HelpLink: function (token) {
if (!help.initialized)
topic = topic.slice(2);
if (help.initialized && !Set.has(help.tags, topic))
- return <>{token}</>;
+ return token;
- XML.ignoreWhitespace = XML.prettyPrinting = false;
let tag = (/^'.*'$/.test(token) ? "o" :
/^\[.*\]$|^E\d{3}$/.test(token) ? "t" :
/^:\w/.test(token) ? "ex" : "k");
topic = topic.replace(/^'(.*)'$/, "$1");
- return <{tag} xmlns={NS}>{topic}</{tag}>;
+ return [tag, { xmlns: "dactyl" }, topic];
},
linkifyHelp: function linkifyHelp(str, help) {
- let re = util.regexp(<![CDATA[
+ let re = util.regexp(literal(/*
(?P<pre> [/\s]|^)
(?P<tag> '[\w-]+' | :(?:[\w-]+!?|!) | (?:._)?<[\w-]+>\w* | \b[a-zA-Z]_(?:[\w[\]]+|.) | \[[\w-;]+\] | E\d{3} )
(?= [[\)!,:;./\s]|$)
- ]]>, "gx");
+ */), "gx");
return this.highlightSubstrings(str, (function () {
for (let res in re.iterate(str))
yield [res.index + res.pre.length, res.tag.length];
- })(), template[help ? "HelpLink" : "helpLink"]);
+ })(), this[help ? "HelpLink" : "helpLink"]);
},
+
// Fixes some strange stack rewinds on NS_ERROR_OUT_OF_MEMORY
// exceptions that we can't catch.
stringify: function stringify(arg) {
}
},
- _sandbox: Class.Memoize(function () Cu.Sandbox(global, { wantXrays: false })),
+ _sandbox: Class.Memoize(function () Cu.Sandbox(Cu.getGlobalForObject(global),
+ { wantXrays: false })),
// if "processStrings" is true, any passed strings will be surrounded by " and
// any line breaks are displayed as \n
highlight: function highlight(arg, processStrings, clip, bw) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
// some objects like window.JSON or getBrowsers()._browsers need the try/catch
try {
let str = this.stringify(arg);
str = util.clip(str, clip);
switch (arg == null ? "undefined" : typeof arg) {
case "number":
- return <span highlight="Number">{str}</span>;
+ return ["span", { highlight: "Number" }, str];
case "string":
if (processStrings)
str = str.quote();
- return <span highlight="String">{str}</span>;
+ return ["span", { highlight: "String" }, str];
case "boolean":
- return <span highlight="Boolean">{str}</span>;
+ return ["span", { highlight: "Boolean" }, str];
case "function":
if (arg instanceof Ci.nsIDOMElement) // wtf?
return util.objectToString(arg, !bw);
str = str.replace("/* use strict */ \n", "/* use strict */ ");
if (processStrings)
- return <span highlight="Function">{str.replace(/\{(.|\n)*(?:)/g, "{ ... }")}</span>;
- <>}</>; /* Vim */
+ return ["span", { highlight: "Function" },
+ str.replace(/\{(.|\n)*(?:)/g, "{ ... }")];
arg = String(arg).replace("/* use strict */ \n", "/* use strict */ ");
- return <>{arg}</>;
+ return arg;
case "undefined":
- return <span highlight="Null">{arg}</span>;
+ return ["span", { highlight: "Null" }, "undefined"];
case "object":
if (arg instanceof Ci.nsIDOMElement)
return util.objectToString(arg, !bw);
+ if (arg instanceof util.Magic)
+ return String(arg);
- // for java packages value.toString() would crash so badly
- // that we cannot even try/catch it
- if (/^\[JavaPackage.*\]$/.test(arg))
- return <>[JavaPackage]</>;
if (processStrings && false)
- str = template.highlightFilter(str, "\n", function () <span highlight="NonText">^J</span>);
- return <span highlight="Object">{str}</span>;
+ str = template._highlightFilter(str, "\n",
+ function () ["span", { highlight: "NonText" },
+ "^J"]);
+ return ["span", { highlight: "Object" }, str];
case "xml":
return arg;
default:
- return <![CDATA[<unknown type>]]>;
+ return "<unknown type>";
}
}
catch (e) {
- return <![CDATA[<unknown>]]>;
+ return "<error: " + e + ">";
}
},
if (filter.length == 0)
return;
- XML.ignoreWhitespace = XML.prettyPrinting = false;
let lcstr = String.toLowerCase(str);
let lcfilter = filter.toLowerCase();
let start = 0;
},
highlightSubstrings: function highlightSubstrings(str, iter, highlight) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- if (typeof str == "xml")
+ if (!isString(str))
return str;
+
if (str == "")
- return <>{str}</>;
+ return DOM.DOMString(str);
- str = String(str).replace(" ", "\u00a0");
- let s = <></>;
+ let s = [""];
let start = 0;
let n = 0, _i;
for (let [i, length, args] in iter) {
break;
_i = i;
- XML.ignoreWhitespace = false;
- s += <>{str.substring(start, i)}</>;
- s += highlight.apply(this, Array.concat(args || str.substr(i, length)));
+ s.push(str.substring(start, i),
+ highlight.apply(this, Array.concat(args || str.substr(i, length))));
start = i + length;
}
- return s + <>{str.substr(start)}</>;
+ s.push(str.substr(start));
+ return s;
},
highlightURL: function highlightURL(str, force) {
if (force || /^[a-zA-Z]+:\/\//.test(str))
- return <a highlight="URL" href={str}>{util.losslessDecodeURI(str)}</a>;
+ return ["a", { highlight: "URL", href: str },
+ util.losslessDecodeURI(str)];
else
return str;
},
- icon: function (item, text) <>
- <span highlight="CompIcon">{item.icon ? <img src={item.icon}/> : <></>}</span><span class="td-strut"/>{text}
- </>,
+ icon: function (item, text) [
+ ["span", { highlight: "CompIcon" },
+ item.icon ? ["img", { src: item.icon }] : []],
+ ["span", { class: "td-strut" }],
+ text
+ ],
jumps: function jumps(index, elems) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- // <e4x>
- return <table>
- <tr style="text-align: left;" highlight="Title">
- <th colspan="2">{_("title.Jump")}</th>
- <th>{_("title.HPos")}</th>
- <th>{_("title.VPos")}</th>
- <th>{_("title.Title")}</th>
- <th>{_("title.URI")}</th>
- </tr>
- {
- this.map(Iterator(elems), function ([idx, val])
- <tr>
- <td class="indicator">{idx == index ? ">" : ""}</td>
- <td>{Math.abs(idx - index)}</td>
- <td>{val.offset ? val.offset.x : ""}</td>
- <td>{val.offset ? val.offset.y : ""}</td>
- <td style="width: 250px; max-width: 500px; overflow: hidden;">{val.title}</td>
- <td><a href={val.URI.spec} highlight="URL jump-list">{util.losslessDecodeURI(val.URI.spec)}</a></td>
- </tr>)
- }
- </table>;
- // </e4x>
+ return ["table", {},
+ ["tr", { style: "text-align: left;", highlight: "Title" },
+ ["th", { colspan: "2" }, _("title.Jump")],
+ ["th", {}, _("title.HPos")],
+ ["th", {}, _("title.VPos")],
+ ["th", {}, _("title.Title")],
+ ["th", {}, _("title.URI")]],
+ this.map(Iterator(elems), function ([idx, val])
+ ["tr", {},
+ ["td", { class: "indicator" }, idx == index ? ">" : ""],
+ ["td", {}, Math.abs(idx - index)],
+ ["td", {}, val.offset ? val.offset.x : ""],
+ ["td", {}, val.offset ? val.offset.y : ""],
+ ["td", { style: "width: 250px; max-width: 500px; overflow: hidden;" }, val.title],
+ ["td", {},
+ ["a", { href: val.URI.spec, highlight: "URL jump-list" },
+ util.losslessDecodeURI(val.URI.spec)]]])];
},
+
options: function options(title, opts, verbose) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- // <e4x>
- return <table>
- <tr highlight="Title" align="left">
- <th>--- {title} ---</th>
- </tr>
- {
- this.map(opts, function (opt)
- <tr>
- <td>
- <div highlight="Message"
- ><span style={opt.isDefault ? "" : "font-weight: bold"}>{opt.pre}{opt.name}</span><span>{opt.value}</span>{
- opt.isDefault || opt.default == null ? "" : <span class="extra-info"> (default: {opt.default})</span>
- }</div>{
- verbose && opt.setFrom ? <div highlight="Message"> Last set from {template.sourceLink(opt.setFrom)}</div> : <></>
- }
- </td>
- </tr>)
- }
- </table>;
- // </e4x>
+ return ["table", {},
+ ["tr", { highlight: "Title", align: "left" },
+ ["th", {}, "--- " + title + " ---"]],
+ this.map(opts, function (opt)
+ ["tr", {},
+ ["td", {},
+ ["div", { highlight: "Message" },
+ ["span", { style: opt.isDefault ? "" : "font-weight: bold" },
+ opt.pre, opt.name],
+ ["span", {}, opt.value],
+ opt.isDefault || opt.default == null ? "" : ["span", { class: "extra-info" }, " (default: ", opt.default, ")"]],
+ verbose && opt.setFrom ? ["div", { highlight: "Message" },
+ " Last set from ",
+ template.sourceLink(opt.setFrom)] : ""]])];
},
sourceLink: function (frame) {
let url = util.fixURI(frame.filename || "unknown");
let path = util.urlPath(url);
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- return <a xmlns:dactyl={NS} dactyl:command="buffer.viewSource"
- href={url} path={path} line={frame.lineNumber}
- highlight="URL">{
- path + ":" + frame.lineNumber
- }</a>;
+ return ["a", { "dactyl:command": "buffer.viewSource",
+ href: url, path: path, line: frame.lineNumber,
+ highlight: "URL" },
+ path + ":" + frame.lineNumber];
},
table: function table(title, data, indent) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- let table = // <e4x>
- <table>
- <tr highlight="Title" align="left">
- <th colspan="2">{title}</th>
- </tr>
- {
- this.map(data, function (datum)
- <tr>
- <td style={"font-weight: bold; min-width: 150px; padding-left: " + (indent || "2ex")}>{datum[0]}</td>
- <td>{datum[1]}</td>
- </tr>)
- }
- </table>;
- // </e4x>
- if (table.tr.length() > 1)
+ let table = ["table", {},
+ ["tr", { highlight: "Title", align: "left" },
+ ["th", { colspan: "2" }, title]],
+ this.map(data, function (datum)
+ ["tr", {},
+ ["td", { style: "font-weight: bold; min-width: 150px; padding-left: " + (indent || "2ex") }, datum[0]],
+ ["td", {}, datum[1]]])];
+
+ if (table[3].length)
return table;
},
tabular: function tabular(headings, style, iter) {
+ let self = this;
// TODO: This might be mind-bogglingly slow. We'll see.
- XML.ignoreWhitespace = XML.prettyPrinting = false;
- // <e4x>
- return <table>
- <tr highlight="Title" align="left">
- {
- this.map(headings, function (h)
- <th>{h}</th>)
- }
- </tr>
- {
- this.map(iter, function (row)
- <tr>
- {
- template.map(Iterator(row), function ([i, d])
- <td style={style[i] || ""}>{d}</td>)
- }
- </tr>)
- }
- </table>;
- // </e4x>
+ return ["table", {},
+ ["tr", { highlight: "Title", align: "left" },
+ this.map(headings, function (h)
+ ["th", {}, h])],
+ this.map(iter, function (row)
+ ["tr", {},
+ self.map(Iterator(row), function ([i, d])
+ ["td", { style: style[i] || "" }, d])])];
},
usage: function usage(iter, format) {
- XML.ignoreWhitespace = XML.prettyPrinting = false;
+ let self = this;
+
format = format || {};
- let desc = format.description || function (item) template.linkifyHelp(item.description);
+ let desc = format.description || function (item) self.linkifyHelp(item.description);
let help = format.help || function (item) item.name;
function sourceLink(frame) {
- let source = template.sourceLink(frame);
- source.@NS::hint = source.text();
+ let source = self.sourceLink(frame);
+ source[1]["dactyl:hint"] = source[2];
return source;
}
- // <e4x>
- return <table>
- { format.headings ?
- <thead highlight="UsageHead">
- <tr highlight="Title" align="left">
- {
- this.map(format.headings, function (h) <th>{h}</th>)
- }
- </tr>
- </thead> : ""
- }
- { format.columns ?
- <colgroup>
- {
- this.map(format.columns, function (c) <col style={c}/>)
- }
- </colgroup> : ""
- }
- <tbody highlight="UsageBody">{
+ return ["table", {},
+ format.headings ?
+ ["thead", { highlight: "UsageHead" },
+ ["tr", { highlight: "Title", align: "left" },
+ this.map(format.headings, function (h) ["th", {}, h])]] :
+ [],
+ format.columns ?
+ ["colgroup", {},
+ this.map(format.columns, function (c) ["col", { style: c }])] :
+ [],
+ ["tbody", { highlight: "UsageBody" },
this.map(iter, function (item)
- <tr highlight="UsageItem">
- <td style="padding-right: 2em;">
- <span highlight="Usage Link">{
- let (name = item.name || item.names[0], frame = item.definedAt)
- !frame ? name :
- template.helpLink(help(item), name, "Title") +
- <span highlight="LinkInfo" xmlns:dactyl={NS}>{_("io.definedAt")} {sourceLink(frame)}</span>
- }</span>
- </td>
- { item.columns ? template.map(item.columns, function (c) <td>{c}</td>) : "" }
- <td>{desc(item)}</td>
- </tr>)
- }</tbody>
- </table>;
- // </e4x>
+ // Urgh.
+ let (name = item.name || item.names[0], frame = item.definedAt)
+ ["tr", { highlight: "UsageItem" },
+ ["td", { style: "padding-right: 2em;" },
+ ["span", { highlight: "Usage Link" },
+ !frame ? name :
+ [self.helpLink(help(item), name, "Title"),
+ ["span", { highlight: "LinkInfo" },
+ _("io.definedAt"), " ",
+ sourceLink(frame)]]]],
+ item.columns ? self.map(item.columns, function (c) ["td", {}, c]) : [],
+ ["td", {}, desc(item)]])]]
}
});
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("util", {
exports: ["DOM", "$", "FailedAssertion", "Math", "NS", "Point", "Util", "XBL", "XHTML", "XUL", "util"],
require: ["dom", "services"]
-}, this);
+});
+
+lazyRequire("overlay", ["overlay"]);
+lazyRequire("storage", ["File", "storage"]);
+lazyRequire("template", ["template"]);
+
+var Magic = Class("Magic", {
+ init: function init(str) {
+ this.str = str;
+ },
+
+ get message() this.str,
-this.lazyRequire("overlay", ["overlay"]);
+ toString: function () this.str
+});
var FailedAssertion = Class("FailedAssertion", ErrorBase, {
init: function init(message, level, noTrace) {
}
var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), {
- init: function () {
+ Magic: Magic,
+
+ init: function init() {
this.Array = array;
this.addObserver(this);
parseForm: deprecated("DOM#formData", function parseForm(elem) values(DOM(elem).formData).toArray()),
scrollIntoView: deprecated("DOM#scrollIntoView", function scrollIntoView(elem, alignWithTop) DOM(elem).scrollIntoView(alignWithTop)),
validateMatcher: deprecated("DOM.validateMatcher", { get: function validateMatcher() DOM.validateMatcher }),
+ xmlToDom: deprecated("DOM.fromJSON", function xmlToDom() DOM.fromXML.apply(DOM, arguments)),
map: deprecated("iter.map", function map(obj, fn, self) iter(obj).map(fn, self).toArray()),
writeToClipboard: deprecated("dactyl.clipboardWrite", function writeToClipboard(str, verbose) util.dactyl.clipboardWrite(str, verbose)),
var global = Class.objectGlobal(obj);
return {
- __noSuchMethod__: function (meth, args) {
+ __noSuchMethod__: function __noSuchMethod__(meth, args) {
let win = overlay.activeWindow;
var dactyl = global && global.dactyl || win && win.dactyl;
}
};
}, {
- __noSuchMethod__: function () this().__noSuchMethod__.apply(null, arguments)
+ __noSuchMethod__: function __noSuchMethod__() this().__noSuchMethod__.apply(null, arguments)
}),
/**
* @param {string} message The message to present to the
* user on failure.
*/
- assert: function (condition, message, quiet) {
+ assert: function assert(condition, message, quiet) {
if (!condition)
throw FailedAssertion(message, 1, quiet === undefined ? true : quiet);
return condition;
{
elements: [],
seen: {},
- valid: function (obj) this.elements.every(function (e) !e.test || e.test(obj))
+ valid: function valid(obj) this.elements.every(function (e) !e.test || e.test(obj))
});
let end = 0;
stack.top.elements.push(update(
function (obj) obj[char] != null ? quote(obj, char) : "",
- { test: function (obj) obj[char] != null }));
+ { test: function test(obj) obj[char] != null }));
for (let elem in array.iterValues(stack))
elem.seen[char] = true;
{
elements: [],
seen: {},
- valid: function (obj) this.elements.every(function (e) !e.test || e.test(obj))
+ valid: function valid(obj) this.elements.every(function (e) !e.test || e.test(obj))
});
let defaults = { lt: "<", gt: ">" };
- let re = util.regexp(<![CDATA[
+ let re = util.regexp(literal(/*
([^]*?) // 1
(?:
(<\{) | // 2
(< ((?:[a-z]-)?[a-z-]+?) (?:\[([0-9]+)\])? >) | // 3 4 5
(\}>) // 6
)
- ]]>, "gixy");
+ */), "gixy");
macro = String(macro);
let end = 0;
for (let match in re.iterate(macro)) {
}
else if (close) {
stack.pop();
- util.assert(stack.length, /*L*/"Unmatched %] in macro");
+ util.assert(stack.length, /*L*/"Unmatched }> in macro");
}
else {
let [, flags, name] = /^((?:[a-z]-)*)(.*)/.exec(macro);
function (obj) obj[name] != null && idx in obj[name] ? quote(obj[name][idx])
: Set.has(obj, name) ? "" : unknown(full),
{
- test: function (obj) obj[name] != null && idx in obj[name]
- && obj[name][idx] !== false
- && (!flags.e || obj[name][idx] != "")
+ test: function test(obj) obj[name] != null && idx in obj[name]
+ && obj[name][idx] !== false
+ && (!flags.e || obj[name][idx] != "")
}));
}
else {
function (obj) obj[name] != null ? quote(obj[name])
: Set.has(obj, name) ? "" : unknown(full),
{
- test: function (obj) obj[name] != null
- && obj[name] !== false
- && (!flags.e || obj[name] != "")
+ test: function test(obj) obj[name] != null
+ && obj[name] !== false
+ && (!flags.e || obj[name] != "")
}));
}
}
},
+ /**
+ * Briefly delay the execution of the passed function.
+ *
+ * @param {function} callback The function to delay.
+ */
+ delay: function delay(callback) {
+ let { mainThread } = services.threading;
+ mainThread.dispatch(callback,
+ mainThread.DISPATCH_NORMAL);
+ },
+
/**
* Removes certain backslash-quoted characters while leaving other
* backslash-quoting sequences untouched.
* @param {string} stack The stack trace from an Error.
* @returns {[string]} The stack frames.
*/
- stackLines: function (stack) {
+ stackLines: function stackLines(stack) {
let lines = [];
let match, re = /([^]*?)@([^@\n]*)(?:\n|$)/g;
while (match = re.exec(stack))
* @param {string} url
* @returns {string|null}
*/
- getHost: function (url) {
+ getHost: function getHost(url) {
try {
return util.createURI(url).host;
}
* @param {Object} r2
* @returns {Object}
*/
- intersection: function (r1, r2) ({
+ intersection: function intersection(r1, r2) ({
get width() this.right - this.left,
get height() this.bottom - this.top,
left: Math.max(r1.left, r2.left),
},
// ripped from Firefox; modified
- unsafeURI: Class.Memoize(function () util.regexp(String.replace(<![CDATA[
+ unsafeURI: Class.Memoize(function () util.regexp(String.replace(literal(/*
[
\s
// Invisible characters (bug 452979)
// Bidi formatting characters. (RFC 3987 sections 3.2 and 4.1 paragraph 6)
U200E U200F U202A U202B U202C U202D U202E
]
- ]]>, /U/g, "\\u"),
+ */), /U/g, "\\u"),
"gx")),
losslessDecodeURI: function losslessDecodeURI(url) {
return url.split("%25").map(function (url) {
* for *obj*.
*/
makeDTD: let (map = { "'": "'", '"': """, "%": "%", "&": "&", "<": "<", ">": ">" })
- function makeDTD(obj) iter(obj)
- .map(function ([k, v]) ["<!ENTITY ", k, " '", String.replace(v == null ? "null" : typeof v == "xml" ? v.toXMLString() : v,
- typeof v == "xml" ? /['%]/g : /['"%&<>]/g,
- function (m) map[m]),
- "'>"].join(""))
- .join("\n"),
+ function makeDTD(obj) {
+ function escape(val) {
+ let isDOM = DOM.isJSONXML(val);
+ return String.replace(val == null ? "null" :
+ isDOM ? DOM.toXML(val)
+ : val,
+ isDOM ? /['%]/g
+ : /['"%&<>]/g,
+ function (m) map[m]);
+ }
+
+ return iter(obj).map(function ([k, v])
+ ["<!ENTITY ", k, " '", escape(v), "'>"].join(""))
+ .join("\n");
+ },
/**
* Converts a URI string into a URI object.
* @returns {string}
*/
objectToString: function objectToString(object, color) {
- // Use E4X literals so html is automatically quoted
- // only when it's asked for. No one wants to see <
- // on their console or :map :foo in their buffer
- // when they expect :map <C-f> :foo.
- XML.prettyPrinting = false;
- XML.ignoreWhitespace = false;
-
if (object == null)
return object + "\n";
catch (e) {
obj = Object.prototype.toString.call(obj);
}
- obj = template.highlightFilter(util.clip(obj, 150), "\n", !color ? function () "^J" : function () <span highlight="NonText">^J</span>);
- let string = <><span highlight="Title Object">{obj}</span>::
</>;
+
+ if (color) {
+ obj = template.highlightFilter(util.clip(obj, 150), "\n",
+ function () ["span", { highlight: "NonText" }, "^J"]);
+ var head = ["span", { highlight: "Title Object" }, obj, "::\n"];
+ }
+ else
+ head = util.clip(obj, 150).replace(/\n/g, "^J") + "::\n";
let keys = [];
keyIter = keys(object)
for (let i in keyIter) {
- let value = <![CDATA[<no value>]]>;
+ let value = Magic("<no value>");
try {
value = object[i];
}
}
}
- value = template.highlight(value, true, 150, !color);
- let key = <span highlight="Key">{i}</span>;
+ let key = i;
if (!isNaN(i))
i = parseInt(i);
else if (/^[A-Z_]+$/.test(i))
i = "";
- keys.push([i, <>{noVal ? value : <>{key}: {value}</>}
</>]);
+
+ if (color)
+ value = template.highlight(value, true, 150, !color);
+ else if (value instanceof Magic)
+ value = String(value);
+ else
+ value = util.clip(String(value).replace(/\n/g, "^J"), 150);
+
+ if (noVal)
+ var val = value;
+ else if (color)
+ val = [["span", { highlight: "Key" }, key], ": ", value];
+ else
+ val = key + ": " + value;
+
+ keys.push([i, val]);
}
}
catch (e) {
return a[0] - b[0];
return String.localeCompare(a[0], b[0]);
}
- string += template.map(keys.sort(compare), function (f) f[1]);
- return color ? <div style="white-space: pre-wrap;">{string}</div> : [s for each (s in string)].join("");
+
+ let vals = template.map(keys.sort(compare), function (f) f[1], "\n");
+ if (color) {
+ return ["div", { style: "white-space: pre-wrap" }, head, vals];
+ }
+ return head + vals.join("");
+ },
+
+ prettifyJSON: function prettifyJSON(data, indent, invalidOK) {
+ const INDENT = indent || " ";
+
+ function rec(data, level, seen) {
+ if (isObject(data)) {
+ if (~seen.indexOf(data))
+ throw Error("Recursive object passed");
+ seen = seen.concat([data]);
+ }
+
+ let prefix = level + INDENT;
+
+ if (data === undefined)
+ data = null;
+
+ if (~["boolean", "number"].indexOf(typeof data) || data === null)
+ res.push(String(data));
+ else if (isinstance(data, ["String", _]))
+ res.push(JSON.stringify(String(data)));
+ else if (isArray(data)) {
+ if (data.length == 0)
+ res.push("[]");
+ else {
+ res.push("[\n")
+ for (let [i, val] in Iterator(data)) {
+ if (i)
+ res.push(",\n");
+ res.push(prefix)
+ rec(val, prefix, seen);
+ }
+ res.push("\n", level, "]");
+ }
+ }
+ else if (isObject(data)) {
+ res.push("{\n")
+
+ let i = 0;
+ for (let [key, val] in Iterator(data)) {
+ if (i++)
+ res.push(",\n");
+ res.push(prefix, JSON.stringify(key), ": ")
+ rec(val, prefix, seen);
+ }
+ if (i > 0)
+ res.push("\n", level, "}")
+ else
+ res[res.length - 1] = "{}";
+ }
+ else if (invalidOK)
+ res.push({}.toString.call(data));
+ else
+ throw Error("Invalid JSON object");
+ }
+
+ let res = [];
+ rec(data, "", []);
+ return res.join("");
},
observers: {
- "dactyl-cleanup-modules": function (subject, reason) {
+ "dactyl-cleanup-modules": function cleanupModules(subject, reason) {
defineModule.loadLog.push("dactyl: util: observe: dactyl-cleanup-modules " + reason);
for (let module in values(defineModule.modules))
if (!this.rehashing)
services.observer.addObserver(this, "dactyl-rehash", true);
},
- "dactyl-rehash": function () {
+ "dactyl-rehash": function dactylRehash() {
services.observer.removeObserver(this, "dactyl-rehash");
defineModule.loadLog.push("dactyl: util: observe: dactyl-rehash");
module.init();
}
},
- "dactyl-purge": function () {
+ "dactyl-purge": function dactylPurge() {
this.rehashing = 1;
},
},
// Replace replacement <tokens>.
if (tokens)
- expr = String.replace(expr, /(\(?P)?<(\w+)>/g, function (m, n1, n2) !n1 && Set.has(tokens, n2) ? tokens[n2].dactylSource || tokens[n2].source || tokens[n2] : m);
+ expr = String.replace(expr, /(\(?P)?<(\w+)>/g,
+ function (m, n1, n2) !n1 && Set.has(tokens, n2) ? tokens[n2].dactylSource
+ || tokens[n2].source
+ || tokens[n2]
+ : m);
// Strip comments and white space.
if (/x/.test(flags))
let res = update(RegExp(expr, flags.replace("x", "")), {
closure: Class.Property(Object.getOwnPropertyDescriptor(Class.prototype, "closure")),
dactylPropertyNames: ["exec", "match", "test", "toSource", "toString", "global", "ignoreCase", "lastIndex", "multiLine", "source", "sticky"],
- iterate: function (str, idx) util.regexp.iterate(this, str, idx)
+ iterate: function iterate(str, idx) util.regexp.iterate(this, str, idx)
});
// Return a struct with properties for named parameters if we
* Reloads dactyl in entirety by disabling the add-on and
* re-enabling it.
*/
- rehash: function (args) {
- storage.session.commandlineArgs = args;
+ rehash: function rehash(args) {
+ storage.storeForSession("commandlineArgs", args);
this.timeout(function () {
this.flushCache();
this.rehashing = true;
let obj = update({}, error, {
toString: function () String(error),
- stack: <>{util.stackLines(String(error.stack || Error().stack)).join("\n").replace(/^/mg, "\t")}</>
+ stack: Magic(util.stackLines(String(error.stack || Error().stack)).join("\n").replace(/^/mg, "\t"))
});
services.console.logStringMessage(obj.stack);
* @param {Window} window
* @returns {nsISelectionController}
*/
- selectionController: function (win)
+ selectionController: function selectionController(win)
win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsISelectionDisplay)
.QueryInterface(Ci.nsISelectionController),
*
* @param {number} delay The time period for which to sleep in milliseconds.
*/
- sleep: function (delay) {
+ sleep: function sleep(delay) {
let mainThread = services.threading.mainThread;
let end = Date.now() + delay;
* @param {number} limit The maximum number of elements to return.
* @returns {[string]}
*/
- split: function (str, re, limit) {
+ split: function split(str, re, limit) {
re.lastIndex = 0;
if (!re.global)
re = RegExp(re.source || re, "g");
* interrupted by pressing <C-c>, in which case,
* Error("Interrupted") will be thrown.
*/
- threadYield: function (flush, interruptable) {
+ threadYield: function threadYield(flush, interruptable) {
this.yielders++;
try {
let mainThread = services.threading.mainThread;
* @param {nsIDOMWindow} win The window for which to find domains.
* @returns {[string]} The visible domains.
*/
- visibleHosts: function (win) {
+ visibleHosts: function visibleHosts(win) {
let res = [], seen = {};
(function rec(frame) {
try {
* @param {nsIDOMWindow} win The window for which to find URIs.
* @returns {[nsIURI]} The visible URIs.
*/
- visibleURIs: function (win) {
+ visibleURIs: function visibleURIs(win) {
let res = [], seen = {};
(function rec(frame) {
try {
catch (e) {
throw e.stack ? e : Error(e);
}
- },
-
- xmlToDom: function () DOM.fromXML.apply(DOM, arguments)
+ }
}, {
Array: array
});
* @singleton
*/
var GlobalMath = Math;
-var Math = update(Object.create(GlobalMath), {
+this.Math = update(Object.create(GlobalMath), {
/**
* Returns the specified *value* constrained to the range *min* - *max*.
*
-
Boolean /* JavaScript booleans */ color: red;
Function /* JavaScript functions */ color: navy;
Null /* JavaScript null values */ color: blue;
Disabled /* Disabled items */ \
color: gray !important;
+!Private;xul|window[privatebrowsingmode] /* A private browsing window */
+
+Private StatusLine::before /* From the default theme: */ \
+ display: -moz-box; \
+ content: ""; \
+ background: url("chrome://browser/skin/privatebrowsing-mask.png") center no-repeat; \
+ width: 30px;
+
CmdLine;>*;;FontFixed /* The command line */ \
padding: 1px !important;
CmdPrompt;.dactyl-commandline-prompt /* The default styling form the command prompt */
completions: [""],
cleanup: ["silent !rm some-nonexistent-rc.penta"]
},
- mksyntax: {
- noOutput: [
- "some-nonexistent-pentadactyl-dir/",
- "! some-nonexistent-pentadactyl-dir/",
- "some-nonexistent-pentadactyl-dir/foo.vim",
- "! some-nonexistent-pentadactyl-dir/foo.vim",
- ],
+ mkvimruntime: {
error: [
- "some-nonexistent-pentadactyl-dir/",
- "some-nonexistent-pentadactyl-dir/foo.vim"
+ "some-nonexistent-pentadactyl-dir/"
],
completions: [
["", hasItems]
- ],
- cleanup: ["silent !rm -r some-nonexistent-pentadactyl-dir/"]
+ ]
},
get mlistkeys() this.listcommands,
mmap: {},
time: {
error: ["", ":some-nonexistent-command"/*, "some_nonexistent_reference"*/], // FIXME
singleOutput: [":js null", "null"]
-
},
get tlistkeys() this.listcommands,
tmap: {},
error: ["foo"],
multiOutput: [
["", function (msg) {
- var res = /(\w+dactyl) (\S+) \(([\^)]+)\) running on:\nMozilla/;
+ var res = /(\w+dactyl) (\S+) \(([\^)]+)\) running on:\nMozilla/.exec(msg);
return res && res[2] != "null" && res[3] != "null";
}]
]
});
},
- commandline: function () {
+ commandline: function initCommandline() {
player.CommandMode = Class("CommandSearchViewMode", modules.CommandMode, {
init: function init(mode) {
this.mode = mode;
get onSubmit() player.closure.onSearchSubmit
});
},
- commands: function () {
+ commands: function initCommands() {
commands.add(["f[ilter]"],
"Filter tracks based on keywords {genre/artist/album/track}",
function (args) {
},
{ argCount: "1" });
},
- completion: function () {
+ completion: function initCompletion() {
completion.album = function album(context, artist) {
context.title = ["Album"];
context.completions = [[v, ""] for ([, v] in Iterator(library.getAlbums(artist)))];
context.completions = [[v, ""] for ([, v] in Iterator(library.getTracks(artist, album)))];
};
},
- mappings: function () {
+ mappings: function initMappings() {
mappings.add([modes.PLAYER],
["x"], "Play track",
function () { ex.playerplay(); });
};
}
},
- options: function () {
+ options: function initOptions() {
options.add(["repeat"],
"Set the playback repeat mode",
"number", 0,
+++ /dev/null
-VIMBALL = melodactyl.vba
-
-vimball: mkvimball.txt syntax/melodactyl.vim ftdetect/melodactyl.vim
- -echo '%MkVimball! ${VIMBALL} .' | vim -u NORC -N -e -s mkvimball.txt
-
-all: vimball
-
-clean:
- rm -f ${VIMBALL}
+++ /dev/null
-au BufNewFile,BufRead *melodactylrc*,*.melo set filetype=melodactyl
+++ /dev/null
-syntax/melodactyl.vim
-ftdetect/melodactyl.vim
<ul replace="features-list">
<li>Vim-like keybindings (<k>h</k>, <k>j</k>, <k>gg</k>, <k>ZZ</k>, <k name="C-f"/>, etc.)</li>
<li>Ex commands (<ex>:quit</ex>, <ex>:open www.foo.com</ex>, …)</li>
- <li>Tab completion for all commands, highly configurable via <o>wildmode</o>, <o>autocomplete</o>, ...</li>
+ <li>Tab completion for all commands, highly configurable via <o>wildmode</o>, <o>autocomplete</o>, …</li>
<li>Hit-a-hint like navigation of links (start with <k>f</k> to follow a link)</li>
<li>Advanced completion of bookmark and history URLs</li>
<li>Vim-like status line with a Wget-like progress bar</li>
-1.0rc1:
+1.1:
+ • Vim runtime files:
+ - renamed :mksyntax to :mkvimruntime which now generates
+ all Vim related files.
+ - Vimball packages are no longer available.
+ • Removed <F1> and <A-F1> mappings.
+ • Add :private command.
+ • Better per-window private browsing support.
+
+1.0:
• Extensive Firefox 4 support, including:
- Fully restartless. Can now be installed, uninstalled,
enabled, disabled, and upgraded without restarting Firefox.
8 add support for filename special characters such as %
8 :redir and 'verbosefile'
8 Add information to dactyl/HACKING file about testing and optimization
+7 handle Print Preview 'mode' properly
7 describe-key command (prompt for a key and display its binding with documentation)
7 use ctrl-n/p in insert mode for word completion
7 make an option to disable session saving by default when you close Firefox
"host": "Firefox",
"hostbin": "firefox",
+ "module-paths": [
+ "resource://dactyl/"
+ ],
+
"autocommands": {
"BookmarkAdd": "Triggered after a page is bookmarked",
"BookmarkChange": "Triggered after a page's bookmark is changed",
},
removeTab: function removeTab(tab) {
- if (this.tabbrowser.mTabs.length > 1)
+ if (window.gInPrintPreviewMode)
+ window.PrintUtils.exitPrintPreview();
+ else if (this.tabbrowser.mTabs.length > 1)
this.tabbrowser.removeTab(tab);
else {
if (modules.buffer.uri.spec !== "about:blank" || window.getWebNavigation().sessionHistory.count > 0) {
}, {
}, {
- commands: function (dactyl, modules, window) {
+ commands: function initCommands(dactyl, modules, window) {
const { commands, completion, config } = modules;
const { document } = window;
privateData: true
});
},
- completion: function (dactyl, modules, window) {
+ completion: function initCompletion(dactyl, modules, window) {
const { CompletionContext, bookmarkcache, completion } = modules;
const { document } = window;
context.completions = Array.map(menu.childNodes, function (n) [n.getAttribute("label"), ""]);
};
},
- events: function (dactyl, modules, window) {
+ events: function initEvents(dactyl, modules, window) {
modules.events.listen(window, "SidebarFocused", function (event) {
modules.config.lastSidebar = window.document.getElementById("sidebar-box")
.getAttribute("sidebarcommand");
"Handled by " + config.host,
function () Events.PASS_THROUGH);
},
- options: function (dactyl, modules, window) {
+ options: function initOptions(dactyl, modules, window) {
modules.options.add(["online"],
"Enables or disables offline mode",
"boolean", true,
+++ /dev/null
-VIMBALL = pentadactyl.vba
-
-vimball: mkvimball.txt syntax/pentadactyl.vim ftdetect/pentadactyl.vim
- -echo '%MkVimball! ${VIMBALL} .' | vim -u NORC -N -e -s mkvimball.txt
-
-all: vimball
-
-clean:
- rm -f ${VIMBALL}
+++ /dev/null
-au BufNewFile,BufRead *pentadactylrc*,*.penta set filetype=pentadactyl
+++ /dev/null
-syntax/pentadactyl.vim
-ftdetect/pentadactyl.vim
em:id="pentadactyl@dactyl.googlecode.com"
em:type="2"
em:name="Pentadactyl"
- em:version="1.0"
+ em:version="1.1pre"
em:description="Firefox for Vim and Links addicts"
em:homepageURL="http://5digits.org/pentadactyl"
em:bootstrap="true"
<em:targetApplication>
<Description
em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
- em:minVersion="4.0"
- em:maxVersion="14.*"/>
+ em:minVersion="8.0"
+ em:maxVersion="22.0a1"/>
</em:targetApplication>
</Description>
</RDF>
}
}, {
}, {
- commands: function () {
+ commands: function initCommands() {
commands.add(["con[tact]"],
"Add an address book entry",
function (args) {
function (args) { addressbook.list(args.string, args.bang); },
{ bang: true });
},
- mappings: function () {
+ mappings: function initMappings() {
var myModes = config.mailModes;
mappings.add(myModes, ["a"],
+++ /dev/null
-VIMBALL = teledactyl.vba
-
-vimball: mkvimball.txt syntax/teledactyl.vim ftdetect/teledactyl.vim
- -echo '%MkVimball! ${VIMBALL} .' | vim -u NORC -N -e -s mkvimball.txt
-
-all: vimball
-
-clean:
- rm -f ${VIMBALL}
+++ /dev/null
-au BufNewFile,BufRead *teledactylrc*,*.tele set filetype=teledactyl
+++ /dev/null
-syntax/teledactyl.vim
-ftdetect/teledactyl.vim
<ul replace="features-list">
<li>Vim-like keybindings (<k>h</k>, <k>j</k>, <k>gg</k>, <k>ZZ</k>, <k name="C-f"/>, etc.)</li>
<li>Ex commands (<ex>:quit</ex>, <ex>:open www.foo.com</ex>, …)</li>
- <li>Tab completion for all commands, highly configurable via <o>wildmode</o>, <o>autocomplete</o>, ...</li>
+ <li>Tab completion for all commands, highly configurable via <o>wildmode</o>, <o>autocomplete</o>, …</li>
<li>Hit-a-hint like navigation of links (start with <k>f</k> to follow a link)</li>
<li>Advanced completion of bookmark and history URLs</li>
<li>Vim-like status line with a Wget-like progress bar</li>