mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2026-02-11 10:25:45 +01:00
Merge some recent fixes into 1.0b5 branch.
This commit is contained in:
@@ -489,6 +489,7 @@ function call(fn) {
|
||||
*/
|
||||
function memoize(obj, key, getter) {
|
||||
if (arguments.length == 1) {
|
||||
obj = update({}, obj);
|
||||
for (let prop in Object.getOwnPropertyNames(obj)) {
|
||||
let get = objproto.__lookupGetter__.call(obj, prop);
|
||||
if (get)
|
||||
@@ -737,9 +738,9 @@ Class.memoize = function memoize(getter)
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
init: function (key) {
|
||||
this.get = function replace() (
|
||||
Class.replaceProperty(this, key, null),
|
||||
Class.replaceProperty(this, key, getter.call(this, key)))
|
||||
this.get = function replace() let (obj = this.instance || this) (
|
||||
Class.replaceProperty(obj, key, null),
|
||||
Class.replaceProperty(obj, key, getter.call(this, key)))
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1196,6 +1197,9 @@ update(iter, {
|
||||
return undefined;
|
||||
},
|
||||
|
||||
sort: function sort(iter, fn, self)
|
||||
array(this.toArray(iter).sort(fn, self)),
|
||||
|
||||
uniq: function uniq(iter) {
|
||||
let seen = {};
|
||||
for (let item in iter)
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// given in the LICENSE.txt file included with this file.
|
||||
"use strict";
|
||||
|
||||
dump(" ======================= bootstrap.jsm " + (typeof JSMLoader) + " ======================= \n");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["JSMLoader"];
|
||||
let global = this;
|
||||
|
||||
|
||||
@@ -36,14 +36,17 @@ var ConfigBase = Class("ConfigBase", {
|
||||
}
|
||||
]]>);
|
||||
|
||||
this.features.push = deprecated("set.add", function push(feature) set.add(this, feature));
|
||||
if (util.haveGecko("2b"))
|
||||
this.features.push("Gecko2");
|
||||
set.add(this.features, "Gecko2");
|
||||
|
||||
this.timeout(function () {
|
||||
services["dactyl:"].pages.dtd = function () [null,
|
||||
iter(config.dtdExtra, (["dactyl." + s, config[s]] for each (s in config.dtdStrings)))
|
||||
.map(function ([k, v]) ["<!ENTITY ", k, " '", String.replace(v, /'/g, "'"), "'>"].join(""))
|
||||
.join("\n")]
|
||||
iter(config.dtdExtra,
|
||||
(["dactyl." + k, v] for ([k, v] in iter(config.dtd))),
|
||||
(["dactyl." + s, config[s]] for each (s in config.dtdStrings)))
|
||||
.map(function ([k, v]) ["<!ENTITY ", k, " '", String.replace(v, /'/g, "'"), "'>"].join(""))
|
||||
.join("\n")]
|
||||
});
|
||||
},
|
||||
|
||||
@@ -119,17 +122,20 @@ var ConfigBase = Class("ConfigBase", {
|
||||
return version;
|
||||
}),
|
||||
|
||||
// TODO: DTD properties. Cleanup.
|
||||
get home() "http://dactyl.sourceforge.net/",
|
||||
get apphome() this.home + this.name,
|
||||
code: "http://code.google.com/p/dactyl/",
|
||||
get issues() this.home + "bug/" + this.name,
|
||||
get plugins() "http://dactyl.sf.net/" + this.name + "/plugins",
|
||||
get faq() this.home + this.name + "/faq",
|
||||
"list.mailto": Class.memoize(function () config.name + "@googlegroups.com"),
|
||||
"list.href": Class.memoize(function () "http://groups.google.com/group/" + config.name),
|
||||
"hg.latest": Class.memoize(function () config.code + "source/browse/"), // XXX
|
||||
"irc": "irc://irc.oftc.net/#pentadactyl",
|
||||
dtd: memoize({
|
||||
get home() "http://dactyl.sourceforge.net/",
|
||||
get apphome() this.home + this.name,
|
||||
code: "http://code.google.com/p/dactyl/",
|
||||
get issues() this.home + "bug/" + this.name,
|
||||
get plugins() "http://dactyl.sf.net/" + this.name + "/plugins",
|
||||
get faq() this.home + this.name + "/faq",
|
||||
|
||||
"list.mailto": Class.memoize(function () config.name + "@googlegroups.com"),
|
||||
"list.href": Class.memoize(function () "http://groups.google.com/group/" + config.name),
|
||||
|
||||
"hg.latest": Class.memoize(function () this.code + "source/browse/"), // XXX
|
||||
"irc": "irc://irc.oftc.net/#pentadactyl",
|
||||
}),
|
||||
|
||||
dtdExtra: {
|
||||
"xmlns.dactyl": "http://vimperator.org/namespaces/liberator",
|
||||
@@ -142,21 +148,11 @@ var ConfigBase = Class("ConfigBase", {
|
||||
|
||||
dtdStrings: [
|
||||
"appName",
|
||||
"apphome",
|
||||
"code",
|
||||
"faq",
|
||||
"fileExt",
|
||||
"hg.latest",
|
||||
"home",
|
||||
"host",
|
||||
"hostbin",
|
||||
"idName",
|
||||
"irc",
|
||||
"issues",
|
||||
"list.href",
|
||||
"list.mailto",
|
||||
"name",
|
||||
"plugins",
|
||||
"version"
|
||||
],
|
||||
|
||||
@@ -208,11 +204,11 @@ var ConfigBase = Class("ConfigBase", {
|
||||
}),
|
||||
|
||||
/**
|
||||
* @property {[["string", "string"]]} A sequence of names and descriptions
|
||||
* @property {Object} A mapping of names and descriptions
|
||||
* of the autocommands available in this application. Primarily used
|
||||
* for completion results.
|
||||
*/
|
||||
autocommands: [],
|
||||
autocommands: {},
|
||||
|
||||
commandContainer: "browser-bottombox",
|
||||
|
||||
@@ -262,23 +258,22 @@ var ConfigBase = Class("ConfigBase", {
|
||||
cleanups: {},
|
||||
|
||||
/**
|
||||
* @property {[["string", "string", "function"]]} An array of
|
||||
* dialogs available via the :dialog command.
|
||||
* [0] name - The name of the dialog, used as the first
|
||||
* argument to :dialog.
|
||||
* [1] description - A description of the dialog, used in
|
||||
* @property {Object} A map of dialogs available via the
|
||||
* :dialog command. Property names map dialog names to an array
|
||||
* as follows:
|
||||
* [0] description - A description of the dialog, used in
|
||||
* command completion results for :dialog.
|
||||
* [2] action - The function executed by :dialog.
|
||||
* [1] action - The function executed by :dialog.
|
||||
*/
|
||||
dialogs: [],
|
||||
dialogs: {},
|
||||
|
||||
/**
|
||||
* @property {string[]} A list of features available in this
|
||||
* @property {set} A list of features available in this
|
||||
* application. Used extensively in feature test macros. Use
|
||||
* dactyl.has(feature) to check for a feature's presence
|
||||
* in this array.
|
||||
*/
|
||||
features: [],
|
||||
features: {},
|
||||
|
||||
/**
|
||||
* @property {string} The file extension used for command script files.
|
||||
@@ -426,9 +421,16 @@ var ConfigBase = Class("ConfigBase", {
|
||||
Keyword color: red;
|
||||
Tag color: blue;
|
||||
|
||||
Usage position: relative; padding-right: 2em;
|
||||
Usage>LineInfo position: absolute; left: 100%; padding: 1ex; margin: -1ex -1em; background: rgba(255, 255, 255, .8); border-radius: 1ex;
|
||||
Usage:not(:hover)>LineInfo opacity: 0; left: 0; width: 1px; height: 1px; overflow: hidden;
|
||||
Link position: relative; padding-right: 2em;
|
||||
Link:not(:hover)>LinkInfo opacity: 0; left: 0; width: 1px; height: 1px; overflow: hidden;
|
||||
LinkInfo {
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
padding: 1ex;
|
||||
margin: -1ex -1em;
|
||||
background: rgba(255, 255, 255, .8);
|
||||
border-radius: 1ex;
|
||||
}
|
||||
|
||||
StatusLine;;;FontFixed {
|
||||
-moz-appearance: none !important;
|
||||
|
||||
@@ -92,7 +92,8 @@ var Highlights = Module("Highlight", {
|
||||
|
||||
keys: function keys() Object.keys(this.highlight).sort(),
|
||||
|
||||
__iterator__: function () values(this.highlight),
|
||||
__iterator__: function () values(this.highlight).sort(function (a, b) String.localeCompare(a.class, b.class))
|
||||
.iterValues(),
|
||||
|
||||
_create: function (agent, args) {
|
||||
let obj = Highlight.apply(Highlight, args);
|
||||
@@ -318,7 +319,7 @@ var Highlights = Module("Highlight", {
|
||||
if (!modify)
|
||||
modules.commandline.commandOutput(
|
||||
template.tabular(["Key", "Sample", "Link", "CSS"],
|
||||
["padding: 0 1em 0 0; vertical-align: top",
|
||||
["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>,
|
||||
|
||||
@@ -79,6 +79,7 @@ var Services = Module("Services", {
|
||||
[Ci.nsIChannel, Ci.nsIInputStreamChannel, Ci.nsIRequest], "setURI");
|
||||
this.addClass("String", "@mozilla.org/supports-string;1", Ci.nsISupportsString, "data");
|
||||
this.addClass("StringStream", "@mozilla.org/io/string-input-stream;1", Ci.nsIStringInputStream, "data");
|
||||
this.addClass("Transfer", "@mozilla.org/transfer;1", Ci.nsITransfer, "init");
|
||||
this.addClass("Timer", "@mozilla.org/timer;1", Ci.nsITimer, "initWithCallback");
|
||||
this.addClass("StreamCopier", "@mozilla.org/network/async-stream-copier;1",Ci.nsIAsyncStreamCopier, "init");
|
||||
this.addClass("Xmlhttp", "@mozilla.org/xmlextras/xmlhttprequest;1", Ci.nsIXMLHttpRequest);
|
||||
@@ -113,10 +114,11 @@ var Services = Module("Services", {
|
||||
}
|
||||
|
||||
["aboutURL", "creator", "description", "developers",
|
||||
"homepageURL", "iconURL", "installDate",
|
||||
"optionsURL", "releaseNotesURI", "updateDate", "version"].forEach(function (item) {
|
||||
addon[item] = getRdfProperty(addon, item);
|
||||
"homepageURL", "installDate", "optionsURL",
|
||||
"releaseNotesURI", "updateDate"].forEach(function (item) {
|
||||
memoize(addon, item, function (item) getRdfProperty(this, item));
|
||||
});
|
||||
|
||||
update(addon, {
|
||||
|
||||
appDisabled: false,
|
||||
@@ -147,7 +149,7 @@ var Services = Module("Services", {
|
||||
for (let [, item] in Iterator(services.extensionManager
|
||||
.getItemList(Ci.nsIUpdateItem["TYPE_" + type.toUpperCase()], {})))
|
||||
res.push(this.getAddonByID(item));
|
||||
callback(res);
|
||||
return (callback || util.identity)(res);
|
||||
},
|
||||
getInstallForFile: function (file, callback, mimetype) {
|
||||
callback({
|
||||
@@ -206,14 +208,7 @@ var Services = Module("Services", {
|
||||
const self = this;
|
||||
if (name in this && ifaces && !this.__lookupGetter__(name) && !(this[name] instanceof Ci.nsISupports))
|
||||
throw TypeError();
|
||||
this.__defineGetter__(name, function () {
|
||||
let res = self._create(class_, ifaces, meth);
|
||||
if (!res)
|
||||
return null;
|
||||
|
||||
delete this[name];
|
||||
return this[name] = res;
|
||||
});
|
||||
memoize(this, name, function () self._create(class_, ifaces, meth));
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -259,9 +259,15 @@ var Storage = Module("Storage", {
|
||||
}
|
||||
}, {
|
||||
}, {
|
||||
init: function (dactyl, modules) {
|
||||
init: function init(dactyl, modules) {
|
||||
init.superapply(this, arguments);
|
||||
storage.infoPath = File(modules.IO.runtimePath.replace(/,.*/, ""))
|
||||
.child("info").child(dactyl.profileName);
|
||||
},
|
||||
|
||||
cleanup: function (dactyl, modules, window) {
|
||||
delete window.dactylStorageRefs;
|
||||
this.removeDeadObservers();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -262,12 +262,13 @@ var Template = Module("Template", {
|
||||
|
||||
sourceLink: function (frame) {
|
||||
let url = (frame.filename || "unknown").replace(/.* -> /, "");
|
||||
let path = util.urlPath(url);
|
||||
|
||||
XML.ignoreWhitespace = false; XML.prettyPrinting = false;
|
||||
return <a xmlns:dactyl={NS} dactyl:command="buffer.viewSource"
|
||||
href={url} line={frame.lineNumber}
|
||||
href={url} path={path} line={frame.lineNumber}
|
||||
highlight="URL">{
|
||||
util.urlPath(url) + ":" + frame.lineNumber
|
||||
path + ":" + frame.lineNumber
|
||||
}</a>
|
||||
},
|
||||
|
||||
@@ -331,11 +332,11 @@ var Template = Module("Template", {
|
||||
this.map(iter, function (item)
|
||||
<tr>
|
||||
<td style="padding-right: 2em;">
|
||||
<span highlight="Usage">{
|
||||
<span highlight="Usage Link">{
|
||||
let (name = item.name || item.names[0], frame = item.definedAt)
|
||||
!frame ? name :
|
||||
template.helpLink(help(item), name, "Title") +
|
||||
<span highlight="LineInfo" xmlns:dactyl={NS}>Defined at {sourceLink(frame)}</span>
|
||||
<span highlight="LinkInfo" xmlns:dactyl={NS}>Defined at {sourceLink(frame)}</span>
|
||||
}</span>
|
||||
</td>
|
||||
<td>{desc(item)}</td>
|
||||
|
||||
@@ -135,6 +135,13 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
||||
throw FailedAssertion(message, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Capitalizes the first character of the given string.
|
||||
* @param {string} str The string to capitalize
|
||||
* @returns {string}
|
||||
*/
|
||||
capitalize: function capitalize(str) str && str[0].toUpperCase() + str.slice(1),
|
||||
|
||||
/**
|
||||
* Returns a RegExp object that matches characters specified in the range
|
||||
* expression *list*, or signals an appropriate error if *list* is invalid.
|
||||
@@ -499,9 +506,10 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
||||
|
||||
stackLines: function (stack) {
|
||||
let lines = [];
|
||||
let match, re = /([^]*?)(@[^@\n]*)(?:\n|$)/g;
|
||||
let match, re = /([^]*?)@([^@\n]*)(?:\n|$)/g;
|
||||
while (match = re.exec(stack))
|
||||
lines.push(match[1].replace(/\n/g, "\\n").substr(0, 80) + match[2]);
|
||||
lines.push(match[1].replace(/\n/g, "\\n").substr(0, 80) + "@" +
|
||||
match[2].replace(/.* -> /, ""));
|
||||
return lines;
|
||||
},
|
||||
|
||||
@@ -653,6 +661,28 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
||||
return strNum[0] + " " + unitVal[unitIndex];
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts *seconds* into a human readable time string.
|
||||
*
|
||||
* @param {number} seconds
|
||||
* @returns {string}
|
||||
*/
|
||||
formatSeconds: function formatSeconds(seconds) {
|
||||
function div(num, denom) [Math.round(num / denom), Math.round(num % denom)];
|
||||
let days, hours, minutes;
|
||||
|
||||
[minutes, seconds] = div(seconds, 60);
|
||||
[hours, minutes] = div(minutes, 60);
|
||||
[days, hours] = div(hours, 24);
|
||||
if (days)
|
||||
return days + " days " + hours + " hours"
|
||||
if (hours)
|
||||
return hours + "h " + minutes + "m";
|
||||
if (minutes)
|
||||
return minutes + ":" + seconds;
|
||||
return seconds + "s";
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the file which backs a given URL, if available.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user