mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2026-01-06 16:34:14 +01:00
Major documentation updates and formatting fixes, and many, many other changes thanks to an MQ glitch, including:
* Significant completion speed improvements * Significantly improve startup speed, in large part by lazily instantiating Options and Commands, lazily installing highlight stylesheets, etc. * Update logos and icons, fix atrocious about page * Fix Teledactyl * JavaScript completion now avoids accessing property values * Add Option#persist to define which options are saved with :mkp * Add new Dactyl component which holds add-on-specific configuration information and removes need for separate components for each dactyl host * Several fixes for latest nightlies * Significant code cleanup and many bug fixes --HG-- rename : muttator/AUTHORS => teledactyl/AUTHORS rename : muttator/Donors => teledactyl/Donors rename : muttator/Makefile => teledactyl/Makefile rename : muttator/NEWS => teledactyl/NEWS rename : muttator/TODO => teledactyl/TODO rename : muttator/chrome.manifest => teledactyl/chrome.manifest rename : muttator/components/commandline-handler.js => teledactyl/components/commandline-handler.js rename : muttator/components/protocols.js => teledactyl/components/protocols.js rename : muttator/content/addressbook.js => teledactyl/content/addressbook.js rename : muttator/content/compose/compose.js => teledactyl/content/compose/compose.js rename : muttator/content/compose/compose.xul => teledactyl/content/compose/compose.xul rename : muttator/content/compose/dactyl.dtd => teledactyl/content/compose/dactyl.dtd rename : muttator/content/compose/dactyl.xul => teledactyl/content/compose/dactyl.xul rename : muttator/content/config.js => teledactyl/content/config.js rename : muttator/content/dactyl.dtd => teledactyl/content/dactyl.dtd rename : muttator/content/logo.png => teledactyl/content/logo.png rename : muttator/content/mail.js => teledactyl/content/mail.js rename : muttator/content/muttator.xul => teledactyl/content/pentadactyl.xul rename : muttator/contrib/vim/Makefile => teledactyl/contrib/vim/Makefile rename : muttator/contrib/vim/ftdetect/muttator.vim => teledactyl/contrib/vim/ftdetect/muttator.vim rename : muttator/contrib/vim/mkvimball.txt => teledactyl/contrib/vim/mkvimball.txt rename : muttator/contrib/vim/syntax/muttator.vim => teledactyl/contrib/vim/syntax/muttator.vim rename : muttator/install.rdf => teledactyl/install.rdf rename : muttator/locale/en-US/Makefile => teledactyl/locale/en-US/Makefile rename : muttator/locale/en-US/all.xml => teledactyl/locale/en-US/all.xml rename : muttator/locale/en-US/autocommands.xml => teledactyl/locale/en-US/autocommands.xml rename : muttator/locale/en-US/gui.xml => teledactyl/locale/en-US/gui.xml rename : muttator/locale/en-US/intro.xml => teledactyl/locale/en-US/intro.xml rename : muttator/skin/icon.png => teledactyl/skin/icon.png
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2009 by Kris Maglione <maglione.k@gmail.com>
|
||||
// Copyright (c) 2009-2010 by 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.
|
||||
@@ -11,6 +11,74 @@ const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let objproto = Object.prototype;
|
||||
let hasOwnProperty = objproto.hasOwnProperty;
|
||||
|
||||
if (!Object.create)
|
||||
Object.create = function (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 (obj, prop, desc) {
|
||||
let value = desc.value;
|
||||
if ("value" in desc)
|
||||
if (desc.writable && !objproto.__lookupGetter__.call(obj, prop)
|
||||
&& !objproto.__lookupSetter__.call(obj, prop))
|
||||
obj[prop] = value;
|
||||
else {
|
||||
objproto.__defineGetter__.call(obj, prop, function () value);
|
||||
if (desc.writable)
|
||||
objproto.__defineSetter__.call(obj, prop, function (val) { value = val; });
|
||||
}
|
||||
|
||||
if ("get" in desc)
|
||||
objproto.__defineGetter__.call(obj, prop, desc.get);
|
||||
if ("set" in desc)
|
||||
objproto.__defineSetter__.call(obj, prop, desc.set);
|
||||
}
|
||||
if (!Object.getOwnPropertyDescriptor)
|
||||
Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(obj, prop) {
|
||||
if (!hasOwnProperty.call(obj, prop))
|
||||
return undefined;
|
||||
let desc = {
|
||||
configurable: true,
|
||||
enumerable: objproto.propertyIsEnumerable.call(obj, prop),
|
||||
};
|
||||
var get = obj.__lookupGetter__(prop),
|
||||
set = obj.__lookupSetter__(prop);
|
||||
if (!get && !set) {
|
||||
desc.value = obj[prop];
|
||||
desc.writable = true;
|
||||
}
|
||||
if (get)
|
||||
desc.get = get;
|
||||
if (set)
|
||||
desc.set = set;
|
||||
return desc;
|
||||
}
|
||||
if (!Object.getOwnPropertyNames)
|
||||
Object.getOwnPropertyNames = function getOwnPropertyNames(obj) {
|
||||
// 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;
|
||||
};
|
||||
if (!Object.getPrototypeOf)
|
||||
Object.getPrototypeOf = function (obj) obj.__proto__;
|
||||
if (!Object.keys)
|
||||
Object.keys = function (obj)
|
||||
Object.getOwnPropertyNames(obj).filter(function (k) objproto.propertyIsEnumerable.call(obj, k));
|
||||
|
||||
let use = {};
|
||||
let loaded = {};
|
||||
let currentModule;
|
||||
@@ -30,17 +98,21 @@ function defmodule(name, module, params) {
|
||||
}
|
||||
currentModule = module;
|
||||
}
|
||||
|
||||
defmodule.loadLog = [];
|
||||
// Object.defineProperty(defmodule.loadLog, "push", { value: function (val) { dump(val + "\n"); this[this.length] = val } });
|
||||
Object.defineProperty(defmodule.loadLog, "push", { value: function (val) { dump(val + "\n"); this[this.length] = val } });
|
||||
defmodule.modules = [];
|
||||
defmodule.times = {};
|
||||
defmodule.time = function (major, minor, func, self) {
|
||||
defmodule.times = { all: 0 };
|
||||
defmodule.time = function time(major, minor, func, self) {
|
||||
let time = Date.now();
|
||||
let res = func.apply(self, Array.slice(arguments, 4));
|
||||
let delta = Date.now() - time;
|
||||
defmodule.times.all += delta;
|
||||
defmodule.times[major] = (defmodule.times[major] || 0) + delta;
|
||||
if (minor)
|
||||
if (minor) {
|
||||
defmodule.times[":" + minor] = (defmodule.times[":" + minor] || 0) + delta;
|
||||
defmodule.times[major + ":" + minor] = (defmodule.times[major + ":" + minor] || 0) + delta;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -66,12 +138,12 @@ defmodule("base", this, {
|
||||
// sed -n 's/^(const|function) ([a-zA-Z0-9_]+).*/ "\2",/p' base.jsm | sort | fmt
|
||||
exports: [
|
||||
"Cc", "Ci", "Class", "Cr", "Cu", "Module", "Object", "Runnable",
|
||||
"Struct", "StructBase", "Timer", "XPCOMUtils", "allkeys", "array",
|
||||
"call", "callable", "curry", "debuggerProperties", "defmodule", "dict",
|
||||
"Struct", "StructBase", "Timer", "UTF8", "XPCOMUtils", "array",
|
||||
"call", "callable", "curry", "debuggerProperties", "defmodule",
|
||||
"endmodule", "extend", "foreach", "isarray", "isgenerator",
|
||||
"isinstance", "isobject", "isstring", "issubclass", "iter", "keys",
|
||||
"memoize", "properties", "requiresMainThread", "set", "update",
|
||||
"values",
|
||||
"isinstance", "isobject", "isstring", "issubclass", "iter", "iterall",
|
||||
"keys", "memoize", "properties", "requiresMainThread", "set",
|
||||
"update", "values",
|
||||
],
|
||||
use: ["services"]
|
||||
});
|
||||
@@ -83,33 +155,13 @@ function Runnable(self, func, args) {
|
||||
};
|
||||
}
|
||||
|
||||
function allkeys(obj) {
|
||||
let ret = {};
|
||||
try {
|
||||
for (; obj; obj = obj.__proto__) {
|
||||
services.get("debugger").wrapValue(obj).getProperties(ret, {});
|
||||
for (let prop in values(ret.value))
|
||||
yield prop.name.stringValue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
let __iterator__ = obj.__iterator__;
|
||||
try {
|
||||
if ("__iterator__" in obj) {
|
||||
yield "__iterator__";
|
||||
delete obj.__iterator__;
|
||||
}
|
||||
for (let k in obj)
|
||||
yield k;
|
||||
}
|
||||
finally {
|
||||
if (__iterator__)
|
||||
obj.__iterator__ = __iterator__;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all of the top-level properties of an object, by
|
||||
* way of the debugger.
|
||||
*
|
||||
* @param {object} obj
|
||||
* @returns [jsdIProperty]
|
||||
*/
|
||||
function debuggerProperties(obj) {
|
||||
if (loaded.services && services.get("debugger").isOn) {
|
||||
let ret = {};
|
||||
@@ -118,58 +170,89 @@ function debuggerProperties(obj) {
|
||||
}
|
||||
}
|
||||
|
||||
let hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
if (!Object.keys)
|
||||
Object.keys = function keys(obj) [k for (k in obj) if (hasOwnProperty.call(obj, k))];
|
||||
|
||||
if (!Object.getOwnPropertyNames)
|
||||
Object.getOwnPropertyNames = function getOwnPropertyNames(obj) {
|
||||
let res = debuggerProperties(obj);
|
||||
if (res)
|
||||
return [prop.name.stringValue for (prop in values(res))];
|
||||
return Object.keys(obj);
|
||||
}
|
||||
|
||||
function properties(obj, prototypes) {
|
||||
/**
|
||||
* Iterates over the names of all of the top-level properties of an
|
||||
* object or, if prototypes is given, all of the properties in the
|
||||
* prototype chain below the top. Uses the debugger if possible.
|
||||
*
|
||||
* @param {object} obj The object to inspect.
|
||||
* @param {boolean} properties Whether to inspect the prototype chain
|
||||
* @default false
|
||||
* @returns {Generator}
|
||||
*/
|
||||
function properties(obj, prototypes, debugger_) {
|
||||
let orig = obj;
|
||||
let seen = {};
|
||||
for (; obj; obj = prototypes && obj.__proto__) {
|
||||
try {
|
||||
var iter = values(Object.getOwnPropertyNames(obj));
|
||||
var iter = (!debugger_ || !services.get("debugger").isOn) && values(Object.getOwnPropertyNames(obj));
|
||||
}
|
||||
catch (e) {
|
||||
catch (e) {}
|
||||
if (!iter)
|
||||
iter = (prop.name.stringValue for (prop in values(debuggerProperties(obj))));
|
||||
}
|
||||
|
||||
for (let key in iter)
|
||||
if (!prototypes || !set.add(seen, key) && obj != orig)
|
||||
yield key
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over all of the top-level, iterable property names of an
|
||||
* object.
|
||||
*
|
||||
* @param {object} obj The object to inspect.
|
||||
* @returns {Generator}
|
||||
*/
|
||||
function keys(obj) {
|
||||
for (var k in obj)
|
||||
if (hasOwnProperty.call(obj, k))
|
||||
yield k;
|
||||
}
|
||||
/**
|
||||
* Iterates over all of the top-level, iterable property values of an
|
||||
* object.
|
||||
*
|
||||
* @param {object} obj The object to inspect.
|
||||
* @returns {Generator}
|
||||
*/
|
||||
function values(obj) {
|
||||
for (var k in obj)
|
||||
if (hasOwnProperty.call(obj, k))
|
||||
yield obj[k];
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over an iterable object and calls a callback for each
|
||||
* element.
|
||||
*
|
||||
* @param {object} iter The iterator.
|
||||
* @param {function} fn The callback.
|
||||
* @param {object} self The this object for 'fn'.
|
||||
*/
|
||||
function foreach(iter, fn, self) {
|
||||
for (let val in iter)
|
||||
fn.call(self, val);
|
||||
}
|
||||
|
||||
function dict(ary) {
|
||||
var obj = {};
|
||||
for (var i = 0; i < ary.length; i++) {
|
||||
var val = ary[i];
|
||||
obj[val[0]] = val[1];
|
||||
}
|
||||
return obj;
|
||||
/**
|
||||
* Iterates over each iterable argument in turn, yielding each value.
|
||||
*
|
||||
* @returns {Generator}
|
||||
*/
|
||||
function iterall() {
|
||||
for (let i = 0; i < arguments.length; i++)
|
||||
for (let j in Iterator(arguments[i]))
|
||||
yield j;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility for managing sets of strings. Given an array, returns an
|
||||
* object with one key for each value thereof.
|
||||
*
|
||||
* @param {[string]} ary @optional
|
||||
* @returns {object}
|
||||
*/
|
||||
function set(ary) {
|
||||
let obj = {};
|
||||
if (ary)
|
||||
@@ -177,33 +260,86 @@ function set(ary) {
|
||||
obj[ary[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
/**
|
||||
* Adds an element to a set and returns true if the element was
|
||||
* previously contained.
|
||||
*
|
||||
* @param {object} set The set.
|
||||
* @param {string} key The key to add.
|
||||
* @returns boolean
|
||||
*/
|
||||
set.add = function (set, key) {
|
||||
let res = this.has(set, key);
|
||||
set[key] = true;
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* Returns true if the given set contains the given key.
|
||||
*
|
||||
* @param {object} set The set.
|
||||
* @param {string} key The key to check.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
set.has = function (set, key) hasOwnProperty.call(set, key);
|
||||
set.remove = function (set, key) { delete set[key]; }
|
||||
/**
|
||||
* Returns a new set containing the members of the first argument which
|
||||
* do not exist in any of the other given arguments.
|
||||
*
|
||||
* @param {object} set The set.
|
||||
* @returns {object}
|
||||
*/
|
||||
set.subtract = function (set) {
|
||||
set = update({}, set);
|
||||
for (let i = 1; i < arguments.length; i++)
|
||||
for (let k in keys(arguments[i]))
|
||||
delete set[k];
|
||||
return set;
|
||||
}
|
||||
/**
|
||||
* Removes an element from a set and returns true if the element was
|
||||
* previously contained.
|
||||
*
|
||||
* @param {object} set The set.
|
||||
* @param {string} key The key to remove.
|
||||
* @returns boolean
|
||||
*/
|
||||
set.remove = function (set, key) {
|
||||
let res = set.has(set, key);
|
||||
delete set[key];
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over an arbitrary object. The following iterators types are
|
||||
* supported, and work as a user would expect:
|
||||
*
|
||||
* • nsIDOMNodeIterator
|
||||
* • mozIStorageStatement
|
||||
*
|
||||
* Additionally, the following array-like objects yield a tuple of the
|
||||
* form [index, element] for each contained element:
|
||||
*
|
||||
* • nsIDOMHTMLCollection
|
||||
* • nsIDOMNodeList
|
||||
*
|
||||
* and the following likewise yield one element of the form
|
||||
* [name, element] for each contained element:
|
||||
*
|
||||
* • nsIDOMNamedNodeMap
|
||||
*
|
||||
* Duck typing is implemented for the any other type. If the object
|
||||
* contains the "enumerator" property, iter is called on that. If the
|
||||
* property is a function, it is called first. If it contains the
|
||||
* property "getNext" along with either "hasMoreItems" or "hasMore", it
|
||||
* is iterated over appropriately.
|
||||
*
|
||||
* For all other cases, this function behaves exactly like the Iterator
|
||||
* function.
|
||||
*
|
||||
* @param {object} obj
|
||||
* @returns {Generator}
|
||||
*/
|
||||
function iter(obj) {
|
||||
if (obj instanceof Ci.nsISimpleEnumerator)
|
||||
return (function () {
|
||||
while (obj.hasMoreElements())
|
||||
yield obj.getNext();
|
||||
})();
|
||||
if (isinstance(obj, [Ci.nsIStringEnumerator, Ci.nsIUTF8StringEnumerator]))
|
||||
return (function () {
|
||||
while (obj.hasMore())
|
||||
yield obj.getNext();
|
||||
})();
|
||||
if (isinstance(obj, Ci.nsIDOMNodeIterator))
|
||||
return (function () {
|
||||
try {
|
||||
while (true)
|
||||
yield obj.nextNode();
|
||||
}
|
||||
catch (e) {}
|
||||
})();
|
||||
if (isinstance(obj, [Ci.nsIDOMHTMLCollection, Ci.nsIDOMNodeList]))
|
||||
return array.iteritems(obj);
|
||||
if (obj instanceof Ci.nsIDOMNamedNodeMap)
|
||||
@@ -217,14 +353,51 @@ function iter(obj) {
|
||||
yield obj.row;
|
||||
obj.reset();
|
||||
})(obj);
|
||||
if ("getNext" in obj) {
|
||||
if ("hasMoreElements" in obj)
|
||||
return (function () {
|
||||
while (obj.hasMoreElements())
|
||||
yield obj.getNext();
|
||||
})();
|
||||
if ("hasMore" in obj)
|
||||
return (function () {
|
||||
while (obj.hasMore())
|
||||
yield obj.getNext();
|
||||
})();
|
||||
}
|
||||
if ("enumerator" in obj) {
|
||||
if (callable(obj.enumerator))
|
||||
return iter(obj.enumerator());
|
||||
return iter(obj.enumerator);
|
||||
}
|
||||
return Iterator(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if both arguments are functions and
|
||||
* (targ() instaneof src) would also return true.
|
||||
*
|
||||
* @param {function} targ
|
||||
* @param {function} src
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function issubclass(targ, src) {
|
||||
return src === targ ||
|
||||
targ && typeof targ === "function" && targ.prototype instanceof src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if targ is an instance or src. If src is an array,
|
||||
* returns true if targ is an instance of any element of src. If src is
|
||||
* the object form of a primitive type, returns true if targ is a
|
||||
* non-boxed version of the type, i.e., if (typeof targ == "string"),
|
||||
* isinstance(targ, String) is true. Finally, if src is a string,
|
||||
* returns true if ({}.toString.call(targ) == "[object <src>]").
|
||||
*
|
||||
* @param {object} targ The object to check.
|
||||
* @param {object|string|[object|string]} src The types to check targ against.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isinstance(targ, src) {
|
||||
const types = {
|
||||
boolean: Boolean,
|
||||
@@ -234,8 +407,8 @@ function isinstance(targ, src) {
|
||||
}
|
||||
src = Array.concat(src);
|
||||
for (var i = 0; i < src.length; i++) {
|
||||
if (typeof src[i] == "string") {
|
||||
if (Object.prototype.toString.call(targ) == "[object " + src[i] + "]")
|
||||
if (typeof src[i] === "string") {
|
||||
if (objproto.toString.call(targ) === "[object " + src[i] + "]")
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@@ -249,9 +422,10 @@ function isinstance(targ, src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isobject(obj) {
|
||||
return typeof obj === "object" && obj != null;
|
||||
}
|
||||
/**
|
||||
* Returns true if obj is a non-null object.
|
||||
*/
|
||||
function isobject(obj) typeof obj === "object" && obj != null;
|
||||
|
||||
/**
|
||||
* Returns true if and only if its sole argument is an
|
||||
@@ -259,9 +433,8 @@ function isobject(obj) {
|
||||
* any window, frame, namespace, or execution context, which
|
||||
* is not the case when using (obj instanceof Array).
|
||||
*/
|
||||
function isarray(val) {
|
||||
return Object.prototype.toString.call(val) == "[object Array]";
|
||||
}
|
||||
const isarray = Array.isArray ||
|
||||
function isarray(val) objproto.toString.call(val) == "[object Array]";
|
||||
|
||||
/**
|
||||
* Returns true if and only if its sole argument is an
|
||||
@@ -269,9 +442,7 @@ function isarray(val) {
|
||||
* functions containing the 'yield' statement and generator
|
||||
* statements such as (x for (x in obj)).
|
||||
*/
|
||||
function isgenerator(val) {
|
||||
return Object.prototype.toString.call(val) == "[object Generator]";
|
||||
}
|
||||
function isgenerator(val) objproto.toString.call(val) == "[object Generator]";
|
||||
|
||||
/**
|
||||
* Returns true if and only if its sole argument is a String,
|
||||
@@ -280,28 +451,30 @@ function isgenerator(val) {
|
||||
* namespace, or execution context, which is not the case when
|
||||
* using (obj instanceof String) or (typeof obj == "string").
|
||||
*/
|
||||
function isstring(val) {
|
||||
return Object.prototype.toString.call(val) == "[object String]";
|
||||
}
|
||||
function isstring(val) objproto.toString.call(val) == "[object String]";
|
||||
|
||||
/**
|
||||
* Returns true if and only if its sole argument may be called
|
||||
* as a function. This includes classes and function objects.
|
||||
*/
|
||||
function callable(val) {
|
||||
return typeof val === "function";
|
||||
}
|
||||
function callable(val) typeof val === "function";
|
||||
|
||||
function call(fn) {
|
||||
fn.apply(arguments[1], Array.slice(arguments, 2));
|
||||
return fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Memoizes an object property value.
|
||||
*
|
||||
* @param {object} obj The object to add the property to.
|
||||
* @param {string} key The property name.
|
||||
* @param {function} getter The function which will return the initial
|
||||
* value of the property.
|
||||
*/
|
||||
function memoize(obj, key, getter) {
|
||||
obj.__defineGetter__(key, function () {
|
||||
delete obj[key];
|
||||
return obj[key] = getter(obj, key);
|
||||
});
|
||||
obj.__defineGetter__(key, function ()
|
||||
Class.replaceProperty(this, key, getter.call(this, key)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,24 +563,15 @@ function update(target) {
|
||||
for (let i = 1; i < arguments.length; i++) {
|
||||
let src = arguments[i];
|
||||
Object.getOwnPropertyNames(src || {}).forEach(function (k) {
|
||||
var get = src.__lookupGetter__(k),
|
||||
set = src.__lookupSetter__(k);
|
||||
if (!get && !set) {
|
||||
var v = src[k];
|
||||
target[k] = v;
|
||||
if (target.__proto__ && callable(v)) {
|
||||
v.superapply = function (self, args) {
|
||||
return target.__proto__[k].apply(self, args);
|
||||
};
|
||||
v.supercall = function (self) {
|
||||
return v.superapply(self, Array.slice(arguments, 1));
|
||||
};
|
||||
}
|
||||
let desc = Object.getOwnPropertyDescriptor(src, k);
|
||||
if (desc.value && callable(desc.value) && Object.getPrototypeOf(target)) {
|
||||
let func = desc.value;
|
||||
desc.value.superapply = function (self, args)
|
||||
Object.getPrototypeOf(target)[k].apply(self, args);
|
||||
desc.value.supercall = function (self)
|
||||
func.superapply(self, Array.slice(arguments, 1));
|
||||
}
|
||||
if (get)
|
||||
target.__defineGetter__(k, get);
|
||||
if (set)
|
||||
target.__defineSetter__(k, set);
|
||||
Object.defineProperty(target, k, desc);
|
||||
});
|
||||
}
|
||||
return target;
|
||||
@@ -424,14 +588,19 @@ function update(target) {
|
||||
* @param {Object} overrides @optional
|
||||
*/
|
||||
function extend(subclass, superclass, overrides) {
|
||||
subclass.prototype = { __proto__: superclass.prototype };
|
||||
subclass.superclass = superclass;
|
||||
|
||||
try {
|
||||
subclass.prototype = Object.create(superclass.prototype);
|
||||
}
|
||||
catch(e) {
|
||||
dump(e + "\n" + String.replace(e.stack, /^/gm, " ") + "\n\n");
|
||||
}
|
||||
update(subclass.prototype, overrides);
|
||||
|
||||
subclass.superclass = superclass.prototype;
|
||||
subclass.prototype.constructor = subclass;
|
||||
subclass.prototype.__class__ = subclass;
|
||||
subclass.prototype._class_ = subclass;
|
||||
|
||||
if (superclass.prototype.constructor === Object.prototype.constructor)
|
||||
if (superclass.prototype.constructor === objproto.constructor)
|
||||
superclass.prototype.constructor = superclass;
|
||||
}
|
||||
|
||||
@@ -459,22 +628,6 @@ function extend(subclass, superclass, overrides) {
|
||||
* @returns {function} The constructor for the resulting class.
|
||||
*/
|
||||
function Class() {
|
||||
function constructor() {
|
||||
let self = {
|
||||
__proto__: Constructor.prototype,
|
||||
constructor: Constructor,
|
||||
get closure() {
|
||||
delete this.closure;
|
||||
function closure(fn) function () fn.apply(self, arguments);
|
||||
for (let k in this)
|
||||
if (!this.__lookupGetter__(k) && callable(this[k]))
|
||||
closure[k] = closure(self[k]);
|
||||
return this.closure = closure;
|
||||
}
|
||||
};
|
||||
var res = self.init.apply(self, arguments);
|
||||
return res !== undefined ? res : self;
|
||||
}
|
||||
|
||||
var args = Array.slice(arguments);
|
||||
if (isstring(args[0]))
|
||||
@@ -483,21 +636,43 @@ function Class() {
|
||||
if (callable(args[0]))
|
||||
superclass = args.shift();
|
||||
|
||||
var Constructor = eval("(function " + (name || superclass.name).replace(/\W/g, "_") +
|
||||
String.substr(constructor, 20) + ")");
|
||||
Constructor.__proto__ = superclass;
|
||||
Constructor.name = name || superclass.name;
|
||||
var Constructor = eval(String.replace(<![CDATA[
|
||||
(function constructor() {
|
||||
let self = Object.create(Constructor.prototype, {
|
||||
constructor: { value: Constructor },
|
||||
closure: {
|
||||
configurable: true,
|
||||
get: function () {
|
||||
function closure(fn) function () fn.apply(self, arguments);
|
||||
for (let k in iterall(properties(this),
|
||||
properties(this, true)))
|
||||
if (!this.__lookupGetter__(k) && callable(this[k]))
|
||||
closure[k] = closure(self[k]);
|
||||
Object.defineProperty(this, "closure", { value: closure });
|
||||
return closure;
|
||||
}
|
||||
}
|
||||
});
|
||||
var res = self.init.apply(self, arguments);
|
||||
return res !== undefined ? res : self;
|
||||
})]]>,
|
||||
"constructor", (name || superclass.classname).replace(/\W/g, "_")));
|
||||
Constructor.classname = name || superclass.classname || superclass.name;
|
||||
|
||||
if (!("init" in superclass.prototype)) {
|
||||
var superc = superclass;
|
||||
if ("init" in superclass.prototype)
|
||||
Constructor.__proto__ = superclass;
|
||||
else {
|
||||
let superc = superclass;
|
||||
superclass = function Shim() {};
|
||||
extend(superclass, superc, {
|
||||
init: superc
|
||||
});
|
||||
superclass.__proto__ = superc;
|
||||
}
|
||||
|
||||
extend(Constructor, superclass, args[0]);
|
||||
update(Constructor, args[1]);
|
||||
Constructor.__proto__ = superclass;
|
||||
args = args.slice(2);
|
||||
Array.forEach(args, function (obj) {
|
||||
if (callable(obj))
|
||||
@@ -506,18 +681,11 @@ function Class() {
|
||||
});
|
||||
return Constructor;
|
||||
}
|
||||
if (Object.defineProperty)
|
||||
Class.replaceProperty = function (obj, prop, value) {
|
||||
Object.defineProperty(obj, prop, { configurable: true, enumerable: true, value: value, writable: true });
|
||||
return value;
|
||||
};
|
||||
else
|
||||
Class.replaceProperty = function (obj, prop, value) {
|
||||
obj.__defineGetter__(prop, function () value);
|
||||
obj.__defineSetter__(prop, function (val) { value = val; });
|
||||
return value;
|
||||
};
|
||||
Class.toString = function () "[class " + this.name + "]";
|
||||
Class.replaceProperty = function (obj, prop, value) {
|
||||
Object.defineProperty(obj, prop, { configurable: true, enumerable: true, value: value, writable: true });
|
||||
return value;
|
||||
};
|
||||
Class.toString = function () "[class " + this.classname + "]";
|
||||
Class.prototype = {
|
||||
/**
|
||||
* Initializes new instances of this class. Called automatically
|
||||
@@ -525,7 +693,7 @@ Class.prototype = {
|
||||
*/
|
||||
init: function () {},
|
||||
|
||||
toString: function () "[instance " + this.constructor.name + "]",
|
||||
toString: function () "[instance " + this.constructor.classname + "]",
|
||||
|
||||
/**
|
||||
* Executes 'callback' after 'timeout' milliseconds. The value of
|
||||
@@ -558,9 +726,9 @@ function Module(name, prototype) {
|
||||
let init = callable(prototype) ? 4 : 3;
|
||||
const module = Class.apply(Class, Array.slice(arguments, 0, init));
|
||||
let instance = module();
|
||||
module.name = name.toLowerCase();
|
||||
module.classname = name.toLowerCase();
|
||||
instance.INIT = arguments[init] || {};
|
||||
currentModule[module.name] = instance;
|
||||
currentModule[module.classname] = instance;
|
||||
defmodule.modules.push(instance);
|
||||
return module;
|
||||
}
|
||||
@@ -597,7 +765,7 @@ else
|
||||
*/
|
||||
function Struct() {
|
||||
let args = Array.slice(arguments);
|
||||
const Struct = Class("Struct", Struct_Base, {
|
||||
const Struct = Class("Struct", StructBase, {
|
||||
length: args.length,
|
||||
members: args
|
||||
});
|
||||
@@ -607,7 +775,7 @@ function Struct() {
|
||||
});
|
||||
return Struct;
|
||||
}
|
||||
let Struct_Base = Class("StructBase", Array, {
|
||||
let StructBase = Class("StructBase", Array, {
|
||||
init: function () {
|
||||
for (let i = 0; i < arguments.length; i++)
|
||||
if (arguments[i] != undefined)
|
||||
@@ -639,7 +807,7 @@ let Struct_Base = Class("StructBase", Array, {
|
||||
*/
|
||||
defaultValue: function (key, val) {
|
||||
let i = this.prototype.members.indexOf(key);
|
||||
this.prototype.__defineGetter__(i, function () (this[i] = val.call(this), this[i])); // Kludge for FF 3.0
|
||||
this.prototype.__defineGetter__(i, function () (this[i] = val.call(this)));
|
||||
this.prototype.__defineSetter__(i, function (value)
|
||||
Class.replaceProperty(this, i, value));
|
||||
}
|
||||
@@ -700,10 +868,26 @@ const Timer = Class("Timer", {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the UTF-8 encoded value of a string mis-encoded into
|
||||
* ISO-8859-1.
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {string}
|
||||
*/
|
||||
function UTF8(str) {
|
||||
try {
|
||||
return decodeURIComponent(escape(str))
|
||||
}
|
||||
catch (e) {
|
||||
return str
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Array utility methods.
|
||||
*/
|
||||
const array = Class("util.Array", Array, {
|
||||
const array = Class("array", Array, {
|
||||
init: function (ary) {
|
||||
if (isinstance(ary, ["Iterator", "Generator"]))
|
||||
ary = [k for (k in ary)];
|
||||
@@ -714,23 +898,19 @@ const array = Class("util.Array", Array, {
|
||||
__proto__: ary,
|
||||
__iterator__: function () this.iteritems(),
|
||||
__noSuchMethod__: function (meth, args) {
|
||||
var res = array[meth].apply(null, [this.__proto__].concat(args));
|
||||
|
||||
var res = array[meth].apply(null, [this.array].concat(args));
|
||||
if (isarray(res))
|
||||
return array(res);
|
||||
return res;
|
||||
},
|
||||
toString: function () this.__proto__.toString(),
|
||||
concat: function () this.__proto__.concat.apply(this.__proto__, arguments),
|
||||
array: ary,
|
||||
toString: function () this.array.toString(),
|
||||
concat: function () this.array.concat.apply(this.array, arguments),
|
||||
filter: function () this.__noSuchMethod__("filter", Array.slice(arguments)),
|
||||
map: function () this.__noSuchMethod__("map", Array.slice(arguments))
|
||||
};
|
||||
}
|
||||
}, {
|
||||
isinstance: function isinstance(obj) {
|
||||
return Object.prototype.toString.call(obj) == "[object Array]";
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts an array to an object. As in lisp, an assoc is an
|
||||
* array of key-value pairs, which maps directly to an object,
|
||||
@@ -834,6 +1014,6 @@ const array = Class("util.Array", Array, {
|
||||
|
||||
endmodule();
|
||||
|
||||
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n");}
|
||||
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);}
|
||||
|
||||
// vim: set fdm=marker sw=4 ts=4 et ft=javascript:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
Components.utils.import("resource://dactyl/base.jsm");
|
||||
defmodule("bookmarkcache", this, {
|
||||
exports: ["Bookmark", "BookmarkCache", "Keyword", "bookmarkcache"],
|
||||
require: ["services", "util"]
|
||||
require: ["services", "storage", "util"]
|
||||
});
|
||||
|
||||
|
||||
@@ -26,11 +26,10 @@ const name = "bookmark-cache";
|
||||
|
||||
const BookmarkCache = Module("BookmarkCache", {
|
||||
init: function init() {
|
||||
|
||||
bookmarks.addObserver(this, false);
|
||||
},
|
||||
|
||||
__iterator__: function () (val for ([, val] in Iterator(self.bookmarks))),
|
||||
__iterator__: function () (val for ([, val] in Iterator(this.bookmarks))),
|
||||
|
||||
get bookmarks() Class.replaceProperty(this, "bookmarks", this.load()),
|
||||
|
||||
@@ -38,9 +37,9 @@ const BookmarkCache = Module("BookmarkCache", {
|
||||
.map(function (s) bookmarks[s]),
|
||||
|
||||
_deleteBookmark: function deleteBookmark(id) {
|
||||
let length = bookmarks.length;
|
||||
bookmarks = bookmarks.filter(function (item) item.id != id);
|
||||
return bookmarks.length < length;
|
||||
let length = this.bookmarks.length;
|
||||
this.bookmarks = this.bookmarks.filter(function (item) item.id != id);
|
||||
return this.bookmarks.length < length;
|
||||
},
|
||||
|
||||
_loadBookmark: function loadBookmark(node) {
|
||||
@@ -118,7 +117,7 @@ const BookmarkCache = Module("BookmarkCache", {
|
||||
onItemMoved: function onItemMoved() {},
|
||||
onItemAdded: function onItemAdded(itemId, folder, index) {
|
||||
if (bookmarks.getItemType(itemId) == bookmarks.TYPE_BOOKMARK) {
|
||||
if (self.isBookmark(itemId)) {
|
||||
if (this.isBookmark(itemId)) {
|
||||
let bmark = this._loadBookmark(this.readBookmark(itemId));
|
||||
this.bookmarks.push(bmark);
|
||||
storage.fireEvent(name, "add", bmark);
|
||||
|
||||
@@ -8,22 +8,40 @@ Components.utils.import("resource://dactyl/base.jsm");
|
||||
defmodule("highlight", this, {
|
||||
exports: ["Highlight", "Highlights", "highlight"],
|
||||
require: ["services", "styles"],
|
||||
use: ["template"]
|
||||
use: ["template", "util"]
|
||||
});
|
||||
|
||||
const Highlight = Struct("class", "selector", "filter", "default", "value", "base");
|
||||
const Highlight = Struct("class", "selector", "sites",
|
||||
"default", "value", "agent",
|
||||
"base", "baseClass", "style");
|
||||
Highlight.liveProperty = function (name, prop) {
|
||||
let i = this.prototype.members.indexOf(name);
|
||||
this.prototype.__defineGetter__(name, function () this[i]);
|
||||
this.prototype.__defineSetter__(name, function (val) {
|
||||
this[i] = val;
|
||||
this.style[prop || name] = this[prop || name];
|
||||
});
|
||||
}
|
||||
Highlight.liveProperty("agent");
|
||||
Highlight.liveProperty("value", "css");
|
||||
Highlight.liveProperty("selector", "css");
|
||||
Highlight.liveProperty("sites");
|
||||
Highlight.liveProperty("style", "css");
|
||||
|
||||
Highlight.defaultValue("filter", function ()
|
||||
this.base ? this.base.filter :
|
||||
["chrome://dactyl/*",
|
||||
"dactyl:*",
|
||||
"file://*"].concat(highlight.styleableChrome).join(","));
|
||||
Highlight.defaultValue("baseClass", function () /^(\w*)/.exec(this.class)[0]);
|
||||
Highlight.defaultValue("selector", function () highlight.selector(this.class));
|
||||
Highlight.defaultValue("sites", function ()
|
||||
this.base ? this.base.sites
|
||||
: ["chrome://dactyl/*", "dactyl:*", "file://*"].concat(
|
||||
highlight.styleableChrome));
|
||||
Highlight.defaultValue("style", function ()
|
||||
styles.addSheet(true, "highlight:" + this.class, this.sites, this.css, this.agent, true));
|
||||
Highlight.defaultValue("value", function () this.default);
|
||||
Highlight.defaultValue("base", function () {
|
||||
let base = /^(\w*)/.exec(this.class)[0];
|
||||
return (base != this.class && base in highlight.highlight) ? highlight.highlight[base] : null;
|
||||
});
|
||||
|
||||
Highlight.prototype.__defineGetter__("base", function ()
|
||||
this.baseClass != this.class && highlight.highlight[this.baseClass] || null);
|
||||
Highlight.prototype.__defineGetter__("css", function ()
|
||||
this.selector + "{" + this.value + "}");
|
||||
Highlight.prototype.toString = function ()
|
||||
"Highlight(" + this.class + ")\n\t"
|
||||
+ [k + ": " + String.quote(v) for ([k, v] in this)]
|
||||
@@ -38,12 +56,47 @@ Highlight.prototype.toString = function ()
|
||||
const Highlights = Module("Highlight", {
|
||||
init: function () {
|
||||
this.highlight = {};
|
||||
this.loaded = {};
|
||||
},
|
||||
|
||||
keys: function keys() Object.keys(this.highlight).sort(),
|
||||
|
||||
__iterator__: function () values(this.highlight),
|
||||
|
||||
_create: function (agent, args) {
|
||||
let obj = Highlight.apply(Highlight, args);
|
||||
|
||||
if (!isarray(obj[2]))
|
||||
obj[2] = obj[2].split(",");
|
||||
obj[5] = agent;
|
||||
|
||||
let old = this.highlight[obj.class];
|
||||
this.highlight[obj.class] = obj;
|
||||
// This *must* come before any other property changes.
|
||||
if (old)
|
||||
obj.style = old.style;
|
||||
|
||||
if (/^[>+ ]/.test(obj.selector))
|
||||
obj.selector = this.selector(obj.class) + obj.selector;
|
||||
if (old && old.value != old.default)
|
||||
obj.value = old.style;
|
||||
|
||||
if (!old && obj.base && obj.base.enabled)
|
||||
obj.style.enabled = true;
|
||||
else
|
||||
this.loaded.__defineSetter__(obj.class, function () {
|
||||
delete this[obj.class];
|
||||
this[obj.class] = true;
|
||||
|
||||
if (obj.class === obj.baseClass)
|
||||
for (let h in highlight)
|
||||
if (h.baseClass === obj.class)
|
||||
this[h.class] = true;
|
||||
obj.style.enabled = true;
|
||||
});
|
||||
return obj;
|
||||
},
|
||||
|
||||
get: function (k) this.highlight[k],
|
||||
set: function (key, newStyle, force, append) {
|
||||
let [, class_, selectors] = key.match(/^([a-zA-Z_-]+)(.*)/);
|
||||
@@ -51,35 +104,40 @@ const Highlights = Module("Highlight", {
|
||||
if (!(class_ in this.highlight))
|
||||
return "Unknown highlight keyword: " + class_;
|
||||
|
||||
let style = this.highlight[key] || Highlight(key);
|
||||
let highlight = this.highlight[key] || this._create(false, [key]);
|
||||
|
||||
if (append)
|
||||
newStyle = (style.value || "").replace(/;?\s*$/, "; " + newStyle);
|
||||
newStyle = (highlight.value || "").replace(/;?\s*$/, "; " + newStyle);
|
||||
if (/^\s*$/.test(newStyle))
|
||||
newStyle = null;
|
||||
if (newStyle == null) {
|
||||
if (style.default == null) {
|
||||
styles.removeSheet(true, style.selector);
|
||||
delete this.highlight[style.class];
|
||||
if (highlight.default == null) {
|
||||
highlight.style.enabled = false;
|
||||
delete this.loaded[highlight.class];
|
||||
delete this.highlight[highlight.class];
|
||||
return null;
|
||||
}
|
||||
newStyle = style.default;
|
||||
newStyle = highlight.default;
|
||||
}
|
||||
|
||||
if (!style.loaded || style.value != newStyle) {
|
||||
styles.removeSheet(true, style.selector);
|
||||
let css = newStyle.replace(/(?:!\s*important\s*)?(?:;?\s*$|;)/g, "!important;")
|
||||
.replace(";!important;", ";", "g"); // Seeming Spidermonkey bug
|
||||
if (!/^\s*(?:!\s*important\s*)?;*\s*$/.test(css)) {
|
||||
css = style.selector + " { " + css + " }";
|
||||
highlight.value = newStyle;
|
||||
if (force)
|
||||
highlight.style.enabled = true;
|
||||
this.highlight[highlight.class] = highlight;
|
||||
return highlight;
|
||||
},
|
||||
|
||||
styles.addSheet(true, "highlight:" + style.class, style.filter, css, true);
|
||||
style.loaded = true;
|
||||
}
|
||||
}
|
||||
style.value = newStyle;
|
||||
this.highlight[style.class] = style;
|
||||
return null;
|
||||
/**
|
||||
* Highlights a node with the given group, and ensures that said
|
||||
* group is loaded.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {string} group
|
||||
*/
|
||||
highlightNode: function (node, group) {
|
||||
node.setAttributeNS(NS.uri, "highlight", group);
|
||||
for each (let h in group.split(" "))
|
||||
this.loaded[h] = true;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -104,30 +162,69 @@ const Highlights = Module("Highlight", {
|
||||
this.set(k, null, true);
|
||||
},
|
||||
|
||||
groupRegexp: RegExp(String.replace(<![CDATA[
|
||||
^
|
||||
(\s* (?:\S|\s\S)+ \s+)
|
||||
\{ ([^}]*) \}
|
||||
\s*
|
||||
$
|
||||
]]>, /\s*/g, ""), "gm"),
|
||||
sheetRegexp: RegExp(String.replace(<![CDATA[
|
||||
^\s*
|
||||
!? \*?
|
||||
( (?:[^;\s]|\s\S)+ )
|
||||
(?:; ( (?:[^;\s]|\s\S)+ )? )?
|
||||
(?:; ( (?:[^ \s]|\s\S)+ ) )?
|
||||
\s* (.*)
|
||||
$
|
||||
]]>, /\s*/g, "")),
|
||||
|
||||
/**
|
||||
* Bulk loads new CSS rules.
|
||||
* Bulk loads new CSS rules, in the format of,
|
||||
*
|
||||
* Rules ::= Rule | Rule "\n" Rule
|
||||
* Rule ::= Bang? Star? MatchSpec Space Space* Css
|
||||
* | Comment
|
||||
* Comment ::= Space* "//" *
|
||||
* Bang ::= "!"
|
||||
* Star ::= "*"
|
||||
* MatchSpec ::= Class
|
||||
* | Class ";" Selector
|
||||
* | Class ";" Selector ";" Sites
|
||||
* CSS ::= CSSLine | "{" CSSLines "}"
|
||||
* CSSLines ::= CSSLine | CSSLine "\n" CSSLines
|
||||
*
|
||||
* Where Class is the name of the sheet, Selector is the CSS
|
||||
* selector for the style, Site is the comma-separated list of site
|
||||
* filters to apply the style to.
|
||||
*
|
||||
* If Selector is not provided, it defaults to [dactyl|highlight~={Class}].
|
||||
* If it is provided and begins with any of "+", ">" or " ", it is
|
||||
* appended to the default.
|
||||
*
|
||||
* If Sites is not provided, it defaults to the chrome documents of
|
||||
* the main application window, dactyl help files, and any other
|
||||
* dactyl-specific documents.
|
||||
*
|
||||
* If Star is provided, the style is applied as an agent sheet.
|
||||
*
|
||||
* The new styles are lazily activated unless Bang or 'eager' is
|
||||
* provided. See {@link Util#xmlToDom}.
|
||||
*
|
||||
* @param {string} css The rules to load. See {@link Highlights#css}.
|
||||
* @param {boolean} eager When true, load all provided rules immediately.
|
||||
*/
|
||||
loadCSS: function (css) {
|
||||
css.replace(/^(\s*\S*\s+)\{((?:.|\n)*?)\}\s*$/gm, function (_, _1, _2) _1 + " " + _2.replace(/\n\s*/g, " "))
|
||||
.split("\n").filter(function (s) /\S/.test(s))
|
||||
.forEach(function (style) {
|
||||
style = Highlight.apply(Highlight,
|
||||
Array.slice(style.match(/^\s*((?:[^,\s]|\s\S)+)(?:,((?:[^,\s]|\s\S)+)?)?(?:,((?:[^,\s]|\s\S)+))?\s*(.*)$/),
|
||||
1));
|
||||
if (/^[>+ ]/.test(style.selector))
|
||||
style.selector = this.selector(style.class) + style.selector;
|
||||
loadCSS: function (css, eager) {
|
||||
String.replace(css, this.groupRegexp, function (m, m1, m2) m1 + " " + m2.replace(/\n\s*/g, " "))
|
||||
.split("\n").filter(function (s) /\S/.test(s) && !/^\s*\/\//.test(s))
|
||||
.forEach(function (highlight) {
|
||||
|
||||
let old = this.highlight[style.class];
|
||||
if (!old)
|
||||
this.highlight[style.class] = style;
|
||||
else if (old.value == old.default)
|
||||
old.value = style.value;
|
||||
}, this);
|
||||
for (let [class_, hl] in Iterator(this.highlight))
|
||||
if (hl.value == hl.default)
|
||||
this.set(class_);
|
||||
let bang = eager || /^\s*!/.test(highlight);
|
||||
let star = /^\s*!?\*/.test(highlight);
|
||||
highlight = this._create(star, this.sheetRegexp.exec(highlight).slice(1));
|
||||
if (bang)
|
||||
highlight.style.enabled = true;
|
||||
}, this);
|
||||
}
|
||||
}, {
|
||||
}, {
|
||||
@@ -181,11 +278,8 @@ const Highlights = Module("Highlight", {
|
||||
if (!key || h.class.indexOf(key) > -1))));
|
||||
else if (!key && clear)
|
||||
highlight.clear();
|
||||
else {
|
||||
let error = highlight.set(key, css, clear, "-append" in args);
|
||||
if (error)
|
||||
dactyl.echoerr(error);
|
||||
}
|
||||
else
|
||||
highlight.set(key, css, clear, "-append" in args);
|
||||
},
|
||||
{
|
||||
// TODO: add this as a standard highlight completion function?
|
||||
@@ -221,7 +315,7 @@ const Highlights = Module("Highlight", {
|
||||
completion.colorScheme = function colorScheme(context) {
|
||||
context.title = ["Color Scheme", "Runtime Path"];
|
||||
context.keys = { text: function (f) f.leafName.replace(/\.vimp$/, ""), description: ".parent.path" };
|
||||
context.completions = util.Array.flatten(
|
||||
context.completions = array.flatten(
|
||||
modules.io.getRuntimeDirectories("colors").map(
|
||||
function (dir) dir.readDirectory().filter(
|
||||
function (file) /\.vimp$/.test(file.leafName))))
|
||||
@@ -232,6 +326,12 @@ const Highlights = Module("Highlight", {
|
||||
context.title = ["Highlight Group", "Value"];
|
||||
context.completions = [[v.class, v.value] for (v in highlight)];
|
||||
};
|
||||
},
|
||||
javascript: function (dactyl, modules, window) {
|
||||
modules.JavaScript.setCompleter(["get", "set"].map(function (m) highlight[m]),
|
||||
[ function (context, obj, args) Iterator(highlight.highlight) ]);
|
||||
modules.JavaScript.setCompleter(["highlightNode"].map(function (m) highlight[m]),
|
||||
[ null, function (context, obj, args) Iterator(highlight.highlight) ]);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ const Sanitizer = Module("sanitizer", tmp.Sanitizer, {
|
||||
services.get("permissions").remove(util.createURI(p.host), p.type);
|
||||
services.get("permissions").add(util.createURI(p.host), p.type, 0);
|
||||
}
|
||||
for (let p in iter(services.get("contentprefs").getPrefs(util.createURI(host)).enumerator))
|
||||
for (let p in iter(services.get("contentprefs").getPrefs(util.createURI(host))))
|
||||
services.get("contentprefs").removePref(util.createURI(host), p.QueryInterface(Ci.nsIProperty).name);
|
||||
}
|
||||
else {
|
||||
@@ -185,12 +185,12 @@ const Sanitizer = Module("sanitizer", tmp.Sanitizer, {
|
||||
prefToArg: function (pref) pref.replace(/.*\./, "").toLowerCase(),
|
||||
|
||||
iterCookies: function iterCookies(host) {
|
||||
for (let c in iter(services.get("cookies").enumerator))
|
||||
for (let c in iter(services.get("cookies")))
|
||||
if (!host || util.isSubdomain(c.QueryInterface(Ci.nsICookie2).rawHost, host))
|
||||
yield c;
|
||||
},
|
||||
iterPermissions: function iterPermissions(host) {
|
||||
for (let p in iter(services.get("permissions").enumerator))
|
||||
for (let p in iter(services.get("permissions")))
|
||||
if (p.QueryInterface(Ci.nsIPermission) && (!host || util.isSubdomain(p.host, host)))
|
||||
yield p;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2008-2009 by Kris Maglione <maglione.k at Gmail>
|
||||
// Copyright (c) 2008-2020 by 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.
|
||||
@@ -9,6 +9,9 @@ defmodule("services", this, {
|
||||
exports: ["Services", "services"]
|
||||
});
|
||||
|
||||
/**
|
||||
* A lazily-instantiated XPCOM class and service cache.
|
||||
*/
|
||||
const Services = Module("Services", {
|
||||
init: function () {
|
||||
this.classes = {};
|
||||
@@ -33,12 +36,13 @@ const Services = Module("Services", {
|
||||
this.add("json", "@mozilla.org/dom/json;1", Ci.nsIJSON, "createInstance");
|
||||
this.add("livemark", "@mozilla.org/browser/livemark-service;2", Ci.nsILivemarkService);
|
||||
this.add("observer", "@mozilla.org/observer-service;1", Ci.nsIObserverService);
|
||||
this.add("pref", "@mozilla.org/preferences-service;1", [Ci.nsIPrefBranch, Ci.nsIPrefBranch2, Ci.nsIPrefService]);
|
||||
this.add("pref", "@mozilla.org/preferences-service;1", [Ci.nsIPrefBranch2, Ci.nsIPrefService]);
|
||||
this.add("privateBrowsing", "@mozilla.org/privatebrowsing;1", Ci.nsIPrivateBrowsingService);
|
||||
this.add("profile", "@mozilla.org/toolkit/profile-service;1", Ci.nsIToolkitProfileService);
|
||||
this.add("runtime", "@mozilla.org/xre/runtime;1", [Ci.nsIXULAppInfo, Ci.nsIXULRuntime]);
|
||||
this.add("rdf", "@mozilla.org/rdf/rdf-service;1", Ci.nsIRDFService);
|
||||
this.add("sessionStore", "@mozilla.org/browser/sessionstore;1", Ci.nsISessionStore);
|
||||
this.add("stringBundle", "@mozilla.org/intl/stringbundle;1", Ci.nsIStringBundleService);
|
||||
this.add("stylesheet", "@mozilla.org/content/style-sheet-service;1", Ci.nsIStyleSheetService);
|
||||
this.add("subscriptLoader", "@mozilla.org/moz/jssubscript-loader;1", Ci.mozIJSSubScriptLoader);
|
||||
this.add("tagging", "@mozilla.org/browser/tagging-service;1", Ci.nsITaggingService);
|
||||
@@ -103,19 +107,19 @@ const Services = Module("Services", {
|
||||
return this.classes[name] = function () self._create(class_, ifaces, "createInstance");
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a new instance of the cached class with the specified name.
|
||||
*
|
||||
* @param {string} name The class's cache key.
|
||||
*/
|
||||
create: function (name) this.classes[name](),
|
||||
|
||||
/**
|
||||
* Returns the cached service with the specified name.
|
||||
*
|
||||
* @param {string} name The service's cache key.
|
||||
*/
|
||||
get: function (name) this.services[name],
|
||||
|
||||
/**
|
||||
* Returns a new instance of the cached class with the specified name.
|
||||
*
|
||||
* @param {string} name The class's cache key.
|
||||
*/
|
||||
create: function (name) this.classes[name]()
|
||||
}, {
|
||||
}, {
|
||||
init: function (dactyl, modules) {
|
||||
|
||||
@@ -1,24 +1,7 @@
|
||||
/***** BEGIN LICENSE BLOCK ***** {{{
|
||||
Copyright ©2008-2009 by Kris Maglione <maglione.k at Gmail>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
}}} ***** END LICENSE BLOCK *****/
|
||||
// Copyright (c) 2008-2010 by 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";
|
||||
|
||||
const myObject = Object;
|
||||
@@ -98,38 +81,6 @@ const StoreBase = Class("StoreBase", {
|
||||
save: function () { savePref(this); },
|
||||
});
|
||||
|
||||
const ObjectStore = Class("ObjectStore", StoreBase, {
|
||||
_constructor: myObject,
|
||||
|
||||
clear: function () {
|
||||
this._object = {};
|
||||
this.fireEvent("clear");
|
||||
},
|
||||
|
||||
get: function get(key, default_) key in this._object ? this._object[key] : this.set(key, default_),
|
||||
|
||||
keys: function keys() Object.keys(this._object),
|
||||
|
||||
remove: function remove(key) {
|
||||
var ret = this._object[key];
|
||||
delete this._object[key];
|
||||
this.fireEvent("remove", key);
|
||||
},
|
||||
|
||||
set: function set(key, val) {
|
||||
var defined = key in this._object;
|
||||
var orig = this._object[key];
|
||||
this._object[key] = val;
|
||||
if (!defined)
|
||||
this.fireEvent("add", key);
|
||||
else if (orig != val)
|
||||
this.fireEvent("change", key);
|
||||
return val;
|
||||
},
|
||||
|
||||
__iterator__: function () Iterator(this._object),
|
||||
});
|
||||
|
||||
const ArrayStore = Class("ArrayStore", StoreBase, {
|
||||
_constructor: Array,
|
||||
|
||||
@@ -176,12 +127,51 @@ const ArrayStore = Class("ArrayStore", StoreBase, {
|
||||
__iterator__: function () Iterator(this._object),
|
||||
});
|
||||
|
||||
const ObjectStore = Class("ObjectStore", StoreBase, {
|
||||
_constructor: myObject,
|
||||
|
||||
clear: function () {
|
||||
this._object = {};
|
||||
this.fireEvent("clear");
|
||||
},
|
||||
|
||||
get: function get(key, default_)
|
||||
key in this._object ? this._object[key] :
|
||||
arguments.length > 1 ? this.set(key, default_) :
|
||||
undefined,
|
||||
|
||||
keys: function keys() Object.keys(this._object),
|
||||
|
||||
remove: function remove(key) {
|
||||
var ret = this._object[key];
|
||||
delete this._object[key];
|
||||
this.fireEvent("remove", key);
|
||||
},
|
||||
|
||||
set: function set(key, val) {
|
||||
var defined = key in this._object;
|
||||
var orig = this._object[key];
|
||||
this._object[key] = val;
|
||||
if (!defined)
|
||||
this.fireEvent("add", key);
|
||||
else if (orig != val)
|
||||
this.fireEvent("change", key);
|
||||
return val;
|
||||
},
|
||||
|
||||
__iterator__: function () Iterator(this._object),
|
||||
});
|
||||
|
||||
var keys = {};
|
||||
var observers = {};
|
||||
|
||||
const Storage = Module("Storage", {
|
||||
alwaysReload: {},
|
||||
|
||||
newObject: function newObject(key, constructor, params) {
|
||||
if (params == null || !isobject(params))
|
||||
throw Error("Invalid argument type");
|
||||
|
||||
if (!(key in keys) || params.reload || this.alwaysReload[key]) {
|
||||
if (key in this && !(params.reload || this.alwaysReload[key]))
|
||||
throw Error();
|
||||
@@ -198,7 +188,7 @@ const Storage = Module("Storage", {
|
||||
},
|
||||
|
||||
newArray: function newArray(key, options) {
|
||||
return this.newObject(key, ArrayStore, { type: Array, __proto__: options });
|
||||
return this.newObject(key, ArrayStore, update({ type: Array }, options));
|
||||
},
|
||||
|
||||
addObserver: function addObserver(key, callback, ref) {
|
||||
@@ -295,7 +285,7 @@ const File = Class("File", {
|
||||
let file = services.create("file");
|
||||
|
||||
if (path instanceof Ci.nsIFile)
|
||||
file = path;
|
||||
file = path.QueryInterface(Ci.nsIFile);
|
||||
else if (/file:\/\//.test(path))
|
||||
file = services.create("file:").getFileFromURLSpec(path);
|
||||
else {
|
||||
@@ -317,9 +307,8 @@ const File = Class("File", {
|
||||
iterDirectory: function () {
|
||||
if (!this.isDirectory())
|
||||
throw Error("Not a directory");
|
||||
let entries = this.directoryEntries;
|
||||
while (entries.hasMoreElements())
|
||||
yield File(entries.getNext().QueryInterface(Ci.nsIFile));
|
||||
for (let file in iter(this.directoryEntries))
|
||||
yield File(file);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -409,6 +398,8 @@ const File = Class("File", {
|
||||
|
||||
if (!perms)
|
||||
perms = parseInt('0644', 8);
|
||||
if (!this.exists()) // OCREAT won't creat the directory
|
||||
this.create(this.NORMAL_FILE_TYPE, perms);
|
||||
|
||||
ofstream.init(this, mode, perms, 0);
|
||||
let ocstream = getStream(0);
|
||||
@@ -567,8 +558,8 @@ const File = Class("File", {
|
||||
replacePathSep: function (path) path.replace("/", File.PATH_SEP, "g")
|
||||
});
|
||||
|
||||
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n");}
|
||||
|
||||
endmodule();
|
||||
|
||||
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);}
|
||||
|
||||
// vim: set fdm=marker sw=4 sts=4 et ft=javascript:
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
Components.utils.import("resource://dactyl/base.jsm");
|
||||
defmodule("styles", this, {
|
||||
exports: ["Style", "Styles", "styles"],
|
||||
require: ["services", "util"]
|
||||
require: ["services", "util"],
|
||||
use: ["template"]
|
||||
});
|
||||
|
||||
const sss = services.get("stylesheet");
|
||||
@@ -17,6 +18,35 @@ const namespace = "@namespace html " + XHTML.uri.quote() + ";\n" +
|
||||
"@namespace dactyl " + NS.uri.quote() + ";\n";
|
||||
|
||||
const Sheet = Struct("name", "id", "sites", "css", "system", "agent");
|
||||
Sheet.liveProperty = function (name) {
|
||||
let i = this.prototype.members.indexOf(name);
|
||||
this.prototype.__defineGetter__(name, function () this[i]);
|
||||
this.prototype.__defineSetter__(name, function (val) {
|
||||
this[i] = val;
|
||||
this.enabled = this.enabled;
|
||||
});
|
||||
}
|
||||
Sheet.liveProperty("agent");
|
||||
Sheet.liveProperty("css");
|
||||
Sheet.liveProperty("sites");
|
||||
Sheet.prototype.__defineGetter__("uri", function () cssUri(this.fullCSS));
|
||||
Sheet.prototype.__defineGetter__("enabled", function () this._enabled);
|
||||
Sheet.prototype.__defineSetter__("enabled", function (on) {
|
||||
if (on != this._enabled || this.uri != this._uri) {
|
||||
if (on)
|
||||
this.enabled = false;
|
||||
else if (!this._uri)
|
||||
return;
|
||||
|
||||
let meth = on ? "registerSheet" : "unregisterSheet";
|
||||
styles[meth](on ? this.uri : this._uri,
|
||||
on ? this.agent : this._agent);
|
||||
|
||||
this._agent = this.agent;
|
||||
this._enabled = Boolean(on);
|
||||
this._uri = this.uri;
|
||||
}
|
||||
});
|
||||
Sheet.prototype.__defineGetter__("fullCSS", function wrapCSS() {
|
||||
let filter = this.sites;
|
||||
let css = this.css;
|
||||
@@ -29,23 +59,8 @@ Sheet.prototype.__defineGetter__("fullCSS", function wrapCSS() {
|
||||
: "domain")
|
||||
+ '("' + part.replace(/"/g, "%22").replace(/\*$/, "") + '")')
|
||||
.join(", ");
|
||||
return "/* Dactyl style #" + this.id + " */ " + namespace + " @-moz-document " + selectors + "{\n" + css + "\n}\n";
|
||||
});
|
||||
Sheet.prototype.__defineGetter__("css", function () this[3]);
|
||||
Sheet.prototype.__defineSetter__("css", function (val) {
|
||||
this.enabled = false;
|
||||
this[3] = val;
|
||||
this.enabled = true;
|
||||
return val;
|
||||
});
|
||||
Sheet.prototype.__defineGetter__("enabled", function () this._enabled);
|
||||
Sheet.prototype.__defineSetter__("enabled", function (on) {
|
||||
this._enabled = Boolean(on);
|
||||
let meth = on ? "registerSheet" : "unregisterSheet";
|
||||
|
||||
styles[meth](cssUri(this.fullCSS));
|
||||
if (this.agent)
|
||||
styles[meth](cssUri(this.fullCSS), true);
|
||||
return "/* Dactyl style #" + this.id + (this.agent ? " (agent)" : "") + " */ "
|
||||
+ namespace + " @-moz-document " + selectors + "{\n" + css + "\n}\n";
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -64,7 +79,7 @@ const Styles = Module("Styles", {
|
||||
this.systemNames = {};
|
||||
},
|
||||
|
||||
get sites() array(this.userSheets).map(function (s) s.sites).flatten().uniq().__proto__,
|
||||
get sites() array(this.userSheets).map(function (s) s.sites).flatten().uniq().array,
|
||||
|
||||
__iterator__: function () Iterator(this.userSheets.concat(this.systemSheets)),
|
||||
|
||||
@@ -81,25 +96,27 @@ const Styles = Module("Styles", {
|
||||
* "*" is matched as a prefix.
|
||||
* @param {string} css The CSS to be applied.
|
||||
*/
|
||||
addSheet: function addSheet(system, name, filter, css, agent) {
|
||||
addSheet: function addSheet(system, name, filter, css, agent, lazy) {
|
||||
let sheets = system ? this.systemSheets : this.userSheets;
|
||||
let names = system ? this.systemNames : this.userNames;
|
||||
if (name && name in names)
|
||||
this.removeSheet(system, name);
|
||||
|
||||
let sheet = Sheet(name, this._id++, filter.split(",").filter(util.identity), String(css), null, system, agent);
|
||||
if (!isarray(filter))
|
||||
filter = filter.split(",");
|
||||
if (name && name in names) {
|
||||
var sheet = names[name];
|
||||
sheet.filter = filter;
|
||||
sheet.css = String(css);
|
||||
}
|
||||
else
|
||||
sheet = Sheet(name, this._id++, filter.filter(util.identity), String(css), system, agent);
|
||||
|
||||
try {
|
||||
if (!lazy)
|
||||
sheet.enabled = true;
|
||||
}
|
||||
catch (e) {
|
||||
return e.echoerr || e;
|
||||
}
|
||||
sheets.push(sheet);
|
||||
|
||||
if (name)
|
||||
names[name] = sheet;
|
||||
return null;
|
||||
return sheet;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -129,14 +146,13 @@ const Styles = Module("Styles", {
|
||||
*/
|
||||
findSheets: function findSheets(system, name, filter, css, index) {
|
||||
let sheets = system ? this.systemSheets : this.userSheets;
|
||||
let names = system ? this.systemNames : this.userNames;
|
||||
|
||||
// Grossly inefficient.
|
||||
let matches = [k for ([k, v] in Iterator(sheets))];
|
||||
if (index)
|
||||
matches = String(index).split(",").filter(function (i) i in sheets);
|
||||
if (name)
|
||||
matches = matches.filter(function (i) sheets[i] == names[name]);
|
||||
matches = matches.filter(function (i) sheets[i].name == name);
|
||||
if (css)
|
||||
matches = matches.filter(function (i) sheets[i].css == css);
|
||||
if (filter)
|
||||
@@ -178,18 +194,18 @@ const Styles = Module("Styles", {
|
||||
return null;
|
||||
|
||||
for (let [, sheet] in Iterator(matches.reverse())) {
|
||||
sheet.enabled = false;
|
||||
if (name)
|
||||
delete names[name];
|
||||
if (sheets.indexOf(sheet) > -1)
|
||||
sheets.splice(sheets.indexOf(sheet), 1);
|
||||
|
||||
/* Re-add if we're only changing the site filter. */
|
||||
if (filter) {
|
||||
let sites = sheet.sites.filter(function (f) f != filter);
|
||||
if (sites.length)
|
||||
this.addSheet(system, name, sites.join(","), css, sheet.agent);
|
||||
if (sites.length) {
|
||||
sheet.sites = sites;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
sheet.enabled = false;
|
||||
if (sheet.name)
|
||||
delete names[sheet.name];
|
||||
if (sheets.indexOf(sheet) > -1)
|
||||
sheets.splice(sheets.indexOf(sheet), 1);
|
||||
}
|
||||
return matches.length;
|
||||
},
|
||||
@@ -256,7 +272,7 @@ const Styles = Module("Styles", {
|
||||
["min-width: 1em; text-align: center; color: red; font-weight: bold;",
|
||||
"padding: 0 1em 0 1ex; vertical-align: top;",
|
||||
"padding: 0 1em 0 0; vertical-align: top;"],
|
||||
([sheet.enabled ? "" : "\u00d7",
|
||||
([sheet.enabled ? "" : UTF8("×"),
|
||||
key,
|
||||
sheet.sites.join(","),
|
||||
sheet.css]
|
||||
@@ -271,9 +287,7 @@ const Styles = Module("Styles", {
|
||||
css = sheet.css + " " + css;
|
||||
}
|
||||
}
|
||||
let err = styles.addSheet(false, name, filter, css);
|
||||
if (err)
|
||||
dactyl.echoerr(err);
|
||||
styles.addSheet(false, name, filter, css);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -377,4 +391,6 @@ const Styles = Module("Styles", {
|
||||
|
||||
endmodule();
|
||||
|
||||
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);}
|
||||
|
||||
// vim:se fdm=marker sw=4 ts=4 et ft=javascript:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2008-2009 by Kris Maglione <maglione.k at Gmail>
|
||||
// Copyright (c) 2008-2010 by 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.
|
||||
@@ -40,6 +40,8 @@ const Template = Module("Template", {
|
||||
if (typeof xml == "xml")
|
||||
return xml;
|
||||
try {
|
||||
XML.ignoreWhitespace = false;
|
||||
XML.prettyPrinting = false;
|
||||
return new XMLList(xml);
|
||||
}
|
||||
catch (e) {}
|
||||
@@ -48,7 +50,7 @@ const Template = Module("Template", {
|
||||
|
||||
bookmarkDescription: function (item, text)
|
||||
<>
|
||||
<a href={item.item.url} highlight="URL">{text}</a> 
|
||||
<a href={item.item.url} highlight="URL">{text || ""}</a> 
|
||||
{
|
||||
!(item.extra && item.extra.length) ? "" :
|
||||
<span class="extra-info">
|
||||
@@ -72,8 +74,8 @@ const Template = Module("Template", {
|
||||
var desc = item[1] || "";
|
||||
}
|
||||
else {
|
||||
var text = this.process[0].call(this, item, item.text);
|
||||
var desc = this.process[1].call(this, item, item.description);
|
||||
var text = this.processor[0].call(this, item, item.result);
|
||||
var desc = this.processor[1].call(this, item, item.description);
|
||||
}
|
||||
|
||||
// <e4x>
|
||||
@@ -82,8 +84,8 @@ const Template = Module("Template", {
|
||||
- from pushing the baseline down and enlarging
|
||||
- the row.
|
||||
-->
|
||||
<li highlight="CompResult">{text} </li>
|
||||
<li highlight="CompDesc">{desc} </li>
|
||||
<li highlight="CompResult">{text} </li>
|
||||
<li highlight="CompDesc">{desc} </li>
|
||||
</div>;
|
||||
// </e4x>
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
|
||||
// Copyright (c) 2007-2009 by Doug Kearns <dougkearns@gmail.com>
|
||||
// Copyright (c) 2008-2009 by Kris Maglione <maglione.k@gmail.com>
|
||||
// Copyright (c) 2008-2010 by 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.
|
||||
@@ -10,7 +10,7 @@ Components.utils.import("resource://dactyl/base.jsm");
|
||||
defmodule("util", this, {
|
||||
exports: ["Math", "NS", "Util", "XHTML", "XUL", "util"],
|
||||
require: ["services"],
|
||||
use: ["template"]
|
||||
use: ["highlight", "template"]
|
||||
});
|
||||
|
||||
const XHTML = Namespace("html", "http://www.w3.org/1999/xhtml");
|
||||
@@ -206,7 +206,7 @@ const Util = Module("Util", {
|
||||
function rec(acc) {
|
||||
if (acc.length == patterns.length)
|
||||
res.push(array(substrings).zip(acc).flatten().join(""));
|
||||
else
|
||||
else
|
||||
for (let [, pattern] in Iterator(patterns[acc.length]))
|
||||
rec(acc.concat(pattern));
|
||||
}
|
||||
@@ -295,12 +295,12 @@ const Util = Module("Util", {
|
||||
null
|
||||
);
|
||||
|
||||
return {
|
||||
__proto__: result,
|
||||
__iterator__: asIterator
|
||||
? function () { let elem; while ((elem = this.iterateNext())) yield elem; }
|
||||
: function () { for (let i = 0; i < this.snapshotLength; i++) yield this.snapshotItem(i); }
|
||||
}
|
||||
return Object.create(result, {
|
||||
__iterator__: {
|
||||
value: asIterator ? function () { let elem; while ((elem = this.iterateNext())) yield elem; }
|
||||
: function () { for (let i = 0; i < this.snapshotLength; i++) yield this.snapshotItem(i); }
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
extend: function extend(dest) {
|
||||
@@ -388,18 +388,17 @@ const Util = Module("Util", {
|
||||
try {
|
||||
let xmlhttp = services.create("xmlhttp");
|
||||
xmlhttp.mozBackgroundRequest = true;
|
||||
if (callback) {
|
||||
if (callback)
|
||||
xmlhttp.onreadystatechange = function () {
|
||||
if (xmlhttp.readyState == 4)
|
||||
callback(xmlhttp);
|
||||
};
|
||||
}
|
||||
xmlhttp.open("GET", url, !!callback);
|
||||
xmlhttp.send(null);
|
||||
return xmlhttp;
|
||||
}
|
||||
catch (e) {
|
||||
util.dactyl.log("Error opening " + String.quote(url) + ": " + e, 1);
|
||||
util.dactyl.log("Error opening " + String.quote(url) + ": " + e, 1);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
@@ -460,9 +459,9 @@ const Util = Module("Util", {
|
||||
* @returns {string}
|
||||
*/
|
||||
makeXPath: function makeXPath(nodes) {
|
||||
return util.Array(nodes).map(util.debrace).flatten()
|
||||
.map(function (node) [node, "xhtml:" + node]).flatten()
|
||||
.map(function (node) "//" + node).join(" | ");
|
||||
return array(nodes).map(util.debrace).flatten()
|
||||
.map(function (node) [node, "xhtml:" + node]).flatten()
|
||||
.map(function (node) "//" + node).join(" | ");
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -480,18 +479,6 @@ const Util = Module("Util", {
|
||||
return ary;
|
||||
},
|
||||
|
||||
/**
|
||||
* Memoize the lookup of a property in an object.
|
||||
*
|
||||
* @param {object} obj The object to alter.
|
||||
* @param {string} key The name of the property to memoize.
|
||||
* @param {function} getter A function of zero to two arguments which
|
||||
* will return the property's value. <b>obj</b> is
|
||||
* passed as the first argument, <b>key</b> as the
|
||||
* second.
|
||||
*/
|
||||
memoize: memoize,
|
||||
|
||||
newThread: function () services.get("threadManager").newThread(0),
|
||||
|
||||
/**
|
||||
@@ -524,34 +511,47 @@ const Util = Module("Util", {
|
||||
if (object === null)
|
||||
return "null\n";
|
||||
|
||||
if (typeof object != "object")
|
||||
if (typeof object !== "object")
|
||||
return false;
|
||||
|
||||
const NAMESPACES = util.Array.toObject([
|
||||
[NS, 'dactyl'],
|
||||
[XHTML, 'html'],
|
||||
[XUL, 'xul']
|
||||
]);
|
||||
if (object instanceof Ci.nsIDOMElement) {
|
||||
const NAMESPACES = array.toObject([
|
||||
[NS, "dactyl"],
|
||||
[XHTML, "html"],
|
||||
[XUL, "xul"]
|
||||
]);
|
||||
let elem = object;
|
||||
if (elem.nodeType == elem.TEXT_NODE)
|
||||
return elem.data;
|
||||
|
||||
function namespaced(node) {
|
||||
var ns = NAMESPACES[node.namespaceURI];
|
||||
if (ns)
|
||||
return ns + ":" + node.localName;
|
||||
return node.localName.toLowerCase();
|
||||
var ns = NAMESPACES[node.namespaceURI] || /^(?:(.*?):)?/.exec(node.name)[0];
|
||||
if (!ns)
|
||||
return node.localName;
|
||||
if (color)
|
||||
return <><span highlight="HelpXMLNamespace">{ns}</span>{node.localName}</>
|
||||
return ns + ":" + node.localName;
|
||||
}
|
||||
try {
|
||||
let hasChildren = elem.firstChild && (!/^\s*$/.test(elem.firstChild) || elem.firstChild.nextSibling)
|
||||
if (color)
|
||||
return <span highlight="HelpXMLBlock"><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>;
|
||||
|
||||
let tag = "<" + [namespaced(elem)].concat(
|
||||
[namespaced(a) + "=" + template.highlight(a.value, true)
|
||||
for ([i, a] in util.Array.iteritems(elem.attributes))]).join(" ");
|
||||
|
||||
if (!elem.firstChild || /^\s*$/.test(elem.firstChild) && !elem.firstChild.nextSibling)
|
||||
tag += '/>';
|
||||
else
|
||||
tag += '>...</' + namespaced(elem) + '>';
|
||||
return tag;
|
||||
for ([i, a] in array.iteritems(elem.attributes))]).join(" ");
|
||||
return tag + (hasChildren ? "/>" : ">...</" + namespaced(elem) + ">");
|
||||
}
|
||||
catch (e) {
|
||||
return {}.toString.call(elem);
|
||||
@@ -562,13 +562,15 @@ const Util = Module("Util", {
|
||||
var obj = String(object);
|
||||
}
|
||||
catch (e) {
|
||||
obj = "[Object]";
|
||||
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>::<br/>
</>;
|
||||
let string = <><span highlight="Title Object">{obj}</span>::<br/>
</>;
|
||||
|
||||
let keys = [];
|
||||
try { // window.content often does not want to be queried with "var i in object"
|
||||
|
||||
// window.content often does not want to be queried with "var i in object"
|
||||
try {
|
||||
let hasValue = !("__iterator__" in object || isinstance(object, ["Generator", "Iterator"]));
|
||||
if (object.dactyl && object.modules && object.modules.modules == object.modules) {
|
||||
object = Iterator(object);
|
||||
@@ -593,7 +595,7 @@ const Util = Module("Util", {
|
||||
i = parseInt(i);
|
||||
else if (/^[A-Z_]+$/.test(i))
|
||||
i = "";
|
||||
keys.push([i, <>{key}{noVal ? "" : <>: {value}</>}<br/>
</>]);
|
||||
keys.push([i, <>{key}{noVal ? "" : <>: {value}</>}<br/>
</>]);
|
||||
}
|
||||
}
|
||||
catch (e) {}
|
||||
@@ -672,7 +674,6 @@ const Util = Module("Util", {
|
||||
selectionController: function (win)
|
||||
win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsISelectionDisplay)
|
||||
.QueryInterface(Ci.nsISelectionController),
|
||||
@@ -714,6 +715,7 @@ const Util = Module("Util", {
|
||||
* string.
|
||||
*
|
||||
* util.split("a, b, c, d, e", /, /, 3) -> ["a", "b", "c, d, e"]
|
||||
*
|
||||
* @param {string} str The string to split.
|
||||
* @param {RegExp|string} re The regular expression on which to split the string.
|
||||
* @param {number} limit The maximum number of elements to return.
|
||||
@@ -775,7 +777,9 @@ const Util = Module("Util", {
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts an E4X XML literal to a DOM node.
|
||||
* Converts an E4X XML literal to a DOM node. Any attribute named
|
||||
* highlight is present, it is transformed into dactyl:highlight,
|
||||
* and the named highlight groups are guaranteed to be loaded.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {Document} doc
|
||||
@@ -797,7 +801,14 @@ const Util = Module("Util", {
|
||||
case "element":
|
||||
let domnode = doc.createElementNS(node.namespace(), node.localName());
|
||||
for each (let attr in node.@*)
|
||||
domnode.setAttributeNS(attr.name() == "highlight" ? NS.uri : attr.namespace(), attr.name(), String(attr));
|
||||
if (attr.name() != "highlight")
|
||||
domnode.setAttributeNS(attr.namespace(), attr.name(), String(attr));
|
||||
else {
|
||||
domnode.setAttributeNS(NS.uri, "highlight", String(attr));
|
||||
for each (let h in String.split(attr, " "))
|
||||
highlight.loaded[h] = true;
|
||||
}
|
||||
|
||||
for each (let child in node.*)
|
||||
domnode.appendChild(xmlToDom(child, doc, nodes));
|
||||
if (nodes && node.@key)
|
||||
@@ -816,9 +827,7 @@ const Util = Module("Util", {
|
||||
* @singleton
|
||||
*/
|
||||
const GlobalMath = Math;
|
||||
var Math = {
|
||||
__proto__: GlobalMath,
|
||||
|
||||
var Math = update(Object.create(GlobalMath), {
|
||||
/**
|
||||
* Returns the specified <b>value</b> constrained to the range <b>min</b> -
|
||||
* <b>max</b>.
|
||||
@@ -829,9 +838,9 @@ var Math = {
|
||||
* @returns {number}
|
||||
*/
|
||||
constrain: function constrain(value, min, max) Math.min(Math.max(min, value), max)
|
||||
};
|
||||
});
|
||||
|
||||
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n");}
|
||||
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);}
|
||||
|
||||
endmodule();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user