mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2026-01-30 03:05:44 +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,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.
|
||||
@@ -18,7 +18,7 @@ const AutoCommands = Module("autocommands", {
|
||||
this._store = [];
|
||||
},
|
||||
|
||||
__iterator__: function () util.Array.itervalues(this._store),
|
||||
__iterator__: function () array.itervalues(this._store),
|
||||
|
||||
/**
|
||||
* Adds a new autocommand. <b>cmd</b> will be executed when one of the
|
||||
@@ -94,7 +94,7 @@ const AutoCommands = Module("autocommands", {
|
||||
+
|
||||
template.map(items, function (item)
|
||||
<tr>
|
||||
<td> {item.pattern.source}</td>
|
||||
<td> {item.pattern.source}</td>
|
||||
<td>{item.command}</td>
|
||||
</tr>))
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -11,13 +11,11 @@ const DEFAULT_FAVICON = "chrome://mozapps/skin/places/defaultFavicon.png";
|
||||
// also includes methods for dealing with keywords and search engines
|
||||
const Bookmarks = Module("bookmarks", {
|
||||
init: function () {
|
||||
let bookmarkObserver = function (key, event, arg) {
|
||||
storage.addObserver("bookmark-cache", function (key, event, arg) {
|
||||
if (event == "add")
|
||||
autocommands.trigger("BookmarkAdd", arg);
|
||||
statusline.updateUrl();
|
||||
};
|
||||
|
||||
storage.addObserver("bookmark-cache", bookmarkObserver, window);
|
||||
}, window);
|
||||
},
|
||||
|
||||
get format() ({
|
||||
@@ -36,7 +34,8 @@ const Bookmarks = Module("bookmarks", {
|
||||
add: function add(starOnly, title, url, keyword, tags, force) {
|
||||
try {
|
||||
let uri = util.createURI(url);
|
||||
if (!force) {
|
||||
if (!force && bookmarks.isBookmarked(uri.spec)) {
|
||||
// WTF? This seems wrong... --Kris
|
||||
for (let bmark in bookmarkcache) {
|
||||
if (bmark[0] == uri.spec) {
|
||||
var id = bmark[5];
|
||||
@@ -74,21 +73,22 @@ const Bookmarks = Module("bookmarks", {
|
||||
|
||||
let count = this.remove(url);
|
||||
if (count > 0)
|
||||
commandline.echo("Removed bookmark: " + url, commandline.HL_NORMAL, commandline.FORCE_SINGLELINE);
|
||||
dactyl.echomsg({ domains: [util.getHost(url)], message: "Removed bookmark: " + url });
|
||||
else {
|
||||
let title = buffer.title || url;
|
||||
let extra = "";
|
||||
if (title != url)
|
||||
extra = " (" + title + ")";
|
||||
this.add(true, title, url);
|
||||
commandline.echo("Added bookmark: " + url + extra, commandline.HL_NORMAL, commandline.FORCE_SINGLELINE);
|
||||
dactyl.echomsg({ domains: [util.getHost(url)], message: "Added bookmark: " + url + extra });
|
||||
}
|
||||
},
|
||||
|
||||
isBookmarked: function isBookmarked(url) {
|
||||
try {
|
||||
return services.get("bookmarks").getBookmarkIdsForURI(makeURI(url), {})
|
||||
.some(bookmarkcache.isRegularBookmark);
|
||||
return services.get("bookmarks")
|
||||
.getBookmarkIdsForURI(makeURI(url), {})
|
||||
.some(bookmarkcache.closure.isRegularBookmark);
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
@@ -99,13 +99,14 @@ const Bookmarks = Module("bookmarks", {
|
||||
remove: function remove(url) {
|
||||
try {
|
||||
let uri = util.newURI(url);
|
||||
let bmarks = services.get("bookmarks").getBookmarkIdsForURI(uri, {})
|
||||
.filter(bookmarkcache.isRegularBookmark);
|
||||
let bmarks = services.get("bookmarks")
|
||||
.getBookmarkIdsForURI(uri, {})
|
||||
.filter(bookmarkcache.closure.isRegularBookmark);
|
||||
bmarks.forEach(services.get("bookmarks").removeItem);
|
||||
return bmarks.length;
|
||||
}
|
||||
catch (e) {
|
||||
dactyl.log(e, 0);
|
||||
dactyl.reportError(e);
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
@@ -287,7 +288,7 @@ const Bookmarks = Module("bookmarks", {
|
||||
args.completeFilter = have.pop();
|
||||
|
||||
let prefix = filter.substr(0, filter.length - args.completeFilter.length);
|
||||
let tags = array.uniq(util.Array.flatten([b.tags for ([k, b] in Iterator(bookmarkcache.bookmarks))]));
|
||||
let tags = array.uniq(array.flatten([b.tags for ([k, b] in Iterator(bookmarkcache.bookmarks))]));
|
||||
|
||||
return [[prefix + tag, tag] for ([i, tag] in Iterator(tags)) if (have.indexOf(tag) < 0)];
|
||||
},
|
||||
@@ -330,7 +331,8 @@ const Bookmarks = Module("bookmarks", {
|
||||
|
||||
if (bookmarks.add(false, title, url, keyword, tags, args.bang)) {
|
||||
let extra = (title == url) ? "" : " (" + title + ")";
|
||||
dactyl.echomsg("Added bookmark: " + url + extra, 1, commandline.FORCE_SINGLELINE);
|
||||
dactyl.echomsg({ domains: [util.getHost(url)], message: "Added bookmark: " + url + extra },
|
||||
1, commandline.FORCE_SINGLELINE);
|
||||
}
|
||||
else
|
||||
dactyl.echoerr("Exxx: Could not add bookmark " + title.quote(), commandline.FORCE_SINGLELINE);
|
||||
@@ -385,7 +387,8 @@ const Bookmarks = Module("bookmarks", {
|
||||
let url = args.string || buffer.URL;
|
||||
let deletedCount = bookmarks.remove(url);
|
||||
|
||||
dactyl.echomsg(deletedCount + " bookmark(s) with url " + url.quote() + " deleted", 1, commandline.FORCE_SINGLELINE);
|
||||
dactyl.echomsg({ domains: [util.getHost(url)], message: deletedCount + " bookmark(s) with url " + url.quote() + " deleted" },
|
||||
1, commandline.FORCE_SINGLELINE);
|
||||
}
|
||||
|
||||
},
|
||||
@@ -493,13 +496,12 @@ const Bookmarks = Module("bookmarks", {
|
||||
return history.get({ uri: window.makeURI(begin), uriIsPrefix: true }).map(function (item) {
|
||||
let rest = item.url.length - end.length;
|
||||
let query = item.url.substring(begin.length, rest);
|
||||
if (item.url.substr(rest) == end && query.indexOf("&") == -1) {
|
||||
if (item.url.substr(rest) == end && query.indexOf("&") == -1)
|
||||
try {
|
||||
item.url = decodeURIComponent(query.replace(/#.*/, ""));
|
||||
item.url = decodeURIComponent(query.replace(/#.*/, "").replace(/\+/g, " "));
|
||||
return item;
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
return null;
|
||||
}).filter(util.identity);
|
||||
};
|
||||
|
||||
@@ -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 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.
|
||||
|
||||
@@ -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 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.
|
||||
@@ -84,7 +84,7 @@ const Buffer = Module("buffer", {
|
||||
const ACCESS_READ = Ci.nsICache.ACCESS_READ;
|
||||
let cacheKey = doc.location.toString().replace(/#.*$/, "");
|
||||
|
||||
for (let proto in util.Array.itervalues(["HTTP", "FTP"])) {
|
||||
for (let proto in array.itervalues(["HTTP", "FTP"])) {
|
||||
try {
|
||||
var cacheEntryDescriptor = services.get("cache").createSession(proto, 0, true)
|
||||
.openCacheEntry(cacheKey, ACCESS_READ, false);
|
||||
@@ -174,9 +174,11 @@ const Buffer = Module("buffer", {
|
||||
// event listener which is is called on each page load, even if the
|
||||
// page is loaded in a background tab
|
||||
onPageLoad: function onPageLoad(event) {
|
||||
if (!dactyl.helpInitialized && event.originalTarget instanceof Document)
|
||||
if (/^dactyl:/.test(event.originalTarget.location.href))
|
||||
if (event.originalTarget instanceof Document)
|
||||
if (/^dactyl:/.test(event.originalTarget.location.href)) {
|
||||
dactyl.initHelp();
|
||||
config.styleHelp();
|
||||
}
|
||||
|
||||
if (event.originalTarget instanceof HTMLDocument) {
|
||||
let doc = event.originalTarget;
|
||||
@@ -197,7 +199,7 @@ const Buffer = Module("buffer", {
|
||||
doc.pageIsFullyLoaded = 1;
|
||||
|
||||
if (doc != config.browser.contentDocument)
|
||||
dactyl.echomsg("Background tab loaded: " + doc.title || doc.location.href, 3);
|
||||
dactyl.echomsg({ domains: [util.getHost(doc.location.href)], message: "Background tab loaded: " + doc.title || doc.location.href }, 3);
|
||||
|
||||
this._triggerLoadAutocmd("PageLoad", doc);
|
||||
}
|
||||
@@ -206,7 +208,11 @@ const Buffer = Module("buffer", {
|
||||
/**
|
||||
* @property {Object} The document loading progress listener.
|
||||
*/
|
||||
progressListener: update({ __proto__: window.XULBrowserWindow }, {
|
||||
progressListener: update(Object.create(window.XULBrowserWindow), {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIWebProgressListener]),
|
||||
|
||||
loadCount: 0,
|
||||
|
||||
// XXX: function may later be needed to detect a canceled synchronous openURL()
|
||||
onStateChange: function onStateChange(webProgress, request, flags, status) {
|
||||
onStateChange.superapply(this, arguments);
|
||||
@@ -223,7 +229,7 @@ const Buffer = Module("buffer", {
|
||||
|
||||
// don't reset mode if a frame of the frameset gets reloaded which
|
||||
// is not the focused frame
|
||||
if (document.commandDispatcher.focusedWindow == webProgress.DOMWindow) {
|
||||
if (document.commandDispatcher.focusedWindow == webProgress.DOMWindow && this.loadCount++) {
|
||||
util.timeout(function () { modes.reset(false); },
|
||||
dactyl.mode == modes.HINTS ? 500 : 0);
|
||||
}
|
||||
@@ -1012,7 +1018,7 @@ const Buffer = Module("buffer", {
|
||||
if (win.scrollMaxX > 0 || win.scrollMaxY > 0)
|
||||
return win;
|
||||
|
||||
for (let frame in util.Array.itervalues(win.frames))
|
||||
for (let frame in array.itervalues(win.frames))
|
||||
if (frame.scrollMaxX > 0 || frame.scrollMaxY > 0)
|
||||
return frame;
|
||||
|
||||
@@ -1314,39 +1320,39 @@ const Buffer = Module("buffer", {
|
||||
group[1].push([i, tab.linkedBrowser]);
|
||||
});
|
||||
|
||||
let orig = context;
|
||||
for (let [id, [name, browsers]] in Iterator(tabGroups)) {
|
||||
context = orig.fork(id, 0);
|
||||
context.anchored = false;
|
||||
context.title = [name || "Buffers"];
|
||||
context.keys = { text: "text", description: "url", icon: "icon" };
|
||||
context.compare = CompletionContext.Sort.number;
|
||||
let process = context.process[0];
|
||||
context.process = [function (item, text)
|
||||
<>
|
||||
<span highlight="Indicator" style="display: inline-block;">{item.item.indicator}</span>
|
||||
{ process.call(this, item, text) }
|
||||
</>];
|
||||
context.pushProcessor(0, function (item, text, next) <>
|
||||
<span highlight="Indicator" style="display: inline-block;">{item.item.indicator}</span>
|
||||
{ next.call(this, item, text) }
|
||||
</>);
|
||||
context.process[1] = function (item, text) template.highlightURL(text);
|
||||
|
||||
context.completions = util.map(util.Array.itervalues(browsers), function ([i, browser]) {
|
||||
let indicator = " ";
|
||||
if (i == tabs.index())
|
||||
indicator = "%"
|
||||
else if (i == tabs.index(tabs.alternate))
|
||||
indicator = "#";
|
||||
context.anchored = false;
|
||||
context.keys = { text: "text", description: "url", icon: "icon" };
|
||||
context.compare = CompletionContext.Sort.number;
|
||||
|
||||
let tab = tabs.getTab(i);
|
||||
let url = browser.contentDocument.location.href;
|
||||
i = i + 1;
|
||||
for (let [id, vals] in Iterator(tabGroups))
|
||||
context.fork(id, 0, this, function (context, [name, browsers]) {
|
||||
context.title = [name || "Buffers"];
|
||||
context.generate = function ()
|
||||
util.map(array.itervalues(browsers), function ([i, browser]) {
|
||||
let indicator = " ";
|
||||
if (i == tabs.index())
|
||||
indicator = "%"
|
||||
else if (i == tabs.index(tabs.alternate))
|
||||
indicator = "#";
|
||||
|
||||
return {
|
||||
text: [i + ": " + (tab.label || "(Untitled)"), i + ": " + url],
|
||||
url: template.highlightURL(url),
|
||||
indicator: indicator,
|
||||
icon: tab.image || DEFAULT_FAVICON
|
||||
};
|
||||
});
|
||||
}
|
||||
let tab = tabs.getTab(i);
|
||||
let url = browser.contentDocument.location.href;
|
||||
i = i + 1;
|
||||
|
||||
return {
|
||||
text: [i + ": " + (tab.label || "(Untitled)"), i + ": " + url],
|
||||
url: url,
|
||||
indicator: indicator,
|
||||
icon: tab.image || DEFAULT_FAVICON
|
||||
};
|
||||
});
|
||||
}, vals);
|
||||
};
|
||||
},
|
||||
events: function () {
|
||||
@@ -1354,6 +1360,15 @@ const Buffer = Module("buffer", {
|
||||
config.browser.removeProgressListener(window.XULBrowserWindow);
|
||||
}
|
||||
catch (e) {} // Why? --djk
|
||||
|
||||
// I hate this whole hack. --Kris
|
||||
let obj = window.XULBrowserWindow, getter;
|
||||
for (let p in properties(obj))
|
||||
if ((getter = obj.__lookupGetter__(p)) && !obj.__lookupSetter__(p)) {
|
||||
this.progressListener.__defineGetter__(p, getter);
|
||||
delete obj[p];
|
||||
}
|
||||
|
||||
config.browser.addProgressListener(this.progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
window.XULBrowserWindow = this.progressListener;
|
||||
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
@@ -1503,7 +1518,8 @@ const Buffer = Module("buffer", {
|
||||
if (elem.readOnly || elem instanceof HTMLInputElement && !set.has(Events.editableInputs, elem.type))
|
||||
return false;
|
||||
let computedStyle = util.computedStyle(elem);
|
||||
return computedStyle.visibility != "hidden" && computedStyle.display != "none";
|
||||
return computedStyle.visibility != "hidden" && computedStyle.display != "none" &&
|
||||
computedStyle.MozUserFocus != "ignore";
|
||||
});
|
||||
|
||||
dactyl.assert(elements.length > 0);
|
||||
@@ -1617,13 +1633,13 @@ const Buffer = Module("buffer", {
|
||||
function () { buffer.showPageInfo(true); });
|
||||
},
|
||||
options: function () {
|
||||
options.add(["nextpattern"], // \u00BB is » (>> in a single char)
|
||||
options.add(["nextpattern"],
|
||||
"Patterns to use when guessing the 'next' page in a document sequence",
|
||||
"stringlist", "\\bnext\\b,^>$,^(>>|\u00BB)$,^(>|\u00BB),(>|\u00BB)$,\\bmore\\b");
|
||||
"stringlist", UTF8("\\bnext\\b,^>$,^(>>|»)$,^(>|»),(>|»)$,\\bmore\\b"));
|
||||
|
||||
options.add(["previouspattern"], // \u00AB is « (<< in a single char)
|
||||
options.add(["previouspattern"],
|
||||
"Patterns to use when guessing the 'previous' page in a document sequence",
|
||||
"stringlist", "\\bprev|previous\\b,^<$,^(<<|\u00AB)$,^(<|\u00AB),(<|\u00AB)$");
|
||||
"stringlist", UTF8("\\bprev|previous\\b,^<$,^(<<|«)$,^(<|«),(<|«)$"));
|
||||
|
||||
options.add(["pageinfo", "pa"],
|
||||
"Desired info in the :pageinfo output",
|
||||
|
||||
@@ -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.
|
||||
@@ -103,31 +103,32 @@ const CommandLine = Module("commandline", {
|
||||
////////////////////// VARIABLES ///////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////{{{
|
||||
|
||||
this._completionList = ItemList("dactyl-completions");
|
||||
memoize(this, "_completionList", function () ItemList("dactyl-completions"));
|
||||
this._completions = null;
|
||||
this._history = null;
|
||||
|
||||
this._startHints = false; // whether we're waiting to start hints mode
|
||||
this._lastSubstring = "";
|
||||
|
||||
this.widgets = {
|
||||
commandline: document.getElementById("dactyl-commandline"),
|
||||
prompt: document.getElementById("dactyl-commandline-prompt"),
|
||||
command: document.getElementById("dactyl-commandline-command"),
|
||||
memoize(this, "widgets", function () {
|
||||
let widgets = {
|
||||
commandline: document.getElementById("dactyl-commandline"),
|
||||
prompt: document.getElementById("dactyl-commandline-prompt"),
|
||||
command: document.getElementById("dactyl-commandline-command"),
|
||||
|
||||
message: document.getElementById("dactyl-message"),
|
||||
message: document.getElementById("dactyl-message"),
|
||||
|
||||
multilineOutput: document.getElementById("dactyl-multiline-output"),
|
||||
multilineInput: document.getElementById("dactyl-multiline-input"),
|
||||
};
|
||||
multilineOutput: document.getElementById("dactyl-multiline-output"),
|
||||
multilineInput: document.getElementById("dactyl-multiline-input"),
|
||||
};
|
||||
|
||||
this.widgets.command.inputField.QueryInterface(Ci.nsIDOMNSEditableElement);
|
||||
this.widgets.message.inputField.QueryInterface(Ci.nsIDOMNSEditableElement);
|
||||
widgets.command.inputField.QueryInterface(Ci.nsIDOMNSEditableElement);
|
||||
widgets.message.inputField.QueryInterface(Ci.nsIDOMNSEditableElement);
|
||||
widgets.mowContainer = widgets.multilineOutput.parentNode;
|
||||
|
||||
// the widget used for multiline output
|
||||
this._outputContainer = this.widgets.multilineOutput.parentNode;
|
||||
|
||||
this.widgets.multilineOutput.contentDocument.body.id = "dactyl-multiline-output-content";
|
||||
widgets.multilineOutput.contentDocument.body.id = "dactyl-multiline-output-content";
|
||||
return widgets;
|
||||
});
|
||||
|
||||
// we need to save the mode which were in before opening the command line
|
||||
// this is then used if we focus the command line again without the "official"
|
||||
@@ -181,12 +182,14 @@ const CommandLine = Module("commandline", {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight the messageBox according to <b>group</b>.
|
||||
*/
|
||||
_setHighlightGroup: function (group) {
|
||||
this.widgets.message.setAttributeNS(NS.uri, "highlight", group);
|
||||
set highlightGroup(group) {
|
||||
highlight.highlightNode(this.widgets.message, group);
|
||||
},
|
||||
get highlightGroup() this.widgets.message.getAttributeNS(NS.uri, "highlight"),
|
||||
|
||||
/**
|
||||
* Determines whether the command line should be visible.
|
||||
@@ -206,7 +209,7 @@ const CommandLine = Module("commandline", {
|
||||
this.widgets.prompt.value = val;
|
||||
this.widgets.prompt.size = val.length;
|
||||
this.widgets.prompt.collapsed = (val == "");
|
||||
this.widgets.prompt.setAttributeNS(NS.uri, "highlight", highlightGroup || commandline.HL_NORMAL);
|
||||
highlight.highlightNode(this.widgets.prompt, highlightGroup || commandline.HL_NORMAL);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -229,8 +232,8 @@ const CommandLine = Module("commandline", {
|
||||
* @param {boolean} forceSingle If provided, don't let over-long
|
||||
* messages move to the MOW.
|
||||
*/
|
||||
_echoLine: function (str, highlightGroup, forceSingle) {
|
||||
this._setHighlightGroup(highlightGroup);
|
||||
_echoLine: function echoLine(str, highlightGroup, forceSingle) {
|
||||
this.highlightGroup = highlightGroup;
|
||||
this.widgets.message.value = str;
|
||||
|
||||
dactyl.triggerObserver("echoLine", str, highlightGroup, forceSingle);
|
||||
@@ -250,7 +253,7 @@ const CommandLine = Module("commandline", {
|
||||
* @param {string} highlightGroup
|
||||
*/
|
||||
// TODO: resize upon a window resize
|
||||
_echoMultiline: function (str, highlightGroup) {
|
||||
_echoMultiline: function echoMultiline(str, highlightGroup) {
|
||||
let doc = this.widgets.multilineOutput.contentDocument;
|
||||
let win = this.widgets.multilineOutput.contentWindow;
|
||||
|
||||
@@ -260,14 +263,15 @@ const CommandLine = Module("commandline", {
|
||||
// Otherwise, white space is significant.
|
||||
// The problem elsewhere is that E4X tends to insert new lines
|
||||
// after interpolated data.
|
||||
XML.ignoreWhitespace = typeof str != "xml";
|
||||
this._lastMowOutput = <div class="ex-command-output" style="white-space: nowrap" highlight={highlightGroup}>{template.maybeXML(str)}</div>;
|
||||
XML.ignoreWhitespace = false;
|
||||
XML.prettyPrinting = false;
|
||||
let style = typeof str === "string" ? "pre" : "nowrap";
|
||||
this._lastMowOutput = <div class="ex-command-output" style={"white-space: " + style} highlight={highlightGroup}>{str}</div>;
|
||||
let output = util.xmlToDom(this._lastMowOutput, doc);
|
||||
XML.ignoreWhitespace = true;
|
||||
|
||||
// FIXME: need to make sure an open MOW is closed when commands
|
||||
// that don't generate output are executed
|
||||
if (this._outputContainer.collapsed)
|
||||
if (this.widgets.mowContainer.collapsed)
|
||||
doc.body.innerHTML = "";
|
||||
|
||||
doc.body.appendChild(output);
|
||||
@@ -417,6 +421,8 @@ const CommandLine = Module("commandline", {
|
||||
this._currentExtendedMode = null;
|
||||
commandline.triggerCallback("cancel", mode);
|
||||
|
||||
if (this._completions)
|
||||
this._completions.previewClear();
|
||||
if (this._history)
|
||||
this._history.save();
|
||||
|
||||
@@ -431,11 +437,11 @@ const CommandLine = Module("commandline", {
|
||||
this._completionList.hide();
|
||||
|
||||
if (!this._keepCommand || this._silent || this._quiet) {
|
||||
this._outputContainer.collapsed = true;
|
||||
this.widgets.mowContainer.collapsed = true;
|
||||
commandline.updateMorePrompt();
|
||||
this.hide();
|
||||
}
|
||||
if (!this._outputContainer.collapsed) {
|
||||
if (!this.widgets.mowContainer.collapsed) {
|
||||
modes.set(modes.COMMAND_LINE, modes.OUTPUT_MULTILINE);
|
||||
commandline.updateMorePrompt();
|
||||
}
|
||||
@@ -492,39 +498,42 @@ const CommandLine = Module("commandline", {
|
||||
|
||||
if (flags & this.APPEND_TO_MESSAGES) {
|
||||
let message = isobject(str) ? str : { message: str };
|
||||
this._messageHistory.add(update({ highlight: highlightGroup }, str));
|
||||
this._messageHistory.add(update({ highlight: highlightGroup }, message));
|
||||
str = message.message;
|
||||
}
|
||||
|
||||
if ((flags & this.ACTIVE_WINDOW) &&
|
||||
window != services.get("windowWatcher").activeWindow &&
|
||||
services.get("windowWatcher").activeWindow.dactyl)
|
||||
return;
|
||||
|
||||
if ((flags & this.DISALLOW_MULTILINE) && !this._outputContainer.collapsed)
|
||||
if ((flags & this.DISALLOW_MULTILINE) && !this.widgets.mowContainer.collapsed)
|
||||
return;
|
||||
|
||||
let single = flags & (this.FORCE_SINGLELINE | this.DISALLOW_MULTILINE);
|
||||
let action = this._echoLine;
|
||||
|
||||
// TODO: this is all a bit convoluted - clean up.
|
||||
// assume that FORCE_MULTILINE output is fully styled
|
||||
if (!(flags & this.FORCE_MULTILINE) && !single && (!this._outputContainer.collapsed || this.widgets.message.value == this._lastEcho)) {
|
||||
highlightGroup += " Message";
|
||||
action = this._echoMultiline;
|
||||
}
|
||||
|
||||
if ((flags & this.FORCE_MULTILINE) || (/\n/.test(str) || typeof str == "xml") && !(flags & this.FORCE_SINGLELINE))
|
||||
action = this._echoMultiline;
|
||||
|
||||
if (single)
|
||||
this._lastEcho = null;
|
||||
else {
|
||||
if (this.widgets.message.value == this._lastEcho)
|
||||
this._echoMultiline(<span highlight="Message">{this._lastEcho}</span>,
|
||||
this.widgets.message.getAttributeNS(NS.uri, "highlight"));
|
||||
this.highlightGroup);
|
||||
this._lastEcho = (action == this._echoLine) && str;
|
||||
}
|
||||
|
||||
// TODO: this is all a bit convoluted - clean up.
|
||||
// assume that FORCE_MULTILINE output is fully styled
|
||||
if (!(flags & this.FORCE_MULTILINE) && !single
|
||||
&& (!this.widgets.mowContainer.collapsed || this.widgets.message.value == this._lastEcho)) {
|
||||
|
||||
highlightGroup += " Message";
|
||||
action = this._echoMultiline;
|
||||
}
|
||||
|
||||
if ((flags & this.FORCE_MULTILINE) || (/\n/.test(str) || typeof str == "xml") && !(flags & this.FORCE_SINGLELINE))
|
||||
action = this._echoMultiline;
|
||||
|
||||
if (action)
|
||||
action.call(this, str, highlightGroup, single);
|
||||
}),
|
||||
@@ -937,7 +946,7 @@ const CommandLine = Module("commandline", {
|
||||
* and what they do.
|
||||
*/
|
||||
updateMorePrompt: function updateMorePrompt(force, showHelp) {
|
||||
if (this._outputContainer.collapsed) {
|
||||
if (this.widgets.mowContainer.collapsed) {
|
||||
this._echoLine("", this.HL_NORMAL);
|
||||
return;
|
||||
}
|
||||
@@ -960,19 +969,25 @@ const CommandLine = Module("commandline", {
|
||||
* @param {boolean} open If true, the widget will be opened if it's not
|
||||
* already so.
|
||||
*/
|
||||
updateOutputHeight: function updateOutputHeight(open) {
|
||||
if (!open && this._outputContainer.collapsed)
|
||||
updateOutputHeight: function updateOutputHeight(open, extra) {
|
||||
if (!open && this.widgets.mowContainer.collapsed)
|
||||
return;
|
||||
|
||||
let doc = this.widgets.multilineOutput.contentDocument;
|
||||
|
||||
let availableHeight = config.outputHeight;
|
||||
if (!this._outputContainer.collapsed)
|
||||
availableHeight += parseFloat(this._outputContainer.height);
|
||||
if (!this.widgets.mowContainer.collapsed)
|
||||
availableHeight += parseFloat(this.widgets.mowContainer.height);
|
||||
availableHeight -= extra || 0;
|
||||
|
||||
doc.body.style.minWidth = this.widgets.commandline.scrollWidth + "px";
|
||||
this._outputContainer.height = Math.min(doc.height, availableHeight) + "px";
|
||||
this.widgets.mowContainer.height = Math.min(doc.height, availableHeight) + "px";
|
||||
this.timeout(function ()
|
||||
this.widgets.mowContainer.height = Math.min(doc.height, availableHeight) + "px",
|
||||
0);
|
||||
|
||||
doc.body.style.minWidth = "";
|
||||
this._outputContainer.collapsed = false;
|
||||
this.widgets.mowContainer.collapsed = false;
|
||||
},
|
||||
|
||||
resetCompletions: function resetCompletions() {
|
||||
@@ -1015,7 +1030,12 @@ const CommandLine = Module("commandline", {
|
||||
if (/^\s*$/.test(str))
|
||||
return;
|
||||
this.store.mutate("filter", function (line) (line.value || line) != str);
|
||||
this.store.push({ value: str, timestamp: Date.now()*1000, privateData: this.checkPrivate(str) });
|
||||
try {
|
||||
this.store.push({ value: str, timestamp: Date.now()*1000, privateData: this.checkPrivate(str) });
|
||||
}
|
||||
catch (e) {
|
||||
dactyl.reportError(e);
|
||||
}
|
||||
this.store.truncate(options["history"], true);
|
||||
},
|
||||
/**
|
||||
@@ -1142,6 +1162,8 @@ const CommandLine = Module("commandline", {
|
||||
|
||||
get wildtype() this.wildtypes[this.wildIndex] || "",
|
||||
|
||||
get wildtypes() this.wildmode.values,
|
||||
|
||||
complete: function complete(show, tabPressed) {
|
||||
this.context.reset();
|
||||
this.context.tabPressed = tabPressed;
|
||||
@@ -1162,7 +1184,7 @@ const CommandLine = Module("commandline", {
|
||||
let substring = "";
|
||||
switch (this.wildtype.replace(/.*:/, "")) {
|
||||
case "":
|
||||
substring = this.items[0].text;
|
||||
substring = this.items[0].result;
|
||||
break;
|
||||
case "longest":
|
||||
if (this.items.length > 1) {
|
||||
@@ -1173,7 +1195,7 @@ const CommandLine = Module("commandline", {
|
||||
case "full":
|
||||
let item = this.items[this.selected != null ? this.selected + 1 : 0];
|
||||
if (item)
|
||||
substring = item.text;
|
||||
substring = item.result;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1227,14 +1249,14 @@ const CommandLine = Module("commandline", {
|
||||
this.wildIndex = 0;
|
||||
}
|
||||
|
||||
this.wildtypes = this.wildmode.values;
|
||||
this.preview();
|
||||
},
|
||||
|
||||
_reset: function _reset() {
|
||||
this.prefix = this.context.value.substring(0, this.start);
|
||||
this.value = this.context.value.substring(this.start, this.caret);
|
||||
this.suffix = this.context.value.substring(this.caret);
|
||||
let value = this.editor.selection.focusNode.textContent;
|
||||
this.prefix = value.substring(0, this.start);
|
||||
this.value = value.substring(this.start, this.caret);
|
||||
this.suffix = value.substring(this.caret);
|
||||
|
||||
this.itemList.reset();
|
||||
this.itemList.selectItem(this.selected);
|
||||
@@ -1301,7 +1323,7 @@ const CommandLine = Module("commandline", {
|
||||
return;
|
||||
|
||||
this.selected = idx;
|
||||
this.completion = this.items[idx].text;
|
||||
this.completion = this.items[idx].result;
|
||||
}
|
||||
|
||||
this.itemList.selectItem(idx);
|
||||
@@ -1320,6 +1342,8 @@ const CommandLine = Module("commandline", {
|
||||
return;
|
||||
|
||||
while (this.tabs.length) {
|
||||
this.wildIndex = Math.min(this.wildIndex, this.wildtypes.length - 1);
|
||||
|
||||
reverse = this.tabs.shift();
|
||||
switch (this.wildtype.replace(/.*:/, "")) {
|
||||
case "":
|
||||
@@ -1340,7 +1364,7 @@ const CommandLine = Module("commandline", {
|
||||
if (this.haveType("list"))
|
||||
this.itemList.show();
|
||||
|
||||
this.wildIndex = Math.constrain(this.wildIndex + 1, 0, this.wildtypes.length - 1);
|
||||
this.wildIndex++;
|
||||
this.preview();
|
||||
|
||||
commandline._statusTimer.tell();
|
||||
@@ -1373,7 +1397,7 @@ const CommandLine = Module("commandline", {
|
||||
|
||||
if (typeof arg === "object")
|
||||
arg = util.objectToString(arg, useColor);
|
||||
else if (typeof arg == "string" && /\n/.test(arg))
|
||||
else if (typeof arg === "string" && /\n/.test(arg))
|
||||
arg = <span highlight="CmdOutput">{arg}</span>;
|
||||
else
|
||||
arg = String(arg);
|
||||
@@ -1533,7 +1557,7 @@ const CommandLine = Module("commandline", {
|
||||
styles: function () {
|
||||
let fontSize = util.computedStyle(document.getElementById(config.mainWindowId)).fontSize;
|
||||
styles.registerSheet("chrome://dactyl/skin/dactyl.css");
|
||||
let error = styles.addSheet(true, "font-size", "chrome://dactyl/content/buffer.xhtml",
|
||||
styles.addSheet(true, "font-size", "chrome://dactyl/content/buffer.xhtml",
|
||||
"body { font-size: " + fontSize + "; }");
|
||||
}
|
||||
});
|
||||
@@ -1542,7 +1566,7 @@ const CommandLine = Module("commandline", {
|
||||
* The list which is used for the completion box (and QuickFix window in
|
||||
* future).
|
||||
*
|
||||
* @param {string} id The id of the <iframe> which will display the list. It
|
||||
* @param {string} id The id of the iframe which will display the list. It
|
||||
* must be in its own container element, whose height it will update as
|
||||
* necessary.
|
||||
*/
|
||||
@@ -1579,12 +1603,15 @@ const ItemList = Class("ItemList", {
|
||||
|
||||
this._minHeight = Math.max(this._minHeight,
|
||||
this._win.scrollY + this._divNodes.completions.getBoundingClientRect().bottom);
|
||||
this._container.height = this._minHeight;
|
||||
|
||||
if (this._container.collapsed)
|
||||
this._div.style.minWidth = "";
|
||||
|
||||
// FIXME: Belongs elsewhere.
|
||||
commandline.updateOutputHeight(false, Math.max(0, this._minHeight - this._container.height));
|
||||
|
||||
this._container.height = this._minHeight;
|
||||
this._container.height -= commandline.getSpaceNeeded()
|
||||
commandline.updateOutputHeight(false);
|
||||
this.timeout(function () { this._container.height -= commandline.getSpaceNeeded(); }, 0);
|
||||
},
|
||||
@@ -1678,7 +1705,7 @@ const ItemList = Class("ItemList", {
|
||||
|
||||
for (let [i, row] in Iterator(context.getRows(start, end, this._doc)))
|
||||
nodes[i] = row;
|
||||
for (let [i, row] in util.Array.iteritems(nodes)) {
|
||||
for (let [i, row] in array.iteritems(nodes)) {
|
||||
if (!row)
|
||||
continue;
|
||||
let display = (i >= start && i < end);
|
||||
|
||||
@@ -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 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.
|
||||
@@ -171,16 +171,10 @@ const Command = Class("Command", {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
hasName: function (name) {
|
||||
for (let [, spec] in Iterator(this.specs)) {
|
||||
let fullName = spec.replace(/\[(\w+)]$/, "$1");
|
||||
let index = spec.indexOf("[");
|
||||
let min = index == -1 ? fullName.length : index;
|
||||
|
||||
if (fullName.indexOf(name) == 0 && name.length >= min)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return this.specs.some(function (spec) {
|
||||
let [, head, tail] = spec.match(/([^[]+)(?:\[(.*)])?/);
|
||||
return name.indexOf(head) == 0 && (head + (tail || "")).indexOf(name) == 0;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -340,25 +334,29 @@ const Commands = Module("commands", {
|
||||
/** @property {Iterator(Command)} @private */
|
||||
__iterator__: function () {
|
||||
let sorted = this._exCommands.sort(function (a, b) a.name > b.name);
|
||||
return util.Array.itervalues(sorted);
|
||||
return array.itervalues(sorted);
|
||||
},
|
||||
|
||||
/** @property {string} The last executed Ex command line. */
|
||||
repeat: null,
|
||||
|
||||
_addCommand: function (command, replace) {
|
||||
if (command.name in this._exMap) {
|
||||
if (command.user && replace)
|
||||
commands.removeUserCommand(command.name);
|
||||
else {
|
||||
dactyl.log("Warning: :" + command.name + " already exists, NOT replacing existing command.", 1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
_addCommand: function (args, replace) {
|
||||
let names = array.flatten(Command.parseSpecs(args[0]));
|
||||
dactyl.assert(!names.some(function (name) name in this._exMap && !this._exMap[name].user, this),
|
||||
"E182: Can't replace non-user command: " + args[0]);
|
||||
if (!replace && args[3] && args[3].user)
|
||||
dactyl.assert(!names.some(function (name) name in this._exMap, this),
|
||||
"Not replacing command " + args[0]);
|
||||
for (let name in names)
|
||||
if (name in this._exMap)
|
||||
commands.removeUserCommand(name);
|
||||
|
||||
this._exCommands.push(command);
|
||||
for (let [,name] in Iterator(command.names))
|
||||
this._exMap[name] = command;
|
||||
let name = names[0];
|
||||
let closure = function () commands._exMap[name];
|
||||
memoize(this._exMap, name, function () Command.apply(null, args));
|
||||
memoize(this._exCommands, this._exCommands.length, closure);
|
||||
for (let alias in values(names.slice(1)))
|
||||
memoize(this._exMap, alias, closure);
|
||||
|
||||
return true;
|
||||
},
|
||||
@@ -375,7 +373,7 @@ const Commands = Module("commands", {
|
||||
* @optional
|
||||
*/
|
||||
add: function (names, description, action, extra) {
|
||||
return this._addCommand(Command(names, description, action, extra), false);
|
||||
return this._addCommand([names, description, action, extra], false);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -395,7 +393,7 @@ const Commands = Module("commands", {
|
||||
extra.user = true;
|
||||
description = description || "User defined command";
|
||||
|
||||
return this._addCommand(Command(names, description, action, extra), replace);
|
||||
return this._addCommand([names, description, action, extra], replace);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -407,7 +405,7 @@ const Commands = Module("commands", {
|
||||
*/
|
||||
commandToString: function (args) {
|
||||
let res = [args.command + (args.bang ? "!" : "")];
|
||||
function quote(str) Commands.quoteArg[/[\s"'\\]|^$/.test(str) ? '"' : ""](str);
|
||||
function quote(str) Commands.quoteArg[/[\s"'\\]|^$/.test(str) ? "'" : ""](str);
|
||||
|
||||
for (let [opt, val] in Iterator(args.options || {})) {
|
||||
let chr = /^-.$/.test(opt) ? " " : "=";
|
||||
@@ -431,8 +429,8 @@ const Commands = Module("commands", {
|
||||
* any of the command's names.
|
||||
* @returns {Command}
|
||||
*/
|
||||
get: function (name) {
|
||||
return this._exMap[name] || this._exCommands.filter(function (cmd) cmd.hasName(name))[0] || null;
|
||||
get: function (name, full) {
|
||||
return this._exMap[name] || !full && this._exCommands.filter(function (cmd) cmd.hasName(name))[0] || null;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -573,7 +571,7 @@ const Commands = Module("commands", {
|
||||
argCount = "*";
|
||||
|
||||
var args = []; // parsed options
|
||||
args.__iterator__ = function () util.Array.iteritems(this);
|
||||
args.__iterator__ = function () array.iteritems(this);
|
||||
args.string = str; // for access to the unparsed string
|
||||
args.literalArg = "";
|
||||
|
||||
@@ -833,11 +831,11 @@ const Commands = Module("commands", {
|
||||
* any of the command's names.
|
||||
*/
|
||||
removeUserCommand: function (name) {
|
||||
for (let [,cmd] in Iterator(this._exCommands))
|
||||
if (cmd.user && cmd.hasName(name))
|
||||
for (let [,name] in Iterator(cmd.names))
|
||||
delete this._exMap[name];
|
||||
this._exCommands = this._exCommands.filter(function (cmd) !(cmd.user && cmd.hasName(name)));
|
||||
let cmd = this.get(name);
|
||||
dactyl.assert(cmd.user, "E184: No such user-defined command: " + name);
|
||||
for (let name in values(cmd.names))
|
||||
delete this._exMap[name];
|
||||
this._exCommands = this._exCommands.filter(function (c) c != cmd);
|
||||
},
|
||||
|
||||
// FIXME: still belong here? Also used for autocommand parameters.
|
||||
@@ -867,8 +865,6 @@ const Commands = Module("commands", {
|
||||
});
|
||||
}
|
||||
}, {
|
||||
QUOTE_STYLE: "rc-ish",
|
||||
|
||||
// returns [count, parsed_argument]
|
||||
parseArg: function (str) {
|
||||
let arg = "";
|
||||
@@ -918,7 +914,7 @@ const Commands = Module("commands", {
|
||||
// dynamically get completions as specified with the command's completer function
|
||||
let command = commands.get(cmd);
|
||||
if (!command) {
|
||||
context.highlight(0, cmd.length, "SPELLCHECK");
|
||||
context.highlight(0, cmd && cmd.length, "SPELLCHECK");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -936,7 +932,8 @@ const Commands = Module("commands", {
|
||||
cmdContext.filter = args.completeFilter;
|
||||
try {
|
||||
let compObject = command.completer.call(command, cmdContext, args);
|
||||
if (compObject instanceof Array) // for now at least, let completion functions return arrays instead of objects
|
||||
|
||||
if (isarray(compObject)) // for now at least, let completion functions return arrays instead of objects
|
||||
compObject = { start: compObject[0], items: compObject[1] };
|
||||
if (compObject != null) {
|
||||
cmdContext.advance(compObject.start);
|
||||
@@ -1041,14 +1038,13 @@ const Commands = Module("commands", {
|
||||
function completerToString(completer) {
|
||||
if (completer)
|
||||
return [k for ([k, v] in Iterator(completeOptionMap)) if (completer == completion[v])][0] || "custom";
|
||||
else
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
|
||||
// TODO: using an array comprehension here generates flakey results across repeated calls
|
||||
// : perhaps we shouldn't allow options in a list call but just ignore them for now
|
||||
// : No, array comprehensions are fine, generator statements aren't. --Kris
|
||||
let cmds = this._exCommands.filter(function (c) c.user && (!cmd || c.name.match("^" + cmd)));
|
||||
let cmds = commands._exCommands.filter(function (c) c.user && (!cmd || c.name.match("^" + cmd)));
|
||||
|
||||
if (cmds.length > 0)
|
||||
commandline.commandOutput(
|
||||
@@ -1101,7 +1097,7 @@ const Commands = Module("commands", {
|
||||
serialize: function () [ {
|
||||
command: this.name,
|
||||
bang: true,
|
||||
options: util.Array.toObject(
|
||||
options: array.toObject(
|
||||
[[v, typeof cmd[k] == "boolean" ? null : cmd[k]]
|
||||
// FIXME: this map is expressed multiple times
|
||||
for ([k, v] in Iterator({ argCount: "-nargs", bang: "-bang", count: "-count", description: "-description" }))
|
||||
@@ -1162,17 +1158,20 @@ const Commands = Module("commands", {
|
||||
};
|
||||
function quote(q, list) {
|
||||
let re = RegExp("[" + list + "]", "g");
|
||||
return function (str) q + String.replace(str, re, function ($0) $0 in Commands.quoteMap ? Commands.quoteMap[$0] : ("\\" + $0)) + q;
|
||||
let res = function (str) q + String.replace(str, re, function ($0) $0 in Commands.quoteMap ? Commands.quoteMap[$0] : ("\\" + $0)) + q;
|
||||
res.list = list;
|
||||
return res;
|
||||
};
|
||||
Commands.complQuote = { // FIXME
|
||||
Commands.complQuote = {
|
||||
'"': ['"', quote("", '\n\t"\\\\'), '"'],
|
||||
"'": ["'", quote("", "\\\\'"), "'"],
|
||||
"": ["", quote("", "\\\\ "), ""]
|
||||
"": ["", quote("", "\\\\ '\""), ""]
|
||||
};
|
||||
|
||||
Commands.quoteArg = {
|
||||
'"': quote('"', '\n\t"\\\\'),
|
||||
"'": quote("'", "\\\\'"),
|
||||
"": quote("", "\\\\ ")
|
||||
"": quote("", "\\\\ '\"")
|
||||
};
|
||||
|
||||
Commands.parseBool = function (arg) {
|
||||
|
||||
@@ -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.
|
||||
@@ -54,7 +54,7 @@ const CompletionContext = Class("CompletionContext", {
|
||||
|
||||
["filters", "keys", "title", "quote"].forEach(function (key)
|
||||
self[key] = parent[key] && util.cloneObject(parent[key]));
|
||||
["anchored", "compare", "editor", "_filter", "filterFunc", "keys", "_process", "top"].forEach(function (key)
|
||||
["anchored", "compare", "editor", "_filter", "filterFunc", "keys", "process", "top"].forEach(function (key)
|
||||
self[key] = parent[key]);
|
||||
|
||||
self.__defineGetter__("value", function () this.top.value);
|
||||
@@ -90,14 +90,34 @@ const CompletionContext = Class("CompletionContext", {
|
||||
this._value = editor;
|
||||
else
|
||||
this.editor = editor;
|
||||
this.compare = function (a, b) String.localeCompare(a.text, b.text);
|
||||
/**
|
||||
* @property {boolean} Specifies whether this context results must
|
||||
* match the filter at the beginning of the string.
|
||||
* @default true
|
||||
*/
|
||||
this.anchored = true;
|
||||
|
||||
this.compare = function (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
|
||||
* is only needed for long, asynchronous completions
|
||||
*/
|
||||
this.cancel = null;
|
||||
/**
|
||||
* @property {[CompletionContext]} A list of active
|
||||
* completion contexts, in the order in which they were
|
||||
* instantiated.
|
||||
*/
|
||||
this.contextList = [];
|
||||
/**
|
||||
* @property {Object} A map of all contexts, keyed on their names.
|
||||
* Names are assigned when a context is forked, with its specified
|
||||
* name appended, after a '/', to its parent's name. May
|
||||
* contain inactive contexts. For active contexts, see
|
||||
* {@link #contextList}.
|
||||
*/
|
||||
this.contexts = { "": this };
|
||||
/**
|
||||
* @property {function} The function used to filter the results.
|
||||
* @default Selects all results which match every predicate in the
|
||||
@@ -114,20 +134,6 @@ const CompletionContext = Class("CompletionContext", {
|
||||
* results.
|
||||
*/
|
||||
this.filters = [CompletionContext.Filter.text];
|
||||
/**
|
||||
* @property {boolean} Specifies whether this context results must
|
||||
* match the filter at the beginning of the string.
|
||||
* @default true
|
||||
*/
|
||||
this.anchored = true;
|
||||
/**
|
||||
* @property {Object} A map of all contexts, keyed on their names.
|
||||
* Names are assigned when a context is forked, with its specified
|
||||
* name appended, after a '/', to its parent's name. May
|
||||
* contain inactive contexts. For active contexts, see
|
||||
* {@link #contextList}.
|
||||
*/
|
||||
this.contexts = { "": this };
|
||||
/**
|
||||
* @property {Object} A mapping of keys, for {@link #getKey}. Given
|
||||
* { key: value }, getKey(item, key) will return values as such:
|
||||
@@ -146,6 +152,9 @@ const CompletionContext = Class("CompletionContext", {
|
||||
* {@link #updateAsync} is true.
|
||||
*/
|
||||
this.onUpdate = function () true;
|
||||
|
||||
this.runCount = 0;
|
||||
|
||||
/**
|
||||
* @property {CompletionContext} The top-level completion context.
|
||||
*/
|
||||
@@ -190,6 +199,7 @@ const CompletionContext = Class("CompletionContext", {
|
||||
: item.item[key];
|
||||
return this;
|
||||
},
|
||||
|
||||
// Temporary
|
||||
/**
|
||||
* @property {Object}
|
||||
@@ -202,7 +212,7 @@ const CompletionContext = Class("CompletionContext", {
|
||||
get allItems() {
|
||||
try {
|
||||
let self = this;
|
||||
let minStart = Math.min.apply(Math, [context.offset for ([k, context] in Iterator(this.contexts)) if (context.items.length && context.hasItems)]);
|
||||
let minStart = Math.min.apply(Math, [context.offset for ([k, context] in Iterator(this.contexts)) if (context.hasItems && context.items.length)]);
|
||||
if (minStart == Infinity)
|
||||
minStart = 0;
|
||||
let items = this.contextList.map(function (context) {
|
||||
@@ -214,7 +224,7 @@ const CompletionContext = Class("CompletionContext", {
|
||||
__proto__: item
|
||||
}));
|
||||
});
|
||||
return { start: minStart, items: util.Array.flatten(items), longestSubstring: this.longestAllSubstring };
|
||||
return { start: minStart, items: array.flatten(items), longestSubstring: this.longestAllSubstring };
|
||||
}
|
||||
catch (e) {
|
||||
dactyl.reportError(e);
|
||||
@@ -235,7 +245,7 @@ const CompletionContext = Class("CompletionContext", {
|
||||
lists.pop());
|
||||
if (!substrings) // FIXME: How is this undefined?
|
||||
return [];
|
||||
return util.Array.uniq(Array.slice(substrings));
|
||||
return array.uniq(Array.slice(substrings));
|
||||
},
|
||||
// Temporary
|
||||
get longestAllSubstring() {
|
||||
@@ -253,14 +263,16 @@ const CompletionContext = Class("CompletionContext", {
|
||||
// Accept a generator
|
||||
if (!isarray(items))
|
||||
items = [x for (x in Iterator(items))];
|
||||
delete this.cache.filtered;
|
||||
delete this.cache.filter;
|
||||
this.cache.rows = [];
|
||||
this.hasItems = items.length > 0;
|
||||
this._completions = items;
|
||||
let self = this;
|
||||
if (this._completions !== items) {
|
||||
delete this.cache.filtered;
|
||||
delete this.cache.filter;
|
||||
this.cache.rows = [];
|
||||
this.hasItems = items.length > 0;
|
||||
this._completions = items;
|
||||
this.itemCache[this.key] = items;
|
||||
}
|
||||
if (this.updateAsync && !this.noUpdate)
|
||||
util.callInMainThread(function () { self.onUpdate.call(self); });
|
||||
util.callInMainThread(function () { this.onUpdate(); }, this);
|
||||
},
|
||||
|
||||
get createRow() this._createRow || template.completionRow, // XXX
|
||||
@@ -293,14 +305,18 @@ const CompletionContext = Class("CompletionContext", {
|
||||
|
||||
get proto() {
|
||||
let res = {};
|
||||
for (let i in Iterator(this.keys)) {
|
||||
function result(quote) {
|
||||
yield ["result", quote ? function () quote[0] + quote[1](this.text) + quote[2]
|
||||
: function () this.text]
|
||||
};
|
||||
for (let i in iterall(this.keys, result(this.quote))) {
|
||||
let [k, v] = i;
|
||||
if (typeof v == "string" && /^[.[]/.test(v))
|
||||
// This is only allowed to be a simple accessor, and shouldn't
|
||||
// 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(this.item)));
|
||||
res.__defineGetter__(k, function () Class.replaceProperty(this, k, v.call(this, this.item)));
|
||||
else
|
||||
res.__defineGetter__(k, function () Class.replaceProperty(this, k, this.item[v]));
|
||||
res.__defineSetter__(k, function (val) Class.replaceProperty(this, k, val));
|
||||
@@ -312,11 +328,16 @@ const CompletionContext = Class("CompletionContext", {
|
||||
set regenerate(val) { if (val) delete this.itemCache[this.key]; },
|
||||
|
||||
get generate() !this._generate ? null : function () {
|
||||
if (this.offset != this.cache.offset)
|
||||
if (this.offset != this.cache.offset || this.lastActivated != this.top.runCount) {
|
||||
this.itemCache = {};
|
||||
this.cache.offset = this.offset;
|
||||
if (!this.itemCache[this.key])
|
||||
this.itemCache[this.key] = this._generate.call(this) || [];
|
||||
this.cache.offset = this.offset;
|
||||
this.lastActivated = this.top.runCount;
|
||||
}
|
||||
if (!this.itemCache[this.key]) {
|
||||
let res = this._generate.call(this) || [];
|
||||
if (res != null)
|
||||
this.itemCache[this.key] = res;
|
||||
}
|
||||
return this.itemCache[this.key];
|
||||
},
|
||||
set generate(arg) {
|
||||
@@ -354,16 +375,27 @@ const CompletionContext = Class("CompletionContext", {
|
||||
get items() {
|
||||
if (!this.hasItems || this.backgroundLock)
|
||||
return [];
|
||||
if (this.cache.filtered && this.cache.filter == this.filter)
|
||||
return this.cache.filtered;
|
||||
this.cache.rows = [];
|
||||
let items = this.completions;
|
||||
|
||||
// Regenerate completions if we must
|
||||
if (this.generate && !this.background) {
|
||||
// XXX
|
||||
this.noUpdate = true;
|
||||
this.completions = items = this.generate();
|
||||
this.completions = this.generate();
|
||||
this.noUpdate = false;
|
||||
}
|
||||
let items = this.completions;
|
||||
|
||||
// Check for cache miss
|
||||
if (this.cache.completions !== this.completions) {
|
||||
this.cache.completions = this.completions;
|
||||
this.cache.constructed = null;
|
||||
this.cache.filtered = null;
|
||||
}
|
||||
|
||||
if (this.cache.filtered && this.cache.filter == this.filter)
|
||||
return this.cache.filtered;
|
||||
|
||||
this.cache.rows = [];
|
||||
this.cache.filter = this.filter;
|
||||
if (items == null)
|
||||
return items;
|
||||
@@ -371,6 +403,7 @@ const CompletionContext = Class("CompletionContext", {
|
||||
let self = this;
|
||||
delete this._substrings;
|
||||
|
||||
// Item matchers
|
||||
if (this.ignoreCase)
|
||||
this.matchString = this.anchored ?
|
||||
function (filter, str) String.toLowerCase(str).indexOf(filter.toLowerCase()) == 0 :
|
||||
@@ -380,36 +413,28 @@ const CompletionContext = Class("CompletionContext", {
|
||||
function (filter, str) String.indexOf(str, filter) == 0 :
|
||||
function (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,
|
||||
template.highlightFilter(item.text, self.filter));
|
||||
|
||||
// Item prototypes
|
||||
let proto = this.proto;
|
||||
let filtered = this.filterFunc(items.map(function (item) ({ __proto__: proto, item: item })));
|
||||
if (!this.cache.constructed)
|
||||
this.cache.constructed = items.map(function (item) Object.create(proto, { item: { value: item, enumerable: true } }));
|
||||
|
||||
// Filters
|
||||
let filtered = this.filterFunc(this.cache.constructed);
|
||||
if (this.maxItems)
|
||||
filtered = filtered.slice(0, this.maxItems);
|
||||
|
||||
// Sorting
|
||||
if (this.sortResults && this.compare)
|
||||
filtered.sort(this.compare);
|
||||
let quote = this.quote;
|
||||
if (quote)
|
||||
filtered.forEach(function (item) {
|
||||
item.unquoted = item.text;
|
||||
item.text = quote[0] + quote[1](item.text) + quote[2];
|
||||
});
|
||||
return this.cache.filtered = filtered;
|
||||
},
|
||||
|
||||
get process() { // FIXME
|
||||
let self = this;
|
||||
let process = this._process;
|
||||
process = [process[0] || template.icon, process[1] || function (item, k) k];
|
||||
let first = process[0];
|
||||
let filter = this.filter;
|
||||
if (!this.anchored)
|
||||
process[0] = function (item, text) first.call(self, item, template.highlightFilter(item.text, filter));
|
||||
return process;
|
||||
},
|
||||
set process(process) {
|
||||
this._process = process;
|
||||
},
|
||||
|
||||
get substrings() {
|
||||
let items = this.items;
|
||||
if (items.length == 0 || !this.hasItems)
|
||||
@@ -418,7 +443,10 @@ const CompletionContext = Class("CompletionContext", {
|
||||
return this._substrings;
|
||||
|
||||
let fixCase = this.ignoreCase ? String.toLowerCase : util.identity;
|
||||
let text = fixCase(items[0].unquoted || items[0].text);
|
||||
let text = fixCase(items[0].text);
|
||||
// Exceedingly long substrings cause Gecko to go into convulsions
|
||||
if (text.length > 100)
|
||||
text = text.substr(0, 100);
|
||||
let filter = fixCase(this.filter);
|
||||
if (this.anchored) {
|
||||
var compare = function compare(text, s) text.substr(0, s.length) == s;
|
||||
@@ -521,7 +549,6 @@ const CompletionContext = Class("CompletionContext", {
|
||||
context.waitingForTab = true;
|
||||
else if (completer)
|
||||
return completer.apply(self || this, [context].concat(Array.slice(arguments, fork.length)));
|
||||
|
||||
if (completer)
|
||||
return null;
|
||||
return context;
|
||||
@@ -535,20 +562,24 @@ const CompletionContext = Class("CompletionContext", {
|
||||
},
|
||||
|
||||
highlight: function highlight(start, length, type) {
|
||||
try { // Gecko < 1.9.1 doesn't have repaintSelection
|
||||
this.selectionTypes[type] = null;
|
||||
if (arguments.length == 0) {
|
||||
for (let type in this.selectionTypes)
|
||||
this.highlight(0, 0, type);
|
||||
this.selectionTypes = {};
|
||||
}
|
||||
try {
|
||||
// Requires Gecko >= 1.9.1
|
||||
this.selectionTypes[type] = true;
|
||||
const selType = Ci.nsISelectionController["SELECTION_" + type];
|
||||
const editor = this.editor;
|
||||
let sel = editor.selectionController.getSelection(selType);
|
||||
let sel = this.editor.selectionController.getSelection(selType);
|
||||
if (length == 0)
|
||||
sel.removeAllRanges();
|
||||
else {
|
||||
let range = editor.selection.getRangeAt(0).cloneRange();
|
||||
let range = this.editor.selection.getRangeAt(0).cloneRange();
|
||||
range.setStart(range.startContainer, this.offset + start);
|
||||
range.setEnd(range.startContainer, this.offset + start + length);
|
||||
sel.addRange(range);
|
||||
}
|
||||
editor.selectionController.repaintSelection(selType);
|
||||
}
|
||||
catch (e) {}
|
||||
},
|
||||
@@ -557,23 +588,19 @@ const CompletionContext = Class("CompletionContext", {
|
||||
return this.matchString(this.filter, str);
|
||||
},
|
||||
|
||||
pushProcessor: function pushProcess(i, fn) {
|
||||
let next = this.process[i];
|
||||
this.process[i] = function (item, text) fn(item, text, next);
|
||||
},
|
||||
|
||||
reset: function reset() {
|
||||
let self = this;
|
||||
if (this.parent)
|
||||
throw Error();
|
||||
// Not ideal.
|
||||
for (let type in this.selectionTypes)
|
||||
this.highlight(0, 0, type);
|
||||
|
||||
/**
|
||||
* @property {[CompletionContext]} A list of active
|
||||
* completion contexts, in the order in which they were
|
||||
* instantiated.
|
||||
*/
|
||||
this.contextList = [];
|
||||
this.offset = 0;
|
||||
this.process = [];
|
||||
this.selectionTypes = {};
|
||||
this.process = [template.icon, function (item, k) k];
|
||||
this.filters = [CompletionContext.Filter.text];
|
||||
this.tabPressed = false;
|
||||
this.title = ["Completions"];
|
||||
this.updateAsync = false;
|
||||
@@ -595,6 +622,10 @@ const CompletionContext = Class("CompletionContext", {
|
||||
if (context != context.top)
|
||||
context.incomplete = false;
|
||||
}
|
||||
this.runCount++;
|
||||
for each (let context in this.contextList)
|
||||
context.lastActivated = this.runCount;
|
||||
this.contextList = [];
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -668,7 +699,7 @@ const Completion = Module("completion", {
|
||||
|
||||
commandline.commandOutput(
|
||||
<div highlight="Completions">
|
||||
{ template.map(context.contextList.filter(function (c) c.hasItems),
|
||||
{ template.map(context.contextList.filter(function (c) c.hasItems && c.items.length),
|
||||
function (context)
|
||||
template.completionRow(context.title, "CompTitle") +
|
||||
template.map(context.items, function (item) context.createRow(item), null, 100)) }
|
||||
@@ -747,7 +778,7 @@ const Completion = Module("completion", {
|
||||
|
||||
let re = RegExp(tokens.filter(util.identity).map(util.escapeRegex).join("|"), "g");
|
||||
function highlight(item, text, i) process[i].call(this, item, template.highlightRegexp(text, re));
|
||||
let process = [template.icon, function (item, k) k];
|
||||
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)
|
||||
|
||||
@@ -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.
|
||||
@@ -12,8 +12,33 @@ const ConfigBase = Class(ModuleBase, {
|
||||
* initialization code. Must call superclass's init function.
|
||||
*/
|
||||
init: function () {
|
||||
this.name = services.get("dactyl:").name;
|
||||
this.appname = services.get("dactyl:").appname;
|
||||
this.host = services.get("dactyl:").host;
|
||||
|
||||
highlight.styleableChrome = this.styleableChrome;
|
||||
highlight.loadCSS(this.CSS);
|
||||
highlight.loadCSS(this.helpCSS);
|
||||
|
||||
let img = Image();
|
||||
img.src = this.logo || "chrome://" + this.name + "/content/logo.png";
|
||||
img.onload = function () {
|
||||
highlight.set("Logo", String(<>
|
||||
display: inline-block;
|
||||
background: url({img.src});
|
||||
width: {img.width}px;
|
||||
height: {img.height}px;
|
||||
</>));
|
||||
img = null;
|
||||
}
|
||||
},
|
||||
|
||||
styleHelp: function () {
|
||||
if (!this.helpStyled)
|
||||
for (let k in keys(highlight.loaded))
|
||||
if (/^(Help|StatusLine)|^(Boolean|Indicator|MoreMsg|Number|Logo|Key(word)?|String)$/.test(k))
|
||||
highlight.loaded[k] = true;
|
||||
this.helpCSS = true;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -92,7 +117,7 @@ const ConfigBase = Class(ModuleBase, {
|
||||
* @property {number} The height (px) that is available to the output
|
||||
* window.
|
||||
*/
|
||||
get outputHeight() config.browser.mPanelContainer.boxObject.height,
|
||||
get outputHeight() this.browser.mPanelContainer.boxObject.height,
|
||||
|
||||
/**
|
||||
* @property {[string]} A list of extra scripts in the dactyl or
|
||||
@@ -105,45 +130,41 @@ const ConfigBase = Class(ModuleBase, {
|
||||
* @property {string} The leaf name of any temp files created by
|
||||
* {@link io.createTempFile}.
|
||||
*/
|
||||
get tempFile() this.name.toLowerCase() + ".tmp",
|
||||
get tempFile() this.name + ".tmp",
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @property {string} The default highlighting rules. They have the
|
||||
* form:
|
||||
* rule ::= selector space space+ css
|
||||
* selector ::= group
|
||||
* | group "," css-selector
|
||||
* | group "," css-selector "," scope
|
||||
* group ::= groupname
|
||||
* | groupname css-selector
|
||||
* @property {string} The default highlighting rules.
|
||||
* See {@link Highlights#loadCSS} for details.
|
||||
*/
|
||||
// <css>
|
||||
CSS: <![CDATA[
|
||||
Boolean color: red;
|
||||
Function color: navy;
|
||||
Null color: blue;
|
||||
Number color: blue;
|
||||
Object color: maroon;
|
||||
String color: green;
|
||||
CSS: UTF8(<><![CDATA[
|
||||
// <css>
|
||||
Boolean color: red;
|
||||
Function color: navy;
|
||||
Null color: blue;
|
||||
Number color: blue;
|
||||
Object color: maroon;
|
||||
String color: green;
|
||||
|
||||
Key font-weight: bold;
|
||||
Key font-weight: bold;
|
||||
|
||||
Enabled color: blue;
|
||||
Disabled color: red;
|
||||
Enabled color: blue;
|
||||
Disabled color: red;
|
||||
|
||||
Normal color: black; background: white;
|
||||
ErrorMsg color: white; background: red; font-weight: bold;
|
||||
InfoMsg color: black; background: white;
|
||||
ModeMsg color: black; background: white;
|
||||
MoreMsg color: green; background: white;
|
||||
WarningMsg color: red; background: white;
|
||||
Message white-space: normal; min-width: 100%; padding-left: 2em; text-indent: -2em; display: block;
|
||||
NonText color: blue; min-height: 16px; padding-left: 2px;
|
||||
Preview color: gray;
|
||||
!Normal color: black !important; background: white !important;
|
||||
ErrorMsg color: white !important; background: red !important; font-weight: bold !important;
|
||||
InfoMsg color: black !important; background: white !important;
|
||||
LineNr color: orange !important; background: white !important;
|
||||
ModeMsg color: black !important; background: white !important;
|
||||
MoreMsg color: green !important; background: white !important;
|
||||
Message white-space: normal; min-width: 100%; padding-left: 2em; text-indent: -2em; display: block;
|
||||
NonText color: blue; min-height: 16px; padding-left: 2px;
|
||||
*Preview color: gray;
|
||||
Question color: green !important; background: white !important; font-weight: bold !important;
|
||||
WarningMsg color: red !important; background: white !important;
|
||||
|
||||
CmdLine,>* font-family: monospace; padding: 1px;
|
||||
CmdOutput white-space: pre;
|
||||
!CmdLine;>* font-family: monospace !important; padding: 1px !important;
|
||||
CmdOutput white-space: pre;
|
||||
|
||||
CompGroup
|
||||
CompGroup:not(:first-of-type) margin-top: .5em;
|
||||
@@ -158,9 +179,10 @@ const ConfigBase = Class(ModuleBase, {
|
||||
CompResult width: 45%; overflow: hidden;
|
||||
CompDesc color: gray; width: 50%;
|
||||
CompLess text-align: center; height: 0; line-height: .5ex; padding-top: 1ex;
|
||||
CompLess::after content: "\2303" /* Unicode up arrowhead */
|
||||
CompLess::after content: "⌃";
|
||||
CompMore text-align: center; height: .5ex; line-height: .5ex; margin-bottom: -.5ex;
|
||||
CompMore::after content: "\2304" /* Unicode down arrowhead */
|
||||
CompMore::after content: "⌄";
|
||||
CompGroup:last-of-type padding-bottom: 1.5ex;
|
||||
|
||||
Gradient height: 1px; margin-bottom: -1px; margin-top: -1px;
|
||||
GradientLeft background-color: magenta;
|
||||
@@ -172,19 +194,16 @@ const ConfigBase = Class(ModuleBase, {
|
||||
Keyword color: red;
|
||||
Tag color: blue;
|
||||
|
||||
LineNr color: orange; background: white;
|
||||
Question color: green; background: white; font-weight: bold;
|
||||
!StatusLine color: white !important; background: black !important
|
||||
StatusLineBroken color: black !important; background: #FFa0a0 !important /* light-red */
|
||||
StatusLineSecure color: black !important; background: #a0a0FF !important /* light-blue */
|
||||
StatusLineExtended color: black !important; background: #a0FFa0 !important /* light-green */
|
||||
|
||||
StatusLine color: white; background: black;
|
||||
StatusLineBroken color: black; background: #FFa0a0 /* light-red */
|
||||
StatusLineSecure color: black; background: #a0a0FF /* light-blue */
|
||||
StatusLineExtended color: black; background: #a0FFa0 /* light-green */
|
||||
|
||||
TabClose,.tab-close-button
|
||||
TabIcon,.tab-icon
|
||||
TabText,.tab-text
|
||||
TabNumber font-weight: bold; margin: 0px; padding-right: .3ex;
|
||||
TabIconNumber {
|
||||
TabClose;.tab-close-button
|
||||
TabIcon;.tab-icon
|
||||
TabText;.tab-text
|
||||
!TabNumber font-weight: bold; margin: 0px; padding-right: .3ex;
|
||||
!TabIconNumber {
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
text-align: center;
|
||||
@@ -195,47 +214,52 @@ const ConfigBase = Class(ModuleBase, {
|
||||
URL text-decoration: none; color: green; background: inherit;
|
||||
URL:hover text-decoration: underline; cursor: pointer;
|
||||
|
||||
FrameIndicator,,* {
|
||||
background-color: red;
|
||||
opacity: 0.5;
|
||||
z-index: 999;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
FrameIndicator;;* {
|
||||
/* This gets released into the wild, so everything is important */
|
||||
background-color: red !important;
|
||||
opacity: 0.5 !important;
|
||||
z-index: 999999 !important;
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
bottom: 0 !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
}
|
||||
|
||||
Bell border: none; background-color: black;
|
||||
Hint,,* {
|
||||
font-family: monospace;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
background-color: red;
|
||||
border-color: ButtonShadow;
|
||||
border-width: 0px;
|
||||
border-style: solid;
|
||||
padding: 0px 1px 0px 1px;
|
||||
!Bell border: none; background-color: black;
|
||||
Hint;;* {
|
||||
/* This gets released into the wild, so everything is important */
|
||||
font: bold 10px monospace !important;
|
||||
background-color: red !important;
|
||||
color: white !important;
|
||||
border: 0px solid ButtonShadow !important;
|
||||
padding: 0px 1px !important;
|
||||
}
|
||||
Hint::after,,* content: attr(number);
|
||||
HintElem,,* background-color: yellow; color: black;
|
||||
HintActive,,* background-color: #88FF00; color: black;
|
||||
HintImage,,* opacity: .5;
|
||||
!Hint::after;;* content: attr(number) !important;
|
||||
!HintElem;;* background-color: yellow !important; color: black !important;
|
||||
!HintActive;;* background-color: #88FF00 !important; color: black !important;
|
||||
!HintImage;;* opacity: .5 !important;
|
||||
|
||||
Help font-size: 8pt; line-height: 1.4em; font-family: -moz-fixed;
|
||||
!Logo
|
||||
// </css>
|
||||
]]></>),
|
||||
|
||||
helpCSS: UTF8(<><![CDATA[
|
||||
// <css>
|
||||
Help font-size: 8pt; line-height: 1.4em; font-family: -moz-fixed, monospace;
|
||||
|
||||
HelpArg color: #6A97D4;
|
||||
HelpOptionalArg color: #6A97D4;
|
||||
|
||||
HelpBody display: block; margin: 1em auto; max-width: 100ex;
|
||||
HelpBorder,*,dactyl://help/* border-color: silver; border-width: 0px; border-style: solid;
|
||||
HelpCode display: block; white-space: pre; margin-left: 2em; font-family: Terminus, Fixed, monospace;
|
||||
HelpBody display: block; margin: 1em auto; max-width: 100ex; padding-bottom: 1em; margin-bottom: 4em; border-bottom-width: 1px;
|
||||
HelpBorder;*;dactyl://help/* border-color: silver; border-width: 0px; border-style: solid;
|
||||
HelpCode display: block; white-space: pre; margin-left: 2em; font-family: monospace;
|
||||
|
||||
HelpDefault margin-right: 1ex; white-space: pre;
|
||||
HelpDefault display: inline-block; margin-right: 1ex; white-space: pre;
|
||||
|
||||
HelpDescription display: block;
|
||||
HelpEm,html|em,dactyl://help/* font-weight: bold; font-style: normal;
|
||||
HelpDescription display: block; clear: right;
|
||||
HelpDescription[short] clear: none;
|
||||
HelpEm;html|em;dactyl://help/* font-weight: bold; font-style: normal;
|
||||
|
||||
HelpEx display: inline-block; color: #527BBD; font-weight: bold;
|
||||
|
||||
@@ -249,32 +273,42 @@ const ConfigBase = Class(ModuleBase, {
|
||||
HelpItem display: block; margin: 1em 1em 1em 10em; clear: both;
|
||||
|
||||
HelpKey color: #102663;
|
||||
HelpKeyword font-weight: bold; color: navy;
|
||||
|
||||
HelpLink,html|a,dactyl://help/* text-decoration: none;
|
||||
HelpLink[href]:hover text-decoration: underline;
|
||||
HelpLink;html|a;dactyl://help/* text-decoration: none !important;
|
||||
HelpLink[href]:hover text-decoration: underline !important;
|
||||
HelpLink[href^="mailto:"]::after content: "✉"; padding-left: .2em;
|
||||
HelpLink[rel=external] {
|
||||
/* Thanks, Wikipedia */
|
||||
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAFVBMVEVmmcwzmcyZzP8AZswAZv////////9E6giVAAAAB3RSTlP///////8AGksDRgAAADhJREFUGFcly0ESAEAEA0Ei6/9P3sEcVB8kmrwFyni0bOeyyDpy9JTLEaOhQq7Ongf5FeMhHS/4AVnsAZubxDVmAAAAAElFTkSuQmCC) no-repeat scroll right center;
|
||||
padding-right: 13px;
|
||||
}
|
||||
|
||||
HelpList,html|ul,dactyl://help/* display: block; list-style: outside disc;
|
||||
HelpOrderedList,html|ol,dactyl://help/* display: block; list-style: outside decimal;
|
||||
HelpListItem,html|li,dactyl://help/* display: list-item;
|
||||
HelpOrderedList;ol[level="1"],ol;dactyl://help/* display: block; list-style: outside decimal;
|
||||
HelpOrderedList2;ol[level="2"],ol ol;dactyl://help/* list-style: outside upper-alpha;
|
||||
HelpOrderedList3;ol[level="3"],ol ol ol;dactyl://help/* list-style: outside lower-roman;
|
||||
HelpList;html|ul;dactyl://help/* display: block; list-style: outside disc;
|
||||
HelpListItem;html|li;dactyl://help/* display: list-item;
|
||||
|
||||
HelpNote color: red; font-weight: bold;
|
||||
|
||||
HelpOpt color: #106326;
|
||||
HelpOptInfo display: inline-block; margin-bottom: 1ex;
|
||||
HelpOptInfo display: block; margin-bottom: 1ex; padding-left: 4em;
|
||||
|
||||
HelpParagraph,html|p,dactyl://help/* display: block; margin: 1em 0em;
|
||||
HelpParagraph;html|p;dactyl://help/* display: block; margin: 1em 0em;
|
||||
HelpParagraph:first-child margin-top: 0;
|
||||
HelpSpec display: block; margin-left: -10em; float: left; clear: left; color: #527BBD; margin-right: 2em;
|
||||
HelpParagraph:last-child margin-bottom: 0;
|
||||
HelpSpec display: block; margin-left: -10em; float: left; clear: left; color: #527BBD; margin-right: 1em;
|
||||
|
||||
HelpString display: inline-block; color: green; font-weight: normal; vertical-align: text-top;
|
||||
HelpString color: green; font-weight: normal;
|
||||
HelpString::before content: '"';
|
||||
HelpString::after content: '"';
|
||||
HelpString[delim]::before content: attr(delim);
|
||||
HelpString[delim]::after content: attr(delim);
|
||||
|
||||
HelpHead,html|h1,dactyl://help/* {
|
||||
HelpHead;html|h1;dactyl://help/* {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
margin: 2em 0 1em;
|
||||
padding-bottom: .2ex;
|
||||
border-bottom-width: 1px;
|
||||
font-size: 2em;
|
||||
@@ -282,9 +316,9 @@ const ConfigBase = Class(ModuleBase, {
|
||||
color: #527BBD;
|
||||
clear: both;
|
||||
}
|
||||
HelpSubhead,html|h2,dactyl://help/* {
|
||||
HelpSubhead;html|h2;dactyl://help/* {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
margin: 2em 0 1em;
|
||||
padding-bottom: .2ex;
|
||||
border-bottom-width: 1px;
|
||||
font-size: 1.2em;
|
||||
@@ -292,7 +326,7 @@ const ConfigBase = Class(ModuleBase, {
|
||||
color: #527BBD;
|
||||
clear: both;
|
||||
}
|
||||
HelpSubsubhead,html|h3,dactyl://help/* {
|
||||
HelpSubsubhead;html|h3;dactyl://help/* {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
padding-bottom: .2ex;
|
||||
@@ -305,12 +339,20 @@ const ConfigBase = Class(ModuleBase, {
|
||||
HelpTOC
|
||||
HelpTOC>ol ol margin-left: -1em;
|
||||
|
||||
HelpTab,html|dl,dactyl://help/* display: table; width: 100%; margin: 1em 0; border-bottom-width: 1px; border-top-width: 1px; padding: .5ex 0; table-layout: fixed;
|
||||
HelpTabColumn,html|column,dactyl://help/* display: table-column;
|
||||
HelpTabColumn:first-child width: 25%;
|
||||
HelpTabTitle,html|dt,dactyl://help/* display: table-cell; padding: .1ex 1ex; font-weight: bold;
|
||||
HelpTabDescription,html|dd,dactyl://help/* display: table-cell; padding: .1ex 1ex; border-width: 0px;
|
||||
HelpTabRow,html|dl>html|tr,dactyl://help/* display: table-row;
|
||||
HelpTab;html|dl;dactyl://help/* {
|
||||
display: table;
|
||||
width: 100%;
|
||||
margin: 1em 0;
|
||||
border-bottom-width: 1px;
|
||||
border-top-width: 1px;
|
||||
padding: .5ex 0;
|
||||
table-layout: fixed;
|
||||
}
|
||||
HelpTabColumn;html|column;dactyl://help/* display: table-column;
|
||||
HelpTabColumn:first-child width: 25%;
|
||||
HelpTabTitle;html|dt;dactyl://help/* display: table-cell; padding: .1ex 1ex; font-weight: bold;
|
||||
HelpTabDescription;html|dd;dactyl://help/* display: table-cell; padding: .1ex 1ex; border-width: 0px;
|
||||
HelpTabRow;html|dl>html|tr;dactyl://help/* display: table-row;
|
||||
|
||||
HelpTag display: inline-block; color: #527BBD; margin-left: 1ex; font-size: 8pt; font-weight: bold;
|
||||
HelpTags display: block; float: right; clear: right;
|
||||
@@ -319,15 +361,31 @@ const ConfigBase = Class(ModuleBase, {
|
||||
|
||||
HelpWarning color: red; font-weight: bold;
|
||||
|
||||
Logo
|
||||
|
||||
Search,,* {
|
||||
font-size: inherit;
|
||||
padding: 0;
|
||||
color: black;
|
||||
background-color: yellow;
|
||||
HelpXML color: #C5F779; background-color: #444444; font-family: Terminus, Fixed, monospace;
|
||||
HelpXMLBlock { white-space: pre; color: #C5F779; background-color: #444444;
|
||||
border: 1px dashed #aaaaaa;
|
||||
display: block;
|
||||
margin-left: 2em;
|
||||
font-family: Terminus, Fixed, monospace;
|
||||
}
|
||||
]]>.toString()
|
||||
HelpXMLAttribute color: #C5F779;
|
||||
HelpXMLAttribute::after color: #E5E5E5; content: "=";
|
||||
HelpXMLComment color: #444444;
|
||||
HelpXMLComment::before content: "<!--";
|
||||
HelpXMLComment::after content: "-->";
|
||||
HelpXMLProcessing color: #C5F779;
|
||||
HelpXMLProcessing::before color: #444444; content: "<?";
|
||||
HelpXMLProcessing::after color: #444444; content: "?>";
|
||||
HelpXMLString color: #C5F779; white-space: pre;
|
||||
HelpXMLString::before content: '"';
|
||||
HelpXMLString::after content: '"';
|
||||
HelpXMLNamespace color: #FFF796;
|
||||
HelpXMLNamespace::after color: #777777; content: ":";
|
||||
HelpXMLTagStart color: #FFF796; white-space: normal; display: inline-block; text-indent: -1.5em; padding-left: 1.5em;
|
||||
HelpXMLTagEnd color: #71BEBE;
|
||||
HelpXMLText color: #E5E5E5;
|
||||
// </css>
|
||||
]]></>)
|
||||
});
|
||||
|
||||
// vim: set fdm=marker sw=4 ts=4 et:
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
return;
|
||||
}
|
||||
catch (e) {
|
||||
if (e !== "Error opening input stream (invalid filename?)")
|
||||
if (e !== "Error opening input stream (invalid filename?)") {
|
||||
dump("dactyl: Trying: " + (base + script + ".js") + ": " + e + "\n" + e.stack);
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
@@ -30,6 +32,7 @@
|
||||
catch (e) {
|
||||
dump("dactyl: Loading script " + script + ": " + e.result + " " + e + "\n");
|
||||
dump(Error().stack + "\n");
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -64,7 +67,7 @@
|
||||
"template",
|
||||
].forEach(modules.load);
|
||||
|
||||
prefix.unshift("chrome://" + modules.Config.prototype.name.toLowerCase() + "/content/");
|
||||
prefix.unshift("chrome://" + modules.services.get("dactyl:").name + "/content/");
|
||||
modules.Config.prototype.scripts.forEach(modules.load);
|
||||
})();
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -204,14 +204,14 @@ const Dactyl = Module("dactyl", {
|
||||
*
|
||||
* @param {string|Object} msg The message to print.
|
||||
*/
|
||||
dump: function () {
|
||||
dump: function dump() {
|
||||
let msg = Array.map(arguments, function (msg) {
|
||||
if (typeof msg == "object")
|
||||
msg = util.objectToString(msg);
|
||||
return msg;
|
||||
}).join(", ");
|
||||
msg = String.replace(msg, /\n?$/, "\n");
|
||||
window.dump(msg.replace(/^./gm, ("config" in modules && config.name.toLowerCase()) + ": $&"));
|
||||
window.dump(msg.replace(/^./gm, ("config" in modules && config.name) + ": $&"));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -220,7 +220,7 @@ const Dactyl = Module("dactyl", {
|
||||
* @param {string} msg The trace message.
|
||||
* @param {number} frames The number of frames to print.
|
||||
*/
|
||||
dumpStack: function (msg, frames) {
|
||||
dumpStack: function dumpStack(msg, frames) {
|
||||
let stack = Error().stack.replace(/(?:.*\n){2}/, "");
|
||||
if (frames != null)
|
||||
[stack] = stack.match(RegExp("(?:.*\n){0," + frames + "}"));
|
||||
@@ -234,7 +234,7 @@ const Dactyl = Module("dactyl", {
|
||||
* @param {number} flags These control the multiline message behaviour.
|
||||
* See {@link CommandLine#echo}.
|
||||
*/
|
||||
echo: function (str, flags) {
|
||||
echo: function echo(str, flags) {
|
||||
commandline.echo(str, commandline.HL_NORMAL, flags);
|
||||
},
|
||||
|
||||
@@ -246,7 +246,7 @@ const Dactyl = Module("dactyl", {
|
||||
* @param {number} flags These control the multiline message behaviour.
|
||||
* See {@link CommandLine#echo}.
|
||||
*/
|
||||
echoerr: function (str, flags) {
|
||||
echoerr: function echoerr(str, flags) {
|
||||
flags |= commandline.APPEND_TO_MESSAGES;
|
||||
|
||||
if (isinstance(str, ["Error", "Exception"]))
|
||||
@@ -293,8 +293,6 @@ const Dactyl = Module("dactyl", {
|
||||
* should be loaded.
|
||||
*/
|
||||
loadScript: function (uri, context) {
|
||||
XML.ignoreWhiteSpace = false;
|
||||
XML.prettyPrinting = false;
|
||||
services.get("subscriptLoader").loadSubScript(uri, context);
|
||||
},
|
||||
|
||||
@@ -395,7 +393,7 @@ const Dactyl = Module("dactyl", {
|
||||
let command = commands.get(cmd);
|
||||
|
||||
if (command === null) {
|
||||
err = "E492: Not a " + config.name.toLowerCase() + " command: " + str;
|
||||
err = "E492: Not a " + config.name + " command: " + str;
|
||||
dactyl.focusContent();
|
||||
}
|
||||
else if (command.action === null)
|
||||
@@ -486,27 +484,19 @@ const Dactyl = Module("dactyl", {
|
||||
* Initialize the help system.
|
||||
*/
|
||||
initHelp: function () {
|
||||
if ("noscriptOverlay" in window) {
|
||||
noscriptOverlay.safeAllow("chrome-data:", true, false);
|
||||
noscriptOverlay.safeAllow("dactyl:", true, false);
|
||||
}
|
||||
if (!this.helpInitialized) {
|
||||
if ("noscriptOverlay" in window) {
|
||||
noscriptOverlay.safeAllow("chrome-data:", true, false);
|
||||
noscriptOverlay.safeAllow("dactyl:", true, false);
|
||||
}
|
||||
|
||||
if(!this.helpInitialized) {
|
||||
let namespaces = [config.name.toLowerCase(), "dactyl"];
|
||||
let namespaces = [config.name, "dactyl"];
|
||||
services.get("dactyl:").init({});
|
||||
|
||||
let tagMap = services.get("dactyl:").HELP_TAGS;
|
||||
let fileMap = services.get("dactyl:").FILE_MAP;
|
||||
let overlayMap = services.get("dactyl:").OVERLAY_MAP;
|
||||
|
||||
// Left as an XPCOM instantiation so it can easilly be moved
|
||||
// into XPCOM code.
|
||||
function XSLTProcessor(sheet) {
|
||||
let xslt = Cc["@mozilla.org/document-transformer;1?type=xslt"].createInstance(Ci.nsIXSLTProcessor);
|
||||
xslt.importStylesheet(util.httpGet(sheet).responseXML);
|
||||
return xslt;
|
||||
}
|
||||
|
||||
// Find help and overlay files with the given name.
|
||||
function findHelpFile(file) {
|
||||
let result = [];
|
||||
@@ -525,23 +515,20 @@ const Dactyl = Module("dactyl", {
|
||||
}
|
||||
// Find the tags in the document.
|
||||
function addTags(file, doc) {
|
||||
doc = XSLT.transformToDocument(doc);
|
||||
for (let elem in util.evaluateXPath("//xhtml:a/@id", doc))
|
||||
tagMap[elem.value] = file;
|
||||
for (let elem in util.evaluateXPath("//@tag|//dactyl:tags/text()|//dactyl:tag/text()", doc))
|
||||
for (let tag in array((elem.value || elem.textContent).split(/\s+/)).compact().itervalues())
|
||||
tagMap[tag] = file;
|
||||
}
|
||||
|
||||
const XSLT = XSLTProcessor("chrome://dactyl/content/help-single.xsl");
|
||||
|
||||
// Scrape the list of help files from all.xml
|
||||
// Always process main and overlay files, since XSLTProcessor and
|
||||
// Manually process main and overlay files, since XSLTProcessor and
|
||||
// XMLHttpRequest don't allow access to chrome documents.
|
||||
tagMap.all = "all";
|
||||
let files = findHelpFile("all").map(function (doc)
|
||||
[f.value for (f in util.evaluateXPath(
|
||||
"//dactyl:include/@href", doc))]);
|
||||
[f.value for (f in util.evaluateXPath("//dactyl:include/@href", doc))]);
|
||||
|
||||
// Scrape the tags from the rest of the help files.
|
||||
util.Array.flatten(files).forEach(function (file) {
|
||||
array.flatten(files).forEach(function (file) {
|
||||
findHelpFile(file).forEach(function (doc) {
|
||||
addTags(file, doc);
|
||||
});
|
||||
@@ -550,7 +537,6 @@ const Dactyl = Module("dactyl", {
|
||||
// Process plugin help entries.
|
||||
XML.ignoreWhiteSpace = false;
|
||||
XML.prettyPrinting = false;
|
||||
XML.prettyIndent = 4;
|
||||
|
||||
let body = XML();
|
||||
for (let [, context] in Iterator(plugins.contexts))
|
||||
@@ -558,11 +544,12 @@ const Dactyl = Module("dactyl", {
|
||||
body += <h2 xmlns={NS.uri} tag={context.INFO.@name + '-plugin'}>{context.INFO.@summary}</h2> +
|
||||
context.INFO;
|
||||
|
||||
let help = '<?xml version="1.0"?>\n' +
|
||||
'<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>\n' +
|
||||
'<!DOCTYPE document SYSTEM "chrome://dactyl/content/dactyl.dtd">' +
|
||||
let help =
|
||||
'<?xml version="1.0"?>\n' +
|
||||
'<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>\n' +
|
||||
'<!DOCTYPE document SYSTEM "chrome://dactyl/content/dactyl.dtd">\n' +
|
||||
<document xmlns={NS}
|
||||
name="plugins" title={config.name + " Plugins"}>
|
||||
name="plugins" title={config.appname + " Plugins"}>
|
||||
<h1 tag="using-plugins">Using Plugins</h1>
|
||||
<toc start="2"/>
|
||||
|
||||
@@ -589,11 +576,11 @@ const Dactyl = Module("dactyl", {
|
||||
function addDataEntry(file, data) // Inideal to an extreme.
|
||||
addURIEntry(file, "data:text/plain;charset=UTF-8," + encodeURI(data));
|
||||
|
||||
let empty = util.Array.toObject(
|
||||
"area base basefont br col frame hr img input isindex link meta param"
|
||||
.split(" ").map(Array.concat));
|
||||
let empty = set("area base basefont br col frame hr img input isindex link meta param"
|
||||
.split(" "));
|
||||
|
||||
let chrome = {};
|
||||
let styles = {};
|
||||
for (let [file,] in Iterator(services.get("dactyl:").FILE_MAP)) {
|
||||
dactyl.open("dactyl://help/" + file);
|
||||
dactyl.modules.events.waitForPageLoad();
|
||||
@@ -612,10 +599,11 @@ const Dactyl = Module("dactyl", {
|
||||
if (node instanceof HTMLHtmlElement)
|
||||
data.push(" xmlns=" + XHTML.uri.quote());
|
||||
|
||||
for (let { name: name, value: value } in util.Array.itervalues(node.attributes)) {
|
||||
for (let { name, value } in array.itervalues(node.attributes)) {
|
||||
if (name == "dactyl:highlight") {
|
||||
name = "class";
|
||||
value = "hl-" + value;
|
||||
set.add(styles, value);
|
||||
}
|
||||
if (name == "href") {
|
||||
if (value.indexOf("dactyl://help-tag/") == 0)
|
||||
@@ -651,11 +639,11 @@ const Dactyl = Module("dactyl", {
|
||||
addDataEntry(file + ".xhtml", data.join(""));
|
||||
}
|
||||
|
||||
let data = [h.selector.replace(/^\[.*?=(.*?)\]/, ".hl-$1").replace(/html\|/, "") +
|
||||
"\t{" + h.value + "}"
|
||||
for (h in highlight) if (/^Help|^Logo/.test(h.class))];
|
||||
|
||||
data = data.join("\n");
|
||||
let data = [h for (h in highlight) if (set.has(styles, h.class) || /^Help/.test(h.class))]
|
||||
.map(function (h)
|
||||
h.selector.replace(/^\[.*?=(.*?)\]/, ".hl-$1").replace(/html\|/, "") + "\t" +
|
||||
"{" + h.value + "}")
|
||||
.join("\n");
|
||||
addDataEntry("help.css", data.replace(/chrome:[^ ")]+\//g, ""));
|
||||
|
||||
let re = /(chrome:[^ ");]+\/)([^ ");]+)/g;
|
||||
@@ -668,6 +656,49 @@ const Dactyl = Module("dactyl", {
|
||||
zip.close();
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates a help entry.
|
||||
*
|
||||
* @param {Command|Map|Option} obj A dactyl <b>Command</b>,
|
||||
* <b>Map</b> or <b>Option</b> object
|
||||
* @param {XMLList} extraHelp Extra help text beyond the description.
|
||||
* @returns {string}
|
||||
*/
|
||||
generateHelp: function generateHelp(obj, extraHelp)
|
||||
{
|
||||
default xml namespace = "";
|
||||
let spec = util.identity;
|
||||
let tag = util.identity;
|
||||
if (obj instanceof Command)
|
||||
tag = spec = function (cmd) <>:{cmd}</>;
|
||||
else if (obj instanceof Map && obj.count)
|
||||
spec = function (map) <><oa>count</oa>{map}</>;
|
||||
else if (obj instanceof Option)
|
||||
tag = spec = function (opt) <>'{opt}'</>;
|
||||
|
||||
XML.prettyPrinting = false;
|
||||
XML.ignoreWhitespace = false;
|
||||
|
||||
// E4X has its warts.
|
||||
let br = <>
|
||||
</>;
|
||||
|
||||
return <>
|
||||
<item>
|
||||
<tags>{template.map(obj.names, tag, " ")}</tags>
|
||||
<spec>{spec((obj.specs || obj.names)[0])}</spec>{
|
||||
!obj.type ? "" : <>
|
||||
<type>{obj.type}</type>
|
||||
<default>{obj.defaultValue}</default></>}
|
||||
<description>{
|
||||
obj.description ? br+<p>{obj.description.replace(/\.?$/, ".")}</p> : "" }{
|
||||
extraHelp ? br+extraHelp : "" }{
|
||||
!(extraHelp || obj.description) ? br+<p>Sorry, no help available.</p> : "" }
|
||||
</description>
|
||||
</item></>.toXMLString();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Opens the help page containing the specified <b>topic</b> if it
|
||||
* exists.
|
||||
@@ -692,8 +723,6 @@ const Dactyl = Module("dactyl", {
|
||||
dactyl.assert(page != null, "E149: Sorry, no help for " + topic);
|
||||
|
||||
dactyl.open("dactyl://help/" + page, { from: "help" });
|
||||
if (options.get("activate").has("all", "help"))
|
||||
content.postMessage("fragmentChange", "*");
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -723,15 +752,15 @@ const Dactyl = Module("dactyl", {
|
||||
});
|
||||
}
|
||||
|
||||
let dirs = io.getRuntimeDirectories("plugin");
|
||||
let dirs = io.getRuntimeDirectories("plugins");
|
||||
|
||||
if (dirs.length == 0) {
|
||||
dactyl.log("No user plugin directory found", 3);
|
||||
return;
|
||||
}
|
||||
|
||||
dactyl.echomsg('Searching for "plugin/**/*.{js,vimp}" in '
|
||||
+ [dir.path.replace(/.plugin$/, "") for ([, dir] in Iterator(dirs))]
|
||||
dactyl.echomsg('Searching for "plugins/**/*.{js,vimp}" in '
|
||||
+ [dir.path.replace(/.plugins$/, "") for ([, dir] in Iterator(dirs))]
|
||||
.join(",").quote(), 2);
|
||||
|
||||
dirs.forEach(function (dir) {
|
||||
@@ -765,20 +794,33 @@ const Dactyl = Module("dactyl", {
|
||||
if (typeof msg == "object")
|
||||
msg = util.objectToString(msg, false);
|
||||
|
||||
services.get("console").logStringMessage(config.name.toLowerCase() + ": " + msg);
|
||||
services.get("console").logStringMessage(config.name + ": " + msg);
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens one or more URLs. Returns true when load was initiated, or
|
||||
* false on error.
|
||||
*
|
||||
* @param {string|string[]} urls Either a URL string or an array of URLs.
|
||||
* The array can look like this:
|
||||
* ["url1", "url2", "url3", ...]
|
||||
* or:
|
||||
* [["url1", postdata1], ["url2", postdata2], ...]
|
||||
* @param {number|Object} where If ommited, CURRENT_TAB is assumed but NEW_TAB
|
||||
* is set when dactyl.forceNewTab is true.
|
||||
* @param {string|Array} urls A representation of the URLs to open. May be
|
||||
* either a string, which will be bassed to
|
||||
* {@see Dactyl#stringToURLArray}, or an array in the same format as
|
||||
* would be returned by the same.
|
||||
* @param {object} params A set of parameters specifing to open the
|
||||
* URLs. The following properties are recognized:
|
||||
*
|
||||
* • background If true, new tabs are opened in the background.
|
||||
*
|
||||
* • from The desgination of the opener, as appears in
|
||||
* 'activate' and 'newtab' options. If present,
|
||||
* the newtab option provides the default 'where'
|
||||
* parameter, and the value of the 'activate'
|
||||
* parameter is inverted if 'background' is true.
|
||||
*
|
||||
* • where One of CURRENT_TAB, NEW_TAB, or NEW_WINDOW
|
||||
*
|
||||
* As a deprecated special case, the where paramater may be provided
|
||||
* by itself, in which case it is transformed into { where: params }.
|
||||
*
|
||||
* @param {boolean} force Don't prompt whether to open more than 20
|
||||
* tabs.
|
||||
* @returns {boolean}
|
||||
@@ -787,30 +829,29 @@ const Dactyl = Module("dactyl", {
|
||||
if (typeof urls == "string")
|
||||
urls = dactyl.stringToURLArray(urls);
|
||||
|
||||
if (urls.length > 20 && !force) {
|
||||
commandline.input("This will open " + urls.length + " new tabs. Would you like to continue? (yes/[no]) ",
|
||||
if (urls.length > 20 && !force)
|
||||
return commandline.input("This will open " + urls.length + " new tabs. Would you like to continue? (yes/[no]) ",
|
||||
function (resp) {
|
||||
if (resp && resp.match(/^y(es)?$/i))
|
||||
dactyl.open(urls, params, true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let flags = 0;
|
||||
params = params || {};
|
||||
if (isarray(params))
|
||||
params = { where: params };
|
||||
|
||||
let flags = 0;
|
||||
for (let [opt, flag] in Iterator({ replace: "REPLACE_HISTORY", hide: "BYPASS_HISTORY" }))
|
||||
if (params[opt])
|
||||
flags |= Ci.nsIWebNavigation["LOAD_FLAGS_" + flag];
|
||||
flags |= params[opt] && Ci.nsIWebNavigation["LOAD_FLAGS_" + flag];
|
||||
|
||||
let where = params.where || dactyl.CURRENT_TAB;
|
||||
let background = ("background" in params) ? params.background : params.where == dactyl.NEW_BACKGROUND_TAB;
|
||||
if ("from" in params && dactyl.has("tabs")) {
|
||||
if (!('where' in params) && options.get("newtab").has("all", params.from))
|
||||
let background = ("background" in params) ? params.background
|
||||
: params.where == dactyl.NEW_BACKGROUND_TAB;
|
||||
|
||||
if (params.from && dactyl.has("tabs")) {
|
||||
if (!params.where && options.get("newtab").has("all", params.from))
|
||||
where = dactyl.NEW_TAB;
|
||||
background = !options.get("activate").has("all", params.from);
|
||||
background ^= !options.get("activate").has("all", params.from);
|
||||
}
|
||||
|
||||
if (urls.length == 0)
|
||||
@@ -829,10 +870,8 @@ const Dactyl = Module("dactyl", {
|
||||
break;
|
||||
|
||||
case dactyl.NEW_TAB:
|
||||
if (!dactyl.has("tabs")) {
|
||||
open(urls, dactyl.NEW_WINDOW);
|
||||
return;
|
||||
}
|
||||
if (!dactyl.has("tabs"))
|
||||
return open(urls, dactyl.NEW_WINDOW);
|
||||
|
||||
options.withContext(function () {
|
||||
options.setPref("browser.tabs.loadInBackground", true);
|
||||
@@ -849,6 +888,9 @@ const Dactyl = Module("dactyl", {
|
||||
}
|
||||
}
|
||||
catch(e) {}
|
||||
// Unfortunately, failed page loads throw exceptions and
|
||||
// cause a lot of unwanted noise. This solution means that
|
||||
// any genuine errors go unreported.
|
||||
}
|
||||
|
||||
if (dactyl.forceNewTab)
|
||||
@@ -860,6 +902,7 @@ const Dactyl = Module("dactyl", {
|
||||
|
||||
for (let [, url] in Iterator(urls)) {
|
||||
open(url, where);
|
||||
where = dactyl.NEW_TAB;
|
||||
background = true;
|
||||
}
|
||||
},
|
||||
@@ -1037,12 +1080,10 @@ const Dactyl = Module("dactyl", {
|
||||
services.get("observer").notifyObservers(null, "quit-application-granted", null);
|
||||
|
||||
// enumerate all windows and call shutdown handlers
|
||||
let windows = services.get("windowMediator").getEnumerator(null);
|
||||
while (windows.hasMoreElements()) {
|
||||
let win = windows.getNext();
|
||||
for (let win in iter(services.get("windowMediator").getEnumerator(null)))
|
||||
if (("tryToClose" in win) && !win.tryToClose())
|
||||
return;
|
||||
}
|
||||
|
||||
services.get("appStartup").quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
|
||||
},
|
||||
|
||||
@@ -1092,14 +1133,7 @@ const Dactyl = Module("dactyl", {
|
||||
* @property {Window[]} Returns an array of all the host application's
|
||||
* open windows.
|
||||
*/
|
||||
get windows() {
|
||||
let windows = [];
|
||||
let enumerator = services.get("windowMediator").getEnumerator("navigator:browser");
|
||||
while (enumerator.hasMoreElements())
|
||||
windows.push(enumerator.getNext());
|
||||
|
||||
return windows;
|
||||
}
|
||||
get windows() [win for (win in iter(services.get("windowMediator").getEnumerator("navigator:browser")))],
|
||||
|
||||
}, {
|
||||
// initially hide all GUI elements, they are later restored unless the user
|
||||
@@ -1193,26 +1227,27 @@ const Dactyl = Module("dactyl", {
|
||||
this);
|
||||
let class_ = dir.map(function (dir) "html|html > xul|scrollbar[orient=" + dir + "]");
|
||||
|
||||
if (class_.length)
|
||||
styles.addSheet(true, "scrollbar", "*", class_.join(", ") + " { visibility: collapse !important; }", true);
|
||||
else
|
||||
styles.removeSheet(true, "scrollbar");
|
||||
styles.addSheet(true, "scrollbar", "*",
|
||||
class_.length ? class_.join(", ") + " { visibility: collapse !important; }" : "");
|
||||
|
||||
options.safeSetPref("layout.scrollbar.side", opts.indexOf("l") >= 0 ? 3 : 2,
|
||||
"See 'guioptions' scrollbar flags.");
|
||||
},
|
||||
validator: function (opts) (opts.indexOf("l") < 0 || opts.indexOf("r") < 0)
|
||||
},
|
||||
tab: {
|
||||
feature: "tabs",
|
||||
opts: {
|
||||
n: ["Tab number", highlight.selector("TabNumber")],
|
||||
N: ["Tab number over icon", highlight.selector("TabIconNumber")]
|
||||
},
|
||||
setter: function (opts) {
|
||||
const self = this;
|
||||
let classes = [v[1] for ([k, v] in Iterator(this.opts)) if (opts.indexOf(k) < 0)];
|
||||
let css = classes.length ? classes.join(",") + "{ display: none; }" : "";
|
||||
styles.addSheet(true, "taboptions", "chrome://*", css);
|
||||
tabs.tabsBound = Array.some(opts, function (k) k in self.opts);
|
||||
|
||||
styles.addSheet(true, "taboptions", "chrome://*",
|
||||
classes.length ? classes.join(",") + "{ display: none; }" : "");
|
||||
|
||||
tabs.tabBinding.enabled = Array.some(opts, function (k) k in this.opts, this);
|
||||
statusline.updateTabCount();
|
||||
}
|
||||
}
|
||||
@@ -1230,13 +1265,14 @@ const Dactyl = Module("dactyl", {
|
||||
"charlist", config.defaults.guioptions || "", {
|
||||
setter: function (value) {
|
||||
for (let [, group] in Iterator(groups))
|
||||
group.setter(value);
|
||||
if (!group.feature || dactyl.has(group.feature))
|
||||
group.setter(value);
|
||||
return value;
|
||||
},
|
||||
completer: function (context) {
|
||||
let opts = [v.opts for ([k, v] in Iterator(groups))];
|
||||
let opts = [v.opts for ([k, v] in Iterator(groups)) if (!v.feature || dactyl.has(v.feature))];
|
||||
opts = opts.map(function (opt) [[k, v[0]] for ([k, v] in Iterator(opt))]);
|
||||
return util.Array.flatten(opts);
|
||||
return array.flatten(opts);
|
||||
},
|
||||
validator: function (val) Option.validateCompleter.call(this, val) &&
|
||||
[v for ([k, v] in Iterator(groups))].every(function (g) !g.validator || g.validator(val))
|
||||
@@ -1252,7 +1288,7 @@ const Dactyl = Module("dactyl", {
|
||||
|
||||
options.add(["titlestring"],
|
||||
"Change the title of the window",
|
||||
"string", config.defaults.titlestring || config.hostApplication,
|
||||
"string", config.defaults.titlestring || config.host,
|
||||
{
|
||||
setter: function (value) {
|
||||
let win = document.documentElement;
|
||||
@@ -1330,13 +1366,13 @@ const Dactyl = Module("dactyl", {
|
||||
{ argCount: "0" });
|
||||
|
||||
commands.add(["dia[log]"],
|
||||
"Open a " + config.name + " dialog",
|
||||
"Open a " + config.appname + " dialog",
|
||||
function (args) {
|
||||
let arg = args[0];
|
||||
let dialog = args[0];
|
||||
|
||||
dactyl.assert(dialog in config.dialogs, "E475: Invalid argument: " + dialog);
|
||||
try {
|
||||
dactyl.assert(args[0] in config.dialogs, "E475: Invalid argument: " + arg);
|
||||
config.dialogs[args[0]][1]();
|
||||
config.dialogs[dialog][1]();
|
||||
}
|
||||
catch (e) {
|
||||
dactyl.echoerr("Error opening " + arg.quote() + ": " + e);
|
||||
@@ -1383,15 +1419,8 @@ const Dactyl = Module("dactyl", {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof AddonManager == "undefined") {
|
||||
if (typeof AddonManager == "undefined")
|
||||
modules.AddonManager = {
|
||||
getInstallForFile: function (file, callback, mimetype) {
|
||||
callback({
|
||||
install: function () {
|
||||
services.get("extensionManager").installItemFromFile(file, "app-profile");
|
||||
}
|
||||
});
|
||||
},
|
||||
getAddonById: function (id, callback) {
|
||||
let addon = id;
|
||||
if (!isobject(addon))
|
||||
@@ -1438,11 +1467,19 @@ const Dactyl = Module("dactyl", {
|
||||
.getItemList(Ci.nsIUpdateItem["TYPE_" + type.toUpperCase()], {})))
|
||||
res.append(this.getAddonById(item));
|
||||
return res;
|
||||
}
|
||||
},
|
||||
getInstallForFile: function (file, callback, mimetype) {
|
||||
callback({
|
||||
install: function () {
|
||||
services.get("extensionManager").installItemFromFile(file, "app-profile");
|
||||
}
|
||||
});
|
||||
},
|
||||
getInstallForURL: function (url, callback, mimetype) {
|
||||
dactyl.assert(false, "Install by URL not implimented");
|
||||
},
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function callResult(method) {
|
||||
@@ -1467,7 +1504,7 @@ const Dactyl = Module("dactyl", {
|
||||
}, {
|
||||
argCount: "1",
|
||||
completer: function (context) {
|
||||
context.filters.push(function ({ item: f }) f.isDirectory() || /\.xpi$/.test(f.leafName));
|
||||
context.filters.push(function ({ item }) item.isDirectory() || /\.xpi$/.test(item.leafName));
|
||||
completion.file(context);
|
||||
}
|
||||
});
|
||||
@@ -1483,13 +1520,13 @@ const Dactyl = Module("dactyl", {
|
||||
name: "exte[nable]",
|
||||
description: "Enable an extension",
|
||||
action: function (addon) addon.userDisabled = false,
|
||||
filter: function ({ item: e }) e.userDisabled
|
||||
filter: function ({ item }) item.userDisabled
|
||||
},
|
||||
{
|
||||
name: "extd[isable]",
|
||||
description: "Disable an extension",
|
||||
action: function (addon) addon.userDisabled = true,
|
||||
filter: function ({ item: e }) !e.userDisabled
|
||||
filter: function ({ item }) !item.userDisabled
|
||||
}
|
||||
].forEach(function (command) {
|
||||
commands.add([command.name],
|
||||
@@ -1535,7 +1572,7 @@ const Dactyl = Module("dactyl", {
|
||||
bang: true,
|
||||
completer: function (context) {
|
||||
completion.extension(context);
|
||||
context.filters.push(function ({ item: e }) e.isActive && e.optionsURL);
|
||||
context.filters.push(function ({ item }) item.isActive && item.optionsURL);
|
||||
},
|
||||
literal: 0
|
||||
});
|
||||
@@ -1543,6 +1580,23 @@ const Dactyl = Module("dactyl", {
|
||||
commands.add(["extens[ions]", "exts"],
|
||||
"List available extensions",
|
||||
function (args) {
|
||||
function addonExtra(e) {
|
||||
let extra;
|
||||
if (e.pendingOperations & AddonManager.PENDING_UNINSTALL)
|
||||
extra = ["Disabled", "uninstalled"];
|
||||
else if (e.pendingOperations & AddonManager.PENDING_DISABLE)
|
||||
extra = ["Disabled", "disabled"];
|
||||
else if (e.pendingOperations & AddonManager.PENDING_INSTALL)
|
||||
extra = ["Enabled", "installed"];
|
||||
else if (e.pendingOperations & AddonManager.PENDING_ENABLE)
|
||||
extra = ["Enabled", "enabled"];
|
||||
else if (e.pendingOperations & AddonManager.PENDING_UPGRADE)
|
||||
extra = ["Enabled", "upgraded"];
|
||||
if (extra)
|
||||
return <> (<span highlight={extra[0]}>{extra[1]}</span>
|
||||
 on restart)</>;
|
||||
return <></>;
|
||||
}
|
||||
AddonManager.getAddonsByTypes(["extension"], function (extensions) {
|
||||
if (args[0])
|
||||
extensions = extensions.filter(function (extension) extension.name.indexOf(args[0]) >= 0);
|
||||
@@ -1555,12 +1609,7 @@ const Dactyl = Module("dactyl", {
|
||||
e.version,
|
||||
(e.isActive ? <span highlight="Enabled">enabled</span>
|
||||
: <span highlight="Disabled">disabled</span>) +
|
||||
((e.userDisabled || e.appDisabled) == !e.isActive ? XML() :
|
||||
<> ({e.userDisabled || e.appDisabled
|
||||
? <span highlight="Disabled">disabled</span>
|
||||
: <span highlight="Enabled">enabled</span>}
|
||||
on restart)
|
||||
</>),
|
||||
addonExtra(e),
|
||||
e.description]
|
||||
for ([, e] in Iterator(extensions)))));
|
||||
else if (filter)
|
||||
@@ -1658,7 +1707,7 @@ const Dactyl = Module("dactyl", {
|
||||
});
|
||||
|
||||
commands.add(["res[tart]"],
|
||||
"Force " + config.name + " to restart",
|
||||
"Force " + config.appname + " to restart",
|
||||
function () { dactyl.restart(); },
|
||||
{ argCount: "0" });
|
||||
|
||||
@@ -1810,7 +1859,7 @@ const Dactyl = Module("dactyl", {
|
||||
dactyl.open("about:");
|
||||
else
|
||||
commandline.commandOutput(<>
|
||||
{config.name} {dactyl.version} running on:<br/>{navigator.userAgent}
|
||||
{config.appname} {dactyl.version} running on:<br/>{navigator.userAgent}
|
||||
</>);
|
||||
}, {
|
||||
argCount: "0",
|
||||
@@ -1836,11 +1885,13 @@ const Dactyl = Module("dactyl", {
|
||||
context.title = ["Extension"];
|
||||
context.anchored = false;
|
||||
context.keys = { text: "name", description: "description", icon: "iconURL" },
|
||||
context.incomplete = true;
|
||||
AddonManager.getAddonsByTypes(["extension"], function (addons) {
|
||||
context.incomplete = false;
|
||||
context.completions = addons;
|
||||
});
|
||||
context.generate = function () {
|
||||
context.incomplete = true;
|
||||
AddonManager.getAddonsByTypes(["extension"], function (addons) {
|
||||
context.incomplete = false;
|
||||
context.completions = addons;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
completion.help = function help(context, unchunked) {
|
||||
@@ -1877,7 +1928,7 @@ const Dactyl = Module("dactyl", {
|
||||
|
||||
dactyl.log("All modules loaded", 3);
|
||||
|
||||
services.add("commandLineHandler", "@mozilla.org/commandlinehandler/general-startup;1?type=" + config.name.toLowerCase());
|
||||
services.add("commandLineHandler", "@mozilla.org/commandlinehandler/general-startup;1?type=" + config.name);
|
||||
|
||||
let commandline = services.get("commandLineHandler").optionValue;
|
||||
if (commandline) {
|
||||
@@ -1892,7 +1943,7 @@ const Dactyl = Module("dactyl", {
|
||||
dactyl.log("Command-line options: " + util.objectToString(dactyl.commandLineOptions), 3);
|
||||
|
||||
// first time intro message
|
||||
const firstTime = "extensions." + config.name.toLowerCase() + ".firsttime";
|
||||
const firstTime = "extensions." + config.name + ".firsttime";
|
||||
if (options.getPref(firstTime, true)) {
|
||||
util.timeout(function () {
|
||||
dactyl.help();
|
||||
@@ -1904,7 +1955,7 @@ const Dactyl = Module("dactyl", {
|
||||
modes.reset();
|
||||
|
||||
// TODO: we should have some class where all this guioptions stuff fits well
|
||||
Dactyl.hideGUI();
|
||||
// Dactyl.hideGUI();
|
||||
|
||||
if (dactyl.commandLineOptions.preCommands)
|
||||
dactyl.commandLineOptions.preCommands.forEach(function (cmd) {
|
||||
@@ -1914,7 +1965,7 @@ const Dactyl = Module("dactyl", {
|
||||
// finally, read the RC file and source plugins
|
||||
// make sourcing asynchronous, otherwise commands that open new tabs won't work
|
||||
util.timeout(function () {
|
||||
let extensionName = config.name.toUpperCase();
|
||||
let extensionName = config.idname;
|
||||
let init = services.get("environment").get(extensionName + "_INIT");
|
||||
let rcFile = io.getRCFile("~");
|
||||
|
||||
@@ -1951,13 +2002,18 @@ const Dactyl = Module("dactyl", {
|
||||
// after sourcing the initialization files, this function will set
|
||||
// all gui options to their default values, if they have not been
|
||||
// set before by any RC file
|
||||
for (let option in options) {
|
||||
for (let option in values(options.needInit))
|
||||
// FIXME:
|
||||
// 'encoding' option should not be set at this timing.
|
||||
// Probably a wrong value is set into the option,
|
||||
// if current page's encoging is not UTF-8.
|
||||
if (option.name != "encoding" && option.setter)
|
||||
option.value = option.value;
|
||||
}
|
||||
try {
|
||||
if (option.name != "encoding");
|
||||
option.value = option.value;
|
||||
}
|
||||
catch (e) {
|
||||
dactyl.reportError(e);
|
||||
}
|
||||
|
||||
if (dactyl.commandLineOptions.postCommands)
|
||||
dactyl.commandLineOptions.postCommands.forEach(function (cmd) {
|
||||
@@ -1969,7 +2025,7 @@ const Dactyl = Module("dactyl", {
|
||||
}, 0);
|
||||
|
||||
statusline.update();
|
||||
dactyl.log(config.name + " fully initialized", 0);
|
||||
dactyl.log(config.appname + " fully initialized", 0);
|
||||
dactyl.initialized = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -23,11 +23,6 @@
|
||||
<script type="application/x-javascript;version=1.8" src="&dactyl.content;dactyl-overlay.js"/>
|
||||
|
||||
<window id="&dactyl.mainWindow;">
|
||||
<stringbundleset id="dactyl-stringbundles">
|
||||
<stringbundle id="dactyl-charset-bundle"
|
||||
src="chrome://global/locale/charsetTitles.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<keyset id="mainKeyset">
|
||||
<key id="key_open_vimbar" key=":" oncommand="window.dactyl ∧ dactyl.modules.commandline.open(':', '', dactyl.modules.modes.EX);" modifiers=""/>
|
||||
<key id="key_stop" keycode="VK_ESCAPE" oncommand="window.dactyl ∧ dactyl.modules.events.onEscape();"/>
|
||||
@@ -43,13 +38,13 @@
|
||||
<commandset id="onPentadactylFocus"
|
||||
commandupdater="true"
|
||||
events="focus"
|
||||
oncommandupdate="if (window.dactyl ∧ dactyl.modules.events != undefined) dactyl.modules.events.onFocusChange(event);"/>
|
||||
oncommandupdate="if (window.dactyl ∧ dactyl.modules.loaded.events) dactyl.modules.events.onFocusChange(event);"/>
|
||||
<commandset id="onPentadactylSelect"
|
||||
commandupdater="true"
|
||||
events="select"
|
||||
oncommandupdate="if (window.dactyl ∧ dactyl.modules.events != undefined) dactyl.modules.events.onSelectionChange(event);"/>
|
||||
oncommandupdate="if (window.dactyl ∧ dactyl.modules.loaded.events) dactyl.modules.events.onSelectionChange(event);"/>
|
||||
|
||||
<!-- As of Firefox 3.1pre, <iframe>.height changes do not seem to have immediate effect,
|
||||
<!-- As of Firefox 3.1pre, iframe.height changes do not seem to have immediate effect,
|
||||
therefore we need to put them into a <vbox> for which that works just fine -->
|
||||
<vbox class="dactyl-container" hidden="false" collapsed="true">
|
||||
<iframe id="dactyl-multiline-output" src="chrome://dactyl/content/buffer.xhtml"
|
||||
@@ -81,7 +76,6 @@
|
||||
oninput="window.dactyl ∧ dactyl.modules.commandline.onMultilineInputEvent(event);"
|
||||
onblur="window.dactyl ∧ dactyl.modules.commandline.onMultilineInputEvent(event);"/>
|
||||
</vbox>
|
||||
|
||||
</window>
|
||||
|
||||
<statusbar id="status-bar" dactyl:highlight="StatusLine">
|
||||
@@ -98,7 +92,6 @@
|
||||
<statusbarpanel id="statusbar-display" hidden="true"/>
|
||||
<statusbarpanel id="statusbar-progresspanel" hidden="true"/>
|
||||
</statusbar>
|
||||
|
||||
</overlay>
|
||||
|
||||
<!-- vim: set fdm=marker sw=4 ts=4 et: -->
|
||||
|
||||
@@ -569,7 +569,7 @@ const Editor = Module("editor", {
|
||||
let list = this.getAbbreviations(filter, lhs);
|
||||
|
||||
if (!list.length)
|
||||
dactyl.echomsg("No this._abbreviations found");
|
||||
dactyl.echomsg("No abbreviations found");
|
||||
else if (list.length == 1) {
|
||||
let [mode, lhs, rhs] = list[0];
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ catch (e) { __dactyl_eval_error = e; }
|
||||
// IMPORTANT: The eval statement *must* remain on the first line
|
||||
// in order for line numbering in any errors to remain correct.
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -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 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.
|
||||
@@ -1173,7 +1173,7 @@ const Events = Module("events", {
|
||||
function () { document.commandDispatcher.rewindFocus(); });
|
||||
|
||||
mappings.add(modes.all,
|
||||
["<C-z>"], "Temporarily ignore all " + config.name + " key bindings",
|
||||
["<C-z>"], "Temporarily ignore all " + config.appname + " key bindings",
|
||||
function () { modes.passAllKeys = true; });
|
||||
|
||||
mappings.add(modes.all,
|
||||
|
||||
@@ -27,20 +27,25 @@ const RangeFinder = Module("rangefinder", {
|
||||
|
||||
let highlighted = this.rangeFind && this.rangeFind.highlighted;
|
||||
let selections = this.rangeFind && this.rangeFind.selections;
|
||||
let regex = false;
|
||||
let matchCase = !(options["ignorecase"] || options["smartcase"] && !/[A-Z]/.test(str));
|
||||
let linksOnly = options["linksearch"];
|
||||
|
||||
str = str.replace(/\\(.|$)/g, function (m, n1) {
|
||||
if (n1 == "l")
|
||||
linksOnly = true;
|
||||
else if (n1 == "L")
|
||||
linksOnly = false;
|
||||
else if (n1 == "c")
|
||||
if (n1 == "c")
|
||||
matchCase = false;
|
||||
else if (n1 == "C")
|
||||
matchCase = true;
|
||||
else if (n1 == "l")
|
||||
linksOnly = true;
|
||||
else if (n1 == "L")
|
||||
linksOnly = false;
|
||||
else if (n1 == "r")
|
||||
regex = true;
|
||||
else if (n1 == "R")
|
||||
regex = false;
|
||||
else
|
||||
return n1;
|
||||
return m;
|
||||
return "";
|
||||
});
|
||||
|
||||
@@ -49,12 +54,13 @@ const RangeFinder = Module("rangefinder", {
|
||||
if (!this.rangeFind
|
||||
|| this.rangeFind.window.get() != window
|
||||
|| linksOnly != !!this.rangeFind.elementPath
|
||||
|| regex != this.rangeFind.regex
|
||||
|| matchCase != this.rangeFind.matchCase
|
||||
|| !!backward != this.rangeFind.reverse) {
|
||||
|
||||
if (this.rangeFind)
|
||||
this.rangeFind.cancel();
|
||||
this.rangeFind = RangeFind(matchCase, backward, linksOnly && options["hinttags"]);
|
||||
this.rangeFind = RangeFind(matchCase, backward, linksOnly && options["hinttags"], regex);
|
||||
this.rangeFind.highlighted = highlighted;
|
||||
this.rangeFind.selections = selections;
|
||||
}
|
||||
@@ -201,7 +207,7 @@ const RangeFinder = Module("rangefinder", {
|
||||
|
||||
},
|
||||
options: function () {
|
||||
options.safeSetPref("accessibility.typeaheadfind.autostart", false);
|
||||
// options.safeSetPref("accessibility.typeaheadfind.autostart", false);
|
||||
// The above should be sufficient, but: https://bugzilla.mozilla.org/show_bug.cgi?id=348187
|
||||
options.safeSetPref("accessibility.typeaheadfind", false);
|
||||
|
||||
@@ -262,13 +268,14 @@ const RangeFinder = Module("rangefinder", {
|
||||
* large amounts of data are concerned (e.g., for API documents).
|
||||
*/
|
||||
const RangeFind = Class("RangeFind", {
|
||||
init: function (matchCase, backward, elementPath) {
|
||||
init: function (matchCase, backward, elementPath, regex) {
|
||||
this.window = Cu.getWeakReference(window);
|
||||
this.elementPath = elementPath || null;
|
||||
this.matchCase = Boolean(matchCase);
|
||||
this.reverse = Boolean(backward);
|
||||
|
||||
this.finder = services.create("find");
|
||||
this.finder.caseSensitive = this.matchCase;
|
||||
this.matchCase = Boolean(matchCase);
|
||||
this.regex = Boolean(regex);
|
||||
|
||||
this.ranges = this.makeFrameList(content);
|
||||
|
||||
@@ -281,6 +288,12 @@ const RangeFind = Class("RangeFind", {
|
||||
|
||||
get backward() this.finder.findBackwards,
|
||||
|
||||
get matchCase() this.finder.caseSensitive,
|
||||
set matchCase(val) this.finder.caseSensitive = Boolean(val),
|
||||
|
||||
get regex() this.finder.regularExpression,
|
||||
set regex(val) this.finder.regularExpression = Boolean(val),
|
||||
|
||||
get searchString() this.lastString,
|
||||
|
||||
get selectedRange() {
|
||||
@@ -437,7 +450,7 @@ const RangeFind = Class("RangeFind", {
|
||||
let pageStart = RangeFind.endpoint(pageRange, true);
|
||||
let pageEnd = RangeFind.endpoint(pageRange, false);
|
||||
|
||||
for (let frame in util.Array.itervalues(win.frames)) {
|
||||
for (let frame in array.itervalues(win.frames)) {
|
||||
let range = doc.createRange();
|
||||
if (util.computedStyle(frame.frameElement).visibility == "visible") {
|
||||
range.selectNode(frame.frameElement);
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
<!DOCTYPE document SYSTEM "chrome://dactyl/content/dactyl.dtd">
|
||||
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:dactyl="http://vimperator.org/namespaces/liberator"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:str="http://exslt.org/strings"
|
||||
xmlns:exsl="http://exslt.org/common"
|
||||
extension-element-prefixes="exsl str">
|
||||
|
||||
<xsl:output method="xml" indent="no"/>
|
||||
|
||||
<xsl:variable name="root" select="/dactyl:document"/>
|
||||
<xsl:variable name="tags">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:for-each select="$root//@tag|$root//dactyl:tags/text()|$root//dactyl:tag/text()">
|
||||
<xsl:value-of select="concat(., ' ')"/>
|
||||
</xsl:for-each>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:template name="parse-tags">
|
||||
<xsl:param name="text"/>
|
||||
<div dactyl:highlight="HelpTags">
|
||||
<xsl:for-each select="str:tokenize($text)">
|
||||
<a id="{.}" dactyl:highlight="HelpTag"><xsl:value-of select="."/></a>
|
||||
</xsl:for-each>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="/">
|
||||
<xsl:call-template name="parse-tags">
|
||||
<xsl:with-param name="text" select="$tags"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2009 by Kris Maglione <kris@vimperator.org>
|
||||
// Copyright (c) 2009-2010 by 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.
|
||||
@@ -13,9 +13,6 @@ function checkFragment() {
|
||||
}
|
||||
|
||||
document.addEventListener("load", checkFragment, true);
|
||||
window.addEventListener("message", function (event) {
|
||||
if (event.data == "fragmentChange")
|
||||
checkFragment();
|
||||
}, true);
|
||||
document.addEventListener("hashChange", checkFragment, true);
|
||||
|
||||
// vim: set fdm=marker sw=4 ts=4 et:
|
||||
|
||||
@@ -6,40 +6,27 @@
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:dactyl="http://vimperator.org/namespaces/liberator"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:str="http://exslt.org/strings"
|
||||
xmlns:exsl="http://exslt.org/common"
|
||||
extension-element-prefixes="exsl str">
|
||||
xmlns:regexp="http://exslt.org/regular-expressions"
|
||||
xmlns:str="http://exslt.org/strings"
|
||||
extension-element-prefixes="exsl regexp str">
|
||||
|
||||
<xsl:output method="xml" indent="no"/>
|
||||
|
||||
<!-- Variable Definitions {{{1 -->
|
||||
|
||||
<xsl:variable name="doc">
|
||||
<xsl:apply-templates select="/dactyl:document" mode="overlay"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="root" select="exsl:node-set($doc)"/>
|
||||
|
||||
<xsl:variable name="tags">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:for-each select="$root//@tag|$root//dactyl:tags/text()|$root//dactyl:tag/text()">
|
||||
<xsl:value-of select="concat(., ' ')"/>
|
||||
</xsl:for-each>
|
||||
</xsl:variable>
|
||||
|
||||
<!-- Process Overlays {{{1 -->
|
||||
|
||||
<xsl:variable name="overlay" select="concat('dactyl://help-overlay/', /dactyl:document/@name)"/>
|
||||
<xsl:variable name="overlaydoc" select="document($overlay)/dactyl:overlay"/>
|
||||
|
||||
<xsl:template name="splice-overlays">
|
||||
<xsl:param name="elem"/>
|
||||
<xsl:param name="tag"/>
|
||||
<xsl:for-each select="$overlaydoc/*[@insertbefore=$tag]">
|
||||
<xsl:for-each select="ancestor::*/dactyl:overlay/*[@insertbefore=$tag]">
|
||||
<xsl:apply-templates select="." mode="overlay"/>
|
||||
</xsl:for-each>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$overlaydoc/*[@replace=$tag] and not($elem[@replace])">
|
||||
<xsl:for-each select="$overlaydoc/*[@replace=$tag]">
|
||||
<xsl:when test="ancestor::*/dactyl:overlay/*[@replace=$tag] and not($elem[@replace])">
|
||||
<xsl:for-each select="ancestor::*/dactyl:overlay/*[@replace=$tag]">
|
||||
<xsl:apply-templates select="." mode="overlay-2"/>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
@@ -49,7 +36,7 @@
|
||||
</xsl:for-each>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:for-each select="$overlaydoc/*[@insertafter=$tag]">
|
||||
<xsl:for-each select="ancestor::*/dactyl:overlay/*[@insertafter=$tag]">
|
||||
<xsl:apply-templates select="." mode="overlay"/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
@@ -75,9 +62,32 @@
|
||||
|
||||
<!-- Process Inclusions {{{1 -->
|
||||
|
||||
<xsl:template name="include">
|
||||
<xsl:param name="root-node" select="."/>
|
||||
<xsl:param name="overlay" select="concat('dactyl://help-overlay/', $root-node/@name)"/>
|
||||
|
||||
<!-- Ridiculous three-pass processing is needed to deal with
|
||||
- lack of dynamic variable scope in XSL 1.0. -->
|
||||
|
||||
<!-- Store a copy of the overlay for the current document. -->
|
||||
<xsl:variable name="doc">
|
||||
<dactyl:document>
|
||||
<xsl:copy-of select="document($overlay)/dactyl:overlay"/>
|
||||
<xsl:copy-of select="$root-node/node()"/>
|
||||
</dactyl:document>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:call-template name="parse-tags">
|
||||
<xsl:with-param name="text" select="concat($root-node/@name, '.xml')"/>
|
||||
</xsl:call-template>
|
||||
<xsl:apply-templates select="exsl:node-set($doc)/dactyl:document/node()[position() != 1]" mode="overlay"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dactyl:include" mode="overlay-2">
|
||||
<div dactyl:highlight="HelpInclude">
|
||||
<xsl:apply-templates select="document(@href)/dactyl:document/node()" mode="overlay"/>
|
||||
<xsl:call-template name="include">
|
||||
<xsl:with-param name="root-node" select="document(@href)/dactyl:document"/>
|
||||
</xsl:call-template>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
@@ -93,22 +103,39 @@
|
||||
<!-- Root {{{1 -->
|
||||
|
||||
<xsl:template match="/">
|
||||
<xsl:for-each select="$root/dactyl:document">
|
||||
<html dactyl:highlight="Help">
|
||||
<head>
|
||||
<title><xsl:value-of select="@title"/></title>
|
||||
<script type="text/javascript"
|
||||
src="chrome://dactyl/content/help.js"/>
|
||||
</head>
|
||||
<body dactyl:highlight="HelpBody">
|
||||
<div dactyl:highlight="Logo"/>
|
||||
<xsl:call-template name="parse-tags">
|
||||
<xsl:with-param name="text" select="concat(@name, '.html')"/>
|
||||
</xsl:call-template>
|
||||
<xsl:apply-templates/>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:for-each>
|
||||
|
||||
<!-- Ridiculous three-pass processing is needed to deal with
|
||||
- lack of dynamic variable scope in XSL 1.0. -->
|
||||
|
||||
<xsl:variable name="doc1">
|
||||
<xsl:call-template name="include">
|
||||
<xsl:with-param name="root-node" select="dactyl:document"/>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="root" select="exsl:node-set($doc1)"/>
|
||||
|
||||
<!-- Store a cache of all tags defined -->
|
||||
<xsl:variable name="doc2">
|
||||
<dactyl:document>
|
||||
<xsl:attribute name="document-tags">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:for-each select="$root//@tag|$root//dactyl:tags/text()|$root//dactyl:tag/text()">
|
||||
<xsl:value-of select="concat(., ' ')"/>
|
||||
</xsl:for-each>
|
||||
</xsl:attribute>
|
||||
<xsl:copy-of select="$root/node()"/>
|
||||
</dactyl:document>
|
||||
</xsl:variable>
|
||||
|
||||
<html dactyl:highlight="Help">
|
||||
<head>
|
||||
<title><xsl:value-of select="@title"/></title>
|
||||
<script type="text/javascript" src="chrome://dactyl/content/help.js"/>
|
||||
</head>
|
||||
<body dactyl:highlight="HelpBody">
|
||||
<xsl:apply-templates select="exsl:node-set($doc2)/dactyl:document/node()" mode="help-1"/>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Table of Contents {{{1 -->
|
||||
@@ -125,14 +152,14 @@
|
||||
local-name() = $tag and not(preceding::*[local-name() = $lasttag][position() = 1 and not(.=$context)])]"/>
|
||||
|
||||
<xsl:if test="$nodes">
|
||||
<ol dactyl:highlight="HelpOrderedList">
|
||||
<ol level="{$level}" dactyl:highlight="HelpOrderedList">
|
||||
<xsl:for-each select="$nodes">
|
||||
<li>
|
||||
<a>
|
||||
<xsl:if test="@tag">
|
||||
<xsl:attribute name="href"><xsl:value-of select="concat('#', substring-before(concat(@tag, ' '), ' '))"/></xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="node()"/>
|
||||
<xsl:apply-templates select="node()" mode="help-1"/>
|
||||
</a>
|
||||
<xsl:call-template name="toc">
|
||||
<xsl:with-param name="level" select="$level + 1"/>
|
||||
@@ -144,7 +171,7 @@
|
||||
</ol>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:toc" mode="pass-2">
|
||||
<xsl:template match="dactyl:toc" mode="help-2">
|
||||
<xsl:variable name="TOC">
|
||||
<context/>
|
||||
<xsl:for-each
|
||||
@@ -174,36 +201,38 @@
|
||||
|
||||
<!-- Items {{{1 -->
|
||||
|
||||
<xsl:template match="dactyl:strut" mode="pass-2">
|
||||
<xsl:template match="dactyl:strut" mode="help-2">
|
||||
<div style="clear: both"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:item" mode="pass-2">
|
||||
<xsl:template match="dactyl:item" mode="help-2">
|
||||
<div dactyl:highlight="HelpItem">
|
||||
<xsl:apply-templates select="dactyl:tags|dactyl:spec|dactyl:strut"/>
|
||||
<xsl:apply-templates select="dactyl:tags|dactyl:spec|dactyl:strut" mode="help-1"/>
|
||||
<xsl:if test="not(dactyl:description/@short)">
|
||||
<hr style="border: 0; height: 0; margin: 0; width: 100%; float: right;"/>
|
||||
<div dactyl:highlight="HelpOptInfo">
|
||||
<xsl:apply-templates select="dactyl:type|dactyl:default"/>
|
||||
<div style="clear: both;"/>
|
||||
</div>
|
||||
<xsl:if test="dactyl:type|dactyl:default">
|
||||
<div dactyl:highlight="HelpOptInfo">
|
||||
<xsl:apply-templates select="dactyl:type|dactyl:default" mode="help-1"/>
|
||||
<div style="clear: both;"/>
|
||||
</div>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="dactyl:description"/>
|
||||
<xsl:apply-templates select="dactyl:description" mode="help-1"/>
|
||||
<div style="clear: both;"/>
|
||||
</div>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:spec[preceding-sibling::dactyl:spec]" mode="pass-2">
|
||||
<!--
|
||||
<xsl:template match="dactyl:item/dactyl:spec[position() = last()]" mode="help-2">
|
||||
<div style="clear: both;"/>
|
||||
<div dactyl:highlight="HelpSpec">
|
||||
<xsl:apply-templates/>
|
||||
</div>
|
||||
<div dactyl:highlight="HelpSpec"><xsl:apply-templates mode="help-1"/></div>
|
||||
</xsl:template>
|
||||
-->
|
||||
|
||||
<xsl:template match="dactyl:default[not(@type='plain')]" mode="pass-2">
|
||||
<xsl:template match="dactyl:default[not(@type='plain')]" mode="help-2">
|
||||
<xsl:variable name="type" select="preceding-sibling::dactyl:type[1] | following-sibling::dactyl:type[1]"/>
|
||||
<span dactyl:highlight="HelpDefault">(default:<xsl:text> </xsl:text>
|
||||
<xsl:choose>
|
||||
<xsl:when test="starts-with($type, 'string') or starts-with($type, 'regex')">
|
||||
<span dactyl:highlight="HelpString"><xsl:apply-templates/></span>
|
||||
<span dactyl:highlight="HelpString"><xsl:apply-templates mode="help-1"/></span>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<span>
|
||||
@@ -214,22 +243,32 @@
|
||||
<xsl:when test="$type = 'charlist'">String</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:apply-templates select="node()" mode="help-1"/>
|
||||
</span>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>)
|
||||
</span>
|
||||
</xsl:choose>)</span>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Tag Definitions {{{1 -->
|
||||
|
||||
<xsl:template match="dactyl:tags" mode="pass-2">
|
||||
<xsl:template match="dactyl:item/dactyl:tags[position() = last()]" mode="help-2">
|
||||
<div style="clear: right"/>
|
||||
<xsl:call-template name="parse-tags">
|
||||
<xsl:with-param name="text" select="."/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:tag|@tag" mode="pass-2">
|
||||
<xsl:template match="dactyl:tags" mode="help-2">
|
||||
<xsl:call-template name="parse-tags">
|
||||
<xsl:with-param name="text" select="."/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
<xsl:template match="@tag[parent::dactyl:p]" mode="help-2">
|
||||
<xsl:call-template name="parse-tags">
|
||||
<xsl:with-param name="text" select="."/>
|
||||
</xsl:call-template>
|
||||
<div style="clear: right"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:tag|@tag" mode="help-2">
|
||||
<xsl:call-template name="parse-tags">
|
||||
<xsl:with-param name="text" select="."/>
|
||||
</xsl:call-template>
|
||||
@@ -249,31 +288,40 @@
|
||||
<xsl:param name="contents" select="text()"/>
|
||||
<xsl:variable name="tag" select="str:tokenize($contents, ' [!')[1]"/>
|
||||
<a href="dactyl://help-tag/{$tag}" style="color: inherit;">
|
||||
<xsl:if test="contains($tags, concat(' ', $tag, ' '))">
|
||||
<xsl:if test="contains(ancestor::*/@document-tags, concat(' ', $tag, ' '))">
|
||||
<xsl:attribute name="href">#<xsl:value-of select="$tag"/></xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="$contents"/>
|
||||
</a>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dactyl:o" mode="pass-2">
|
||||
<span dactyl:highlight="HelpOption">
|
||||
<xsl:template match="dactyl:o" mode="help-2">
|
||||
<span dactyl:highlight="HelpOpt">
|
||||
<xsl:call-template name="linkify-tag">
|
||||
<xsl:with-param name="contents" select='concat("'", text(), "'")'/>
|
||||
</xsl:call-template>
|
||||
</span>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:t" mode="pass-2">
|
||||
<xsl:template match="dactyl:pref" mode="help-2">
|
||||
<a href="http://kb.mozillazine.org/{text()}" dactyl:highlight="HelpOpt"
|
||||
>'<xsl:apply-templates select="@*|node()" mode="help-1"/>'</a>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:t" mode="help-2">
|
||||
<span dactyl:highlight="HelpTopic">
|
||||
<xsl:call-template name="linkify-tag"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:k" mode="pass-2">
|
||||
<xsl:template match="dactyl:k" mode="help-2">
|
||||
<span dactyl:highlight="HelpKey">
|
||||
<xsl:call-template name="linkify-tag"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:k[@name]" mode="pass-2">
|
||||
<xsl:template match="dactyl:kwd" mode="help-2">
|
||||
<span dactyl:highlight="HelpKeyword">
|
||||
<xsl:apply-templates select="@*|node()" mode="help-1"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:k[@name]" mode="help-2">
|
||||
<span dactyl:highlight="HelpKey">
|
||||
<xsl:call-template name="linkify-tag">
|
||||
<xsl:with-param name="contents" select="concat('<', @name, '>', .)"/>
|
||||
@@ -283,100 +331,117 @@
|
||||
|
||||
<!-- HTML-ish elements {{{1 -->
|
||||
|
||||
<xsl:template match="dactyl:dl" mode="pass-2">
|
||||
<xsl:template match="dactyl:dl" mode="help-2">
|
||||
<dl>
|
||||
<column/>
|
||||
<column/>
|
||||
<xsl:for-each select="dactyl:dt">
|
||||
<tr>
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:apply-templates select="following-sibling::dactyl:dd[1]"/>
|
||||
<xsl:apply-templates select="." mode="help-1"/>
|
||||
<xsl:apply-templates select="following-sibling::dactyl:dd[1]" mode="help-1"/>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</dl>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dactyl:link" mode="pass-2">
|
||||
<a href="{@topic}"><xsl:apply-templates select="@*|node()"/></a>
|
||||
<xsl:template match="dactyl:link" mode="help-2">
|
||||
<a href="{@topic}">
|
||||
<xsl:if test="regexp:match(@topic, '^[a-zA-Z]*:', '')
|
||||
and not(starts-with(@topic, 'mailto:'))">
|
||||
<xsl:attribute name="rel">external</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="@*|node()" mode="help-1"/>
|
||||
</a>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dactyl:hl" mode="help-2">
|
||||
<span dactyl:highlight="{@key}"><xsl:apply-templates select="@*|node()" mode="help-1"/></span>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:h" mode="help-2">
|
||||
<em><xsl:apply-templates select="@*|node()" mode="help-1"/></em>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:em | dactyl:tt | dactyl:p |
|
||||
dactyl:dt | dactyl:dd |
|
||||
dactyl:ol | dactyl:ul | dactyl:li |
|
||||
dactyl:h1 | dactyl:h2 | dactyl:h3"
|
||||
mode="pass-2">
|
||||
<xsl:element name="html:{local-name()}">
|
||||
<xsl:apply-templates select="@*|node()"/>
|
||||
mode="help-2">
|
||||
<xsl:element name="{local-name()}">
|
||||
<xsl:apply-templates select="@*|node()" mode="help-1"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dactyl:code" mode="pass-2">
|
||||
<pre dactyl:highlight="HelpCode"><xsl:apply-templates select="@*|node()"/></pre>
|
||||
<xsl:template match="dactyl:code" mode="help-2">
|
||||
<pre dactyl:highlight="HelpCode"><xsl:apply-templates select="@*|node()" mode="help-1"/></pre>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Help elements {{{1 -->
|
||||
|
||||
<xsl:template match="dactyl:a" mode="pass-2">
|
||||
<span dactyl:highlight="HelpArg">{<xsl:apply-templates select="@*|node()"/>}</span>
|
||||
<xsl:template match="dactyl:a" mode="help-2">
|
||||
<span dactyl:highlight="HelpArg">{<xsl:apply-templates select="@*|node()" mode="help-1"/>}</span>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:oa" mode="pass-2">
|
||||
<span dactyl:highlight="HelpOptionalArg">[<xsl:apply-templates select="@*|node()"/>]</span>
|
||||
<xsl:template match="dactyl:oa" mode="help-2">
|
||||
<span dactyl:highlight="HelpOptionalArg">[<xsl:apply-templates select="@*|node()" mode="help-1"/>]</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dactyl:note" mode="pass-2">
|
||||
<xsl:template match="dactyl:note" mode="help-2">
|
||||
<p style="clear: both;">
|
||||
<xsl:apply-templates select="@*"/>
|
||||
<xsl:apply-templates select="@*" mode="help-1"/>
|
||||
<div style="clear: both;"/>
|
||||
<span dactyl:highlight="HelpNote">Note:</span>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:apply-templates select="node()"/>
|
||||
<xsl:apply-templates select="node()" mode="help-1"/>
|
||||
</p>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:warning" mode="pass-2">
|
||||
<xsl:template match="dactyl:warning" mode="help-2">
|
||||
<p style="clear: both;">
|
||||
<xsl:apply-templates select="@*"/>
|
||||
<xsl:apply-templates select="@*" mode="help-1"/>
|
||||
<div style="clear: both;"/>
|
||||
<span dactyl:highlight="HelpWarning">Warning:</span>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:apply-templates select="node()"/>
|
||||
<xsl:apply-templates select="node()" mode="help-1"/>
|
||||
</p>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:default" mode="pass-2">
|
||||
<span dactyl:highlight="HelpDefault">
|
||||
(default:<xsl:text> </xsl:text><xsl:apply-templates select="@*|node()"/>)
|
||||
</span>
|
||||
<xsl:template match="dactyl:default" mode="help-2">
|
||||
<span dactyl:highlight="HelpDefault">(default:<xsl:text> </xsl:text><xsl:apply-templates select="@*|node()" mode="help-1"/>)</span>
|
||||
</xsl:template>
|
||||
|
||||
<!-- HTML-ify other elements {{{1 -->
|
||||
|
||||
<xsl:template match="dactyl:ex" mode="pass-2">
|
||||
<xsl:template match="dactyl:ex" mode="help-2">
|
||||
<span dactyl:highlight="HelpEx">
|
||||
<xsl:variable name="tag" select="str:tokenize(text(), ' [!')[1]"/>
|
||||
<a href="dactyl://help-tag/{$tag}" style="color: inherit;">
|
||||
<xsl:if test="contains($tags, concat(' ', $tag, ' '))">
|
||||
<xsl:if test="contains(ancestor::*/@document-tags, concat(' ', $tag, ' '))">
|
||||
<xsl:attribute name="href">#<xsl:value-of select="$tag"/></xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:apply-templates mode="help-1"/>
|
||||
</a>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dactyl:description | dactyl:example | dactyl:spec" mode="pass-2">
|
||||
<xsl:template match="dactyl:description | dactyl:example | dactyl:spec" mode="help-2">
|
||||
<div>
|
||||
<xsl:if test="self::dactyl:description"><xsl:attribute name="dactyl:highlight">HelpDescription</xsl:attribute></xsl:if>
|
||||
<xsl:if test="self::dactyl:example"><xsl:attribute name="dactyl:highlight">HelpExample</xsl:attribute></xsl:if>
|
||||
<xsl:if test="self::dactyl:spec"><xsl:attribute name="dactyl:highlight">HelpSpec</xsl:attribute></xsl:if>
|
||||
<xsl:apply-templates select="@*|node()"/>
|
||||
<xsl:apply-templates select="@*|node()" mode="help-1"/>
|
||||
</div>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:str | dactyl:t | dactyl:type" mode="pass-2">
|
||||
<xsl:template match="dactyl:str | dactyl:type" mode="help-2">
|
||||
<span>
|
||||
<xsl:if test="self::dactyl:str"><xsl:attribute name="dactyl:highlight">HelpString</xsl:attribute></xsl:if>
|
||||
<xsl:if test="self::dactyl:t"><xsl:attribute name="dactyl:highlight">HelpTopic</xsl:attribute></xsl:if>
|
||||
<xsl:if test="self::dactyl:type"><xsl:attribute name="dactyl:highlight">HelpType</xsl:attribute></xsl:if>
|
||||
<xsl:apply-templates select="@*|node()"/>
|
||||
<xsl:apply-templates select="@*|node()" mode="help-1"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:xml-block" mode="help-2">
|
||||
<div dactyl:highlight="HelpXMLBlock">
|
||||
<xsl:call-template name="xml-highlight"/>
|
||||
</div>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:xml-highlight" mode="help-2">
|
||||
<xsl:call-template name="xml-highlight"/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Plugins {{{1 -->
|
||||
|
||||
@@ -400,59 +465,133 @@
|
||||
</span>
|
||||
</div>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:author[@email]" mode="pass-2">
|
||||
<xsl:template match="dactyl:author[@email]" mode="help-2">
|
||||
<xsl:call-template name="info">
|
||||
<xsl:with-param name="label" select="'Author'"/>
|
||||
<xsl:with-param name="extra">
|
||||
<xsl:text> </xsl:text><a href="mailto:{@email}">✉</a>
|
||||
<xsl:text> </xsl:text><a href="mailto:{@email}"></a>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:author" mode="pass-2">
|
||||
<xsl:template match="dactyl:author" mode="help-2">
|
||||
<xsl:call-template name="info">
|
||||
<xsl:with-param name="label" select="'Author'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:license" mode="pass-2">
|
||||
<xsl:template match="dactyl:license" mode="help-2">
|
||||
<xsl:call-template name="info">
|
||||
<xsl:with-param name="label" select="'License'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
<xsl:template match="dactyl:plugin" mode="pass-2">
|
||||
<xsl:template match="dactyl:plugin" mode="help-2">
|
||||
<xsl:call-template name="info">
|
||||
<xsl:with-param name="label" select="'Plugin'"/>
|
||||
<xsl:with-param name="nodes">
|
||||
<span><xsl:value-of select="@name"/></span>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:if test="@version">
|
||||
<xsl:call-template name="info">
|
||||
<xsl:with-param name="label" select="'Version'"/>
|
||||
<xsl:with-param name="link" select="''"/>
|
||||
<xsl:with-param name="nodes">
|
||||
<span><xsl:value-of select="@version"/></span>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates mode="help-1"/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Special Element Templates {{{1 -->
|
||||
|
||||
<xsl:template match="dactyl:logo">
|
||||
<xsl:template match="dactyl:logo" mode="help-1">
|
||||
<span dactyl:highlight="Logo"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dactyl:pan[dactyl:handle]">
|
||||
<form style="text-align:center" xmlns="http://www.w3.org/1999/xhtml"
|
||||
action="https://www.paypal.com/cgi-bin/webscr" method="post">
|
||||
<input type="hidden" name="cmd" value="_s-xclick"/>
|
||||
<input type="image" src="chrome://dactyl/content/x-click-but21.png" border="0" name="submit" alt="Donate with PayPal"/>
|
||||
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHPwYJKoZIhvcNAQcEoIIHMDCCBywCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYAUOJADCwiik68MpIUKcMAtNfs4Cx6RY7604ZujgKj7WVaiELWyhUUDSaq8+iLYaNkRUq+dDld96KwhfodqP3MEmIzpQ/qKvh5+4JzTWSBU5G1lHzc4NJQw6TpXKloPxxXhuGKzZ84/asKZIZpLfkP5i8VtqVFecu7qYc0q1U2KoDELMAkGBSsOAwIaBQAwgbwGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIWR7nX4WwgcqAgZgO41g/NtgfBwI14LlJx3p5Hc4nHsQD2wyu5l4BMndkc3mc0uRTXvzutcfPBxYC4aGV5UDn6c+XPzsne+OAdSs4/0a2DJe85SBDOlVyOekz3rRhy5+6XKpKQ7qfiMpKROladi4opfMac/aDUPhGeVsY0jtQCtelIE199iaVKhlbiDvfE7nzV5dLU4d3VZwSDuWBIrIIi9GMtKCCA4cwggODMIIC7KADAgECAgEAMA0GCSqGSIb3DQEBBQUAMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTAeFw0wNDAyMTMxMDEzMTVaFw0zNTAyMTMxMDEzMTVaMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwUdO3fxEzEtcnI7ZKZL412XvZPugoni7i7D7prCe0AtaHTc97CYgm7NsAtJyxNLixmhLV8pyIEaiHXWAh8fPKW+R017+EmXrr9EaquPmsVvTywAAE1PMNOKqo2kl4Gxiz9zZqIajOm1fZGWcGS0f5JQ2kBqNbvbg2/Za+GJ/qwUCAwEAAaOB7jCB6zAdBgNVHQ4EFgQUlp98u8ZvF71ZP1LXChvsENZklGswgbsGA1UdIwSBszCBsIAUlp98u8ZvF71ZP1LXChvsENZklGuhgZSkgZEwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAgV86VpqAWuXvX6Oro4qJ1tYVIT5DgWpE692Ag422H7yRIr/9j/iKG4Thia/Oflx4TdL+IFJBAyPK9v6zZNZtBgPBynXb048hsP16l2vi0k5Q2JKiPDsEfBhGI+HnxLXEaUWAcVfCsQFvd2A1sxRr67ip5y2wwBelUecP3AjJ+YcxggGaMIIBlgIBATCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTA4MDYwNTE0NDk1OFowIwYJKoZIhvcNAQkEMRYEFBpY8FafLq7i3V0czWS9TbR/RjyQMA0GCSqGSIb3DQEBAQUABIGAPvYR9EC2ynooWAvX0iw9aZYTrpX2XrTl6lYkZaLrhM1zKn4RuaiL33sPtq0o0uSKm98gQHzh4P6wmzES0jzHucZjCU4VlpW0fC+/pJxswbW7Qux+ObsNx3f45OcvprqMMZyJiEOULcNhxkm9pCeXQMUGwlHoRRtAxYK2T8L/rQQ=-----END PKCS7-----
|
||||
"/>
|
||||
</form>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Process Tree {{{1 -->
|
||||
|
||||
<xsl:template match="@*|node()" mode="pass-2">
|
||||
<xsl:template match="@*|node()" mode="help-2">
|
||||
<xsl:copy>
|
||||
<xsl:apply-templates select="@*|node()"/>
|
||||
<xsl:apply-templates select="@*|node()" mode="help-1"/>
|
||||
</xsl:copy>
|
||||
</xsl:template>
|
||||
<xsl:template match="@*|node()">
|
||||
<xsl:apply-templates select="." mode="pass-2"/>
|
||||
<xsl:template match="@*|node()" mode="help-1">
|
||||
<xsl:apply-templates select="." mode="help-2"/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- XML Highlighting (xsl:import doesn't work in Firefox 3.x) {{{1 -->
|
||||
<xsl:template name="xml-highlight">
|
||||
<div dactyl:highlight="HelpXML">
|
||||
<xsl:apply-templates mode="xml-highlight"/>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="xml-namespace">
|
||||
<xsl:param name="node" select="."/>
|
||||
<xsl:if test="name($node) != local-name($node)">
|
||||
<span dactyl:highlight="HelpXMLNamespace">
|
||||
<xsl:value-of select="substring-before(name($node), ':')"/>
|
||||
</span>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="local-name($node)"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="*" mode="xml-highlight">
|
||||
<span dactyl:highlight="HelpXMLTagStart">
|
||||
<xsl:text><</xsl:text>
|
||||
<xsl:call-template name="xml-namespace"/>
|
||||
<xsl:apply-templates select="@*" mode="xml-highlight"/>
|
||||
<xsl:text>/></xsl:text>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="*[node()]" mode="xml-highlight">
|
||||
<span dactyl:highlight="HelpXMLTagStart">
|
||||
<xsl:text><</xsl:text>
|
||||
<xsl:call-template name="xml-namespace"/>
|
||||
<xsl:apply-templates select="@*" mode="xml-highlight"/>
|
||||
<xsl:text>></xsl:text>
|
||||
</span>
|
||||
<xsl:apply-templates select="node()" mode="xml-highlight"/>
|
||||
<span dactyl:highlight="HelpXMLTagEnd">
|
||||
<xsl:text></</xsl:text>
|
||||
<xsl:call-template name="xml-namespace"/>
|
||||
<xsl:text>></xsl:text>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dactyl:escape | dactyl:escape[node()]" mode="xml-highlight">
|
||||
<span dactyl:highlight="HelpXMLText">
|
||||
<xsl:apply-templates mode="help-1"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="@*" mode="xml-highlight">
|
||||
<xsl:text> </xsl:text>
|
||||
<span dactyl:highlight="HelpXMLAttribute">
|
||||
<xsl:call-template name="xml-namespace"/>
|
||||
</span>
|
||||
<span dactyl:highlight="HelpXMLString">
|
||||
<xsl:value-of select="regexp:replace(., '"', 'g', '&quot;')"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="comment()" mode="xml-highlight">
|
||||
<span dactyl:highlight="HelpXMLComment">
|
||||
<xsl:value-of select="."/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="processing-instruction()" mode="xml-highlight">
|
||||
<span dactyl:highlight="HelpXMLProcessing">
|
||||
<xsl:value-of select="."/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="text()" mode="xml-highlight">
|
||||
<span dactyl:highlight="HelpXMLText">
|
||||
<xsl:value-of select="regexp:replace(., '<', 'g', '&lt;')"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -36,26 +36,26 @@ const Hints = Module("hints", {
|
||||
function images() util.makeXPath(["img"]);
|
||||
|
||||
this._hintModes = {
|
||||
";": Mode("Focus hint", function (elem) buffer.focusElement(elem), extended),
|
||||
"?": Mode("Show information for hint", function (elem) buffer.showElementInfo(elem), extended),
|
||||
";": Mode("Focus hint", function (elem) buffer.focusElement(elem), extended),
|
||||
"?": Mode("Show information for hint", function (elem) buffer.showElementInfo(elem), extended),
|
||||
s: Mode("Save hint", function (elem) buffer.saveLink(elem, true)),
|
||||
a: Mode("Save hint with prompt", function (elem) buffer.saveLink(elem, false)),
|
||||
f: Mode("Focus frame", function (elem) elem.ownerDocument.defaultView.focus(), function () ["body"]),
|
||||
o: Mode("Follow hint", function (elem) buffer.followLink(elem, dactyl.CURRENT_TAB)),
|
||||
t: Mode("Follow hint in a new tab", function (elem) buffer.followLink(elem, dactyl.NEW_TAB)),
|
||||
b: Mode("Follow hint in a background tab", function (elem) buffer.followLink(elem, dactyl.NEW_BACKGROUND_TAB)),
|
||||
w: Mode("Follow hint in a new window", function (elem) buffer.followLink(elem, dactyl.NEW_WINDOW), extended),
|
||||
w: Mode("Follow hint in a new window", function (elem) buffer.followLink(elem, dactyl.NEW_WINDOW), extended),
|
||||
F: Mode("Open multiple hints in tabs", function (elem) { buffer.followLink(elem, dactyl.NEW_BACKGROUND_TAB); hints.show("F") }),
|
||||
O: Mode("Generate an ':open URL' using hint", function (elem, loc) commandline.open(":", "open " + loc, modes.EX)),
|
||||
T: Mode("Generate a ':tabopen URL' using hint", function (elem, loc) commandline.open(":", "tabopen " + loc, modes.EX)),
|
||||
W: Mode("Generate a ':winopen URL' using hint", function (elem, loc) commandline.open(":", "winopen " + loc, modes.EX)),
|
||||
v: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, false), extended),
|
||||
V: Mode("View hint source in external editor", function (elem, loc) buffer.viewSource(loc, true), extended),
|
||||
v: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, false), extended),
|
||||
V: Mode("View hint source in external editor", function (elem, loc) buffer.viewSource(loc, true), extended),
|
||||
y: Mode("Yank hint location", function (elem, loc) dactyl.clipboardWrite(loc, true)),
|
||||
Y: Mode("Yank hint description", function (elem) dactyl.clipboardWrite(elem.textContent || "", true), extended),
|
||||
c: Mode("Open context menu", function (elem) buffer.openContextMenu(elem), extended),
|
||||
i: Mode("Show image", function (elem) dactyl.open(elem.src), images),
|
||||
I: Mode("Show image in a new tab", function (elem) dactyl.open(elem.src, dactyl.NEW_TAB), images)
|
||||
c: Mode("Open context menu", function (elem) buffer.openContextMenu(elem), extended),
|
||||
i: Mode("Show image", function (elem) dactyl.open(elem.src), images),
|
||||
I: Mode("Show image in a new tab", function (elem) dactyl.open(elem.src, dactyl.NEW_TAB), images)
|
||||
};
|
||||
},
|
||||
|
||||
@@ -351,7 +351,7 @@ const Hints = Module("hints", {
|
||||
|
||||
if (hint.text == "" && hint.elem.firstChild && hint.elem.firstChild instanceof HTMLImageElement) {
|
||||
if (!hint.imgSpan) {
|
||||
var rect = hint.elem.firstChild.getBoundingClientRect();
|
||||
let rect = hint.elem.firstChild.getBoundingClientRect();
|
||||
if (!rect)
|
||||
continue;
|
||||
|
||||
@@ -1054,7 +1054,7 @@ const Hints = Module("hints", {
|
||||
["wordstartswith", "The typed characters are split on whitespace. The resulting groups must all match the beginings of words, in order."],
|
||||
["firstletters", "Behaves like wordstartswith, but all groups much match a sequence of words."],
|
||||
["custom", "Delegate to a custom function: dactyl.plugins.customHintMatcher(hintString)"],
|
||||
["transliterated", "When true, special latin characters are translated to their ascii equivalent (e.g., \u00e9 -> e)"]
|
||||
["transliterated", UTF8("When true, special latin characters are translated to their ascii equivalent (e.g., é -> e)")]
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -45,11 +45,12 @@ const History = Module("history", {
|
||||
let sh = window.getWebNavigation().sessionHistory;
|
||||
let obj = [];
|
||||
obj.index = sh.index;
|
||||
obj.__iterator__ = function () util.Array.iteritems(this);
|
||||
obj.__iterator__ = function () array.iteritems(this);
|
||||
for (let i in util.range(0, sh.count)) {
|
||||
obj[i] = { index: i, __proto__: sh.getEntryAtIndex(i, false) };
|
||||
util.memoize(obj[i], "icon",
|
||||
function (obj) services.get("favicon").getFaviconImageForPage(obj.URI).spec);
|
||||
obj[i] = update(Object.create(sh.getEntryAtIndex(i, false)),
|
||||
{ index: i });
|
||||
memoize(obj[i], "icon",
|
||||
function () services.get("favicon").getFaviconImageForPage(this.URI).spec);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
@@ -64,7 +65,10 @@ const History = Module("history", {
|
||||
dactyl.beep();
|
||||
else {
|
||||
let index = Math.constrain(current + steps, start, end);
|
||||
window.getWebNavigation().gotoIndex(index);
|
||||
try {
|
||||
window.getWebNavigation().gotoIndex(index);
|
||||
}
|
||||
catch (e) {} // We get NS_ERROR_FILE_NOT_FOUND if files in history don't exist
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -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>
|
||||
// Some code based on Venkman
|
||||
//
|
||||
// This work is licensed for reuse under an MIT license. Details are
|
||||
@@ -19,16 +19,15 @@ function Script(file) {
|
||||
}
|
||||
self = { __proto__: plugins };
|
||||
plugins.contexts[file.path] = self;
|
||||
plugins[file.path] = self;
|
||||
self.NAME = file.leafName.replace(/\..*/, "").replace(/-([a-z])/g, function (m, n1) n1.toUpperCase());
|
||||
self.PATH = file.path;
|
||||
self.__context__ = self;
|
||||
self.__proto__ = plugins;
|
||||
|
||||
// This belongs elsewhere
|
||||
for (let [, dir] in Iterator(io.getRuntimeDirectories("plugin"))) {
|
||||
if (dir.contains(file, false))
|
||||
plugins[self.NAME] = self;
|
||||
}
|
||||
if (io.getRuntimeDirectories("plugins").some(
|
||||
function (dir) dir.contains(file, false)))
|
||||
plugins[self.NAME] = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -54,7 +53,8 @@ const IO = Module("io", {
|
||||
let file = download.targetFile.path;
|
||||
let size = download.size;
|
||||
|
||||
dactyl.echomsg("Download of " + title + " to " + file + " finished", 1, commandline.ACTIVE_WINDOW);
|
||||
dactyl.echomsg({ domains: [util.getHost(url)], message: "Download of " + title + " to " + file + " finished" },
|
||||
1, commandline.ACTIVE_WINDOW);
|
||||
autocommands.trigger("DownloadPost", { url: url, title: title, file: file, size: size });
|
||||
}
|
||||
},
|
||||
@@ -179,8 +179,8 @@ const IO = Module("io", {
|
||||
getRCFile: function (dir, always) {
|
||||
dir = dir || "~";
|
||||
|
||||
let rcFile1 = File.joinPaths(dir, "." + config.name.toLowerCase() + "rc");
|
||||
let rcFile2 = File.joinPaths(dir, "_" + config.name.toLowerCase() + "rc");
|
||||
let rcFile1 = File.joinPaths(dir, "." + config.name + "rc");
|
||||
let rcFile2 = File.joinPaths(dir, "_" + config.name + "rc");
|
||||
|
||||
if (dactyl.has("Win32"))
|
||||
[rcFile1, rcFile2] = [rcFile2, rcFile1];
|
||||
@@ -346,6 +346,8 @@ lookup:
|
||||
dactyl.helpInitialized = false;
|
||||
}
|
||||
catch (e) {
|
||||
if (isstring(e))
|
||||
e = { message: e };
|
||||
let err = new Error();
|
||||
for (let [k, v] in Iterator(e))
|
||||
err[k] = v;
|
||||
@@ -508,10 +510,10 @@ lookup:
|
||||
* variable.
|
||||
*/
|
||||
get runtimePath() {
|
||||
const rtpvar = config.name.toUpperCase() + "_RUNTIME";
|
||||
const rtpvar = config.idname + "_RUNTIME";
|
||||
let rtp = services.get("environment").get(rtpvar);
|
||||
if (!rtp) {
|
||||
rtp = "~/" + (dactyl.has("Win32") ? "" : ".") + config.name.toLowerCase();
|
||||
rtp = "~/" + (dactyl.has("Win32") ? "" : ".") + config.name;
|
||||
services.get("environment").set(rtpvar, rtp);
|
||||
}
|
||||
return rtp;
|
||||
@@ -582,7 +584,7 @@ lookup:
|
||||
{ argCount: "0" });
|
||||
|
||||
// "mkv[imperatorrc]" or "mkm[uttatorrc]"
|
||||
commands.add([config.name.toLowerCase().replace(/(.)(.*)/, "mk$1[$2rc]")],
|
||||
commands.add([config.name.replace(/(.)(.*)/, "mk$1[$2rc]")],
|
||||
"Write current key mappings and changed options to the config file",
|
||||
function (args) {
|
||||
dactyl.assert(args.length <= 1, "E172: Only one file name allowed");
|
||||
@@ -595,7 +597,7 @@ lookup:
|
||||
|
||||
// TODO: Use a set/specifiable list here:
|
||||
let lines = [cmd.serialize().map(commands.commandToString) for (cmd in commands) if (cmd.serialize)];
|
||||
lines = util.Array.flatten(lines);
|
||||
lines = array.flatten(lines);
|
||||
|
||||
// source a user .pentadactylrc file
|
||||
lines.unshift('"' + dactyl.version + "\n");
|
||||
@@ -608,7 +610,7 @@ lookup:
|
||||
arguments: [filename + ".local"]
|
||||
}));
|
||||
|
||||
lines.push("\n\" vim: set ft=" + config.name.toLowerCase() + ":");
|
||||
lines.push("\n\" vim: set ft=" + config.name + ":");
|
||||
|
||||
try {
|
||||
file.write(lines.join("\n"));
|
||||
@@ -669,9 +671,13 @@ lookup:
|
||||
|
||||
// NOTE: Vim doesn't replace ! preceded by 2 or more backslashes and documents it - desirable?
|
||||
// pass through a raw bang when escaped or substitute the last command
|
||||
arg = arg.replace(/(\\)*!/g,
|
||||
function (m) /^\\(\\\\)*!$/.test(m) ? m.replace("\\!", "!") : m.replace("!", io._lastRunCommand)
|
||||
);
|
||||
|
||||
// This is an asinine and irritating feature when we have searchable
|
||||
// command-line history. --Kris
|
||||
if (options["banghist"])
|
||||
arg = arg.replace(/(\\)*!/g,
|
||||
function (m) /^\\(\\\\)*!$/.test(m) ? m.replace("\\!", "!") : m.replace("!", io._lastRunCommand)
|
||||
);
|
||||
|
||||
io._lastRunCommand = arg;
|
||||
|
||||
@@ -691,19 +697,20 @@ lookup:
|
||||
completion: function () {
|
||||
completion.charset = function (context) {
|
||||
context.anchored = false;
|
||||
context.generate = function () {
|
||||
let names = util.Array(
|
||||
"more1 more2 more3 more4 more5 unicode".split(" ").map(function (key)
|
||||
options.getPref("intl.charsetmenu.browser." + key).split(', '))
|
||||
).flatten().uniq();
|
||||
let bundle = document.getElementById("dactyl-charset-bundle");
|
||||
return names.map(function (name) [name, bundle.getString(name.toLowerCase() + ".title")]);
|
||||
let bundle = services.get("stringBundle").createBundle(
|
||||
"chrome://global/locale/charsetTitles.properties");
|
||||
context.keys = {
|
||||
text: util.identity,
|
||||
description: function (charset) bundle.GetStringFromName(charset.toLowerCase() + ".title")
|
||||
};
|
||||
context.generate = function () array("more1 more2 more3 more4 more5 unicode".split(" "))
|
||||
.map(function (key) options.getPref("intl.charsetmenu.browser." + key).split(', '))
|
||||
.flatten().uniq().array;
|
||||
};
|
||||
|
||||
completion.directory = function directory(context, full) {
|
||||
this.file(context, full);
|
||||
context.filters.push(function ({ item: f }) f.isDirectory());
|
||||
context.filters.push(function ({ item }) item.isDirectory());
|
||||
};
|
||||
|
||||
completion.environment = function environment(context) {
|
||||
@@ -737,7 +744,7 @@ lookup:
|
||||
|
||||
if (options["wildignore"]) {
|
||||
let wig = options.get("wildignore");
|
||||
context.filters.push(function ({item: f}) f.isDirectory() || !wig.getKey(this.name));
|
||||
context.filters.push(function ({ item }) item.isDirectory() || !wig.getKey(this.name));
|
||||
}
|
||||
|
||||
// context.background = true;
|
||||
@@ -765,7 +772,7 @@ lookup:
|
||||
}
|
||||
}
|
||||
|
||||
return util.Array.flatten(commands);
|
||||
return array.flatten(commands);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -795,6 +802,10 @@ lookup:
|
||||
shellcmdflag = "-c";
|
||||
}
|
||||
|
||||
options.add(["banghist", "bh"],
|
||||
"Replace occurances of ! with the previous command when executing external commands",
|
||||
"banghist", true);
|
||||
|
||||
options.add(["fileencoding", "fenc"],
|
||||
"Sets the character encoding of read and written files",
|
||||
"string", "UTF-8", {
|
||||
|
||||
@@ -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.
|
||||
@@ -41,11 +41,13 @@ const JavaScript = Module("javascript", {
|
||||
let seen = {};
|
||||
for (let key in properties(obj, !toplevel)) {
|
||||
set.add(seen, key);
|
||||
yield [key, this.getKey(obj, key)];
|
||||
yield key;
|
||||
}
|
||||
// Properties aren't visible in an XPCNativeWrapper until
|
||||
// they're accessed.
|
||||
for (let key in properties(this.getKey(obj, "wrappedJSObject"), !toplevel))
|
||||
if (!set.has(seen, key))
|
||||
yield [key, this.getKey(obj, key)];
|
||||
if (key in obj && !set.has(seen, key))
|
||||
yield key;
|
||||
},
|
||||
|
||||
objectKeys: function objectKeys(obj, toplevel) {
|
||||
@@ -110,15 +112,14 @@ const JavaScript = Module("javascript", {
|
||||
},
|
||||
|
||||
_pop: function pop(arg) {
|
||||
if (this._top.char != arg) {
|
||||
this.context.highlight(this._top.offset, this._i - this._top.offset, "SPELLCHECK");
|
||||
this.context.highlight(this._top.offset, 1, "FIND");
|
||||
throw new Error("Invalid JS");
|
||||
}
|
||||
|
||||
if (this._i == this.context.caret - 1)
|
||||
this.context.highlight(this._top.offset, 1, "FIND");
|
||||
|
||||
if (this._top.char != arg) {
|
||||
this.context.highlight(this._top.offset, this._i - this._top.offset, "SPELLCHECK");
|
||||
throw Error("Invalid JS");
|
||||
}
|
||||
|
||||
// The closing character of this stack frame will have pushed a new
|
||||
// statement, leaving us with an empty statement. This doesn't matter,
|
||||
// now, as we simply throw away the frame when we pop it, but it may later.
|
||||
@@ -139,11 +140,13 @@ const JavaScript = Module("javascript", {
|
||||
|
||||
// Reuse the old stack.
|
||||
if (this._str && filter.substr(0, this._str.length) == this._str) {
|
||||
this.context.highlight(0, 0, "FIND");
|
||||
this._i = this._str.length;
|
||||
if (this.popStatement)
|
||||
this._top.statements.pop();
|
||||
}
|
||||
else {
|
||||
this.context.highlight();
|
||||
this._stack = [];
|
||||
this._functions = [];
|
||||
this._push("#root");
|
||||
@@ -239,7 +242,7 @@ const JavaScript = Module("javascript", {
|
||||
_getObj: function (frame, stop) {
|
||||
let statement = this._get(frame, 0, "statements") || 0; // Current statement.
|
||||
let prev = statement;
|
||||
let obj;
|
||||
let obj = null;
|
||||
let cacheKey;
|
||||
for (let [, dot] in Iterator(this._get(frame).dots.concat(stop))) {
|
||||
if (dot < statement)
|
||||
@@ -285,19 +288,19 @@ const JavaScript = Module("javascript", {
|
||||
return [dot + 1 + space.length, obj, key];
|
||||
},
|
||||
|
||||
_fill: function (context, obj, name, compl, anchored, key, last, offset) {
|
||||
context.title = [name];
|
||||
context.anchored = anchored;
|
||||
context.filter = key;
|
||||
_fill: function (context, args) {
|
||||
context.title = [args.name];
|
||||
context.anchored = args.anchored;
|
||||
context.filter = args.filter;
|
||||
context.itemCache = context.parent.itemCache;
|
||||
context.key = name + last;
|
||||
context.key = args.name + args.last;
|
||||
|
||||
if (last != null)
|
||||
context.quote = [last, function (text) util.escapeString(text.substr(offset), ""), last];
|
||||
if (args.last != null)
|
||||
context.quote = [args.last, function (text) util.escapeString(text.substr(args.offset), ""), args.last];
|
||||
else // We're not looking for a quoted string, so filter out anything that's not a valid identifier
|
||||
context.filters.push(function (item) /^[a-zA-Z_$][\w$]*$/.test(item.text));
|
||||
|
||||
compl.call(self, context, obj);
|
||||
args.completer.call(self, context, args.obj);
|
||||
},
|
||||
|
||||
_complete: function (objects, key, compl, string, last) {
|
||||
@@ -309,7 +312,10 @@ const JavaScript = Module("javascript", {
|
||||
let orig = compl;
|
||||
if (!compl) {
|
||||
compl = function (context, obj, recurse) {
|
||||
context.process = [null, function highlight(item, v) template.highlight(typeof v == "xml" ? new String(v.toXMLString()) : v, true)];
|
||||
|
||||
context.process[1] = function highlight(item, v)
|
||||
template.highlight(typeof v == "xml" ? new String(v.toXMLString()) : v, true);
|
||||
|
||||
// Sort in a logical fashion for object keys:
|
||||
// Numbers are sorted as numbers, rather than strings, and appear first.
|
||||
// Constants are unsorted, and appear before other non-null strings.
|
||||
@@ -321,14 +327,15 @@ const JavaScript = Module("javascript", {
|
||||
return a.key - b.key;
|
||||
return isnan(b.key) - isnan(a.key) || compare(a, b);
|
||||
};
|
||||
context.keys = { text: 0, description: 1,
|
||||
context.keys = {
|
||||
text: util.identity,
|
||||
description: function (item) self.getKey(obj, item),
|
||||
key: function (item) {
|
||||
let key = item[0];
|
||||
if (!isNaN(key))
|
||||
return parseInt(key);
|
||||
else if (/^[A-Z_][A-Z0-9_]*$/.test(key))
|
||||
if (/^[A-Z_][A-Z0-9_]*$/.test(key))
|
||||
return ""
|
||||
return key;
|
||||
return item;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -339,37 +346,51 @@ const JavaScript = Module("javascript", {
|
||||
context.generate = function () self.objectKeys(obj, !recurse);
|
||||
};
|
||||
}
|
||||
|
||||
let args = {
|
||||
completer: compl,
|
||||
anchored: true,
|
||||
filter: key + (string || ""),
|
||||
last: last,
|
||||
offset: key.length
|
||||
};
|
||||
|
||||
// TODO: Make this a generic completion helper function.
|
||||
let filter = key + (string || "");
|
||||
for (let [, obj] in Iterator(objects)) {
|
||||
for (let [, obj] in Iterator(objects))
|
||||
this.context.fork(obj[1], this._top.offset, this, this._fill,
|
||||
obj[0], obj[1], compl,
|
||||
true, filter, last, key.length);
|
||||
}
|
||||
update(args, {
|
||||
obj: obj[0],
|
||||
name: obj[1],
|
||||
}));
|
||||
|
||||
if (orig)
|
||||
return;
|
||||
|
||||
for (let [, obj] in Iterator(objects)) {
|
||||
let name = obj[1] + " (prototypes)";
|
||||
this.context.fork(name, this._top.offset, this, this._fill,
|
||||
obj[0], name, function (a, b) compl(a, b, true),
|
||||
true, filter, last, key.length);
|
||||
}
|
||||
for (let [, obj] in Iterator(objects))
|
||||
this.context.fork(obj[1] + "/prototypes", this._top.offset, this, this._fill,
|
||||
update(args, {
|
||||
obj: obj[0],
|
||||
name: obj[1] + " (prototypes)",
|
||||
completer: function (a, b) compl(a, b, true)
|
||||
}));
|
||||
|
||||
for (let [, obj] in Iterator(objects)) {
|
||||
let name = obj[1] + " (substrings)";
|
||||
this.context.fork(name, this._top.offset, this, this._fill,
|
||||
obj[0], name, compl,
|
||||
false, filter, last, key.length);
|
||||
}
|
||||
for (let [, obj] in Iterator(objects))
|
||||
this.context.fork(obj[1] + "/substrings", this._top.offset, this, this._fill,
|
||||
update(args, {
|
||||
obj: obj[0],
|
||||
name: obj[1] + " (substrings)",
|
||||
anchored: false,
|
||||
completer: compl
|
||||
}));
|
||||
|
||||
for (let [, obj] in Iterator(objects)) {
|
||||
let name = obj[1] + " (prototype substrings)";
|
||||
this.context.fork(name, this._top.offset, this, this._fill,
|
||||
obj[0], name, function (a, b) compl(a, b, true),
|
||||
false, filter, last, key.length);
|
||||
}
|
||||
for (let [, obj] in Iterator(objects))
|
||||
this.context.fork(obj[1] + "/prototypes/substrings", this._top.offset, this, this._fill,
|
||||
update(args, {
|
||||
obj: obj[0],
|
||||
name: obj[1] + " (prototype substrings)",
|
||||
anchored: false,
|
||||
completer: function (a, b) compl(a, b, true)
|
||||
}));
|
||||
},
|
||||
|
||||
_getKey: function () {
|
||||
@@ -398,7 +419,7 @@ const JavaScript = Module("javascript", {
|
||||
}
|
||||
|
||||
this.context.getCache("evalled", Object);
|
||||
this.context.getCache("evalContext", function () ({ __proto__: userContext }));;
|
||||
this.context.getCache("evalContext", function () ({ __proto__: userContext }));
|
||||
|
||||
// Okay, have parse stack. Figure out what we're completing.
|
||||
|
||||
@@ -478,7 +499,7 @@ const JavaScript = Module("javascript", {
|
||||
for (let [i, idx] in Iterator(this._get(-2).comma)) {
|
||||
let arg = this._str.substring(prev + 1, idx);
|
||||
prev = idx;
|
||||
util.memoize(args, i, function () self.evalled(arg));
|
||||
memoize(args, i, function () self.evalled(arg));
|
||||
}
|
||||
let key = this._getKey();
|
||||
args.push(key + string);
|
||||
|
||||
@@ -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 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.
|
||||
@@ -383,7 +383,7 @@ const Mappings = Module("mappings", {
|
||||
let [lhs, rhs] = args;
|
||||
|
||||
if (!rhs) // list the mapping
|
||||
mappings.list(modes, this._expandLeader(lhs));
|
||||
mappings.list(modes, mappings._expandLeader(lhs));
|
||||
else {
|
||||
// this matches Vim's behaviour
|
||||
if (/^<Nop>$/i.test(rhs))
|
||||
@@ -467,7 +467,7 @@ const Mappings = Module("mappings", {
|
||||
addMapCommands("", [modes.NORMAL, modes.VISUAL], "");
|
||||
|
||||
for (let mode in modes.mainModes)
|
||||
if (mode.char && !commands.get(mode.char + "map"))
|
||||
if (mode.char && !commands.get(mode.char + "map", true))
|
||||
addMapCommands(mode.char,
|
||||
[m.mask for (m in modes.mainModes) if (m.char == mode.char)],
|
||||
[mode.disp.toLowerCase()]);
|
||||
@@ -489,8 +489,7 @@ const Mappings = Module("mappings", {
|
||||
null,
|
||||
function (context, obj, args) {
|
||||
let mode = args[0];
|
||||
return util.Array.flatten(
|
||||
[
|
||||
return array.flatten([
|
||||
[[name, map.description] for ([i, name] in Iterator(map.names))]
|
||||
for ([i, map] in Iterator(mappings._user[mode].concat(mappings._main[mode])))
|
||||
]);
|
||||
|
||||
@@ -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.
|
||||
@@ -17,7 +17,7 @@ const Marks = Module("marks", {
|
||||
this._urlMarks = storage.newMap("url-marks", { privateData: true, replacer: replacer, store: true });
|
||||
|
||||
try {
|
||||
if(isarray(Iterator(this._localMarks).next()));
|
||||
if(isarray(Iterator(this._localMarks).next()[1]))
|
||||
this._localMarks.clear();
|
||||
}
|
||||
catch(e) {}
|
||||
@@ -31,7 +31,7 @@ const Marks = Module("marks", {
|
||||
*/
|
||||
get all() {
|
||||
let lmarks = array(Iterator(this._localMarks.get(this.localURI) || {}));
|
||||
let umarks = array(Iterator(this._urlMarks)).__proto__;
|
||||
let umarks = array(Iterator(this._urlMarks)).array;
|
||||
|
||||
return lmarks.concat(umarks).sort(function (a, b) String.localeCompare(a[0], b[0]));
|
||||
},
|
||||
@@ -54,9 +54,7 @@ const Marks = Module("marks", {
|
||||
let win = window.content;
|
||||
let doc = win.document;
|
||||
|
||||
if (!doc.body)
|
||||
return;
|
||||
if (doc.body instanceof HTMLFrameSetElement) {
|
||||
if (doc.body && doc.body instanceof HTMLFrameSetElement) {
|
||||
if (!silent)
|
||||
dactyl.echoerr("Marks support for frameset pages not implemented yet");
|
||||
return;
|
||||
@@ -72,8 +70,8 @@ const Marks = Module("marks", {
|
||||
dactyl.log("Adding URL mark: " + Marks.markToString(mark, res), 5);
|
||||
}
|
||||
else if (Marks.isLocalMark(mark)) {
|
||||
let marks = this._localMarks.get(doc.URL, {});
|
||||
marks[mark] = { location: doc.URL, position: position, timestamp: Date.now()*1000 };
|
||||
let marks = this._localMarks.get(doc.documentURI, {});
|
||||
marks[mark] = { location: doc.documentURI, position: position, timestamp: Date.now()*1000 };
|
||||
this._localMarks.changed();
|
||||
if (!silent)
|
||||
dactyl.log("Adding local mark: " + Marks.markToString(mark, marks[mark]), 5);
|
||||
@@ -237,7 +235,7 @@ const Marks = Module("marks", {
|
||||
// NOTE: this currently differs from Vim's behavior which
|
||||
// deletes any valid marks in the arg list, up to the first
|
||||
// invalid arg, as well as giving the error message.
|
||||
dactyl.assert(!matches, "E475: Invalid argument: " + matches[0]);
|
||||
dactyl.assert(!matches, "E475: Invalid argument: " + (matches && matches[0]));
|
||||
|
||||
// check for illegal ranges - only allow a-z A-Z 0-9
|
||||
if ((matches = args.match(/[a-zA-Z0-9]-[a-zA-Z0-9]/g))) {
|
||||
|
||||
@@ -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.
|
||||
@@ -120,7 +120,7 @@ const Modes = Module("modes", {
|
||||
|
||||
NONE: 0,
|
||||
|
||||
__iterator__: function () util.Array.itervalues(this.all),
|
||||
__iterator__: function () array.itervalues(this.all),
|
||||
|
||||
get all() this._mainModes.slice(),
|
||||
|
||||
@@ -155,7 +155,8 @@ const Modes = Module("modes", {
|
||||
|
||||
getCharModes: function (chr) [m for (m in values(this._modeMap)) if (m.char == chr)],
|
||||
|
||||
matchModes: function (obj) [m for (m in values(this._modeMap)) if (Object.keys(obj).every(function (k) obj[k] == (m[k] || false)))],
|
||||
matchModes: function (obj)
|
||||
[m for (m in values(this._modeMap)) if (Object.keys(obj).every(function (k) obj[k] == (m[k] || false)))],
|
||||
|
||||
// show the current mode string in the command line
|
||||
show: function () {
|
||||
|
||||
@@ -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.
|
||||
@@ -15,7 +15,7 @@ const ModuleBase = Class("ModuleBase", {
|
||||
*/
|
||||
requires: [],
|
||||
|
||||
toString: function () "[module " + this.constructor.name + "]"
|
||||
toString: function () "[module " + this.constructor.classname + "]"
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -76,26 +76,29 @@ window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad, false);
|
||||
|
||||
Module.list.forEach(function(module) {
|
||||
modules.__defineGetter__(module.name, function() {
|
||||
delete modules[module.name];
|
||||
return load(module.name, null, Components.stack.caller);
|
||||
modules.__defineGetter__(module.classname, function() {
|
||||
delete modules[module.classname];
|
||||
return load(module.classname, null, Components.stack.caller);
|
||||
});
|
||||
});
|
||||
|
||||
function dump(str) window.dump(String.replace(str, /\n?$/, "\n").replace(/^/m, Config.prototype.name.toLowerCase() + ": "));
|
||||
function dump(str) window.dump(String.replace(str, /\n?$/, "\n").replace(/^/m, services.get("dactyl:").name + ": "));
|
||||
const start = Date.now();
|
||||
const deferredInit = { load: [] };
|
||||
const seen = set();
|
||||
const loaded = set(["init"]);
|
||||
modules.loaded = loaded;
|
||||
|
||||
function init(module) {
|
||||
function init(func, mod)
|
||||
function () defmodule.time(module.name || module.constructor.name, mod, func, module, dactyl, modules, window);
|
||||
function () defmodule.time(module.classname || module.constructor.classname, mod,
|
||||
func, module,
|
||||
dactyl, modules, window);
|
||||
|
||||
set.add(loaded, module.constructor.name);
|
||||
set.add(loaded, module.constructor.classname);
|
||||
for (let [mod, func] in Iterator(module.INIT)) {
|
||||
if (mod in loaded)
|
||||
init(func)();
|
||||
init(func, mod)();
|
||||
else {
|
||||
deferredInit[mod] = deferredInit[mod] || [];
|
||||
deferredInit[mod].push(init(func, mod));
|
||||
@@ -112,34 +115,35 @@ window.addEventListener("load", function onLoad() {
|
||||
}
|
||||
|
||||
try {
|
||||
if (module.name in loaded)
|
||||
if (module.classname in loaded)
|
||||
return;
|
||||
if (module.name in seen)
|
||||
if (module.classname in seen)
|
||||
throw Error("Module dependency loop.");
|
||||
set.add(seen, module.name);
|
||||
set.add(seen, module.classname);
|
||||
|
||||
for (let dep in values(module.requires))
|
||||
load(Module.constructors[dep], module.name);
|
||||
load(Module.constructors[dep], module.classname);
|
||||
|
||||
defmodule.loadLog.push("Load" + (isstring(prereq) ? " " + prereq + " dependency: " : ": ") + module.name);
|
||||
defmodule.loadLog.push("Load" + (isstring(prereq) ? " " + prereq + " dependency: " : ": ") + module.classname);
|
||||
if (frame && frame.filename)
|
||||
defmodule.loadLog.push(" from: " + frame.filename + ":" + frame.lineNumber);
|
||||
|
||||
delete modules[module.name];
|
||||
modules[module.name] = defmodule.time(module.name, "init", module);
|
||||
delete modules[module.classname];
|
||||
modules[module.classname] = defmodule.time(module.classname, "init", module);
|
||||
|
||||
init(modules[module.name]);
|
||||
for (let [, fn] in iter(deferredInit[module.name] || []))
|
||||
init(modules[module.classname]);
|
||||
for (let [, fn] in iter(deferredInit[module.classname] || []))
|
||||
fn();
|
||||
}
|
||||
catch (e) {
|
||||
dump("Loading " + (module && module.name) + ": " + e + "\n" + (e.stack || ""));
|
||||
dump("Loading " + (module && module.classname) + ": " + e + "\n" + (e.stack || ""));
|
||||
}
|
||||
return modules[module.name];
|
||||
return modules[module.classname];
|
||||
}
|
||||
|
||||
Module.list.forEach(load);
|
||||
deferredInit["load"].forEach(call);
|
||||
modules.times = update({}, defmodule.times);
|
||||
|
||||
dump("Loaded in " + (Date.now() - start) + "ms");
|
||||
}, false);
|
||||
|
||||
@@ -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.
|
||||
@@ -23,6 +23,8 @@
|
||||
* completer - see {@link Option#completer}
|
||||
* domains - see {@link Option#domains}
|
||||
* getter - see {@link Option#getter}
|
||||
* initialValue - Initial value is loaded from getter
|
||||
* persist - see {@link Option#persist}
|
||||
* privateData - see {@link Option#privateData}
|
||||
* scope - see {@link Option#scope}
|
||||
* setter - see {@link Option#setter}
|
||||
@@ -56,9 +58,9 @@ const Option = Class("Option", {
|
||||
|
||||
// add no{option} variant of boolean {option} to this.names
|
||||
if (this.type == "boolean")
|
||||
this.names = array([name, "no" + name] for (name in values(names))).flatten().__proto__;
|
||||
this.names = array([name, "no" + name] for (name in values(names))).flatten().array;
|
||||
|
||||
if (this.globalValue == undefined)
|
||||
if (this.globalValue == undefined && !this.initialValue)
|
||||
this.globalValue = this.parseValues(this.defaultValue);
|
||||
},
|
||||
|
||||
@@ -295,6 +297,13 @@ const Option = Class("Option", {
|
||||
*/
|
||||
getter: null,
|
||||
|
||||
/**
|
||||
* @property {boolean} When true, this options values will be saved
|
||||
* when generating a configuration file.
|
||||
* @default true
|
||||
*/
|
||||
persist: true,
|
||||
|
||||
/**
|
||||
* @property {boolean|function(values)} When true, values of this
|
||||
* option may contain private data which should be purged from
|
||||
@@ -363,18 +372,23 @@ const Option = Class("Option", {
|
||||
let re = RegExp(val);
|
||||
re.bang = bang;
|
||||
re.result = arguments.length == 2 ? result : !bang;
|
||||
re.toString = function () Option.unparseRegex(this);
|
||||
return re;
|
||||
},
|
||||
unparseRegex: function (re) re.bang + re.source + (typeof re.result == "string" ? ":" + re.result : ""),
|
||||
unparseRegex: function (re) re.bang + re.source.replace(/\\(.)/g, function (m, n1) n1 == "/" ? n1 : m) +
|
||||
(typeof re.result == "string" ? ":" + re.result : ""),
|
||||
|
||||
getKey: {
|
||||
stringlist: function (k) this.values.indexOf(k) >= 0,
|
||||
get charlist() this.stringlist,
|
||||
|
||||
regexlist: function (k) {
|
||||
for (let re in values(this.values))
|
||||
if (re.test(k))
|
||||
return re.result;
|
||||
return null;
|
||||
}
|
||||
},
|
||||
get regexmap() this.regexlist
|
||||
},
|
||||
|
||||
joinValues: {
|
||||
@@ -382,6 +396,7 @@ const Option = Class("Option", {
|
||||
stringlist: function (vals) vals.join(","),
|
||||
stringmap: function (vals) [k + ":" + v for ([k, v] in Iterator(vals))].join(","),
|
||||
regexlist: function (vals) vals.map(Option.unparseRegex).join(","),
|
||||
get regexmap() this.regexlist
|
||||
},
|
||||
|
||||
parseValues: {
|
||||
@@ -430,10 +445,10 @@ const Option = Class("Option", {
|
||||
|
||||
switch (operator) {
|
||||
case "+":
|
||||
return util.Array.uniq(Array.concat(orig, values), true);
|
||||
return array.uniq(Array.concat(orig, values), true);
|
||||
case "^":
|
||||
// NOTE: Vim doesn't prepend if there's a match in the current value
|
||||
return util.Array.uniq(Array.concat(values, orig), true);
|
||||
return array.uniq(Array.concat(values, orig), true);
|
||||
case "-":
|
||||
return orig.filter(function (item) values.indexOf(item) == -1);
|
||||
case "=":
|
||||
@@ -452,10 +467,10 @@ const Option = Class("Option", {
|
||||
values = Array.concat(values);
|
||||
switch (operator) {
|
||||
case "+":
|
||||
return util.Array.uniq(Array.concat(this.values, values), true);
|
||||
return array.uniq(Array.concat(this.values, values), true);
|
||||
case "^":
|
||||
// NOTE: Vim doesn't prepend if there's a match in the current value
|
||||
return util.Array.uniq(Array.concat(values, this.values), true);
|
||||
return array.uniq(Array.concat(values, this.values), true);
|
||||
case "-":
|
||||
return this.values.filter(function (item) values.indexOf(item) == -1);
|
||||
case "=":
|
||||
@@ -468,6 +483,9 @@ const Option = Class("Option", {
|
||||
}
|
||||
return null;
|
||||
},
|
||||
get charlist() this.stringlist,
|
||||
get regexlist() this.stringlist,
|
||||
get regexmap() this.stringlist,
|
||||
|
||||
string: function (operator, values, scope, invert) {
|
||||
switch (operator) {
|
||||
@@ -503,21 +521,14 @@ const Option = Class("Option", {
|
||||
}
|
||||
});
|
||||
|
||||
Option.joinValues["regexmap"] = Option.joinValues["regexlist"];
|
||||
|
||||
Option.getKey["charlist"] = Option.getKey["stringlist"];
|
||||
Option.getKey["regexmap"] = Option.getKey["regexlist"];
|
||||
|
||||
Option.ops["charlist"] = Option.ops["stringlist"];
|
||||
Option.ops["regexlist"] = Option.ops["stringlist"];
|
||||
Option.ops["regexmap"] = Option.ops["stringlist"];
|
||||
|
||||
/**
|
||||
* @instance options
|
||||
*/
|
||||
const Options = Module("options", {
|
||||
init: function () {
|
||||
this._optionHash = {};
|
||||
this.needInit = [];
|
||||
this._options = [];
|
||||
this._optionMap = {};
|
||||
this._prefContexts = [];
|
||||
|
||||
for (let [, pref] in Iterator(this.allPrefs(Options.OLD_SAVED))) {
|
||||
@@ -541,45 +552,28 @@ const Options = Module("options", {
|
||||
});
|
||||
}
|
||||
|
||||
function optionObserver(key, event, option) {
|
||||
storage.newMap("options", { store: false });
|
||||
storage.addObserver("options", function optionObserver(key, event, option) {
|
||||
// Trigger any setters.
|
||||
let opt = options.get(option);
|
||||
if (event == "change" && opt)
|
||||
opt.setValues(opt.globalValue, Option.SCOPE_GLOBAL, true);
|
||||
}
|
||||
}, window);
|
||||
|
||||
storage.newMap("options", { store: false });
|
||||
storage.addObserver("options", optionObserver, window);
|
||||
|
||||
this.prefObserver.register();
|
||||
this._branch = services.get("pref").getBranch("").QueryInterface(Ci.nsIPrefBranch2);
|
||||
this._branch.addObserver("", this, false);
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.prefObserver.unregister();
|
||||
this._branch.removeObserver("", this);
|
||||
},
|
||||
|
||||
/** @property {Iterator(Option)} @private */
|
||||
__iterator__: function ()
|
||||
array(values(this._optionHash)).sort(function (a, b) String.localeCompare(a.name, b.name))
|
||||
.itervalues(),
|
||||
|
||||
/** @property {Object} Observes preference value changes. */
|
||||
prefObserver: {
|
||||
register: function () {
|
||||
// better way to monitor all changes?
|
||||
this._branch = services.get("pref").getBranch("").QueryInterface(Ci.nsIPrefBranch2);
|
||||
this._branch.addObserver("", this, false);
|
||||
},
|
||||
|
||||
unregister: function () {
|
||||
if (this._branch)
|
||||
this._branch.removeObserver("", this);
|
||||
},
|
||||
|
||||
observe: function (subject, topic, data) {
|
||||
if (topic != "nsPref:changed")
|
||||
return;
|
||||
values(this._options.sort(function (a, b) String.localeCompare(a.name, b.name))),
|
||||
|
||||
observe: function (subject, topic, data) {
|
||||
if (topic == "nsPref:changed") {
|
||||
// subject is the nsIPrefBranch we're observing (after appropriate QI)
|
||||
// data is the name of the pref that's been changed (relative to subject)
|
||||
switch (data) {
|
||||
@@ -588,7 +582,7 @@ const Options = Module("options", {
|
||||
dactyl.mode = value ? modes.CARET : modes.NORMAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -601,29 +595,28 @@ const Options = Module("options", {
|
||||
* @param {Object} extra An optional extra configuration hash (see
|
||||
* {@link Map#extraInfo}).
|
||||
* @optional
|
||||
* @returns {boolean} Whether the option was created.
|
||||
*/
|
||||
add: function (names, description, type, defaultValue, extraInfo) {
|
||||
if (!extraInfo)
|
||||
extraInfo = {};
|
||||
|
||||
let option = Option(names, description, type, defaultValue, extraInfo);
|
||||
|
||||
if (!option)
|
||||
return false;
|
||||
|
||||
if (option.name in this._optionHash) {
|
||||
// never replace for now
|
||||
dactyl.log("Warning: " + names[0].quote() + " already exists, NOT replacing existing option.", 1);
|
||||
return false;
|
||||
let name = names[0];
|
||||
if (name in this._optionMap) {
|
||||
dactyl.log("Warning: " + name.quote() + " already exists: replacing existing option.", 1);
|
||||
this.remove(name);
|
||||
}
|
||||
|
||||
// quickly access options with options["wildmode"]:
|
||||
this.__defineGetter__(option.name, function () option.value);
|
||||
this.__defineSetter__(option.name, function (value) { option.value = value; });
|
||||
let closure = function () options._optionMap[name];
|
||||
memoize(this._options, this._options.length, closure);
|
||||
memoize(this._optionMap, name, function () Option(names, description, type, defaultValue, extraInfo));
|
||||
for (let alias in values(names.slice(1)))
|
||||
memoize(this._optionMap, alias, closure);
|
||||
if (extraInfo.setter)
|
||||
memoize(this.needInit, this.needInit.length, closure);
|
||||
|
||||
this._optionHash[option.name] = option;
|
||||
return true;
|
||||
// quickly access options with options["wildmode"]:
|
||||
this.__defineGetter__(name, function () this._optionMap[name].value);
|
||||
this.__defineSetter__(name, function (value) { this._optionMap[name].value = value; });
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -646,12 +639,8 @@ const Options = Module("options", {
|
||||
if (!scope)
|
||||
scope = Option.SCOPE_BOTH;
|
||||
|
||||
if (name in this._optionHash)
|
||||
return (this._optionHash[name].scope & scope) && this._optionHash[name];
|
||||
|
||||
for (let opt in values(this._optionHash))
|
||||
if (opt.hasName(name))
|
||||
return (opt.scope & scope) && opt;
|
||||
if (name in this._optionMap && (this._optionMap[name].scope & scope))
|
||||
return this._optionMap[name];
|
||||
return null;
|
||||
},
|
||||
|
||||
@@ -734,7 +723,7 @@ const Options = Module("options", {
|
||||
};
|
||||
|
||||
commandline.commandOutput(
|
||||
template.options(config.hostApplication + " Options", prefs()));
|
||||
template.options(config.host + " Options", prefs()));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -751,7 +740,7 @@ const Options = Module("options", {
|
||||
let matches, prefix, postfix, valueGiven;
|
||||
|
||||
[matches, prefix, ret.name, postfix, valueGiven, ret.operator, ret.value] =
|
||||
args.match(/^\s*(no|inv)?([a-z_]*)([?&!])?\s*(([-+^]?)=(.*))?\s*$/) || [];
|
||||
args.match(/^\s*(no|inv)?([a-z_-]*?)([?&!])?\s*(([-+^]?)=(.*))?\s*$/) || [];
|
||||
|
||||
ret.args = args;
|
||||
ret.onlyNonDefault = false; // used for :set to print non-default options
|
||||
@@ -760,8 +749,13 @@ const Options = Module("options", {
|
||||
ret.onlyNonDefault = true;
|
||||
}
|
||||
|
||||
if (matches)
|
||||
if (matches) {
|
||||
ret.option = options.get(ret.name, ret.scope);
|
||||
if (!ret.option && (ret.option = options.get(prefix + ret.name, ret.scope))) {
|
||||
ret.name = prefix + ret.name;
|
||||
prefix = "";
|
||||
}
|
||||
}
|
||||
|
||||
ret.prefix = prefix;
|
||||
ret.postfix = postfix;
|
||||
@@ -795,10 +789,10 @@ const Options = Module("options", {
|
||||
* any of the options's names.
|
||||
*/
|
||||
remove: function (name) {
|
||||
for each (let option in this._optionHash) {
|
||||
if (option.hasName(name))
|
||||
delete this._optionHash[option.name];
|
||||
}
|
||||
let opt = this.get(name);
|
||||
for (let name in values(opt.names))
|
||||
delete this._optionMap[name];
|
||||
this._options = this._options.filter(function (o) o != opt);
|
||||
},
|
||||
|
||||
/** @property {Object} The options store. */
|
||||
@@ -1023,7 +1017,7 @@ const Options = Module("options", {
|
||||
}
|
||||
|
||||
if (name == "all" && reset)
|
||||
commandline.input("Warning: Resetting all preferences may make " + config.hostApplication + " unusable. Continue (yes/[no]): ",
|
||||
commandline.input("Warning: Resetting all preferences may make " + config.host + " unusable. Continue (yes/[no]): ",
|
||||
function (resp) {
|
||||
if (resp == "yes")
|
||||
for (let pref in values(options.allPrefs()))
|
||||
@@ -1037,20 +1031,14 @@ const Options = Module("options", {
|
||||
else if (invertBoolean)
|
||||
options.invertPref(name);
|
||||
else if (valueGiven) {
|
||||
switch (value) {
|
||||
case undefined:
|
||||
if (value == undefined)
|
||||
value = "";
|
||||
break;
|
||||
case "true":
|
||||
else if (value == "true")
|
||||
value = true;
|
||||
break;
|
||||
case "false":
|
||||
value = false;
|
||||
break;
|
||||
default:
|
||||
if (/^\d+$/.test(value))
|
||||
value = parseInt(value, 10);
|
||||
}
|
||||
else if (value == "false")
|
||||
value = true;
|
||||
else if (/^\d+$/.test(value))
|
||||
value = parseInt(value, 10);
|
||||
options.setPref(name, value);
|
||||
}
|
||||
else
|
||||
@@ -1123,7 +1111,7 @@ const Options = Module("options", {
|
||||
context.completions = [
|
||||
[options._loadPreference(filter, null, false), "Current Value"],
|
||||
[options._loadPreference(filter, null, true), "Default Value"]
|
||||
].filter(function ([k]) k != null);
|
||||
].filter(function ([k]) k != null && k.length < 200);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1134,15 +1122,10 @@ const Options = Module("options", {
|
||||
let prefix = opt.prefix;
|
||||
|
||||
if (context.filter.indexOf("=") == -1) {
|
||||
if (prefix)
|
||||
context.filters.push(function ({ item: opt }) opt.type == "boolean" || prefix == "inv" && opt.values instanceof Array);
|
||||
return completion.option(context, opt.scope);
|
||||
if (false && prefix)
|
||||
context.filters.push(function ({ item }) item.type == "boolean" || prefix == "inv" && isarray(item.values));
|
||||
return completion.option(context, opt.scope, prefix);
|
||||
}
|
||||
else if (prefix == "no")
|
||||
return null;
|
||||
|
||||
if (prefix)
|
||||
context.advance(prefix.length);
|
||||
|
||||
let option = opt.option;
|
||||
context.advance(context.filter.indexOf("=") + 1);
|
||||
@@ -1155,17 +1138,33 @@ const Options = Module("options", {
|
||||
if (opt.get || opt.reset || !option || prefix)
|
||||
return null;
|
||||
|
||||
if (!opt.value) {
|
||||
if (!opt.value && !opt.operator && !opt.invert) {
|
||||
context.fork("default", 0, this, function (context) {
|
||||
context.title = ["Extra Completions"];
|
||||
context.completions = [
|
||||
[option.value, "Current value"],
|
||||
[option.defaultValue, "Default value"]
|
||||
].filter(function (f) f[0] != "");
|
||||
].filter(function (f) f[0] != "" && f[0].length < 200);
|
||||
});
|
||||
}
|
||||
|
||||
return context.fork("values", 0, completion, "optionValue", opt.name, opt.operator);
|
||||
let optcontext = context.fork("values");
|
||||
completion.optionValue(optcontext, opt.name, opt.operator);
|
||||
|
||||
// Fill in the current values if we're removing
|
||||
if (opt.operator == "-" && isarray(opt.values)) {
|
||||
let have = set([i.text for (i in context.allItems)]);
|
||||
context = context.fork("current-values", 0);
|
||||
context.anchored = optcontext.anchored
|
||||
context.maxItems = optcontext.maxItems
|
||||
|
||||
context.filters.push(function (i) !set.has(have, i.text));
|
||||
completion.optionValue(context, opt.name, opt.operator, null,
|
||||
function (context) {
|
||||
context.generate = function () option.values.map(function (o) [o, ""])
|
||||
});
|
||||
context.title = ["Current values"];
|
||||
}
|
||||
}
|
||||
|
||||
commands.add(["let"],
|
||||
@@ -1321,17 +1320,21 @@ const Options = Module("options", {
|
||||
});
|
||||
},
|
||||
completion: function () {
|
||||
completion.option = function option(context, scope) {
|
||||
completion.option = function option(context, scope, prefix) {
|
||||
context.title = ["Option"];
|
||||
context.keys = { text: "names", description: "description" };
|
||||
context.completions = options;
|
||||
if (prefix == "inv")
|
||||
context.keys.text = function (opt)
|
||||
opt.type == "boolean" || isarray(opt.values) ? opt.names.map(function (n) "inv" + n)
|
||||
: opt.names;
|
||||
if (scope)
|
||||
context.filters.push(function ({ item: opt }) opt.scope & scope);
|
||||
context.filters.push(function ({ item }) item.scope & scope);
|
||||
};
|
||||
|
||||
completion.optionValue = function (context, name, op, curValue) {
|
||||
completion.optionValue = function (context, name, op, curValue, completer) {
|
||||
let opt = options.get(name);
|
||||
let completer = opt.completer;
|
||||
completer = completer || opt.completer;
|
||||
if (!completer)
|
||||
return;
|
||||
|
||||
@@ -1372,31 +1375,24 @@ const Options = Module("options", {
|
||||
context.advance(context.filter.length - len);
|
||||
|
||||
context.title = ["Option Value"];
|
||||
let completions = completer(context);
|
||||
if (!isarray(completions))
|
||||
completions = array(completions).__proto__;
|
||||
if (!completions)
|
||||
return;
|
||||
|
||||
// Not Vim compatible, but is a significant enough improvement
|
||||
// that it's worth breaking compatibility.
|
||||
if (isarray(newValues)) {
|
||||
completions = completions.filter(function (val) newValues.indexOf(val[0]) == -1);
|
||||
switch (op) {
|
||||
case "+":
|
||||
completions = completions.filter(function (val) curValues.indexOf(val[0]) == -1);
|
||||
break;
|
||||
case "-":
|
||||
completions = completions.filter(function (val) curValues.indexOf(val[0]) > -1);
|
||||
break;
|
||||
}
|
||||
context.filters.push(function (i) newValues.indexOf(i.text) == -1);
|
||||
if (op == "+")
|
||||
context.filters.push(function (i) curValues.indexOf(i.text) == -1);
|
||||
if (op == "-")
|
||||
context.filters.push(function (i) curValues.indexOf(i.text) > -1);
|
||||
}
|
||||
context.completions = completions;
|
||||
|
||||
let res = completer.call(opt, context);
|
||||
if (res)
|
||||
context.completions = res;
|
||||
};
|
||||
|
||||
completion.preference = function preference(context) {
|
||||
context.anchored = false;
|
||||
context.title = [config.hostApplication + " Preference", "Value"];
|
||||
context.title = [config.host + " Preference", "Value"];
|
||||
context.keys = { text: function (item) item, description: function (item) options.getPref(item) };
|
||||
context.completions = options.allPrefs();
|
||||
};
|
||||
@@ -1404,14 +1400,14 @@ const Options = Module("options", {
|
||||
javascript: function () {
|
||||
JavaScript.setCompleter(this.get, [function () ([o.name, o.description] for (o in options))]);
|
||||
JavaScript.setCompleter([this.getPref, this.safeSetPref, this.setPref, this.resetPref, this.invertPref],
|
||||
[function () options.allPrefs().map(function (pref) [pref, ""])]);
|
||||
[function (context) (context.anchored=false, options.allPrefs().map(function (pref) [pref, ""]))]);
|
||||
},
|
||||
sanitizer: function () {
|
||||
sanitizer.addItem("options", {
|
||||
description: "Options containing hostname data",
|
||||
action: function (timespan, host) {
|
||||
if (host)
|
||||
for (let opt in values(options._optionHash))
|
||||
for (let opt in values(options._options))
|
||||
if (timespan.contains(opt.lastSet * 1000) && opt.domains)
|
||||
try {
|
||||
opt.values = opt.filterDomain(host, opt.values);
|
||||
@@ -1421,12 +1417,12 @@ const Options = Module("options", {
|
||||
}
|
||||
},
|
||||
privateEnter: function () {
|
||||
for (let opt in values(options._optionHash))
|
||||
for (let opt in values(options._options))
|
||||
if (opt.privateData && (!callable(opt.privateData) || opt.privateData(opt.values)))
|
||||
opt.oldValue = opt.value;
|
||||
},
|
||||
privateLeave: function () {
|
||||
for (let opt in values(options._optionHash))
|
||||
for (let opt in values(options._options))
|
||||
if (opt.oldValue != null) {
|
||||
opt.value = opt.oldValue;
|
||||
opt.oldValue = null;
|
||||
|
||||
@@ -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.
|
||||
@@ -26,7 +26,7 @@ const QuickMarks = Module("quickmarks", {
|
||||
*/
|
||||
add: function add(qmark, location) {
|
||||
this._qmarks.set(qmark, location);
|
||||
dactyl.echomsg("Added Quick Mark '" + qmark + "': " + location, 1);
|
||||
dactyl.echomsg({ domains: [util.getHost(location)], message: "Added Quick Mark '" + qmark + "': " + location }, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
@@ -14,8 +14,9 @@ const StatusLine = Module("statusline", {
|
||||
this._statusBar.collapsed = true; // it is later restored unless the user sets laststatus=0
|
||||
|
||||
// our status bar fields
|
||||
this.widgets = dict(["status", "url", "inputbuffer", "progress", "tabcount", "bufferposition", "zoomlevel"].map(
|
||||
function (field) [field, document.getElementById("dactyl-statusline-field-" + field)]));
|
||||
this.widgets = array(["status", "url", "inputbuffer", "progress", "tabcount", "bufferposition", "zoomlevel"]
|
||||
.map(function (field) [field, document.getElementById("dactyl-statusline-field-" + field)]))
|
||||
.toObject();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -36,7 +37,7 @@ const StatusLine = Module("statusline", {
|
||||
insecure: "StatusLine"
|
||||
};
|
||||
|
||||
this._statusBar.setAttributeNS(NS.uri, "highlight", highlightGroup[type]);
|
||||
highlight.highlightNode(this._statusBar, highlightGroup[type]);
|
||||
},
|
||||
|
||||
// update all fields of the statusline
|
||||
@@ -115,8 +116,8 @@ const StatusLine = Module("statusline", {
|
||||
}
|
||||
if (modules.bookmarks) {
|
||||
if (bookmarks.isBookmarked(buffer.URL))
|
||||
modified += "\u2764"; // a heart symbol: ❤
|
||||
//modified += "\u2665"; // a heart symbol: ♥
|
||||
modified += UTF8("❤");
|
||||
//modified += UTF8("♥");
|
||||
}
|
||||
|
||||
if (modified)
|
||||
@@ -206,7 +207,9 @@ const StatusLine = Module("statusline", {
|
||||
let win = document.commandDispatcher.focusedWindow;
|
||||
if (!win)
|
||||
return;
|
||||
percent = win.scrollMaxY == 0 ? -1 : win.scrollY / win.scrollMaxY;
|
||||
win.scrollY;
|
||||
percent = win.scrollY == 0 ? 0 : // This prevents a forced rendering
|
||||
win.scrollMaxY == 0 ? -1 : win.scrollY / win.scrollMaxY;
|
||||
}
|
||||
|
||||
let bufferPositionStr = "";
|
||||
@@ -255,11 +258,11 @@ const StatusLine = Module("statusline", {
|
||||
{
|
||||
setter: function setter(value) {
|
||||
if (value == 0)
|
||||
document.getElementById("status-bar").collapsed = true;
|
||||
statusline._statusBar.collapsed = true;
|
||||
else if (value == 1)
|
||||
dactyl.echoerr("show status line only with > 1 window not implemented yet");
|
||||
else
|
||||
document.getElementById("status-bar").collapsed = false;
|
||||
statusline._statusBar.collapsed = false;
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
@@ -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 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.
|
||||
@@ -21,6 +21,13 @@ const Tabs = Module("tabs", {
|
||||
this._lastBufferSwitchArgs = "";
|
||||
this._lastBufferSwitchSpecial = true;
|
||||
|
||||
let fragment = dactyl.has("MacUnix") ? "tab-mac" : "tab";
|
||||
this.tabBinding = styles.addSheet(true, "tab-binding", "chrome://browser/content/browser.xul",
|
||||
".tabbrowser-tab { -moz-binding: url(chrome://dactyl/content/bindings.xml#" + fragment + ") !important; }" +
|
||||
// FIXME: better solution for themes?
|
||||
".tabbrowser-tab[busy] > .tab-icon > .tab-icon-image { list-style-image: url('chrome://global/skin/icons/loading_16.png') !important; }",
|
||||
false, true);
|
||||
|
||||
// hide tabs initially to prevent flickering when 'stal' would hide them
|
||||
// on startup
|
||||
if (config.hasTabbrowser)
|
||||
@@ -74,22 +81,6 @@ const Tabs = Module("tabs", {
|
||||
return store.options;
|
||||
},
|
||||
|
||||
/**
|
||||
* @property {boolean} Whether the tab numbering XBL binding has been
|
||||
* applied.
|
||||
*/
|
||||
get tabsBound() Boolean(styles.get(true, "tab-binding")),
|
||||
set tabsBound(val) {
|
||||
let fragment = dactyl.has("MacUnix") ? "tab-mac" : "tab";
|
||||
if (!val)
|
||||
styles.removeSheet(true, "tab-binding");
|
||||
else if (!this.tabsBound)
|
||||
styles.addSheet(true, "tab-binding", "chrome://browser/content/browser.xul",
|
||||
".tabbrowser-tab { -moz-binding: url(chrome://dactyl/content/bindings.xml#" + fragment + ") !important; }" +
|
||||
// FIXME: better solution for themes?
|
||||
".tabbrowser-tab[busy] > .tab-icon > .tab-icon-image { list-style-image: url('chrome://global/skin/icons/loading_16.png') !important; }");
|
||||
},
|
||||
|
||||
get visibleTabs() config.tabbrowser.visibleTabs || this.allTabs.filter(function (tab) !tab.hidden),
|
||||
|
||||
/**
|
||||
@@ -721,7 +712,7 @@ const Tabs = Module("tabs", {
|
||||
});
|
||||
|
||||
commands.add(["quita[ll]", "qa[ll]"],
|
||||
"Quit " + config.name,
|
||||
"Quit " + config.appname,
|
||||
function (args) { dactyl.quit(false, args.bang); }, {
|
||||
argCount: "0",
|
||||
bang: true
|
||||
@@ -831,7 +822,7 @@ const Tabs = Module("tabs", {
|
||||
argCount: "+",
|
||||
completer: function (context, args) {
|
||||
if (args.completeArg == 0) {
|
||||
context.filters.push(function ({ item: win }) win != window);
|
||||
context.filters.push(function ({ item }) item != window);
|
||||
completion.window(context);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 KiB |
Reference in New Issue
Block a user