mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-22 15:18:00 +01:00
Lots of rangefinder and Gecko 2 tabbing fixes.
This commit is contained in:
@@ -119,7 +119,7 @@ const AutoCommands = Module("autocommands", {
|
|||||||
|
|
||||||
let autoCmds = this._store.filter(function (autoCmd) autoCmd.event == event);
|
let autoCmds = this._store.filter(function (autoCmd) autoCmd.event == event);
|
||||||
|
|
||||||
dactyl.echomsg("Executing " + event + " Auto commands for \"*\"", 8);
|
dactyl.echomsg('Executing ' + event + ' Auto commands for "*"', 8);
|
||||||
|
|
||||||
let lastPattern = null;
|
let lastPattern = null;
|
||||||
let url = args.url || "";
|
let url = args.url || "";
|
||||||
@@ -127,7 +127,7 @@ const AutoCommands = Module("autocommands", {
|
|||||||
for (let [, autoCmd] in Iterator(autoCmds)) {
|
for (let [, autoCmd] in Iterator(autoCmds)) {
|
||||||
if (autoCmd.pattern.test(url)) {
|
if (autoCmd.pattern.test(url)) {
|
||||||
if (!lastPattern || lastPattern.source != autoCmd.pattern.source)
|
if (!lastPattern || lastPattern.source != autoCmd.pattern.source)
|
||||||
dactyl.echomsg("Executing " + event + " Auto commands for \"" + autoCmd.pattern.source + "\"", 8);
|
dactyl.echomsg("Executing " + event + " Auto commands for " + autoCmd.pattern.source.quote(), 8);
|
||||||
|
|
||||||
lastPattern = autoCmd.pattern;
|
lastPattern = autoCmd.pattern;
|
||||||
dactyl.echomsg("autocommand " + autoCmd.command, 9);
|
dactyl.echomsg("autocommand " + autoCmd.command, 9);
|
||||||
@@ -167,7 +167,7 @@ const AutoCommands = Module("autocommands", {
|
|||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
// NOTE: event can only be a comma separated list for |:au {event} {pat} {cmd}|
|
// NOTE: event can only be a comma separated list for |:au {event} {pat} {cmd}|
|
||||||
let validEvents = config.autocommands.map(function (event) event[0]);
|
let validEvents = keys(config.autocommands);
|
||||||
validEvents.push("*");
|
validEvents.push("*");
|
||||||
|
|
||||||
events = event.split(",");
|
events = event.split(",");
|
||||||
@@ -227,7 +227,7 @@ const AutoCommands = Module("autocommands", {
|
|||||||
|
|
||||||
let [event, url] = args;
|
let [event, url] = args;
|
||||||
let defaultURL = url || buffer.URL;
|
let defaultURL = url || buffer.URL;
|
||||||
let validEvents = config.autocommands.map(function (e) e[0]);
|
let validEvents = keys(config.autocommands);
|
||||||
|
|
||||||
// TODO: add command validators
|
// TODO: add command validators
|
||||||
dactyl.assert(event != "*",
|
dactyl.assert(event != "*",
|
||||||
@@ -257,10 +257,10 @@ const AutoCommands = Module("autocommands", {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
completion: function () {
|
completion: function () {
|
||||||
JavaScript.setCompleter(this.get, [function () config.autocommands]);
|
JavaScript.setCompleter(this.get, [function () Iterator(config.autocommands)]);
|
||||||
|
|
||||||
completion.autocmdEvent = function autocmdEvent(context) {
|
completion.autocmdEvent = function autocmdEvent(context) {
|
||||||
context.completions = config.autocommands;
|
context.completions = Iterator(config.autocommands);
|
||||||
};
|
};
|
||||||
|
|
||||||
completion.macro = function macro(context) {
|
completion.macro = function macro(context) {
|
||||||
@@ -273,7 +273,7 @@ const AutoCommands = Module("autocommands", {
|
|||||||
"List of autocommand event names which should be ignored",
|
"List of autocommand event names which should be ignored",
|
||||||
"stringlist", "",
|
"stringlist", "",
|
||||||
{
|
{
|
||||||
completer: function () config.autocommands.concat([["all", "All events"]])
|
completer: function () Iterator(update({ all: "All Events" }, config.autocommands))
|
||||||
});
|
});
|
||||||
|
|
||||||
options.add(["strictfocus", "sf"],
|
options.add(["strictfocus", "sf"],
|
||||||
|
|||||||
@@ -88,13 +88,18 @@ function dict(ary) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function set(ary) {
|
function set(ary) {
|
||||||
var obj = {};
|
let obj = {};
|
||||||
if (ary)
|
if (ary)
|
||||||
for (var i = 0; i < ary.length; i++)
|
for (var i = 0; i < ary.length; i++)
|
||||||
obj[ary[i]] = true;
|
obj[ary[i]] = true;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
set.add = function (set, key) { set[key] = true; }
|
set.add = function (set, key) {
|
||||||
|
let res = this.has(set, key);
|
||||||
|
set[key] = true;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
set.has = function (set, key) Object.prototype.hasOwnProperty.call(set, key);
|
||||||
set.remove = function (set, key) { delete set[key]; }
|
set.remove = function (set, key) { delete set[key]; }
|
||||||
|
|
||||||
function iter(obj) {
|
function iter(obj) {
|
||||||
@@ -142,6 +147,8 @@ function isinstance(targ, src) {
|
|||||||
for (var i = 0; i < src.length; i++) {
|
for (var i = 0; i < src.length; i++) {
|
||||||
if (targ instanceof src[i])
|
if (targ instanceof src[i])
|
||||||
return true;
|
return true;
|
||||||
|
if (typeof src[i] == "string")
|
||||||
|
return Object.prototype.toString(targ) == "[object " + src[i] + "]";
|
||||||
var type = types[typeof targ];
|
var type = types[typeof targ];
|
||||||
if (type && issubclass(src[i], type))
|
if (type && issubclass(src[i], type))
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -12,15 +12,18 @@
|
|||||||
<children/>
|
<children/>
|
||||||
</content>
|
</content>
|
||||||
</binding>
|
</binding>
|
||||||
|
|
||||||
<binding id="compitem-td">
|
<binding id="compitem-td">
|
||||||
<!-- No white space. The table is white-space: pre; :( -->
|
<!-- No white space. The table is white-space: pre; :( -->
|
||||||
<content><html:span class="td-strut"/><html:span class="td-span"><children/></html:span></content>
|
<content><html:span class="td-strut"/><html:span class="td-span"><children/></html:span></content>
|
||||||
</binding>
|
</binding>
|
||||||
|
|
||||||
<binding id="tab" display="xul:hbox"
|
<binding id="tab" display="xul:hbox"
|
||||||
extends="chrome://global/content/bindings/tabbox.xml#tab">
|
extends="chrome://browser/content/tabbrowser.xml#tabbrowser-tab">
|
||||||
<content chromedir="ltr" closetabtext="Close Tab">
|
<content context="tabContextMenu" closetabtext="Close Tab">
|
||||||
<xul:stack class="tab-icon dactyl-tab-stack">
|
<xul:stack class="tab-icon dactyl-tab-stack">
|
||||||
<xul:image xbl:inherits="validate,src=image" class="tab-icon-image" dactyl:highlight="TabIcon"/>
|
<xul:image xbl:inherits="validate,src=image" role="presentation"
|
||||||
|
class="tab-icon-image" dactyl:highlight="TabIcon"/>
|
||||||
<xul:vbox>
|
<xul:vbox>
|
||||||
<xul:spring flex="1"/>
|
<xul:spring flex="1"/>
|
||||||
<xul:label xbl:inherits="value=ordinal" dactyl:highlight="TabIconNumber"/>
|
<xul:label xbl:inherits="value=ordinal" dactyl:highlight="TabIconNumber"/>
|
||||||
@@ -28,10 +31,16 @@
|
|||||||
</xul:vbox>
|
</xul:vbox>
|
||||||
</xul:stack>
|
</xul:stack>
|
||||||
<xul:label xbl:inherits="value=ordinal" dactyl:highlight="TabNumber"/>
|
<xul:label xbl:inherits="value=ordinal" dactyl:highlight="TabNumber"/>
|
||||||
<xul:label flex="1" xbl:inherits="value=label,crop,accesskey" class="tab-text" dactyl:highlight="TabText"/>
|
<xul:label flex="1"
|
||||||
<xul:toolbarbutton anonid="close-button" tabindex="-1" class="tab-close-button" dactyl:highlight="TabClose"/>
|
xbl:inherits="value=label,crop,accesskey"
|
||||||
|
class="tab-text" dactyl:highlight="TabText"
|
||||||
|
role="presentation"/>
|
||||||
|
<xul:toolbarbutton anonid="close-button"
|
||||||
|
tabindex="-1"
|
||||||
|
class="tab-close-button" dactyl:highlight="TabClose"/>
|
||||||
</content>
|
</content>
|
||||||
</binding>
|
</binding>
|
||||||
|
|
||||||
<binding id="tab-mac"
|
<binding id="tab-mac"
|
||||||
extends="chrome://browser/content/tabbrowser.xml#tabbrowser-tab">
|
extends="chrome://browser/content/tabbrowser.xml#tabbrowser-tab">
|
||||||
<content chromedir="ltr" closetabtext="Close Tab">
|
<content chromedir="ltr" closetabtext="Close Tab">
|
||||||
|
|||||||
@@ -435,11 +435,11 @@ const Bookmarks = Module("bookmarks", {
|
|||||||
return dactyl.open(items.map(function (i) i.url), dactyl.NEW_TAB);
|
return dactyl.open(items.map(function (i) i.url), dactyl.NEW_TAB);
|
||||||
|
|
||||||
if (filter.length > 0 && tags.length > 0)
|
if (filter.length > 0 && tags.length > 0)
|
||||||
dactyl.echoerr("E283: No bookmarks matching tags: \"" + tags + "\" and string: \"" + filter + "\"");
|
dactyl.echoerr("E283: No bookmarks matching tags: " + tags.quote() + " and string: " + filter.quote());
|
||||||
else if (filter.length > 0)
|
else if (filter.length > 0)
|
||||||
dactyl.echoerr("E283: No bookmarks matching string: \"" + filter + "\"");
|
dactyl.echoerr("E283: No bookmarks matching string: " + filter.quote());
|
||||||
else if (tags.length > 0)
|
else if (tags.length > 0)
|
||||||
dactyl.echoerr("E283: No bookmarks matching tags: \"" + tags + "\"");
|
dactyl.echoerr("E283: No bookmarks matching tags: " + tags.quote());
|
||||||
else
|
else
|
||||||
dactyl.echoerr("No bookmarks set");
|
dactyl.echoerr("No bookmarks set");
|
||||||
return null;
|
return null;
|
||||||
@@ -497,7 +497,7 @@ const Bookmarks = Module("bookmarks", {
|
|||||||
dactyl.echomsg("Added bookmark: " + url + extra, 1, commandline.FORCE_SINGLELINE);
|
dactyl.echomsg("Added bookmark: " + url + extra, 1, commandline.FORCE_SINGLELINE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dactyl.echoerr("Exxx: Could not add bookmark `" + title + "'", commandline.FORCE_SINGLELINE);
|
dactyl.echoerr("Exxx: Could not add bookmark " + title.quote(), commandline.FORCE_SINGLELINE);
|
||||||
}, {
|
}, {
|
||||||
argCount: "?",
|
argCount: "?",
|
||||||
bang: true,
|
bang: true,
|
||||||
|
|||||||
@@ -582,7 +582,7 @@ const Buffer = Module("buffer", {
|
|||||||
let offsetX = 1;
|
let offsetX = 1;
|
||||||
let offsetY = 1;
|
let offsetY = 1;
|
||||||
|
|
||||||
if (isinstance(elem [HTMLFrameElement, HTMLIFrameElement])) {
|
if (isinstance(elem, [HTMLFrameElement, HTMLIFrameElement])) {
|
||||||
buffer.focusElement(elem);
|
buffer.focusElement(elem);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1308,9 +1308,23 @@ const Buffer = Module("buffer", {
|
|||||||
};
|
};
|
||||||
|
|
||||||
completion.buffer = function buffer(context) {
|
completion.buffer = function buffer(context) {
|
||||||
filter = context.filter.toLowerCase();
|
let filter = context.filter.toLowerCase();
|
||||||
|
let defItem = { parent: { getTitle: function () "" } };
|
||||||
|
let tabGroups = {};
|
||||||
|
tabs.getGroups();
|
||||||
|
tabs.allTabs.forEach(function (tab, i) {
|
||||||
|
let group = (tab.tabItem || defItem).parent || defItem.parent;
|
||||||
|
if (!set.has(tabGroups, group.id))
|
||||||
|
tabGroups[group.id] = [group.getTitle(), []];
|
||||||
|
group = tabGroups[group.id];
|
||||||
|
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.anchored = false;
|
||||||
context.title = ["Buffer", "URL"];
|
context.title = [name || "Buffers"];
|
||||||
context.keys = { text: "text", description: "url", icon: "icon" };
|
context.keys = { text: "text", description: "url", icon: "icon" };
|
||||||
context.compare = CompletionContext.Sort.number;
|
context.compare = CompletionContext.Sort.number;
|
||||||
let process = context.process[0];
|
let process = context.process[0];
|
||||||
@@ -1320,7 +1334,7 @@ const Buffer = Module("buffer", {
|
|||||||
{ process.call(this, item, text) }
|
{ process.call(this, item, text) }
|
||||||
</>];
|
</>];
|
||||||
|
|
||||||
context.completions = util.map(tabs.browsers, function ([i, browser]) {
|
context.completions = util.map(util.Array.itervalues(browsers), function ([i, browser]) {
|
||||||
let indicator = " ";
|
let indicator = " ";
|
||||||
if (i == tabs.index())
|
if (i == tabs.index())
|
||||||
indicator = "%"
|
indicator = "%"
|
||||||
@@ -1338,9 +1352,11 @@ const Buffer = Module("buffer", {
|
|||||||
icon: tab.image || DEFAULT_FAVICON
|
icon: tab.image || DEFAULT_FAVICON
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
events: function () {
|
events: function () {
|
||||||
|
/*
|
||||||
window.XULBrowserWindow = this.progressListener;
|
window.XULBrowserWindow = this.progressListener;
|
||||||
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIWebNavigation)
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
@@ -1349,6 +1365,7 @@ const Buffer = Module("buffer", {
|
|||||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIXULWindow)
|
.getInterface(Ci.nsIXULWindow)
|
||||||
.XULBrowserWindow = this.progressListener;
|
.XULBrowserWindow = this.progressListener;
|
||||||
|
*/
|
||||||
|
|
||||||
try {
|
try {
|
||||||
config.browser.addProgressListener(this.progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
|
config.browser.addProgressListener(this.progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||||
@@ -1592,7 +1609,7 @@ const Buffer = Module("buffer", {
|
|||||||
function (count) { buffer.zoomOut(Math.max(count, 1) * 3, true); },
|
function (count) { buffer.zoomOut(Math.max(count, 1) * 3, true); },
|
||||||
{ count: true });
|
{ count: true });
|
||||||
|
|
||||||
mappings.add(myModes, ["ZZ", "zZ"],
|
mappings.add(myModes, ["zZ"],
|
||||||
"Set full zoom value of current web page",
|
"Set full zoom value of current web page",
|
||||||
function (count) { buffer.fullZoom = count > 1 ? count : 100; },
|
function (count) { buffer.fullZoom = count > 1 ? count : 100; },
|
||||||
{ count: true });
|
{ count: true });
|
||||||
|
|||||||
@@ -613,6 +613,7 @@ const CommandLine = Module("commandline", {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
onEvent: function onEvent(event) {
|
onEvent: function onEvent(event) {
|
||||||
|
try {
|
||||||
let command = this.command;
|
let command = this.command;
|
||||||
|
|
||||||
if (event.type == "blur") {
|
if (event.type == "blur") {
|
||||||
@@ -686,6 +687,10 @@ const CommandLine = Module("commandline", {
|
|||||||
if (/^<(Tab|S-Tab)>$/.test(key))
|
if (/^<(Tab|S-Tab)>$/.test(key))
|
||||||
this._tabTimer.flush();
|
this._tabTimer.flush();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
dactyl.reportError(e);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1724,6 +1729,8 @@ const ItemList = Class("ItemList", {
|
|||||||
|
|
||||||
// if @param selectedItem is given, show the list and select that item
|
// if @param selectedItem is given, show the list and select that item
|
||||||
setItems: function setItems(newItems, selectedItem) {
|
setItems: function setItems(newItems, selectedItem) {
|
||||||
|
if (this._selItem > -1)
|
||||||
|
this._getCompletion(this._selItem).removeAttribute("selected");
|
||||||
if (this._container.collapsed)
|
if (this._container.collapsed)
|
||||||
this._minHeight = 0;
|
this._minHeight = 0;
|
||||||
this._startIndex = this._endIndex = this._selIndex = -1;
|
this._startIndex = this._endIndex = this._selIndex = -1;
|
||||||
@@ -1737,9 +1744,6 @@ const ItemList = Class("ItemList", {
|
|||||||
|
|
||||||
// select index, refill list if necessary
|
// select index, refill list if necessary
|
||||||
selectItem: function selectItem(index) {
|
selectItem: function selectItem(index) {
|
||||||
//if (this._container.collapsed) // FIXME
|
|
||||||
// return;
|
|
||||||
|
|
||||||
//let now = Date.now();
|
//let now = Date.now();
|
||||||
|
|
||||||
if (this._div == null)
|
if (this._div == null)
|
||||||
|
|||||||
@@ -670,8 +670,10 @@ const Completion = Module("completion", {
|
|||||||
|
|
||||||
let list = template.commandOutput(
|
let list = template.commandOutput(
|
||||||
<div highlight="Completions">
|
<div highlight="Completions">
|
||||||
{ template.completionRow(context.title, "CompTitle") }
|
{ template.map(context.contextList.filter(function (c) c.hasItems),
|
||||||
{ template.map(context.items, function (item) context.createRow(item), null, 100) }
|
function (context)
|
||||||
|
template.completionRow(context.title, "CompTitle") +
|
||||||
|
template.map(context.items, function (item) context.createRow(item), null, 100)) }
|
||||||
</div>);
|
</div>);
|
||||||
commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
|
commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -60,7 +60,6 @@
|
|||||||
|
|
||||||
prefix.unshift("chrome://" + modules.Config.prototype.name.toLowerCase() + "/content/");
|
prefix.unshift("chrome://" + modules.Config.prototype.name.toLowerCase() + "/content/");
|
||||||
modules.Config.prototype.scripts.forEach(load);
|
modules.Config.prototype.scripts.forEach(load);
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// vim: set fdm=marker sw=4 ts=4 et:
|
// vim: set fdm=marker sw=4 ts=4 et:
|
||||||
|
|||||||
@@ -73,11 +73,11 @@ const Dactyl = Module("dactyl", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
autocommands.trigger(config.name + "LeavePre", {});
|
autocommands.trigger("LeavePre", {});
|
||||||
storage.saveAll();
|
storage.saveAll();
|
||||||
dactyl.triggerObserver("shutdown", null);
|
dactyl.triggerObserver("shutdown", null);
|
||||||
dactyl.dump("All dactyl modules destroyed\n");
|
dactyl.dump("All dactyl modules destroyed\n");
|
||||||
autocommands.trigger(config.name + "Leave", {});
|
autocommands.trigger("Leave", {});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -682,11 +682,12 @@ const Dactyl = Module("dactyl", {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dactyl.echomsg('Searching for "plugin/**/*.{js,vimp}" in "'
|
dactyl.echomsg('Searching for "plugin/**/*.{js,vimp}" in '
|
||||||
+ [dir.path.replace(/.plugin$/, "") for ([, dir] in Iterator(dirs))].join(",") + '"', 2);
|
+ [dir.path.replace(/.plugin$/, "") for ([, dir] in Iterator(dirs))]
|
||||||
|
.join(",").quote(), 2);
|
||||||
|
|
||||||
dirs.forEach(function (dir) {
|
dirs.forEach(function (dir) {
|
||||||
dactyl.echomsg("Searching for \"" + (dir.path + "/**/*.{js,vimp}") + "\"", 3);
|
dactyl.echomsg("Searching for " + (dir.path + "/**/*.{js,vimp}").quote(), 3);
|
||||||
sourceDirectory(dir);
|
sourceDirectory(dir);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -735,11 +736,6 @@ const Dactyl = Module("dactyl", {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
open: function (urls, params, force) {
|
open: function (urls, params, force) {
|
||||||
// convert the string to an array of converted URLs
|
|
||||||
// -> see dactyl.stringToURLArray for more details
|
|
||||||
//
|
|
||||||
// This is strange. And counterintuitive. Is it really
|
|
||||||
// necessary? --Kris
|
|
||||||
if (typeof urls == "string")
|
if (typeof urls == "string")
|
||||||
urls = dactyl.stringToURLArray(urls);
|
urls = dactyl.stringToURLArray(urls);
|
||||||
|
|
||||||
@@ -867,7 +863,7 @@ const Dactyl = Module("dactyl", {
|
|||||||
urls = [str];
|
urls = [str];
|
||||||
|
|
||||||
return urls.map(function (url) {
|
return urls.map(function (url) {
|
||||||
if (/^\.?\//.test(url)) {
|
if (/^[.~]?\//.test(url)) {
|
||||||
try {
|
try {
|
||||||
// Try to find a matching file.
|
// Try to find a matching file.
|
||||||
let file = io.File(url);
|
let file = io.File(url);
|
||||||
@@ -1444,7 +1440,7 @@ const Dactyl = Module("dactyl", {
|
|||||||
else if (file.isReadable() && file.isFile())
|
else if (file.isReadable() && file.isFile())
|
||||||
AddonManager.getInstallForFile(file, callResult("install"), "application/x-xpinstall");
|
AddonManager.getInstallForFile(file, callResult("install"), "application/x-xpinstall");
|
||||||
else if (file.isDirectory())
|
else if (file.isDirectory())
|
||||||
dactyl.echomsg("Cannot install a directory: \"" + file.path + "\"", 0);
|
dactyl.echomsg("Cannot install a directory: " + file.path.quote(), 0);
|
||||||
else
|
else
|
||||||
dactyl.echoerr("E484: Can't open file " + file.path);
|
dactyl.echoerr("E484: Can't open file " + file.path);
|
||||||
}, {
|
}, {
|
||||||
@@ -1552,7 +1548,7 @@ const Dactyl = Module("dactyl", {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (filter)
|
if (filter)
|
||||||
dactyl.echoerr("Exxx: No extension matching \"" + filter + "\"");
|
dactyl.echoerr("Exxx: No extension matching " + filter.quote());
|
||||||
else
|
else
|
||||||
dactyl.echoerr("No extensions installed");
|
dactyl.echoerr("No extensions installed");
|
||||||
}
|
}
|
||||||
@@ -1953,7 +1949,7 @@ const Dactyl = Module("dactyl", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
dactyl.triggerObserver("enter", null);
|
dactyl.triggerObserver("enter", null);
|
||||||
autocommands.trigger(config.name + "Enter", {});
|
autocommands.trigger("Enter", {});
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
statusline.update();
|
statusline.update();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
let backwards = mode == modes.FIND_BACKWARD;
|
let backwards = mode == modes.FIND_BACKWARD;
|
||||||
commandline.open(backwards ? "?" : "/", "", mode);
|
commandline.open(backwards ? "?" : "/", "", mode);
|
||||||
|
|
||||||
if (this.rangeFind)
|
if (this.rangeFind && this.rangeFind.window.get() == window)
|
||||||
this.rangeFind.reset();
|
this.rangeFind.reset();
|
||||||
this.find("", backwards);
|
this.find("", backwards);
|
||||||
},
|
},
|
||||||
@@ -28,6 +28,7 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
this.rangeFind = null;
|
this.rangeFind = null;
|
||||||
|
|
||||||
let highlighted = this.rangeFind && this.rangeFind.highlighted;
|
let highlighted = this.rangeFind && this.rangeFind.highlighted;
|
||||||
|
let selections = this.rangeFind && this.rangeFind.selections;
|
||||||
let matchCase = !(options["ignorecase"] || options["smartcase"] && !/[A-Z]/.test(str));
|
let matchCase = !(options["ignorecase"] || options["smartcase"] && !/[A-Z]/.test(str));
|
||||||
let linksOnly = options["linksearch"];
|
let linksOnly = options["linksearch"];
|
||||||
|
|
||||||
@@ -45,15 +46,19 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
// It's possible, with :tabdetach, for the rangeFind to actually move
|
// It's possible, with :tabdetach for instance, for the rangeFind to
|
||||||
// from one window to another, which breaks things.
|
// actually move from one window to another, which breaks things.
|
||||||
if (!this.rangeFind || this.rangeFind.window.get() != window ||
|
if (!this.rangeFind
|
||||||
linksOnly ^ !!this.rangeFind.elementPath ||
|
|| this.rangeFind.window.get() != window
|
||||||
matchCase ^ this.rangeFind.matchCase || backward ^ this.rangeFind.reverse) {
|
|| linksOnly != !!this.rangeFind.elementPath
|
||||||
|
|| matchCase != this.rangeFind.matchCase
|
||||||
|
|| !!backward != this.rangeFind.reverse) {
|
||||||
|
|
||||||
if (this.rangeFind)
|
if (this.rangeFind)
|
||||||
this.rangeFind.cancel();
|
this.rangeFind.cancel();
|
||||||
this.rangeFind = RangeFind(matchCase, backward, linksOnly && options["hinttags"]);
|
this.rangeFind = RangeFind(matchCase, backward, linksOnly && options["hinttags"]);
|
||||||
this.rangeFind.highlighted = highlighted;
|
this.rangeFind.highlighted = highlighted;
|
||||||
|
this.rangeFind.selections = selections;
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
@@ -71,15 +76,15 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
this.find(this.lastSearchPattern);
|
this.find(this.lastSearchPattern);
|
||||||
else if (!this.rangeFind.search(null, reverse))
|
else if (!this.rangeFind.search(null, reverse))
|
||||||
dactyl.echoerr("E486: Pattern not found: " + this.lastSearchPattern);
|
dactyl.echoerr("E486: Pattern not found: " + this.lastSearchPattern);
|
||||||
else if (this.rangeFind.wrapped) {
|
else if (this.rangeFind.wrapped)
|
||||||
// hack needed, because wrapping causes a "scroll" event which clears
|
// hack needed, because wrapping causes a "scroll" event which
|
||||||
// our command line
|
// clears our command line
|
||||||
this.setTimeout(function () {
|
this.setTimeout(function () {
|
||||||
let msg = this.rangeFind.backward ? "search hit TOP, continuing at BOTTOM"
|
let msg = this.rangeFind.backward ? "search hit TOP, continuing at BOTTOM"
|
||||||
: "search hit BOTTOM, continuing at TOP";
|
: "search hit BOTTOM, continuing at TOP";
|
||||||
commandline.echo(msg, commandline.HL_WARNINGMSG, commandline.APPEND_TO_MESSAGES);
|
commandline.echo(msg, commandline.HL_WARNINGMSG,
|
||||||
|
commandline.APPEND_TO_MESSAGES | commandline.FORCE_SINGLELINE);
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
commandline.echo((this.rangeFind.backward ? "?" : "/") + this.lastSearchPattern, null, commandline.FORCE_SINGLELINE);
|
commandline.echo((this.rangeFind.backward ? "?" : "/") + this.lastSearchPattern, null, commandline.FORCE_SINGLELINE);
|
||||||
|
|
||||||
@@ -197,6 +202,10 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
modes.addMode("FIND_BACKWARD", true);
|
modes.addMode("FIND_BACKWARD", true);
|
||||||
},
|
},
|
||||||
options: function () {
|
options: function () {
|
||||||
|
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);
|
||||||
|
|
||||||
options.add(["hlsearch", "hls"],
|
options.add(["hlsearch", "hls"],
|
||||||
"Highlight previous search pattern matches",
|
"Highlight previous search pattern matches",
|
||||||
"boolean", "false", {
|
"boolean", "false", {
|
||||||
@@ -267,27 +276,31 @@ const RangeFind = Class("RangeFind", {
|
|||||||
this.reset();
|
this.reset();
|
||||||
|
|
||||||
this.highlighted = null;
|
this.highlighted = null;
|
||||||
|
this.selections = [];
|
||||||
this.lastString = "";
|
this.lastString = "";
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get backward() this.finder.findBackwards,
|
||||||
|
|
||||||
|
get searchString() this.lastString,
|
||||||
|
|
||||||
get selectedRange() {
|
get selectedRange() {
|
||||||
let range = RangeFind.Range(tabs.localStore.focusedFrame || content);
|
let selection = (tabs.localStore.focusedFrame || content).getSelection();
|
||||||
return (range.selection.rangeCount ? range.selection.getRangeAt(0) : this.ranges[0].range).cloneRange();
|
return (selection.rangeCount ? selection.getRangeAt(0) : this.ranges[0].range).cloneRange();
|
||||||
|
},
|
||||||
|
set selectedRange(range) {
|
||||||
|
this.range.selection.removeAllRanges();
|
||||||
|
this.range.selection.addRange(range);
|
||||||
|
this.range.selectionController.scrollSelectionIntoView(
|
||||||
|
this.range.selectionController.SELECTION_NORMAL, 0, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
reset: function () {
|
cancel: function () {
|
||||||
this.startRange = this.selectedRange;
|
this.purgeListeners();
|
||||||
this.startRange.collapse(!this.reverse);
|
this.range.deselect();
|
||||||
this.lastRange = this.selectedRange;
|
this.range.descroll();
|
||||||
this.range = this.findRange(this.startRange);
|
|
||||||
this.ranges.first = this.range;
|
|
||||||
this.ranges.forEach(function (range) range.save());
|
|
||||||
this.forward = null;
|
|
||||||
this.found = false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
sameDocument: function (r1, r2) r1 && r2 && r1.endContainer.ownerDocument == r2.endContainer.ownerDocument,
|
|
||||||
|
|
||||||
compareRanges: function (r1, r2)
|
compareRanges: function (r1, r2)
|
||||||
this.backward ? r1.compareBoundaryPoints(Range.END_TO_START, r2)
|
this.backward ? r1.compareBoundaryPoints(Range.END_TO_START, r2)
|
||||||
: -r1.compareBoundaryPoints(Range.START_TO_END, r2),
|
: -r1.compareBoundaryPoints(Range.START_TO_END, r2),
|
||||||
@@ -296,9 +309,7 @@ const RangeFind = Class("RangeFind", {
|
|||||||
let doc = range.startContainer.ownerDocument;
|
let doc = range.startContainer.ownerDocument;
|
||||||
let win = doc.defaultView;
|
let win = doc.defaultView;
|
||||||
let ranges = this.ranges.filter(function (r)
|
let ranges = this.ranges.filter(function (r)
|
||||||
r.window == win &&
|
r.window == win && RangeFind.contains(r.range, range));
|
||||||
r.range.compareBoundaryPoints(Range.START_TO_END, range) >= 0 &&
|
|
||||||
r.range.compareBoundaryPoints(Range.END_TO_START, range) <= 0);
|
|
||||||
|
|
||||||
if (this.backward)
|
if (this.backward)
|
||||||
return ranges[ranges.length - 1];
|
return ranges[ranges.length - 1];
|
||||||
@@ -308,10 +319,8 @@ const RangeFind = Class("RangeFind", {
|
|||||||
findSubRanges: function (range) {
|
findSubRanges: function (range) {
|
||||||
let doc = range.startContainer.ownerDocument;
|
let doc = range.startContainer.ownerDocument;
|
||||||
for (let elem in util.evaluateXPath(this.elementPath, doc)) {
|
for (let elem in util.evaluateXPath(this.elementPath, doc)) {
|
||||||
let r = doc.createRange();
|
let r = RangeFind.nodeRange(elem);
|
||||||
r.selectNode(elem);
|
if (RangeFind.contains(range, r))
|
||||||
if (range.compareBoundaryPoints(Range.START_TO_END, r) >= 0 &&
|
|
||||||
range.compareBoundaryPoints(Range.END_TO_START, r) <= 0)
|
|
||||||
yield r;
|
yield r;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -322,7 +331,62 @@ const RangeFind = Class("RangeFind", {
|
|||||||
this.lastRange.commonAncestorContainer).snapshotItem(0);
|
this.lastRange.commonAncestorContainer).snapshotItem(0);
|
||||||
if(node) {
|
if(node) {
|
||||||
node.focus();
|
node.focus();
|
||||||
this.search(null, false); // Rehighlight collapsed range
|
// Rehighlight collapsed selection
|
||||||
|
this.selectedRange = this.lastRange;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
highlight: function (clear) {
|
||||||
|
|
||||||
|
if (!clear && (!this.lastString || this.lastString == this.highlighted))
|
||||||
|
return;
|
||||||
|
if (clear && !this.highlighted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!clear && this.highlighted)
|
||||||
|
this.highlight(true);
|
||||||
|
|
||||||
|
if (clear) {
|
||||||
|
this.selections.forEach(function (selection) {
|
||||||
|
selection.removeAllRanges();
|
||||||
|
});
|
||||||
|
this.selections = [];
|
||||||
|
this.highlighted = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.selections = [];
|
||||||
|
let string = this.lastString;
|
||||||
|
for (let r in this.iter(string)) {
|
||||||
|
let controller = this.range.selectionController;
|
||||||
|
for (let node=r.startContainer; node; node=node.parentNode)
|
||||||
|
if (node instanceof Ci.nsIDOMNSEditableElement) {
|
||||||
|
controller = node.editor.selectionController;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sel = controller.getSelection(Ci.nsISelectionController.SELECTION_FIND);
|
||||||
|
sel.addRange(r);
|
||||||
|
if (this.selections.indexOf(sel) < 0)
|
||||||
|
this.selections.push(sel);
|
||||||
|
}
|
||||||
|
this.highlighted = this.lastString;
|
||||||
|
this.selectedRange = this.lastRange;
|
||||||
|
this.addListeners();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
iter: function (word) {
|
||||||
|
let saved = ["range", "lastRange", "lastString"].map(function (s) [s, this[s]], this);
|
||||||
|
try {
|
||||||
|
this.range = this.ranges[0];
|
||||||
|
this.lastRange = null;
|
||||||
|
this.lastString = word;
|
||||||
|
var res;
|
||||||
|
while ((res = this.search(null, this.reverse, true)))
|
||||||
|
yield res;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
saved.forEach(function ([k, v]) this[k] = v, this);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -334,8 +398,7 @@ const RangeFind = Class("RangeFind", {
|
|||||||
|
|
||||||
function pushRange(start, end) {
|
function pushRange(start, end) {
|
||||||
function push(r) {
|
function push(r) {
|
||||||
r = RangeFind.Range(r, frames.length);
|
if (r = RangeFind.Range(r, frames.length))
|
||||||
if (r)
|
|
||||||
frames.push(r);
|
frames.push(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,19 +414,20 @@ const RangeFind = Class("RangeFind", {
|
|||||||
}
|
}
|
||||||
function rec(win) {
|
function rec(win) {
|
||||||
let doc = win.document;
|
let doc = win.document;
|
||||||
let pageRange = doc.createRange();
|
let pageRange = RangeFind.nodeRange(doc.body || doc.documentElement.lastChild);
|
||||||
pageRange.selectNode(doc.body || doc.documentElement.lastChild);
|
|
||||||
backup = backup || pageRange;
|
backup = backup || pageRange;
|
||||||
let pageStart = RangeFind.endpoint(pageRange, true);
|
let pageStart = RangeFind.endpoint(pageRange, true);
|
||||||
let pageEnd = RangeFind.endpoint(pageRange, false);
|
let pageEnd = RangeFind.endpoint(pageRange, false);
|
||||||
|
|
||||||
for (let frame in util.Array.itervalues(win.frames)) {
|
for (let frame in util.Array.itervalues(win.frames)) {
|
||||||
let range = doc.createRange();
|
let range = doc.createRange();
|
||||||
|
if (util.computedStyle(frame.frameElement).visibility == "visible") {
|
||||||
range.selectNode(frame.frameElement);
|
range.selectNode(frame.frameElement);
|
||||||
pushRange(pageStart, RangeFind.endpoint(range, true));
|
pushRange(pageStart, RangeFind.endpoint(range, true));
|
||||||
pageStart = RangeFind.endpoint(range, false);
|
pageStart = RangeFind.endpoint(range, false);
|
||||||
rec(frame);
|
rec(frame);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pushRange(pageStart, pageEnd);
|
pushRange(pageStart, pageEnd);
|
||||||
}
|
}
|
||||||
rec(win);
|
rec(win);
|
||||||
@@ -372,6 +436,17 @@ const RangeFind = Class("RangeFind", {
|
|||||||
return frames;
|
return frames;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
reset: function () {
|
||||||
|
this.startRange = this.selectedRange;
|
||||||
|
this.startRange.collapse(!this.reverse);
|
||||||
|
this.lastRange = this.selectedRange;
|
||||||
|
this.range = this.findRange(this.startRange);
|
||||||
|
this.ranges.first = this.range;
|
||||||
|
this.ranges.forEach(function (range) range.save());
|
||||||
|
this.forward = null;
|
||||||
|
this.found = false;
|
||||||
|
},
|
||||||
|
|
||||||
// This doesn't work yet.
|
// This doesn't work yet.
|
||||||
resetCaret: function () {
|
resetCaret: function () {
|
||||||
let equal = RangeFind.equal;
|
let equal = RangeFind.equal;
|
||||||
@@ -406,24 +481,6 @@ const RangeFind = Class("RangeFind", {
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
get searchString() this.lastString,
|
|
||||||
get backward() this.finder.findBackwards,
|
|
||||||
|
|
||||||
iter: function (word) {
|
|
||||||
let saved = ["range", "lastRange", "lastString"].map(this.closure(function (s) [s, this[s]]));
|
|
||||||
try {
|
|
||||||
this.range = this.ranges[0];
|
|
||||||
this.lastRange = null;
|
|
||||||
this.lastString = word;
|
|
||||||
var res;
|
|
||||||
while ((res = this.search(null, this.reverse, true)))
|
|
||||||
yield res;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
saved.forEach(function ([k, v]) this[k] = v, this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
search: function (word, reverse, private_) {
|
search: function (word, reverse, private_) {
|
||||||
if (!private_ && this.lastRange && !RangeFind.equal(this.selectedRange, this.lastRange))
|
if (!private_ && this.lastRange && !RangeFind.equal(this.selectedRange, this.lastRange))
|
||||||
this.reset();
|
this.reset();
|
||||||
@@ -450,110 +507,57 @@ const RangeFind = Class("RangeFind", {
|
|||||||
else {
|
else {
|
||||||
function indices() {
|
function indices() {
|
||||||
let idx = this.range.index;
|
let idx = this.range.index;
|
||||||
for (let i in this.backward ? util.range(idx + 1, 0, -1) : util.range(idx, this.ranges.length))
|
if (this.backward)
|
||||||
|
var groups = [util.range(idx + 1, 0, -1), util.range(this.ranges.length, idx, -1)];
|
||||||
|
else
|
||||||
|
var groups = [util.range(idx, this.ranges.length), util.range(0, idx + 1)];
|
||||||
|
|
||||||
|
for (let i in groups[0])
|
||||||
yield i;
|
yield i;
|
||||||
if (private_)
|
|
||||||
return;
|
if (!private_) {
|
||||||
this.wrapped = true;
|
this.wrapped = true;
|
||||||
this.lastRange = null;
|
this.lastRange = null;
|
||||||
for (let i in this.backward ? util.range(this.ranges.length, idx, -1) : util.range(0, idx + 1))
|
for (let i in groups[1])
|
||||||
yield i;
|
yield i;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (let i in indices.call(this)) {
|
for (let i in indices.call(this)) {
|
||||||
|
if (!private_ && this.range.window != this.ranges[i].window && this.range.window != this.ranges[i].window.parent) {
|
||||||
|
this.range.descroll();
|
||||||
|
this.range.deselect();
|
||||||
|
}
|
||||||
this.range = this.ranges[i];
|
this.range = this.ranges[i];
|
||||||
|
|
||||||
let start = this.sameDocument(this.lastRange, this.range.range) && this.range.intersects(this.lastRange) ?
|
let start = RangeFind.sameDocument(this.lastRange, this.range.range) && this.range.intersects(this.lastRange) ?
|
||||||
RangeFind.endpoint(this.lastRange, !(again ^ this.backward)) :
|
RangeFind.endpoint(this.lastRange, !(again ^ this.backward)) :
|
||||||
RangeFind.endpoint(this.range.range, !this.backward);;
|
RangeFind.endpoint(this.range.range, !this.backward);;
|
||||||
|
|
||||||
if (this.backward && !again)
|
if (this.backward && !again)
|
||||||
start = RangeFind.endpoint(this.startRange, false);
|
start = RangeFind.endpoint(this.startRange, false);
|
||||||
|
|
||||||
var range = this.finder.Find(word, this.range.range, start, this.range.range);
|
var range = this.finder.Find(word, this.range.range, start, this.range.range);
|
||||||
if (range)
|
if (range)
|
||||||
break;
|
break;
|
||||||
if (!private_) {
|
|
||||||
this.range.descroll();
|
|
||||||
this.range.deselect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (range)
|
if (range)
|
||||||
this.lastRange = range.cloneRange();
|
this.lastRange = range.cloneRange();
|
||||||
if (private_)
|
if (!private_) {
|
||||||
return range;
|
|
||||||
|
|
||||||
this.lastString = word;
|
this.lastString = word;
|
||||||
if (range == null) {
|
if (range == null) {
|
||||||
this.cancel();
|
this.cancel();
|
||||||
this.found = false;
|
this.found = false;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
this.range.selection.removeAllRanges();
|
|
||||||
this.range.selection.addRange(range);
|
|
||||||
this.range.selectionController.scrollSelectionIntoView(
|
|
||||||
this.range.selectionController.SELECTION_NORMAL, 0, false);
|
|
||||||
this.found = true;
|
this.found = true;
|
||||||
|
}
|
||||||
|
if (range && (!private_ || private_ < 0))
|
||||||
|
this.selectedRange = range;
|
||||||
return range;
|
return range;
|
||||||
},
|
},
|
||||||
|
|
||||||
highlight: function (clear) {
|
|
||||||
|
|
||||||
if (!clear && (!this.lastString || this.lastString == this.highlighted))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!clear && this.highlighted)
|
|
||||||
this.highlight(true);
|
|
||||||
|
|
||||||
if (clear && !this.highlighted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let span = util.xmlToDom(<span highlight="Search"/>, this.range.document);
|
|
||||||
|
|
||||||
function highlight(range) {
|
|
||||||
let startContainer = range.startContainer;
|
|
||||||
let startOffset = range.startOffset;
|
|
||||||
let node = startContainer.ownerDocument.importNode(span, true);
|
|
||||||
|
|
||||||
let docfrag = range.extractContents();
|
|
||||||
let before = startContainer.splitText(startOffset);
|
|
||||||
let parent = before.parentNode;
|
|
||||||
node.appendChild(docfrag);
|
|
||||||
parent.insertBefore(node, before);
|
|
||||||
range.selectNode(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
function unhighlight(range) {
|
|
||||||
let elem = range.startContainer;
|
|
||||||
while (!(elem instanceof Element) && elem.parentNode)
|
|
||||||
elem = elem.parentNode;
|
|
||||||
if (elem.getAttributeNS(NS.uri, "highlight") != "Search")
|
|
||||||
return;
|
|
||||||
|
|
||||||
let docfrag = range.extractContents();
|
|
||||||
|
|
||||||
let parent = elem.parentNode;
|
|
||||||
parent.replaceChild(docfrag, elem);
|
|
||||||
parent.normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
let action = clear ? unhighlight : highlight;
|
|
||||||
let string = this[clear ? "highlighted" : "lastString"];
|
|
||||||
for (let r in this.iter(string)) {
|
|
||||||
action(r);
|
|
||||||
this.lastRange = r;
|
|
||||||
}
|
|
||||||
if (clear) {
|
|
||||||
this.highlighted = null;
|
|
||||||
this.purgeListeners();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.highlighted = this.lastString;
|
|
||||||
this.addListeners();
|
|
||||||
this.search(null, false); // Rehighlight collapsed range
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
addListeners: function () {
|
addListeners: function () {
|
||||||
for (let range in values(this.ranges))
|
for (let range in values(this.ranges))
|
||||||
range.window.addEventListener("unload", this.closure.onUnload, true);
|
range.window.addEventListener("unload", this.closure.onUnload, true);
|
||||||
@@ -562,32 +566,23 @@ const RangeFind = Class("RangeFind", {
|
|||||||
for (let range in values(this.ranges))
|
for (let range in values(this.ranges))
|
||||||
range.window.removeEventListener("unload", this.closure.onUnload, true);
|
range.window.removeEventListener("unload", this.closure.onUnload, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
onUnload: function (event) {
|
onUnload: function (event) {
|
||||||
this.purgeListeners();
|
this.purgeListeners();
|
||||||
if (this.highlighted)
|
if (this.highlighted)
|
||||||
this.highlight(false);
|
this.highlight(false);
|
||||||
this.stale = true;
|
this.stale = true;
|
||||||
},
|
|
||||||
|
|
||||||
cancel: function () {
|
|
||||||
this.purgeListeners();
|
|
||||||
this.range.deselect();
|
|
||||||
this.range.descroll();
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
Range: Class("RangeFind.Range", {
|
Range: Class("RangeFind.Range", {
|
||||||
init: function (range, index) {
|
init: function (range, index) {
|
||||||
if (range instanceof Ci.nsIDOMWindow) { // Kludge
|
|
||||||
this.document = range.document;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
|
||||||
|
this.range = range;
|
||||||
this.document = range.startContainer.ownerDocument;
|
this.document = range.startContainer.ownerDocument;
|
||||||
this.window = this.document.defaultView;
|
this.window = this.document.defaultView;
|
||||||
this.range = range;
|
this.docShell = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShell);
|
||||||
|
|
||||||
if (this.selection == null)
|
if (this.selection == null)
|
||||||
return false;
|
return false;
|
||||||
@@ -617,14 +612,6 @@ const RangeFind = Class("RangeFind", {
|
|||||||
this.selection.addRange(this.initialSelection);
|
this.selection.addRange(this.initialSelection);
|
||||||
},
|
},
|
||||||
|
|
||||||
get docShell() {
|
|
||||||
if (this._docShell)
|
|
||||||
return this._docShell;
|
|
||||||
for (let shell in iter(config.browser.docShell.getDocShellEnumerator(Ci.nsIDocShellTreeItem.typeAll, Ci.nsIDocShell.ENUMERATE_FORWARDS)))
|
|
||||||
if (shell.QueryInterface(nsIWebNavigation).document == this.document)
|
|
||||||
return this._docShell = shell;
|
|
||||||
throw Error();
|
|
||||||
},
|
|
||||||
get selectionController() this.docShell
|
get selectionController() this.docShell
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsISelectionDisplay)
|
.getInterface(Ci.nsISelectionDisplay)
|
||||||
@@ -637,8 +624,9 @@ const RangeFind = Class("RangeFind", {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
}),
|
}),
|
||||||
selectNodePath: ["ancestor-or-self::" + s for ([i, s] in Iterator(
|
contains: function (range, r)
|
||||||
["a", "xhtml:a", "*[@onclick]"]))].join(" | "),
|
range.compareBoundaryPoints(Range.START_TO_END, r) >= 0 &&
|
||||||
|
range.compareBoundaryPoints(Range.END_TO_START, r) <= 0,
|
||||||
endpoint: function (range, before) {
|
endpoint: function (range, before) {
|
||||||
range = range.cloneRange();
|
range = range.cloneRange();
|
||||||
range.collapse(before);
|
range.collapse(before);
|
||||||
@@ -650,7 +638,15 @@ const RangeFind = Class("RangeFind", {
|
|||||||
}
|
}
|
||||||
catch (e) {}
|
catch (e) {}
|
||||||
return false;
|
return false;
|
||||||
}
|
},
|
||||||
|
nodeRange: function (node) {
|
||||||
|
let range = node.ownerDocument.createRange();
|
||||||
|
range.selectNode(node);
|
||||||
|
return range;
|
||||||
|
},
|
||||||
|
sameDocument: function (r1, r2) r1 && r2 && r1.endContainer.ownerDocument == r2.endContainer.ownerDocument,
|
||||||
|
selectNodePath: ["a", "xhtml:a", "*[@onclick]"].map(
|
||||||
|
function (p) "ancestor-or-self::" + p).join(" | ")
|
||||||
});
|
});
|
||||||
|
|
||||||
// vim: set fdm=marker sw=4 ts=4 et:
|
// vim: set fdm=marker sw=4 ts=4 et:
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ const History = Module("history", {
|
|||||||
return dactyl.open(items.map(function (i) i.url), dactyl.NEW_TAB);
|
return dactyl.open(items.map(function (i) i.url), dactyl.NEW_TAB);
|
||||||
|
|
||||||
if (filter.length > 0)
|
if (filter.length > 0)
|
||||||
dactyl.echoerr("E283: No history matching \"" + filter + "\"");
|
dactyl.echoerr("E283: No history matching " + filter.quote());
|
||||||
else
|
else
|
||||||
dactyl.echoerr("No history set");
|
dactyl.echoerr("No history set");
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ const IO = Module("io", {
|
|||||||
let dir = File(newDir);
|
let dir = File(newDir);
|
||||||
|
|
||||||
if (!dir.exists() || !dir.isDirectory()) {
|
if (!dir.exists() || !dir.isDirectory()) {
|
||||||
dactyl.echoerr("E344: Can't find directory \"" + dir.path + "\" in path");
|
dactyl.echoerr("E344: Can't find directory " + dir.path.quote());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,14 +564,14 @@ lookup:
|
|||||||
let dirs = File.getPathsFromPathList(options["runtimepath"]);
|
let dirs = File.getPathsFromPathList(options["runtimepath"]);
|
||||||
let found = false;
|
let found = false;
|
||||||
|
|
||||||
dactyl.echomsg("Searching for \"" + paths.join(" ") + "\" in \"" + options["runtimepath"] + "\"", 2);
|
dactyl.echomsg("Searching for " + paths.join(" ").quote() + " in " + options["runtimepath"].quote(), 2);
|
||||||
|
|
||||||
outer:
|
outer:
|
||||||
for (let [, dir] in Iterator(dirs)) {
|
for (let [, dir] in Iterator(dirs)) {
|
||||||
for (let [, path] in Iterator(paths)) {
|
for (let [, path] in Iterator(paths)) {
|
||||||
let file = File.joinPaths(dir, path);
|
let file = File.joinPaths(dir, path);
|
||||||
|
|
||||||
dactyl.echomsg("Searching for \"" + file.path + "\"", 3);
|
dactyl.echomsg("Searching for " + file.path.quote(), 3);
|
||||||
|
|
||||||
if (file.exists() && file.isFile() && file.isReadable()) {
|
if (file.exists() && file.isFile() && file.isReadable()) {
|
||||||
io.source(file.path, false);
|
io.source(file.path, false);
|
||||||
@@ -584,7 +584,7 @@ lookup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
dactyl.echomsg("not found in 'runtimepath': \"" + paths.join(" ") + "\"", 1);
|
dactyl.echomsg("not found in 'runtimepath': " + paths.join(" ").quote(), 1);
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
},
|
},
|
||||||
@@ -609,9 +609,9 @@ lookup:
|
|||||||
if (!file.exists() || !file.isReadable() || file.isDirectory()) {
|
if (!file.exists() || !file.isReadable() || file.isDirectory()) {
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
if (file.exists() && file.isDirectory())
|
if (file.exists() && file.isDirectory())
|
||||||
dactyl.echomsg("Cannot source a directory: \"" + filename + "\"", 0);
|
dactyl.echomsg("Cannot source a directory: " + filename.quote(), 0);
|
||||||
else
|
else
|
||||||
dactyl.echomsg("could not source: \"" + filename + "\"", 1);
|
dactyl.echomsg("could not source: " + filename.quote(), 1);
|
||||||
|
|
||||||
dactyl.echoerr("E484: Can't open file " + filename);
|
dactyl.echoerr("E484: Can't open file " + filename);
|
||||||
}
|
}
|
||||||
@@ -619,7 +619,7 @@ lookup:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dactyl.echomsg("sourcing \"" + filename + "\"", 2);
|
dactyl.echomsg("sourcing " + filename.quote(), 2);
|
||||||
|
|
||||||
let str = file.read();
|
let str = file.read();
|
||||||
let uri = services.get("io").newFileURI(file);
|
let uri = services.get("io").newFileURI(file);
|
||||||
@@ -705,7 +705,7 @@ lookup:
|
|||||||
if (this._scriptNames.indexOf(file.path) == -1)
|
if (this._scriptNames.indexOf(file.path) == -1)
|
||||||
this._scriptNames.push(file.path);
|
this._scriptNames.push(file.path);
|
||||||
|
|
||||||
dactyl.echomsg("finished sourcing \"" + filename + "\"", 2);
|
dactyl.echomsg("finished sourcing " + filename.quote(), 2);
|
||||||
|
|
||||||
dactyl.log("Sourced: " + filename, 3);
|
dactyl.log("Sourced: " + filename, 3);
|
||||||
}
|
}
|
||||||
@@ -880,7 +880,7 @@ lookup:
|
|||||||
let file = File(filename);
|
let file = File(filename);
|
||||||
|
|
||||||
dactyl.assert(!file.exists() || args.bang,
|
dactyl.assert(!file.exists() || args.bang,
|
||||||
"E189: \"" + filename + "\" exists (add ! to override)");
|
"E189: " + filename.quote() + " exists (add ! to override)");
|
||||||
|
|
||||||
// TODO: Use a set/specifiable list here:
|
// TODO: Use a set/specifiable list here:
|
||||||
let lines = [cmd.serial().map(commands.commandToString) for (cmd in commands) if (cmd.serial)];
|
let lines = [cmd.serial().map(commands.commandToString) for (cmd in commands) if (cmd.serial)];
|
||||||
@@ -903,7 +903,7 @@ lookup:
|
|||||||
file.write(lines.join("\n"));
|
file.write(lines.join("\n"));
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
dactyl.echoerr("E190: Cannot open \"" + filename + "\" for writing");
|
dactyl.echoerr("E190: Cannot open " + filename.quote() + " for writing");
|
||||||
dactyl.log("Could not write to " + file.path + ": " + e.message); // XXX
|
dactyl.log("Could not write to " + file.path + ": " + e.message); // XXX
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
|||||||
@@ -49,10 +49,8 @@ const JavaScript = Module("javascript", {
|
|||||||
for (; obj; obj = !toplevel && obj.__proto__) {
|
for (; obj; obj = !toplevel && obj.__proto__) {
|
||||||
services.get("debugger").wrapValue(obj).getProperties(ret, {});
|
services.get("debugger").wrapValue(obj).getProperties(ret, {});
|
||||||
for (let prop in values(ret.value)) {
|
for (let prop in values(ret.value)) {
|
||||||
let name = '|' + prop.name.stringValue;
|
if (set.add(seen, prop.name.stringValue))
|
||||||
if (name in seen)
|
|
||||||
continue;
|
continue;
|
||||||
seen[name] = 1;
|
|
||||||
if (toplevel || obj !== orig)
|
if (toplevel || obj !== orig)
|
||||||
yield [prop.name.stringValue, top.getProperty(prop.name.stringValue).value.getWrappedValue()]
|
yield [prop.name.stringValue, top.getProperty(prop.name.stringValue).value.getWrappedValue()]
|
||||||
}
|
}
|
||||||
@@ -61,7 +59,7 @@ const JavaScript = Module("javascript", {
|
|||||||
// This only lists ENUMERABLE properties.
|
// This only lists ENUMERABLE properties.
|
||||||
try {
|
try {
|
||||||
for (let k in orig)
|
for (let k in orig)
|
||||||
if (k in orig && !('|' + k in seen)
|
if (k in orig && !(set.has(seen, k))
|
||||||
&& Object.hasOwnProperty(orig, k) == toplevel)
|
&& Object.hasOwnProperty(orig, k) == toplevel)
|
||||||
yield [k, this.getKey(orig, k)]
|
yield [k, this.getKey(orig, k)]
|
||||||
}
|
}
|
||||||
@@ -298,14 +296,18 @@ const JavaScript = Module("javascript", {
|
|||||||
continue;
|
continue;
|
||||||
if (dot > stop || dot <= prev)
|
if (dot > stop || dot <= prev)
|
||||||
break;
|
break;
|
||||||
let s = this._str.substring(prev, dot);
|
|
||||||
|
|
||||||
|
let s = this._str.substring(prev, dot);
|
||||||
if (prev != statement)
|
if (prev != statement)
|
||||||
s = JavaScript.EVAL_TMP + "." + s;
|
s = JavaScript.EVAL_TMP + "." + s;
|
||||||
cacheKey = this._str.substring(statement, dot);
|
cacheKey = this._str.substring(statement, dot);
|
||||||
|
|
||||||
if (this._checkFunction(prev, dot, cacheKey))
|
if (this._checkFunction(prev, dot, cacheKey))
|
||||||
return [];
|
return [];
|
||||||
|
if (prev != statement && obj == null) {
|
||||||
|
this.context.message = "Error: " + cacheKey.quote() + " is " + String(obj);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
prev = dot + 1;
|
prev = dot + 1;
|
||||||
obj = this.eval(s, cacheKey, obj);
|
obj = this.eval(s, cacheKey, obj);
|
||||||
@@ -338,7 +340,7 @@ const JavaScript = Module("javascript", {
|
|||||||
context.anchored = anchored;
|
context.anchored = anchored;
|
||||||
context.filter = key;
|
context.filter = key;
|
||||||
context.itemCache = context.parent.itemCache;
|
context.itemCache = context.parent.itemCache;
|
||||||
context.key = name;
|
context.key = name + last;
|
||||||
|
|
||||||
if (last != null)
|
if (last != null)
|
||||||
context.quote = [last, function (text) util.escapeString(text.substr(offset), ""), last];
|
context.quote = [last, function (text) util.escapeString(text.substr(offset), ""), last];
|
||||||
@@ -435,7 +437,7 @@ const JavaScript = Module("javascript", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.context.getCache("eval", Object);
|
this.context.getCache("eval", 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.
|
// Okay, have parse stack. Figure out what we're completing.
|
||||||
|
|
||||||
|
|||||||
@@ -792,10 +792,11 @@ const Options = Module("options", {
|
|||||||
*/
|
*/
|
||||||
// FIXME: Well it used to. I'm looking at you mst! --djk
|
// FIXME: Well it used to. I'm looking at you mst! --djk
|
||||||
safeSetPref: function (name, value, message) {
|
safeSetPref: function (name, value, message) {
|
||||||
let val = this._loadPreference(name, null, false);
|
let curval = this._loadPreference(name, null, false);
|
||||||
let def = this._loadPreference(name, null, true);
|
let defval = this._loadPreference(name, null, true);
|
||||||
let lib = this._loadPreference(Options.SAVED + name);
|
let saved = this._loadPreference(Options.SAVED + name);
|
||||||
if (lib == null && val != def || val != lib) {
|
|
||||||
|
if (saved == null && curval != defval || curval != saved) {
|
||||||
let msg = "Warning: setting preference " + name + ", but it's changed from its default value.";
|
let msg = "Warning: setting preference " + name + ", but it's changed from its default value.";
|
||||||
if (message)
|
if (message)
|
||||||
msg += " " + message;
|
msg += " " + message;
|
||||||
@@ -952,14 +953,6 @@ const Options = Module("options", {
|
|||||||
SAVED: "extensions.dactyl.saved.",
|
SAVED: "extensions.dactyl.saved.",
|
||||||
OLD_SAVED: "dactyl.saved."
|
OLD_SAVED: "dactyl.saved."
|
||||||
}, {
|
}, {
|
||||||
commandline: function () {
|
|
||||||
// TODO: maybe reset in .destroy()?
|
|
||||||
// TODO: move to buffer.js
|
|
||||||
// we have our own typeahead find implementation
|
|
||||||
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=348187
|
|
||||||
options.safeSetPref("accessibility.typeaheadfind.autostart", false);
|
|
||||||
options.safeSetPref("accessibility.typeaheadfind", false); // actually the above setting should do it, but has no effect in Firefox
|
|
||||||
},
|
|
||||||
commands: function () {
|
commands: function () {
|
||||||
function setAction(args, modifiers) {
|
function setAction(args, modifiers) {
|
||||||
let bang = args.bang;
|
let bang = args.bang;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ const QuickMarks = Module("quickmarks", {
|
|||||||
|
|
||||||
if (filter.length > 0) {
|
if (filter.length > 0) {
|
||||||
marks = marks.filter(function (qmark) filter.indexOf(qmark) >= 0);
|
marks = marks.filter(function (qmark) filter.indexOf(qmark) >= 0);
|
||||||
dactyl.assert(marks.length >= 0, "E283: No QuickMarks matching \"" + filter + "\"");
|
dactyl.assert(marks.length >= 0, "E283: No QuickMarks matching " + filter.quote());
|
||||||
}
|
}
|
||||||
|
|
||||||
let items = [[mark, this._qmarks.get(mark)] for ([k, mark] in Iterator(marks))];
|
let items = [[mark, this._qmarks.get(mark)] for ([k, mark] in Iterator(marks))];
|
||||||
@@ -138,7 +138,7 @@ const QuickMarks = Module("quickmarks", {
|
|||||||
args = args.string;
|
args = args.string;
|
||||||
|
|
||||||
// ignore invalid qmark characters unless there are no valid qmark chars
|
// ignore invalid qmark characters unless there are no valid qmark chars
|
||||||
dactyl.assert(!args || /[a-zA-Z0-9]/.test(args), "E283: No QuickMarks matching \"" + args + "\"");
|
dactyl.assert(!args || /[a-zA-Z0-9]/.test(args), "E283: No QuickMarks matching " + args.quote());
|
||||||
|
|
||||||
let filter = args.replace(/[^a-zA-Z0-9]/g, "");
|
let filter = args.replace(/[^a-zA-Z0-9]/g, "");
|
||||||
quickmarks.list(filter);
|
quickmarks.list(filter);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
// TODO:
|
// TODO:
|
||||||
// - fix Sanitize autocommand
|
// - fix Sanitize autocommand
|
||||||
// - add warning for TIMESPAN_EVERYTHING?
|
// - add warning for TIMESPAN_EVERYTHING?
|
||||||
// - respect privacy.clearOnShutdown et al or recommend PentadactylLeave autocommand?
|
// - respect privacy.clearOnShutdown et al or recommend Leave autocommand?
|
||||||
// - add support for :set sanitizeitems=all like 'eventignore'?
|
// - add support for :set sanitizeitems=all like 'eventignore'?
|
||||||
// - integrate with the Clear Private Data dialog?
|
// - integrate with the Clear Private Data dialog?
|
||||||
|
|
||||||
|
|||||||
@@ -188,10 +188,10 @@ const StatusLine = Module("statusline", {
|
|||||||
|
|
||||||
// update the ordinal which is used for numbered tabs
|
// update the ordinal which is used for numbered tabs
|
||||||
if (options.get("guioptions").has("n", "N"))
|
if (options.get("guioptions").has("n", "N"))
|
||||||
for (let [i, tab] in util.Array.iteritems(config.browser.mTabs))
|
for (let [i, tab] in Iterator(tabs.visibleTabs))
|
||||||
tab.setAttribute("ordinal", i + 1);
|
tab.setAttribute("ordinal", i + 1);
|
||||||
|
|
||||||
this.widgets.tabcount.value = "[" + (tabs.index() + 1) + "/" + tabs.count + "]";
|
this.widgets.tabcount.value = "[" + (tabs.index(null, true) + 1) + "/" + tabs.visibleTabs.length + "]";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ const Tabs = Module("tabs", {
|
|||||||
setTimeout(function () { dactyl.focusContent(true); }, 10); // just make sure, that no widget has focus
|
setTimeout(function () { dactyl.focusContent(true); }, 10); // just make sure, that no widget has focus
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get allTabs() Array.slice(config.tabbrowser.tabContainer.childNodes),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property {Object} The previously accessed tab or null if no tab
|
* @property {Object} The previously accessed tab or null if no tab
|
||||||
* other than the current one has been accessed.
|
* other than the current one has been accessed.
|
||||||
@@ -59,6 +61,21 @@ const Tabs = Module("tabs", {
|
|||||||
yield [i, browsers[i]];
|
yield [i, browsers[i]];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} The number of tabs in the current window.
|
||||||
|
*/
|
||||||
|
get count() config.tabbrowser.mTabs.length,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {Object} The local options store for the current tab.
|
||||||
|
*/
|
||||||
|
get options() {
|
||||||
|
let store = this.localStore;
|
||||||
|
if (!("options" in store))
|
||||||
|
store.options = {};
|
||||||
|
return store.options;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property {boolean} Whether the tab numbering XBL binding has been
|
* @property {boolean} Whether the tab numbering XBL binding has been
|
||||||
* applied.
|
* applied.
|
||||||
@@ -75,20 +92,7 @@ const Tabs = Module("tabs", {
|
|||||||
".tabbrowser-tab[busy] > .tab-icon > .tab-icon-image { list-style-image: url('chrome://global/skin/icons/loading_16.png') !important; }");
|
".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),
|
||||||
* @property {number} The number of tabs in the current window.
|
|
||||||
*/
|
|
||||||
get count() config.tabbrowser.mTabs.length,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @property {Object} The local options store for the current tab.
|
|
||||||
*/
|
|
||||||
get options() {
|
|
||||||
let store = this.localStore;
|
|
||||||
if (!("options" in store))
|
|
||||||
store.options = {};
|
|
||||||
return store.options;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the local state store for the tab at the specified
|
* Returns the local state store for the tab at the specified
|
||||||
@@ -123,37 +127,33 @@ const Tabs = Module("tabs", {
|
|||||||
get closedTabs() services.get("json").decode(services.get("sessionStore").getClosedTabData(window)),
|
get closedTabs() services.get("json").decode(services.get("sessionStore").getClosedTabData(window)),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the index of <b>tab</b> or the index of the currently
|
* Clones the specified <b>tab</b> and append it to the tab list.
|
||||||
* selected tab if <b>tab</b> is not specified. This is a 0-based
|
|
||||||
* index.
|
|
||||||
*
|
*
|
||||||
* @param {Object} tab A tab from the current tab list.
|
* @param {Object} tab The tab to clone.
|
||||||
* @returns {number}
|
* @param {boolean} activate Whether to select the newly cloned tab.
|
||||||
*/
|
*/
|
||||||
index: function (tab) {
|
cloneTab: function (tab, activate) {
|
||||||
if (tab)
|
let newTab = config.tabbrowser.addTab();
|
||||||
return Array.indexOf(config.tabbrowser.mTabs, tab);
|
Tabs.copyTab(newTab, tab);
|
||||||
else
|
|
||||||
return config.tabbrowser.mTabContainer.selectedIndex;
|
if (activate)
|
||||||
|
config.tabbrowser.mTabContainer.selectedItem = newTab;
|
||||||
|
|
||||||
|
return newTab;
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: implement filter
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of all tabs in the tab list.
|
* Detaches the specified <b>tab</b> and open it in a new window. If no
|
||||||
|
* tab is specified the currently selected tab is detached.
|
||||||
*
|
*
|
||||||
* @returns {Object[]}
|
* @param {Object} tab The tab to detach.
|
||||||
*/
|
*/
|
||||||
// FIXME: why not return the tab element?
|
detachTab: function (tab) {
|
||||||
// : unused? Remove me.
|
if (!tab)
|
||||||
get: function () {
|
tab = config.tabbrowser.mTabContainer.selectedItem;
|
||||||
let buffers = [];
|
|
||||||
for (let [i, browser] in this.browsers) {
|
services.get("windowWatcher")
|
||||||
let title = browser.contentTitle || "(Untitled)";
|
.openWindow(window, window.getBrowserURL(), null, "chrome,dialog=no,all", tab);
|
||||||
let uri = browser.currentURI.spec;
|
|
||||||
let number = i + 1;
|
|
||||||
buffers.push([number, title, uri]);
|
|
||||||
}
|
|
||||||
return buffers;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,6 +171,26 @@ const Tabs = Module("tabs", {
|
|||||||
return -1;
|
return -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If TabView exists, returns the Panorama window. If the Panorama
|
||||||
|
* is has not yet initialized, this function will not return until
|
||||||
|
* it has.
|
||||||
|
*
|
||||||
|
* @returns {Window}
|
||||||
|
*/
|
||||||
|
getGroups: function () {
|
||||||
|
if ("_groups" in this)
|
||||||
|
return this._groups;
|
||||||
|
if (window.TabView && TabView._initFrame)
|
||||||
|
TabView._initFrame();
|
||||||
|
let iframe = document.getElementById("tab-view");
|
||||||
|
this._groups = this._groups = iframe ? iframe.contentWindow : null;
|
||||||
|
if (this._groups)
|
||||||
|
while (!this._groups.TabItems)
|
||||||
|
dactyl.threadYield(false, true);
|
||||||
|
return this._groups;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the tab at the specified <b>index</b> or the currently
|
* Returns the tab at the specified <b>index</b> or the currently
|
||||||
* selected tab if <b>index</b> is not specified. This is a 0-based
|
* selected tab if <b>index</b> is not specified. This is a 0-based
|
||||||
@@ -180,12 +200,72 @@ const Tabs = Module("tabs", {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
getTab: function (index) {
|
getTab: function (index) {
|
||||||
if (index != undefined)
|
if (index != null)
|
||||||
return config.tabbrowser.mTabs[index];
|
return config.tabbrowser.mTabs[index];
|
||||||
else
|
else
|
||||||
return config.tabbrowser.mCurrentTab;
|
return config.tabbrowser.mCurrentTab;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of <b>tab</b> or the index of the currently
|
||||||
|
* selected tab if <b>tab</b> is not specified. This is a 0-based
|
||||||
|
* index.
|
||||||
|
*
|
||||||
|
* @param {<xul:tab/>} tab A tab from the current tab list.
|
||||||
|
* @param {boolean} visible Whether to consider only visible tabs.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
index: function (tab, visible) {
|
||||||
|
let tabs = this[visible ? "visibleTabs" : "allTabs"];
|
||||||
|
return tabs.indexOf(tab || config.tabbrowser.mCurrentTab);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param spec can either be:
|
||||||
|
* - an absolute integer
|
||||||
|
* - "" for the current tab
|
||||||
|
* - "+1" for the next tab
|
||||||
|
* - "-3" for the tab, which is 3 positions left of the current
|
||||||
|
* - "$" for the last tab
|
||||||
|
*/
|
||||||
|
indexFromSpec: function (spec, wrap) {
|
||||||
|
if (spec instanceof Node)
|
||||||
|
return this.allTabs.indexOf(spec);
|
||||||
|
|
||||||
|
let tabs = this.visibleTabs;
|
||||||
|
let position = this.index(null, true);
|
||||||
|
|
||||||
|
if (spec == null || spec === "")
|
||||||
|
return position;
|
||||||
|
|
||||||
|
if (typeof spec === "number")
|
||||||
|
position = spec;
|
||||||
|
else if (spec === "$")
|
||||||
|
position = tabs.length - 1;
|
||||||
|
else if (/^[+-]\d+$/.test(spec))
|
||||||
|
position += parseInt(spec, 10);
|
||||||
|
else if (/^\d+$/.test(spec))
|
||||||
|
position = parseInt(spec, 10);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (position >= tabs.length)
|
||||||
|
position = wrap ? position % tabs.length : tabs.length - 1;
|
||||||
|
else if (position < 0)
|
||||||
|
position = wrap ? (position % tabs.length) + tabs.length : 0;
|
||||||
|
|
||||||
|
return this.allTabs.indexOf(tabs[position]);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all tabs from the tab list except the specified <b>tab</b>.
|
||||||
|
*
|
||||||
|
* @param {Object} tab The tab to keep.
|
||||||
|
*/
|
||||||
|
keepOnly: function (tab) {
|
||||||
|
config.tabbrowser.removeAllTabsBut(tab);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists all tabs matching <b>filter</b>.
|
* Lists all tabs matching <b>filter</b>.
|
||||||
*
|
*
|
||||||
@@ -206,7 +286,7 @@ const Tabs = Module("tabs", {
|
|||||||
* list.
|
* list.
|
||||||
*/
|
*/
|
||||||
move: function (tab, spec, wrap) {
|
move: function (tab, spec, wrap) {
|
||||||
let index = Tabs.indexFromSpec(spec, wrap);
|
let index = tabs.indexFromSpec(spec, wrap);
|
||||||
config.tabbrowser.moveTabTo(tab, index);
|
config.tabbrowser.moveTabTo(tab, index);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -223,96 +303,31 @@ const Tabs = Module("tabs", {
|
|||||||
*/
|
*/
|
||||||
// FIXME: what is quitOnLastTab {1,2} all about then, eh? --djk
|
// FIXME: what is quitOnLastTab {1,2} all about then, eh? --djk
|
||||||
remove: function (tab, count, focusLeftTab, quitOnLastTab) {
|
remove: function (tab, count, focusLeftTab, quitOnLastTab) {
|
||||||
let removeOrBlankTab = {
|
count = Math.max(count, 1);
|
||||||
Firefox: function (tab) {
|
|
||||||
if (config.tabbrowser.mTabs.length > 1)
|
|
||||||
config.tabbrowser.removeTab(tab);
|
|
||||||
else {
|
|
||||||
if (buffer.URL != "about:blank" ||
|
|
||||||
window.getWebNavigation().sessionHistory.count > 0) {
|
|
||||||
dactyl.open("about:blank", dactyl.NEW_BACKGROUND_TAB);
|
|
||||||
config.tabbrowser.removeTab(tab);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
dactyl.beep();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Thunderbird: function (tab) {
|
|
||||||
if (config.tabbrowser.mTabs.length > 1)
|
|
||||||
config.tabbrowser.removeTab(tab);
|
|
||||||
else
|
|
||||||
dactyl.beep();
|
|
||||||
},
|
|
||||||
Songbird: function (tab) {
|
|
||||||
if (config.tabbrowser.mTabs.length > 1)
|
|
||||||
config.tabbrowser.removeTab(tab);
|
|
||||||
else {
|
|
||||||
if (buffer.URL != "about:blank" || window.getWebNavigation().sessionHistory.count > 0) {
|
|
||||||
dactyl.open("about:blank", dactyl.NEW_BACKGROUND_TAB);
|
|
||||||
config.tabbrowser.removeTab(tab);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
dactyl.beep();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}[config.hostApplication] || function () {};
|
|
||||||
|
|
||||||
if (typeof count != "number" || count < 1)
|
if (quitOnLastTab >= 1 && this.count <= count) {
|
||||||
count = 1;
|
|
||||||
|
|
||||||
if (quitOnLastTab >= 1 && config.tabbrowser.mTabs.length <= count) {
|
|
||||||
if (dactyl.windows.length > 1)
|
if (dactyl.windows.length > 1)
|
||||||
window.close();
|
window.close();
|
||||||
else
|
else
|
||||||
dactyl.quit(quitOnLastTab == 2);
|
dactyl.quit(quitOnLastTab == 2);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = this.index(tab);
|
let tabs = this.visibleTabs
|
||||||
if (focusLeftTab) {
|
if (tabs.indexOf(tab) < 0)
|
||||||
let lastRemovedTab = 0;
|
tabs = this.allTabs;
|
||||||
for (let i = index; i > index - count && i >= 0; i--) {
|
let index = tabs.indexOf(tab);
|
||||||
removeOrBlankTab(this.getTab(i));
|
|
||||||
lastRemovedTab = i > 0 ? i : 1;
|
|
||||||
}
|
|
||||||
config.tabbrowser.mTabContainer.selectedIndex = lastRemovedTab - 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let i = index + count - 1;
|
|
||||||
if (i >= this.count)
|
|
||||||
i = this.count - 1;
|
|
||||||
|
|
||||||
for (; i >= index; i--)
|
let next = index + (focusLeftTab ? -count : count);
|
||||||
removeOrBlankTab(this.getTab(i));
|
if (!(next in tabs))
|
||||||
config.tabbrowser.mTabContainer.selectedIndex = index;
|
next = index + (focusLeftTab ? 1 : -1);
|
||||||
}
|
if (next in tabs)
|
||||||
},
|
config.tabbrowser.mTabContainer.selectedItem = tabs[next];
|
||||||
|
|
||||||
/**
|
if (focusLeftTab)
|
||||||
* Removes all tabs from the tab list except the specified <b>tab</b>.
|
tabs.slice(Math.max(0, index+1 - count), index+1).forEach(config.removeTab);
|
||||||
*
|
|
||||||
* @param {Object} tab The tab to keep.
|
|
||||||
*/
|
|
||||||
keepOnly: function (tab) {
|
|
||||||
config.tabbrowser.removeAllTabsBut(tab);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects the tab at the position specified by <b>spec</b>.
|
|
||||||
*
|
|
||||||
* @param {string} spec See {@link Tabs.indexFromSpec}
|
|
||||||
* @param {boolean} wrap Whether an out of bounds <b>spec</b> causes
|
|
||||||
* the selection position to wrap around the start/end of the tab
|
|
||||||
* list.
|
|
||||||
*/
|
|
||||||
select: function (spec, wrap) {
|
|
||||||
let index = Tabs.indexFromSpec(spec, wrap);
|
|
||||||
// FIXME:
|
|
||||||
if (index == -1)
|
|
||||||
dactyl.beep();
|
|
||||||
else
|
else
|
||||||
config.tabbrowser.mTabContainer.selectedIndex = index;
|
tabs.slice(index, index + count).forEach(config.removeTab);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -353,6 +368,40 @@ const Tabs = Module("tabs", {
|
|||||||
config.tabbrowser.reloadAllTabs();
|
config.tabbrowser.reloadAllTabs();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the tab at the position specified by <b>spec</b>.
|
||||||
|
*
|
||||||
|
* @param {string} spec See {@link Tabs.indexFromSpec}
|
||||||
|
* @param {boolean} wrap Whether an out of bounds <b>spec</b> causes
|
||||||
|
* the selection position to wrap around the start/end of the tab
|
||||||
|
* list.
|
||||||
|
*/
|
||||||
|
select: function (spec, wrap) {
|
||||||
|
let index = tabs.indexFromSpec(spec, wrap);
|
||||||
|
if (index == -1)
|
||||||
|
dactyl.beep();
|
||||||
|
else
|
||||||
|
config.tabbrowser.mTabContainer.selectedIndex = index;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the alternate tab.
|
||||||
|
*/
|
||||||
|
selectAlternateTab: function () {
|
||||||
|
dactyl.assert(tabs.alternate != null && tabs.getTab() != tabs.alternate,
|
||||||
|
"E23: No alternate page");
|
||||||
|
|
||||||
|
// NOTE: this currently relies on v.tabs.index() returning the
|
||||||
|
// currently selected tab index when passed null
|
||||||
|
let index = tabs.index(tabs.alternate);
|
||||||
|
|
||||||
|
// TODO: since a tab close is more like a bdelete for us we
|
||||||
|
// should probably reopen the closed tab when a 'deleted'
|
||||||
|
// alternate is selected
|
||||||
|
dactyl.assert(index >= 0, "E86: Buffer does not exist"); // TODO: This should read "Buffer N does not exist"
|
||||||
|
tabs.select(index);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops loading the specified tab.
|
* Stops loading the specified tab.
|
||||||
*
|
*
|
||||||
@@ -398,7 +447,7 @@ const Tabs = Module("tabs", {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buffer = this._lastBufferSwitchArgs;
|
buffer = this._lastBufferSwitchArgs;
|
||||||
if (allowNonUnique === undefined || allowNonUnique == null) // XXX
|
if (allowNonUnique == null) // XXX
|
||||||
allowNonUnique = this._lastBufferSwitchSpecial;
|
allowNonUnique = this._lastBufferSwitchSpecial;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,14 +456,12 @@ const Tabs = Module("tabs", {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!count || count < 1)
|
count = Math.max(1, count || 1);
|
||||||
count = 1;
|
reverse = Boolean(reverse);
|
||||||
if (typeof reverse != "boolean")
|
|
||||||
reverse = false;
|
|
||||||
|
|
||||||
let matches = buffer.match(/^(\d+):?/);
|
let matches = buffer.match(/^(\d+):?/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
tabs.select(parseInt(matches[1], 10) - 1, false); // make it zero-based
|
tabs.select(this.allTabs[parseInt(matches[1], 10) - 1], false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,8 +471,9 @@ const Tabs = Module("tabs", {
|
|||||||
let nbrowsers = config.tabbrowser.browsers.length;
|
let nbrowsers = config.tabbrowser.browsers.length;
|
||||||
for (let [i, ] in tabs.browsers) {
|
for (let [i, ] in tabs.browsers) {
|
||||||
let index = (i + first) % nbrowsers;
|
let index = (i + first) % nbrowsers;
|
||||||
let url = config.tabbrowser.getBrowserAtIndex(index).contentDocument.location.href;
|
let browser = config.tabbrowser.getBrowserAtIndex(index);
|
||||||
let title = config.tabbrowser.getBrowserAtIndex(index).contentDocument.title.toLowerCase();
|
let url = browser.contentDocument.location.href;
|
||||||
|
let title = browser.contentDocument.title.toLowerCase();
|
||||||
if (url == buffer) {
|
if (url == buffer) {
|
||||||
tabs.select(index, false);
|
tabs.select(index, false);
|
||||||
return;
|
return;
|
||||||
@@ -434,69 +482,19 @@ const Tabs = Module("tabs", {
|
|||||||
if (url.indexOf(buffer) >= 0 || title.indexOf(lowerBuffer) >= 0)
|
if (url.indexOf(buffer) >= 0 || title.indexOf(lowerBuffer) >= 0)
|
||||||
matches.push(index);
|
matches.push(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matches.length == 0)
|
if (matches.length == 0)
|
||||||
dactyl.echoerr("E94: No matching buffer for " + buffer);
|
dactyl.echoerr("E94: No matching buffer for " + buffer);
|
||||||
else if (matches.length > 1 && !allowNonUnique)
|
else if (matches.length > 1 && !allowNonUnique)
|
||||||
dactyl.echoerr("E93: More than one match for " + buffer);
|
dactyl.echoerr("E93: More than one match for " + buffer);
|
||||||
else {
|
else {
|
||||||
if (reverse) {
|
let index = (count - 1) % matches.length;
|
||||||
|
if (reverse)
|
||||||
index = matches.length - count;
|
index = matches.length - count;
|
||||||
while (index < 0)
|
|
||||||
index += matches.length;
|
index = Array.indexOf(config.tabbrowser.browsers, matches[index]);
|
||||||
|
tabs.select(index, false);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
index = (count - 1) % matches.length;
|
|
||||||
|
|
||||||
tabs.select(matches[index], false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clones the specified <b>tab</b> and append it to the tab list.
|
|
||||||
*
|
|
||||||
* @param {Object} tab The tab to clone.
|
|
||||||
* @param {boolean} activate Whether to select the newly cloned tab.
|
|
||||||
*/
|
|
||||||
cloneTab: function (tab, activate) {
|
|
||||||
let newTab = config.tabbrowser.addTab();
|
|
||||||
Tabs.copyTab(newTab, tab);
|
|
||||||
|
|
||||||
if (activate)
|
|
||||||
config.tabbrowser.mTabContainer.selectedItem = newTab;
|
|
||||||
|
|
||||||
return newTab;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detaches the specified <b>tab</b> and open it in a new window. If no
|
|
||||||
* tab is specified the currently selected tab is detached.
|
|
||||||
*
|
|
||||||
* @param {Object} tab The tab to detach.
|
|
||||||
*/
|
|
||||||
detachTab: function (tab) {
|
|
||||||
if (!tab)
|
|
||||||
tab = config.tabbrowser.mTabContainer.selectedItem;
|
|
||||||
|
|
||||||
services.get("windowWatcher")
|
|
||||||
.openWindow(window, window.getBrowserURL(), null, "chrome,dialog=no,all", tab);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects the alternate tab.
|
|
||||||
*/
|
|
||||||
selectAlternateTab: function () {
|
|
||||||
dactyl.assert(tabs.alternate != null && tabs.getTab() != tabs.alternate,
|
|
||||||
"E23: No alternate page");
|
|
||||||
|
|
||||||
// NOTE: this currently relies on v.tabs.index() returning the
|
|
||||||
// currently selected tab index when passed null
|
|
||||||
let index = tabs.index(tabs.alternate);
|
|
||||||
|
|
||||||
// TODO: since a tab close is more like a bdelete for us we
|
|
||||||
// should probably reopen the closed tab when a 'deleted'
|
|
||||||
// alternate is selected
|
|
||||||
dactyl.assert(index >= 0, "E86: Buffer does not exist"); // TODO: This should read "Buffer N does not exist"
|
|
||||||
tabs.select(index);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// NOTE: when restarting a session FF selects the first tab and then the
|
// NOTE: when restarting a session FF selects the first tab and then the
|
||||||
@@ -520,41 +518,6 @@ const Tabs = Module("tabs", {
|
|||||||
|
|
||||||
let tabState = services.get("sessionStore").getTabState(from);
|
let tabState = services.get("sessionStore").getTabState(from);
|
||||||
services.get("sessionStore").setTabState(to, tabState);
|
services.get("sessionStore").setTabState(to, tabState);
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param spec can either be:
|
|
||||||
* - an absolute integer
|
|
||||||
* - "" for the current tab
|
|
||||||
* - "+1" for the next tab
|
|
||||||
* - "-3" for the tab, which is 3 positions left of the current
|
|
||||||
* - "$" for the last tab
|
|
||||||
*/
|
|
||||||
indexFromSpec: function (spec, wrap) {
|
|
||||||
let position = config.tabbrowser.mTabContainer.selectedIndex;
|
|
||||||
let length = config.tabbrowser.mTabs.length;
|
|
||||||
let last = length - 1;
|
|
||||||
|
|
||||||
if (spec === undefined || spec === "")
|
|
||||||
return position;
|
|
||||||
|
|
||||||
if (typeof spec === "number")
|
|
||||||
position = spec;
|
|
||||||
else if (spec === "$")
|
|
||||||
position = last;
|
|
||||||
else if (/^[+-]\d+$/.test(spec))
|
|
||||||
position += parseInt(spec, 10);
|
|
||||||
else if (/^\d+$/.test(spec))
|
|
||||||
position = parseInt(spec, 10);
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (position > last)
|
|
||||||
position = wrap ? position % length : last;
|
|
||||||
else if (position < 0)
|
|
||||||
position = wrap ? (position % length) + length : 0;
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
commands: function () {
|
commands: function () {
|
||||||
@@ -1037,7 +1000,7 @@ const Tabs = Module("tabs", {
|
|||||||
let pref = "browser.tabStrip.autoHide";
|
let pref = "browser.tabStrip.autoHide";
|
||||||
if (options.getPref(pref) == null) // Try for FF 3.0 & 3.1
|
if (options.getPref(pref) == null) // Try for FF 3.0 & 3.1
|
||||||
pref = "browser.tabs.autoHide";
|
pref = "browser.tabs.autoHide";
|
||||||
options.safeSetPref(pref, value == 1);
|
options.safeSetPref(pref, value == 1, "See 'showtabline' option.");
|
||||||
tabStrip.collapsed = false;
|
tabStrip.collapsed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1098,8 +1061,10 @@ const Tabs = Module("tabs", {
|
|||||||
restriction = 2;
|
restriction = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
options.safeSetPref("browser.link.open_newwindow", open, "See 'popups' option.");
|
options.safeSetPref("browser.link.open_newwindow", open,
|
||||||
options.safeSetPref("browser.link.open_newwindow.restriction", restriction, "See 'popups' option.");
|
"See 'popups' option.");
|
||||||
|
options.safeSetPref("browser.link.open_newwindow.restriction", restriction,
|
||||||
|
"See 'popups' option.");
|
||||||
return values;
|
return values;
|
||||||
},
|
},
|
||||||
completer: function (context) [
|
completer: function (context) [
|
||||||
|
|||||||
@@ -452,7 +452,8 @@ const Util = Module("util", {
|
|||||||
let result = doc.evaluate(expression, elem,
|
let result = doc.evaluate(expression, elem,
|
||||||
function lookupNamespaceURI(prefix) {
|
function lookupNamespaceURI(prefix) {
|
||||||
return {
|
return {
|
||||||
xhtml: "http://www.w3.org/1999/xhtml",
|
xul: XUL.uri,
|
||||||
|
xhtml: XHTML.uri,
|
||||||
xhtml2: "http://www.w3.org/2002/06/xhtml2",
|
xhtml2: "http://www.w3.org/2002/06/xhtml2",
|
||||||
dactyl: NS.uri
|
dactyl: NS.uri
|
||||||
}[prefix] || null;
|
}[prefix] || null;
|
||||||
|
|||||||
@@ -25,14 +25,20 @@
|
|||||||
<p>Search forward for the first occurrence of <a>pattern</a>.</p>
|
<p>Search forward for the first occurrence of <a>pattern</a>.</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If <str>\c</str> appears anywhere in the pattern the whole pattern is handled as though
|
The following escape sequences can be used to modify the
|
||||||
<o>ignorecase</o> is on. <str>\C</str> forces case-sensitive matching for the whole pattern.
|
behavior of the search. When flags conflict, the last to
|
||||||
</p>
|
appear is the one that takes effect.
|
||||||
<p>
|
|
||||||
If <str>\l</str> appears in the pattern only the text of links is searched for a
|
|
||||||
match as though <o>linksearch</o> is on. <str>\L</str> forces the entire page to be searched
|
|
||||||
for a match.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>\c</dt> <dd>Perform case insensitive search (default
|
||||||
|
if <o>ignorecase</o> is set).</dd>
|
||||||
|
<dt>\C</dt> <dd>Perform case sensitive search</dd>
|
||||||
|
<dt>\l</dt> <dd>Search only in links, as defined by
|
||||||
|
<o>hinttags</o>. (default if <o>linksearch</o> is
|
||||||
|
set).</dd>
|
||||||
|
<dt>\L</dt> <dd>Do not search only in links.</dd>
|
||||||
|
</dl>
|
||||||
</description>
|
</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
@@ -54,7 +60,7 @@
|
|||||||
<tags>n</tags>
|
<tags>n</tags>
|
||||||
<spec>n</spec>
|
<spec>n</spec>
|
||||||
<description>
|
<description>
|
||||||
<p>Find next. Repeat the last search 1 time (until count is supported).</p>
|
<p>Find next. Repeat the last search.</p>
|
||||||
</description>
|
</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
@@ -63,10 +69,7 @@
|
|||||||
<tags>N</tags>
|
<tags>N</tags>
|
||||||
<spec>N</spec>
|
<spec>N</spec>
|
||||||
<description>
|
<description>
|
||||||
<p>
|
<p>Find previous. Repeat the last search in the opposite direction.</p>
|
||||||
Find previous. Repeat the last search 1 time (until count is supported) in the
|
|
||||||
opposite direction.
|
|
||||||
</p>
|
|
||||||
</description>
|
</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
|||||||
@@ -14,83 +14,53 @@ const Config = Module("config", ConfigBase, {
|
|||||||
hostApplication: "Thunderbird", // TODO: can this be found out otherwise? gBrandBundle.getString("brandShortName");
|
hostApplication: "Thunderbird", // TODO: can this be found out otherwise? gBrandBundle.getString("brandShortName");
|
||||||
// Yes, but it will be localized unlike all other strings. So, it's best left until we i18n dactyl. --djk
|
// Yes, but it will be localized unlike all other strings. So, it's best left until we i18n dactyl. --djk
|
||||||
|
|
||||||
get mainWindowId() this.isComposeWindow ? "msgcomposeWindow" : "messengerWindow",
|
autocommands: {
|
||||||
|
DOMLoad: "Triggered when a page's DOM content has fully loaded",
|
||||||
|
FolderLoad: "Triggered after switching folders in Thunderbird",
|
||||||
|
PageLoadPre: "Triggered after a page load is initiated",
|
||||||
|
PageLoad: "Triggered when a page gets (re)loaded/opened",
|
||||||
|
Enter: "Triggered after Thunderbird starts",
|
||||||
|
Leave: "Triggered before exiting Thunderbird",
|
||||||
|
LeavePre: "Triggered before exiting Thunderbird",
|
||||||
|
},
|
||||||
|
|
||||||
|
get browser() getBrowser(),
|
||||||
|
|
||||||
|
dialogs: {
|
||||||
|
about: ["About Thunderbird",
|
||||||
|
function () { window.openAboutDialog(); }],
|
||||||
|
addons: ["Manage Add-ons",
|
||||||
|
function () { window.openAddonsMgr(); }],
|
||||||
|
addressbook: ["Address book",
|
||||||
|
function () { window.toAddressBook(); }],
|
||||||
|
checkupdates: ["Check for updates",
|
||||||
|
function () { window.checkForUpdates(); }],
|
||||||
|
console: ["JavaScript console",
|
||||||
|
function () { window.toJavaScriptConsole(); }],
|
||||||
|
dominspector: ["DOM Inspector",
|
||||||
|
function () { window.inspectDOMDocument(content.document); }],
|
||||||
|
downloads: ["Manage Downloads",
|
||||||
|
function () { window.toOpenWindowByType('Download:Manager', 'chrome://mozapps/content/downloads/downloads.xul', 'chrome,dialog=no,resizable'); }],
|
||||||
|
preferences: ["Show Thunderbird preferences dialog",
|
||||||
|
function () { openOptionsDialog(); }],
|
||||||
|
printsetup: ["Setup the page size and orientation before printing",
|
||||||
|
function () { PrintUtils.showPageSetup(); }],
|
||||||
|
print: ["Show print dialog",
|
||||||
|
function () { PrintUtils.print(); }],
|
||||||
|
saveframe: ["Save frame to disk",
|
||||||
|
function () { window.saveFrameDocument(); }],
|
||||||
|
savepage: ["Save page to disk",
|
||||||
|
function () { window.saveDocument(window.content.document); }],
|
||||||
|
},
|
||||||
|
|
||||||
/*** optional options, there are checked for existence and a fallback provided ***/
|
|
||||||
features: ["hints", "mail", "marks", "addressbook", "tabs"],
|
|
||||||
defaults: {
|
defaults: {
|
||||||
guioptions: "frb",
|
guioptions: "frb",
|
||||||
showtabline: 1,
|
showtabline: 1,
|
||||||
titlestring: "Muttator"
|
titlestring: "Muttator"
|
||||||
},
|
},
|
||||||
|
|
||||||
guioptions: {
|
/*** optional options, there are checked for existence and a fallback provided ***/
|
||||||
m: ["MenuBar", ["mail-toolbar-menubar2"]],
|
features: ["hints", "mail", "marks", "addressbook", "tabs"],
|
||||||
T: ["Toolbar" , ["mail-bar2"]],
|
|
||||||
f: ["Folder list", ["folderPaneBox", "folderpane_splitter"]],
|
|
||||||
F: ["Folder list header", ["folderPaneHeader"]]
|
|
||||||
},
|
|
||||||
|
|
||||||
get isComposeWindow() window.wintype == "msgcompose",
|
|
||||||
get browserModes() [modes.MESSAGE],
|
|
||||||
get mailModes() [modes.NORMAL],
|
|
||||||
// focusContent() focuses this widget
|
|
||||||
get mainWidget() this.isComposeWindow ? document.getElementById("content-frame") : GetThreadTree(),
|
|
||||||
get visualbellWindow() document.getElementById(this.mainWindowId),
|
|
||||||
styleableChrome: ["chrome://messenger/content/messenger.xul",
|
|
||||||
"chrome://messenger/content/messengercompose/messengercompose.xul"],
|
|
||||||
|
|
||||||
autocommands: [["DOMLoad", "Triggered when a page's DOM content has fully loaded"],
|
|
||||||
["FolderLoad", "Triggered after switching folders in Thunderbird"],
|
|
||||||
["PageLoadPre", "Triggered after a page load is initiated"],
|
|
||||||
["PageLoad", "Triggered when a page gets (re)loaded/opened"],
|
|
||||||
["MuttatorEnter", "Triggered after Thunderbird starts"],
|
|
||||||
["MuttatorLeave", "Triggered before exiting Thunderbird"],
|
|
||||||
["MuttatorLeavePre", "Triggered before exiting Thunderbird"]],
|
|
||||||
dialogs: [
|
|
||||||
["about", "About Thunderbird",
|
|
||||||
function () { window.openAboutDialog(); }],
|
|
||||||
["addons", "Manage Add-ons",
|
|
||||||
function () { window.openAddonsMgr(); }],
|
|
||||||
["addressbook", "Address book",
|
|
||||||
function () { window.toAddressBook(); }],
|
|
||||||
["checkupdates", "Check for updates",
|
|
||||||
function () { window.checkForUpdates(); }],
|
|
||||||
/*["cleardata", "Clear private data",
|
|
||||||
function () { Cc[GLUE_CID].getService(Ci.nsIBrowserGlue).sanitize(window || null); }],*/
|
|
||||||
["console", "JavaScript console",
|
|
||||||
function () { window.toJavaScriptConsole(); }],
|
|
||||||
/*["customizetoolbar", "Customize the Toolbar",
|
|
||||||
function () { BrowserCustomizeToolbar(); }],*/
|
|
||||||
["dominspector", "DOM Inspector",
|
|
||||||
function () { window.inspectDOMDocument(content.document); }],
|
|
||||||
["downloads", "Manage Downloads",
|
|
||||||
function () { window.toOpenWindowByType('Download:Manager', 'chrome://mozapps/content/downloads/downloads.xul', 'chrome,dialog=no,resizable'); }],
|
|
||||||
/*["import", "Import Preferences, Bookmarks, History, etc. from other browsers",
|
|
||||||
function () { BrowserImport(); }],
|
|
||||||
["openfile", "Open the file selector dialog",
|
|
||||||
function () { BrowserOpenFileWindow(); }],
|
|
||||||
["pageinfo", "Show information about the current page",
|
|
||||||
function () { BrowserPageInfo(); }],
|
|
||||||
["pagesource", "View page source",
|
|
||||||
function () { BrowserViewSourceOfDocument(content.document); }],*/
|
|
||||||
["preferences", "Show Thunderbird preferences dialog",
|
|
||||||
function () { openOptionsDialog(); }],
|
|
||||||
/*["printpreview", "Preview the page before printing",
|
|
||||||
function () { PrintUtils.printPreview(onEnterPrintPreview, onExitPrintPreview); }],*/
|
|
||||||
["printsetup", "Setup the page size and orientation before printing",
|
|
||||||
function () { PrintUtils.showPageSetup(); }],
|
|
||||||
["print", "Show print dialog",
|
|
||||||
function () { PrintUtils.print(); }],
|
|
||||||
["saveframe", "Save frame to disk",
|
|
||||||
function () { window.saveFrameDocument(); }],
|
|
||||||
["savepage", "Save page to disk",
|
|
||||||
function () { window.saveDocument(window.content.document); }],
|
|
||||||
/*["searchengines", "Manage installed search engines",
|
|
||||||
function () { openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
|
|
||||||
["selectionsource", "View selection source",
|
|
||||||
function () { buffer.viewSelectionSource(); }]*/
|
|
||||||
],
|
|
||||||
|
|
||||||
focusChange: function (win) {
|
focusChange: function (win) {
|
||||||
// we switch to -- MESSAGE -- mode for Muttator, when the main HTML widget gets focus
|
// we switch to -- MESSAGE -- mode for Muttator, when the main HTML widget gets focus
|
||||||
@@ -102,23 +72,28 @@ const Config = Module("config", ConfigBase, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
get browser() getBrowser(),
|
guioptions: {
|
||||||
tabbrowser: {
|
m: ["MenuBar", ["mail-toolbar-menubar2"]],
|
||||||
__proto__: document.getElementById("tabmail"),
|
T: ["Toolbar" , ["mail-bar2"]],
|
||||||
get mTabContainer() this.tabContainer,
|
f: ["Folder list", ["folderPaneBox", "folderpane_splitter"]],
|
||||||
get mTabs() this.tabContainer.childNodes,
|
F: ["Folder list header", ["folderPaneHeader"]]
|
||||||
get mCurrentTab() this.tabContainer.selectedItem,
|
|
||||||
get mStrip() this.tabStrip,
|
|
||||||
get browsers() [browser for (browser in Iterator(this.mTabs))]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// they are sorted by relevance, not alphabetically
|
// they are sorted by relevance, not alphabetically
|
||||||
helpFiles: ["intro.html", "version.html"],
|
helpFiles: ["intro.html", "version.html"],
|
||||||
|
|
||||||
|
get isComposeWindow() window.wintype == "msgcompose",
|
||||||
|
|
||||||
|
get mainWidget() this.isComposeWindow ? document.getElementById("content-frame") : GetThreadTree(),
|
||||||
|
|
||||||
|
get mainWindowId() this.isComposeWindow ? "msgcomposeWindow" : "messengerWindow",
|
||||||
|
|
||||||
modes: [
|
modes: [
|
||||||
["MESSAGE", { char: "m" }],
|
["MESSAGE", { char: "m" }],
|
||||||
["COMPOSE"]
|
["COMPOSE"]
|
||||||
],
|
],
|
||||||
|
get browserModes() [modes.MESSAGE],
|
||||||
|
get mailModes() [modes.NORMAL],
|
||||||
|
|
||||||
// NOTE: as I don't use TB I have no idea how robust this is. --djk
|
// NOTE: as I don't use TB I have no idea how robust this is. --djk
|
||||||
get outputHeight() {
|
get outputHeight() {
|
||||||
@@ -137,15 +112,35 @@ const Config = Module("config", ConfigBase, {
|
|||||||
return document.getElementById("appcontent").boxObject.height;
|
return document.getElementById("appcontent").boxObject.height;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeTab: function (tab) {
|
||||||
|
if (config.tabbrowser.mTabs.length > 1)
|
||||||
|
config.tabbrowser.removeTab(tab);
|
||||||
|
else
|
||||||
|
dactyl.beep();
|
||||||
|
},
|
||||||
|
|
||||||
get scripts() this.isComposeWindow ? ["compose/compose.js"] : [
|
get scripts() this.isComposeWindow ? ["compose/compose.js"] : [
|
||||||
"addressbook.js",
|
"addressbook.js",
|
||||||
"mail.js",
|
"mail.js",
|
||||||
"tabs.js",
|
"tabs.js",
|
||||||
],
|
],
|
||||||
|
|
||||||
|
styleableChrome: ["chrome://messenger/content/messenger.xul",
|
||||||
|
"chrome://messenger/content/messengercompose/messengercompose.xul"],
|
||||||
|
|
||||||
|
tabbrowser: {
|
||||||
|
__proto__: document.getElementById("tabmail"),
|
||||||
|
get mTabContainer() this.tabContainer,
|
||||||
|
get mTabs() this.tabContainer.childNodes,
|
||||||
|
get mCurrentTab() this.tabContainer.selectedItem,
|
||||||
|
get mStrip() this.tabStrip,
|
||||||
|
get browsers() [browser for (browser in Iterator(this.mTabs))]
|
||||||
|
},
|
||||||
|
|
||||||
// to allow Vim to :set ft=mail automatically
|
// to allow Vim to :set ft=mail automatically
|
||||||
tempFile: "mutt-ator-mail",
|
tempFile: "mutt-ator-mail",
|
||||||
|
|
||||||
|
get visualbellWindow() document.getElementById(this.mainWindowId),
|
||||||
}, {
|
}, {
|
||||||
}, {
|
}, {
|
||||||
commands: function () {
|
commands: function () {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
2009-XX-XX:
|
2009-XX-XX:
|
||||||
|
* Use only visible tabs for tab numbering, gt/gn/gN, etc.
|
||||||
|
* Group tabs in :buffer completions by panorama groups
|
||||||
* Replaced 'focuscontent' with 'strictfocus'
|
* Replaced 'focuscontent' with 'strictfocus'
|
||||||
* Replaced previous incremental search implementation
|
* Replaced previous incremental search implementation
|
||||||
* gf now toggles between source and content view.
|
* gf now toggles between source and content view.
|
||||||
'|' key binding has been removed.
|
'|' key binding has been removed.
|
||||||
* :open now only opens files begining with / or ./
|
* :open now only opens files begining with /, ./, or ~/
|
||||||
* Page zoom information is now shown in the status bar
|
* Page zoom information is now shown in the status bar
|
||||||
* Added ZO, ZI, ZM, and ZR as aliases for zO, zI, zM, and zR
|
* Added ZO, ZI, ZM, and ZR as aliases for zO, zI, zM, and zR
|
||||||
* Add basic plugin authorship documentation
|
* Add basic plugin authorship documentation
|
||||||
|
|||||||
@@ -13,8 +13,26 @@ const Config = Module("config", ConfigBase, {
|
|||||||
name: "Pentadactyl",
|
name: "Pentadactyl",
|
||||||
hostApplication: "Firefox",
|
hostApplication: "Firefox",
|
||||||
|
|
||||||
/*** optional options, there are checked for existence and a fallback provided ***/
|
get visualbellWindow() getBrowser().mPanelContainer,
|
||||||
features: ["bookmarks", "hints", "history", "marks", "quickmarks", "sanitizer", "session", "tabs", "tabs_undo", "windows"],
|
styleableChrome: ["chrome://browser/content/browser.xul"],
|
||||||
|
|
||||||
|
autocommands: {
|
||||||
|
BookmarkAdd: "Triggered after a page is bookmarked",
|
||||||
|
ColorScheme: "Triggered after a color scheme has been loaded",
|
||||||
|
DOMLoad: "Triggered when a page's DOM content has fully loaded",
|
||||||
|
DownloadPost: "Triggered when a download has completed",
|
||||||
|
Fullscreen: "Triggered when the browser's fullscreen state changes",
|
||||||
|
LocationChange: "Triggered when changing tabs or when navigation to a new location",
|
||||||
|
PageLoadPre: "Triggered after a page load is initiated",
|
||||||
|
PageLoad: "Triggered when a page gets (re)loaded/opened",
|
||||||
|
PrivateMode: "Triggered when private mode is activated or deactivated",
|
||||||
|
Sanitize: "Triggered when a sanitizeable item is cleared",
|
||||||
|
ShellCmdPost: "Triggered after executing a shell command with :!cmd",
|
||||||
|
Enter: "Triggered after Firefox starts",
|
||||||
|
LeavePre: "Triggered before exiting Firefox, just before destroying each module",
|
||||||
|
Leave: "Triggered before exiting Firefox",
|
||||||
|
},
|
||||||
|
|
||||||
defaults: {
|
defaults: {
|
||||||
complete: "slf",
|
complete: "slf",
|
||||||
guioptions: "rb",
|
guioptions: "rb",
|
||||||
@@ -22,30 +40,6 @@ const Config = Module("config", ConfigBase, {
|
|||||||
titlestring: "Pentadactyl"
|
titlestring: "Pentadactyl"
|
||||||
},
|
},
|
||||||
|
|
||||||
guioptions: {
|
|
||||||
m: ["Menubar", ["toolbar-menubar"]],
|
|
||||||
T: ["Toolbar", ["nav-bar"]],
|
|
||||||
B: ["Bookmark bar", ["PersonalToolbar"]]
|
|
||||||
},
|
|
||||||
|
|
||||||
get visualbellWindow() getBrowser().mPanelContainer,
|
|
||||||
styleableChrome: ["chrome://browser/content/browser.xul"],
|
|
||||||
|
|
||||||
autocommands: [["BookmarkAdd", "Triggered after a page is bookmarked"],
|
|
||||||
["ColorScheme", "Triggered after a color scheme has been loaded"],
|
|
||||||
["DOMLoad", "Triggered when a page's DOM content has fully loaded"],
|
|
||||||
["DownloadPost", "Triggered when a download has completed"],
|
|
||||||
["Fullscreen", "Triggered when the browser's fullscreen state changes"],
|
|
||||||
["LocationChange", "Triggered when changing tabs or when navigation to a new location"],
|
|
||||||
["PageLoadPre", "Triggered after a page load is initiated"],
|
|
||||||
["PageLoad", "Triggered when a page gets (re)loaded/opened"],
|
|
||||||
["PrivateMode", "Triggered when private mode is activated or deactivated"],
|
|
||||||
["Sanitize", "Triggered when a sanitizeable item is cleared"],
|
|
||||||
["ShellCmdPost", "Triggered after executing a shell command with :!cmd"],
|
|
||||||
["PentadactylEnter", "Triggered after Firefox starts"],
|
|
||||||
["PentadactylLeavePre","Triggered before exiting Firefox, just before destroying each module"],
|
|
||||||
["PentadactylLeave", "Triggered before exiting Firefox"]],
|
|
||||||
|
|
||||||
dialogs: {
|
dialogs: {
|
||||||
about: ["About Firefox",
|
about: ["About Firefox",
|
||||||
function () { window.openDialog("chrome://browser/content/aboutDialog.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
|
function () { window.openDialog("chrome://browser/content/aboutDialog.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
|
||||||
@@ -99,10 +93,34 @@ const Config = Module("config", ConfigBase, {
|
|||||||
function () { buffer.viewSelectionSource(); }]
|
function () { buffer.viewSelectionSource(); }]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
features: [
|
||||||
|
"bookmarks", "hints", "history", "marks", "quickmarks", "sanitizer",
|
||||||
|
"session", "tabs", "tabs_undo", "windows"
|
||||||
|
],
|
||||||
|
|
||||||
|
guioptions: {
|
||||||
|
m: ["Menubar", ["toolbar-menubar"]],
|
||||||
|
T: ["Toolbar", ["nav-bar"]],
|
||||||
|
B: ["Bookmark bar", ["PersonalToolbar"]]
|
||||||
|
},
|
||||||
|
|
||||||
hasTabbrowser: true,
|
hasTabbrowser: true,
|
||||||
|
|
||||||
ignoreKeys: {},
|
ignoreKeys: {},
|
||||||
|
|
||||||
|
removeTab: function (tab) {
|
||||||
|
if (config.tabbrowser.mTabs.length > 1)
|
||||||
|
config.tabbrowser.removeTab(tab);
|
||||||
|
else {
|
||||||
|
if (buffer.URL != "about:blank" || window.getWebNavigation().sessionHistory.count > 0) {
|
||||||
|
dactyl.open("about:blank", dactyl.NEW_BACKGROUND_TAB);
|
||||||
|
config.tabbrowser.removeTab(tab);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dactyl.beep();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
scripts: [
|
scripts: [
|
||||||
"browser.js",
|
"browser.js",
|
||||||
"bookmarks.js",
|
"bookmarks.js",
|
||||||
@@ -114,7 +132,6 @@ const Config = Module("config", ConfigBase, {
|
|||||||
|
|
||||||
get tempFile() {
|
get tempFile() {
|
||||||
let prefix = this.name.toLowerCase();
|
let prefix = this.name.toLowerCase();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
prefix += "-" + window.content.document.location.hostname;
|
prefix += "-" + window.content.document.location.hostname;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
<!ENTITY dactyl.name "pentadactyl">
|
<!ENTITY dactyl.name "pentadactyl">
|
||||||
<!ENTITY dactyl.idname "PENTADACTYL">
|
<!ENTITY dactyl.idname "PENTADACTYL">
|
||||||
<!ENTITY dactyl.appname "Pentadactyl">
|
<!ENTITY dactyl.appname "Pentadactyl">
|
||||||
|
<!ENTITY dactyl.apphome "http://dactyl.googlecode.com/">
|
||||||
|
<!ENTITY dactyl.maillist "pentadactyl@googlegroups.com">
|
||||||
<!ENTITY dactyl.host "&brandShortName;">
|
<!ENTITY dactyl.host "&brandShortName;">
|
||||||
<!ENTITY dactyl.hostbin "firefox">
|
<!ENTITY dactyl.hostbin "firefox">
|
||||||
<!ENTITY dactyl.statusBefore "statusbar-display">
|
<!ENTITY dactyl.statusBefore "statusbar-display">
|
||||||
|
|||||||
@@ -19,9 +19,9 @@
|
|||||||
<dt>PrivateMode</dt> <dd>Triggered when private mode is activated or deactivated</dd>
|
<dt>PrivateMode</dt> <dd>Triggered when private mode is activated or deactivated</dd>
|
||||||
<dt>Sanitize</dt> <dd>Triggered when privata data are sanitized</dd>
|
<dt>Sanitize</dt> <dd>Triggered when privata data are sanitized</dd>
|
||||||
<dt>ShellCmdPost</dt> <dd>Triggered after executing a shell command with <ex>:!</ex><a>cmd</a></dd>
|
<dt>ShellCmdPost</dt> <dd>Triggered after executing a shell command with <ex>:!</ex><a>cmd</a></dd>
|
||||||
<dt>&dactyl.appname;Enter</dt> <dd>Triggered after &dactyl.host; starts</dd>
|
<dt>Enter</dt> <dd>Triggered after &dactyl.host; starts</dd>
|
||||||
<dt>&dactyl.appname;LeavePre</dt><dd>Triggered before exiting &dactyl.host;, just before destroying each module</dd>
|
<dt>LeavePre</dt> <dd>Triggered before exiting &dactyl.host;, just before destroying each module</dd>
|
||||||
<dt>&dactyl.appname;Leave</dt> <dd>Triggered before exiting &dactyl.host;</dd>
|
<dt>Leave</dt> <dd>Triggered before exiting &dactyl.host;</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl tag="autocommand-args" replace="autocommand-args">
|
<dl tag="autocommand-args" replace="autocommand-args">
|
||||||
|
|||||||
@@ -14,48 +14,28 @@
|
|||||||
<link topic="http://vimperator.org">&dactyl.appname;</link> is a free browser add-on for &dactyl.host;,
|
<link topic="http://vimperator.org">&dactyl.appname;</link> is a free browser add-on for &dactyl.host;,
|
||||||
which makes it look and behave like the
|
which makes it look and behave like the
|
||||||
<link topic="http://www.vim.org">Vim</link>
|
<link topic="http://www.vim.org">Vim</link>
|
||||||
text editor. It has similar key bindings, and you could call it a modal
|
text editor.
|
||||||
web browser, as key bindings differ according to which mode you are in.
|
|
||||||
|
|
||||||
<warning tag="warning">
|
<warning tag="warning">
|
||||||
To provide the most authentic Vim experience, the &dactyl.host; menubar and toolbar are hidden.
|
To provide the most authentic Vim experience, the &dactyl.host;
|
||||||
</warning>
|
menubar and toolbar are hidden.
|
||||||
|
|
||||||
<p>If you really need them, type: <ex>:set guioptions+=mT</ex> to get them back.</p>
|
|
||||||
<p>
|
<p>
|
||||||
If you don't like &dactyl.appname; at all, you can uninstall it by typing
|
If you really need them, type: <ex>:set guioptions+=mT</ex> to
|
||||||
<ex>:extdelete &dactyl.appname;</ex> or <ex>:extdisable &dactyl.appname;</ex> to disable it.
|
get them back.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If you like it but can't remember the shortcuts, then press
|
If you don't like &dactyl.appname; at all, you can uninstall it
|
||||||
|
by typing <ex>:extdelete &dactyl.appname;</ex> or disable it
|
||||||
|
with <ex>:extdisable &dactyl.appname;</ex>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you like it but can't remember the shortcuts, then type
|
||||||
<key name="F1"/> or <ex>:help</ex> to get this help window back.
|
<key name="F1"/> or <ex>:help</ex> to get this help window back.
|
||||||
</p>
|
</p>
|
||||||
|
</warning>
|
||||||
<tags>author donaton sponsor</tags>
|
|
||||||
<strut/>
|
|
||||||
<p>
|
|
||||||
&dactyl.appname; was initially written by
|
|
||||||
<link topic="mailto:stubenschrott@vimperator.org">Martin
|
|
||||||
Stubenschrott</link> but has found many other
|
|
||||||
<link topic="http://vimperator.org/trac/wiki/&dactyl.appname;/Authors">contributors</link>
|
|
||||||
in the meanwhile. If you appreciate the work on &dactyl.appname; and want to
|
|
||||||
encourage us working on it more, you can send us greetings, patches, or
|
|
||||||
donations (thanks a lot to
|
|
||||||
<link topic="http://vimperator.org/trac/wiki/&dactyl.appname;/Donors">these
|
|
||||||
people</link>
|
|
||||||
who already did):
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pan><handle/></pan>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If you prefer getting some nice products for your money, you can also support
|
|
||||||
us by buying some cool
|
|
||||||
<link topic="http://www.zazzle.com/maxauthority*">merchandise</link> like
|
|
||||||
t-shirts or mugs. Of course, as we believe in free, open source software, only
|
|
||||||
support us financially if you really like &dactyl.appname; and the money doesn't hurt
|
|
||||||
— otherwise just use it, recommend it, and like it :)
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 tag="overview">Help topics</h2>
|
<h2 tag="overview">Help topics</h2>
|
||||||
|
|
||||||
@@ -156,10 +136,11 @@ web browser, as key bindings differ according to which mode you are in.
|
|||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You can also jump directly to the help of a specific command with <ex>:help o</ex>
|
You can also jump directly to the help of a specific command via the <ex>:help</ex> command.
|
||||||
or <ex>:help :set</ex>.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<example><ex>:help :help</ex></example>
|
||||||
|
|
||||||
<h2 tag="features">Features</h2>
|
<h2 tag="features">Features</h2>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@@ -188,15 +169,14 @@ or <ex>:help :set</ex>.
|
|||||||
<h2 tag="contact">Contact</h2>
|
<h2 tag="contact">Contact</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Please send comments/bug reports/patches to the mailing list, where we will
|
Please send comments, questions, or patches to the
|
||||||
properly answer any questions. You can also join the
|
<link topic="mailto:&dactyl.maillist;">mailing list</link>,
|
||||||
<link topic="irc://irc.freenode.net/pentadactyl">#pentadactyl</link> IRC channel
|
where we will do our best to answer any questions. You can also
|
||||||
on <link target="http://www.freenode.net/">Freenode</link> or check the
|
check the
|
||||||
<link topic="http://vimperator.org/trac/wiki/&dactyl.appname;/Wiki">Wiki</link> for
|
<link topic="http://code.google.com/p/dactyl/wiki">wiki</link> for
|
||||||
<link topic="http://vimperator.org/trac/wiki/&dactyl.appname;/FAQ">
|
<link topic="http://code.google.com/p/dactyl/wiki/FAQ">FAQ</link>.
|
||||||
frequently asked questions (FAQ)
|
Issue reports can be entered in the
|
||||||
</link>. Make sure, you have read the TODO file first, as we are aware of many
|
<link topic="http://code.google.com/p/dactyl/issues/list">issue tracker</link>.
|
||||||
things which can be improved when we find time for it or receive patches.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>
|
|
||||||
|
|
||||||
<!DOCTYPE overlay SYSTEM "chrome://dactyl/content/dactyl.dtd">
|
|
||||||
|
|
||||||
<overlay
|
|
||||||
xmlns="http://vimperator.org/namespaces/liberator"
|
|
||||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
|
||||||
|
|
||||||
<item insertbefore=":set">
|
|
||||||
<tags>:seg :way</tags>
|
|
||||||
<spec>:se[a]</spec>
|
|
||||||
<description>
|
|
||||||
<p>Show all options that differ from their default value.</p>
|
|
||||||
</description>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item insertafter=":set-default">
|
|
||||||
<tags>:sturm :drang</tags>
|
|
||||||
<spec>:und</spec>
|
|
||||||
<description>
|
|
||||||
<p>Show all options that differ from their default value.</p>
|
|
||||||
</description>
|
|
||||||
</item>
|
|
||||||
</overlay>
|
|
||||||
<!-- vim:se sts=4 sw=4 et: -->
|
|
||||||
@@ -122,20 +122,24 @@
|
|||||||
Scrolling the browser window is done with simple keystrokes:
|
Scrolling the browser window is done with simple keystrokes:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<dl>
|
||||||
<li><k>j</k>/<k>k</k> –
|
<dt><k>j</k>/<k>k</k></dt>
|
||||||
|
<dd>
|
||||||
scroll window down/up by one line, respectively
|
scroll window down/up by one line, respectively
|
||||||
</li>
|
</dd>
|
||||||
<li><k>h</k>/<k>l</k> –
|
<dt><k>h</k>/<k>l</k></dt>
|
||||||
|
<dd>
|
||||||
scroll window left/right
|
scroll window left/right
|
||||||
</li>
|
</dd>
|
||||||
<li><k name="Space"/>/<k name="C-b"/> –
|
<dt><k name="Space"/>/<k name="C-b"/></dt>
|
||||||
|
<dd>
|
||||||
scroll down/up by one page
|
scroll down/up by one page
|
||||||
</li>
|
</dd>
|
||||||
<li><k name="C-d"/>/<k name="C-u"/> –
|
<dt><k name="C-d"/>/<k name="C-u"/></dt>
|
||||||
|
<dd>
|
||||||
scroll down/up by 1/2 page
|
scroll down/up by 1/2 page
|
||||||
</li>
|
</dd>
|
||||||
</ul>
|
</dl>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Your standard buttons (<k name="Up"/>/<k name="Down"/>/<k name="PgUp"/>/<k name="PgDn"/>) will
|
Your standard buttons (<k name="Up"/>/<k name="Down"/>/<k name="PgUp"/>/<k name="PgDn"/>) will
|
||||||
@@ -149,31 +153,36 @@
|
|||||||
scrolling.
|
scrolling.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<dl>
|
||||||
<li><k name="C-o"/>/<k name="C-i"/> –
|
<dt><k name="C-o"/>/<k name="C-i"/></dt>
|
||||||
|
<dd>
|
||||||
move Back/Forward in the current window/tab's history, respectively
|
move Back/Forward in the current window/tab's history, respectively
|
||||||
</li>
|
</dd>
|
||||||
</ul>
|
</dl>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Move between tabs using these keystrokes which may also be familiar to tabbing
|
Move between tabs using these keystrokes which may also be familiar to tabbing
|
||||||
Vimmers.
|
Vimmers.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<dl>
|
||||||
<li><k>gt</k>/<k name="C-n"/> –
|
<dt><k>gt</k>/<k name="C-n"/></dt>
|
||||||
|
<dd>
|
||||||
go to the next tab
|
go to the next tab
|
||||||
</li>
|
</dd>
|
||||||
<li><k>gT</k>/<k name="C-p"/> –
|
<dt><k>gT</k>/<k name="C-p"/></dt>
|
||||||
|
<dd>
|
||||||
go to the previous tab
|
go to the previous tab
|
||||||
</li>
|
</dd>
|
||||||
<li><k>g0</k>/<k>g$</k> –
|
<dt><k>g0</k>/<k>g$</k></dt>
|
||||||
|
<dd>
|
||||||
go to the first/last tab
|
go to the first/last tab
|
||||||
</li>
|
</dd>
|
||||||
<li><k>d</k> –
|
<dt><k>d</k></dt>
|
||||||
|
<dd>
|
||||||
close the active tab (delete the buffer)
|
close the active tab (delete the buffer)
|
||||||
</li>
|
</dd>
|
||||||
</ul>
|
</dl>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To open a web page in a new tab, use the <ex>:tabopen <a>url</a></ex>. To open a URL in
|
To open a web page in a new tab, use the <ex>:tabopen <a>url</a></ex>. To open a URL in
|
||||||
@@ -186,8 +195,8 @@
|
|||||||
<ex>:open my.webmail.com<key name="CR"/></ex>
|
<ex>:open my.webmail.com<key name="CR"/></ex>
|
||||||
<k>o</k>my.webmail.com<key name="CR"/>
|
<k>o</k>my.webmail.com<key name="CR"/>
|
||||||
|
|
||||||
<ex>:tabopen vimperator.org<key name="CR"/></ex>
|
<ex>:tabopen google.com<key name="CR"/></ex>
|
||||||
<k>t</k>vimperator.org<key name="CR"/>
|
<k>t</k>google.com<key name="CR"/>
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
<h2 tag="hints-tutorial">Some hints about surfing…</h2>
|
<h2 tag="hints-tutorial">Some hints about surfing…</h2>
|
||||||
@@ -225,7 +234,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To test it, try this link: <link target="http://vimperator.org/">&dactyl.appname; Homepage</link>.
|
To test it, try this link: <link target="&dactyl.apphome;">&dactyl.appname; Homepage</link>.
|
||||||
Activate QuickHint mode with <k>f</k> or <k>F</k> to highlight all currently
|
Activate QuickHint mode with <k>f</k> or <k>F</k> to highlight all currently
|
||||||
visible links. Then start typing the text of the link. The link should be
|
visible links. Then start typing the text of the link. The link should be
|
||||||
uniquely identified soon, and &dactyl.appname; will open it. Once you're done,
|
uniquely identified soon, and &dactyl.appname; will open it. Once you're done,
|
||||||
@@ -250,7 +259,7 @@
|
|||||||
|
|
||||||
<code><k name="Esc"/></code>
|
<code><k name="Esc"/></code>
|
||||||
|
|
||||||
<h2 tag="pentadactylrc">Saving for posterity - pentadactylrc</h2>
|
<h2 tag="pentadactylrc">Saving for posterity—pentadactylrc</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Once you get &dactyl.appname; set up with your desired options, maps, and commands,
|
Once you get &dactyl.appname; set up with your desired options, maps, and commands,
|
||||||
@@ -275,17 +284,24 @@
|
|||||||
&dactyl.appname; supports all of Vim's classic methods of exiting.
|
&dactyl.appname; supports all of Vim's classic methods of exiting.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<dl>
|
||||||
<li><ex>:xall</ex> – command to quit and save the current browsing
|
<dt><ex>:xall</ex></dt>
|
||||||
session for next time; the default.
|
<dd>
|
||||||
</li>
|
command to quit and save the current browsing session for next time; the default.
|
||||||
<li><ex>:qall</ex> – command to quit <em>without</em> saving the session
|
</dd>
|
||||||
</li>
|
<dt><ex>:qall</ex></dt>
|
||||||
<li><k>ZZ</k> – Normal mode mapping equivalent to <ex>:xall</ex>
|
<dd>
|
||||||
</li>
|
command to quit <em>without</em> saving the session
|
||||||
<li><k>ZQ</k> – Normal mode mapping equivalent to <ex>:qall</ex>
|
</dd>
|
||||||
</li>
|
<dt><k>ZZ</k></dt>
|
||||||
</ul>
|
<dd>
|
||||||
|
Normal mode mapping equivalent to <ex>:xall</ex>
|
||||||
|
</dd>
|
||||||
|
<dt><k>ZQ</k></dt>
|
||||||
|
<dd>
|
||||||
|
Normal mode mapping equivalent to <ex>:qall</ex>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
<h2 tag="whither-&dactyl.host;">Where did &dactyl.host; go?</h2>
|
<h2 tag="whither-&dactyl.host;">Where did &dactyl.host; go?</h2>
|
||||||
|
|
||||||
@@ -296,24 +312,28 @@
|
|||||||
make the best use of them.
|
make the best use of them.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<dl>
|
||||||
<li><ex>:dialog</ex> –
|
<dt><ex>:dialog</ex></dt>
|
||||||
|
<dd>
|
||||||
To access some of &dactyl.host;'s many dialog windows, you can use the
|
To access some of &dactyl.host;'s many dialog windows, you can use the
|
||||||
<ex>:dialog</ex> command. See <ex>:help :dialog</ex>.
|
<ex>:dialog</ex> command. See <ex>:help :dialog</ex>.
|
||||||
</li>
|
</dd>
|
||||||
<li><ex>:bmarks</ex> –
|
<dt><ex>:bmarks</ex></dt>
|
||||||
|
<dd>
|
||||||
&dactyl.appname; provides a new interface to bookmarks, but they're still your
|
&dactyl.appname; provides a new interface to bookmarks, but they're still your
|
||||||
standard &dactyl.host; bookmarks under the hood. <ex>:bmark</ex> will add a new
|
standard &dactyl.host; bookmarks under the hood. <ex>:bmark</ex> will add a new
|
||||||
bookmark, while <ex>:bmarks</ex> will list the bookmarks currently defined.
|
bookmark, while <ex>:bmarks</ex> will list the bookmarks currently defined.
|
||||||
</li>
|
</dd>
|
||||||
<li><ex>:history</ex> –
|
<dt><ex>:history</ex></dt>
|
||||||
|
<dd>
|
||||||
It's exactly what it sounds like. This command will display a colorized,
|
It's exactly what it sounds like. This command will display a colorized,
|
||||||
scrollable and clickable list of the locations in &dactyl.appname;'s history.
|
scrollable and clickable list of the locations in &dactyl.appname;'s history.
|
||||||
</li>
|
</dd>
|
||||||
<li><ex>:emenu</ex> –
|
<dt><ex>:emenu</ex></dt>
|
||||||
|
<dd>
|
||||||
Access the &dactyl.host; menus through the &dactyl.appname; command line.
|
Access the &dactyl.host; menus through the &dactyl.appname; command line.
|
||||||
</li>
|
</dd>
|
||||||
</ul>
|
</dl>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Feel free to explore at this point. If you use the <ex>:tabopen</ex> command,
|
Feel free to explore at this point. If you use the <ex>:tabopen</ex> command,
|
||||||
|
|||||||
@@ -44,98 +44,74 @@ const Config = Module("config", ConfigBase, {
|
|||||||
|
|
||||||
styleableChrome: ["chrome://gonzo/content/xul/mainplayer.xul"],
|
styleableChrome: ["chrome://gonzo/content/xul/mainplayer.xul"],
|
||||||
|
|
||||||
autocommands: [["BookmarkAdd", "Triggered after a page is bookmarked"],
|
autocommands: {
|
||||||
["ColorScheme", "Triggered after a color scheme has been loaded"],
|
BookmarkAdd: "Triggered after a page is bookmarked",
|
||||||
["DOMLoad", "Triggered when a page's DOM content has fully loaded"],
|
ColorScheme: "Triggered after a color scheme has been loaded",
|
||||||
["DownloadPost", "Triggered when a download has completed"],
|
DOMLoad: "Triggered when a page's DOM content has fully loaded",
|
||||||
["Fullscreen", "Triggered when the browser's fullscreen state changes"],
|
DownloadPost: "Triggered when a download has completed",
|
||||||
["LocationChange", "Triggered when changing tabs or when navigation to a new location"],
|
Fullscreen: "Triggered when the browser's fullscreen state changes",
|
||||||
["PageLoadPre", "Triggered after a page load is initiated"],
|
LocationChange: "Triggered when changing tabs or when navigation to a new location",
|
||||||
["PageLoad", "Triggered when a page gets (re)loaded/opened"],
|
PageLoadPre: "Triggered after a page load is initiated",
|
||||||
["ShellCmdPost", "Triggered after executing a shell command with :!cmd"],
|
PageLoad: "Triggered when a page gets (re)loaded/opened",
|
||||||
["TrackChangePre", "Triggered before a playing track is changed"],
|
ShellCmdPost: "Triggered after executing a shell command with :!cmd",
|
||||||
["TrackChange", "Triggered after a playing track has changed"],
|
TrackChangePre: "Triggered before a playing track is changed",
|
||||||
["ViewChangePre", "Triggered before a sequencer view is changed"],
|
TrackChange: "Triggered after a playing track has changed",
|
||||||
["ViewChange", "Triggered after a sequencer view is changed"],
|
ViewChangePre: "Triggered before a sequencer view is changed",
|
||||||
["StreamStart", "Triggered after a stream has started"],
|
ViewChange: "Triggered after a sequencer view is changed",
|
||||||
["StreamPause", "Triggered after a stream has paused"],
|
StreamStart: "Triggered after a stream has started",
|
||||||
["StreamEnd", "Triggered after a stream has ended"],
|
StreamPause: "Triggered after a stream has paused",
|
||||||
["StreamStop", "Triggered after a stream has stopped"],
|
StreamEnd: "Triggered after a stream has ended",
|
||||||
["XulmusEnter", "Triggered after Songbird starts"],
|
StreamStop: "Triggered after a stream has stopped",
|
||||||
["XulmusLeavePre", "Triggered before exiting Songbird, just before destroying each module"],
|
Enter: "Triggered after Songbird starts",
|
||||||
["XulmusLeave", "Triggered before exiting Songbird"]],
|
LeavePre: "Triggered before exiting Songbird, just before destroying each module",
|
||||||
|
Leave: "Triggered before exiting Songbird",
|
||||||
|
},
|
||||||
|
|
||||||
// TODO: remove those which don't make sense, can't be provided.
|
// TODO: remove those which don't make sense, can't be provided.
|
||||||
dialogs: [
|
dialogs: {
|
||||||
["about", "About Songbird",
|
about: ["About Songbird",
|
||||||
function () { window.openDialog("chrome://songbird/content/xul/about.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
|
function () { window.openDialog("chrome://songbird/content/xul/about.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
|
||||||
/*
|
addons: ["Manage Add-ons",
|
||||||
["addbookmark", "Add bookmark for the current page",
|
|
||||||
function () { PlacesCommandHook.bookmarkCurrentPage(true, PlacesUtils.bookmarksRootId); }],
|
|
||||||
*/
|
|
||||||
["addons", "Manage Add-ons",
|
|
||||||
function () { SBOpenPreferences("paneAddons"); }],
|
function () { SBOpenPreferences("paneAddons"); }],
|
||||||
/*
|
checkupdates: ["Check for updates",
|
||||||
["bookmarks", "List your bookmarks",
|
|
||||||
function () { window.openDialog("chrome://browser/content/bookmarks/bookmarksPanel.xul", "Bookmarks", "dialog,centerscreen,width=600,height=600"); }],
|
|
||||||
*/
|
|
||||||
["checkupdates", "Check for updates",
|
|
||||||
function () { window.checkForUpdates(); }],
|
function () { window.checkForUpdates(); }],
|
||||||
["cleardata", "Clear private data",
|
cleardata: ["Clear private data",
|
||||||
function () { Sanitizer.showUI(); }],
|
function () { Sanitizer.showUI(); }],
|
||||||
["cookies", "List your cookies",
|
cookies: ["List your cookies",
|
||||||
function () { window.toOpenWindowByType("Browser:Cookies", "chrome://browser/content/preferences/cookies.xul", "chrome,dialog=no,resizable"); }],
|
function () { window.toOpenWindowByType("Browser:Cookies", "chrome://browser/content/preferences/cookies.xul", "chrome,dialog=no,resizable"); }],
|
||||||
["console", "JavaScript console",
|
console: ["JavaScript console",
|
||||||
function () { window.toJavaScriptConsole(); }],
|
function () { window.toJavaScriptConsole(); }],
|
||||||
/*
|
dominspector: ["DOM Inspector",
|
||||||
["customizetoolbar", "Customize the Toolbar",
|
|
||||||
function () { window.BrowserCustomizeToolbar(); }],
|
|
||||||
*/
|
|
||||||
["dominspector", "DOM Inspector",
|
|
||||||
function () { try { window.inspectDOMDocument(content.document); } catch (e) { dactyl.echoerr("DOM Inspector extension not installed"); } }],
|
function () { try { window.inspectDOMDocument(content.document); } catch (e) { dactyl.echoerr("DOM Inspector extension not installed"); } }],
|
||||||
["downloads", "Manage Downloads",
|
downloads: ["Manage Downloads",
|
||||||
function () { window.toOpenWindowByType("Download:Manager", "chrome://mozapps/content/downloads/downloads.xul", "chrome,dialog=no,resizable"); }],
|
function () { window.toOpenWindowByType("Download:Manager", "chrome://mozapps/content/downloads/downloads.xul", "chrome,dialog=no,resizable"); }],
|
||||||
/*
|
jumpto: ["Jump to a media item",
|
||||||
["history", "List your history",
|
|
||||||
function () { window.openDialog("chrome://browser/content/history/history-panel.xul", "History", "dialog,centerscreen,width=600,height=600"); }],
|
|
||||||
["import", "Import Preferences, Bookmarks, History, etc. from other browsers",
|
|
||||||
function () { window.BrowserImport(); }],
|
|
||||||
*/
|
|
||||||
["jumpto", "Jump to a media item",
|
|
||||||
function () { onJumpToFileKey(); }],
|
function () { onJumpToFileKey(); }],
|
||||||
["newsmartplaylist", "Open the file selector dialog",
|
newsmartplaylist: ["Open the file selector dialog",
|
||||||
function () { SBNewSmartPlaylist(); }],
|
function () { SBNewSmartPlaylist(); }],
|
||||||
["openfile", "Open the file selector dialog",
|
openfile: ["Open the file selector dialog",
|
||||||
function () { SBFileOpen(); }],
|
function () { SBFileOpen(); }],
|
||||||
/*
|
pagesource: ["View page source",
|
||||||
["pageinfo", "Show information about the current page",
|
|
||||||
function () { window.BrowserPageInfo(); }],
|
|
||||||
*/
|
|
||||||
["pagesource", "View page source",
|
|
||||||
function () { window.BrowserViewSourceOfDocument(content.document); }],
|
function () { window.BrowserViewSourceOfDocument(content.document); }],
|
||||||
["places", "Places Organizer: Manage your bookmarks and history",
|
places: ["Places Organizer: Manage your bookmarks and history",
|
||||||
function () { PlacesCommandHook.showPlacesOrganizer(ORGANIZER_ROOT_BOOKMARKS); }],
|
function () { PlacesCommandHook.showPlacesOrganizer(ORGANIZER_ROOT_BOOKMARKS); }],
|
||||||
["preferences", "Show Songbird preferences dialog",
|
preferences: ["Show Songbird preferences dialog",
|
||||||
function () { window.openPreferences(); }],
|
function () { window.openPreferences(); }],
|
||||||
/*
|
printsetup: ["Setup the page size and orientation before printing",
|
||||||
["printpreview", "Preview the page before printing",
|
|
||||||
function () { PrintUtils.printPreview(onEnterPrintPreview, onExitPrintPreview); }],
|
|
||||||
*/
|
|
||||||
["printsetup", "Setup the page size and orientation before printing",
|
|
||||||
function () { PrintUtils.showPageSetup(); }],
|
function () { PrintUtils.showPageSetup(); }],
|
||||||
["print", "Show print dialog",
|
print: ["Show print dialog",
|
||||||
function () { PrintUtils.print(); }],
|
function () { PrintUtils.print(); }],
|
||||||
["saveframe", "Save frame to disk",
|
saveframe: ["Save frame to disk",
|
||||||
function () { window.saveFrameDocument(); }],
|
function () { window.saveFrameDocument(); }],
|
||||||
["savepage", "Save page to disk",
|
savepage: ["Save page to disk",
|
||||||
function () { window.saveDocument(window.content.document); }],
|
function () { window.saveDocument(window.content.document); }],
|
||||||
["searchengines", "Manage installed search engines",
|
searchengines: ["Manage installed search engines",
|
||||||
function () { window.openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
|
function () { window.openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
|
||||||
["selectionsource", "View selection source",
|
selectionsource: ["View selection source",
|
||||||
function () { buffer.viewSelectionSource(); }],
|
function () { buffer.viewSelectionSource(); }],
|
||||||
["subscribe", "Add a new subscription",
|
subscribe: ["Add a new subscription",
|
||||||
function () { SBSubscribe(); }]
|
function () { SBSubscribe(); }]
|
||||||
],
|
},
|
||||||
|
|
||||||
focusChange: function () {
|
focusChange: function () {
|
||||||
// Switch to -- PLAYER -- mode for Songbird Media Player.
|
// Switch to -- PLAYER -- mode for Songbird Media Player.
|
||||||
@@ -153,14 +129,27 @@ const Config = Module("config", ConfigBase, {
|
|||||||
|
|
||||||
modes: [["PLAYER", { char: "p" }]],
|
modes: [["PLAYER", { char: "p" }]],
|
||||||
|
|
||||||
|
removeTab: function (tab) {
|
||||||
|
if (config.tabbrowser.mTabs.length > 1)
|
||||||
|
config.tabbrowser.removeTab(tab);
|
||||||
|
else {
|
||||||
|
if (buffer.URL != "about:blank" || window.getWebNavigation().sessionHistory.count > 0) {
|
||||||
|
dactyl.open("about:blank", dactyl.NEW_BACKGROUND_TAB);
|
||||||
|
config.tabbrowser.removeTab(tab);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dactyl.beep();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
scripts: [
|
scripts: [
|
||||||
"browser.js",
|
"browser",
|
||||||
"bookmarks.js",
|
"bookmarks",
|
||||||
"history.js",
|
"history",
|
||||||
"quickmarks.js",
|
"quickmarks",
|
||||||
"tabs.js",
|
"tabs",
|
||||||
"player.js",
|
"player",
|
||||||
"library.js"
|
"library"
|
||||||
],
|
],
|
||||||
|
|
||||||
// FIXME: tab arg and media tab exception?
|
// FIXME: tab arg and media tab exception?
|
||||||
|
|||||||
Reference in New Issue
Block a user