mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2026-01-06 06:34:13 +01:00
Fix tab number updates in FF36. Closes issue 300.
This commit is contained in:
@@ -65,7 +65,7 @@ var Browser = Module("browser", {
|
||||
|
||||
mappings: function () {
|
||||
mappings.add([modes.NORMAL],
|
||||
["y"], "Yank current location to the clipboard",
|
||||
["y", "<yank-location>"], "Yank current location to the clipboard",
|
||||
function () { dactyl.clipboardWrite(buffer.uri.spec, true); });
|
||||
|
||||
// opening websites
|
||||
|
||||
@@ -1651,7 +1651,7 @@ var Buffer = Module("buffer", {
|
||||
mappings: function () {
|
||||
var myModes = config.browserModes;
|
||||
|
||||
mappings.add(myModes, ["."],
|
||||
mappings.add(myModes, [".", "<repeat-key>"],
|
||||
"Repeat the last key event",
|
||||
function (args) {
|
||||
if (mappings.repeat) {
|
||||
@@ -1670,31 +1670,31 @@ var Buffer = Module("buffer", {
|
||||
function () { ex.stop(); });
|
||||
|
||||
// scrolling
|
||||
mappings.add(myModes, ["j", "<Down>", "<C-e>"],
|
||||
mappings.add(myModes, ["j", "<Down>", "<C-e>", "<scroll-down-line>"],
|
||||
"Scroll document down",
|
||||
function (args) { buffer.scrollVertical("lines", Math.max(args.count, 1)); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["k", "<Up>", "<C-y>"],
|
||||
mappings.add(myModes, ["k", "<Up>", "<C-y>", "<scroll-up-line>"],
|
||||
"Scroll document up",
|
||||
function (args) { buffer.scrollVertical("lines", -Math.max(args.count, 1)); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, dactyl.has("mail") ? ["h"] : ["h", "<Left>"],
|
||||
mappings.add(myModes, dactyl.has("mail") ? ["h", "<scroll-left-column>"] : ["h", "<Left>", "<scroll-left-column>"],
|
||||
"Scroll document to the left",
|
||||
function (args) { buffer.scrollHorizontal("columns", -Math.max(args.count, 1)); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, dactyl.has("mail") ? ["l"] : ["l", "<Right>"],
|
||||
mappings.add(myModes, dactyl.has("mail") ? ["l", "<scroll-right-column>"] : ["l", "<Right>", "<scroll-right-column>"],
|
||||
"Scroll document to the right",
|
||||
function (args) { buffer.scrollHorizontal("columns", Math.max(args.count, 1)); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["0", "^"],
|
||||
mappings.add(myModes, ["0", "^", "<scroll-begin>"],
|
||||
"Scroll to the absolute left of the document",
|
||||
function () { buffer.scrollToPercent(0, null); });
|
||||
|
||||
mappings.add(myModes, ["$"],
|
||||
mappings.add(myModes, ["$", "<scroll-end>"],
|
||||
"Scroll to the absolute right of the document",
|
||||
function () { buffer.scrollToPercent(100, null); });
|
||||
|
||||
@@ -1708,7 +1708,7 @@ var Buffer = Module("buffer", {
|
||||
function (args) { buffer.scrollToPercent(null, args.count != null ? args.count : 100); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["%"],
|
||||
mappings.add(myModes, ["%", "<scroll-percent>"],
|
||||
"Scroll to {count} percent of the document",
|
||||
function (args) {
|
||||
dactyl.assert(args.count > 0 && args.count <= 100);
|
||||
@@ -1716,59 +1716,59 @@ var Buffer = Module("buffer", {
|
||||
},
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["<C-d>"],
|
||||
mappings.add(myModes, ["<C-d>", "<scroll-down>"],
|
||||
"Scroll window downwards in the buffer",
|
||||
function (args) { buffer._scrollByScrollSize(args.count, true); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["<C-u>"],
|
||||
mappings.add(myModes, ["<C-u>", "<scroll-up>"],
|
||||
"Scroll window upwards in the buffer",
|
||||
function (args) { buffer._scrollByScrollSize(args.count, false); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["<C-b>", "<PageUp>", "<S-Space>"],
|
||||
mappings.add(myModes, ["<C-b>", "<PageUp>", "<S-Space>", "<scroll-page-up>"],
|
||||
"Scroll up a full page",
|
||||
function (args) { buffer.scrollVertical("pages", -Math.max(args.count, 1)); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["<C-f>", "<PageDown>", "<Space>"],
|
||||
mappings.add(myModes, ["<C-f>", "<PageDown>", "<Space>", "<scroll-page-down>"],
|
||||
"Scroll down a full page",
|
||||
function (args) { buffer.scrollVertical("pages", Math.max(args.count, 1)); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["]f"],
|
||||
mappings.add(myModes, ["]f", "<previous-frame>"],
|
||||
"Focus next frame",
|
||||
function (args) { buffer.shiftFrameFocus(Math.max(args.count, 1)); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["[f"],
|
||||
mappings.add(myModes, ["[f", "<next-frame>"],
|
||||
"Focus previous frame",
|
||||
function (args) { buffer.shiftFrameFocus(-Math.max(args.count, 1)); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["]]"],
|
||||
mappings.add(myModes, ["]]", "<next-page>"],
|
||||
"Follow the link labeled 'next' or '>' if it exists",
|
||||
function (args) {
|
||||
buffer.findLink("next", options["nextpattern"], (args.count || 1) - 1, true);
|
||||
},
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["[["],
|
||||
mappings.add(myModes, ["[[", "<previous-page>"],
|
||||
"Follow the link labeled 'prev', 'previous' or '<' if it exists",
|
||||
function (args) {
|
||||
buffer.findLink("previous", options["previouspattern"], (args.count || 1) - 1, true);
|
||||
},
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["gf"],
|
||||
mappings.add(myModes, ["gf", "<view-source>"],
|
||||
"Toggle between rendered and source view",
|
||||
function () { buffer.viewSource(null, false); });
|
||||
|
||||
mappings.add(myModes, ["gF"],
|
||||
mappings.add(myModes, ["gF", "<view-source-externally>"],
|
||||
"View source with an external editor",
|
||||
function () { buffer.viewSource(null, true); });
|
||||
|
||||
mappings.add(myModes, ["gi"],
|
||||
mappings.add(myModes, ["gi", "<focus-input>"],
|
||||
"Focus last used input field",
|
||||
function (args) {
|
||||
let elem = buffer.lastInputField;
|
||||
@@ -1808,7 +1808,7 @@ var Buffer = Module("buffer", {
|
||||
dactyl.open(url, { from: "paste", where: dactyl.NEW_TAB, background: true });
|
||||
});
|
||||
|
||||
mappings.add(myModes, ["p", "<MiddleMouse>"],
|
||||
mappings.add(myModes, ["p", "<MiddleMouse>", "<open-clipboard-url>"],
|
||||
"Open (put) a URL based on the current clipboard contents in the current buffer",
|
||||
function () {
|
||||
let url = dactyl.clipboardRead();
|
||||
@@ -1816,7 +1816,7 @@ var Buffer = Module("buffer", {
|
||||
dactyl.open(url);
|
||||
});
|
||||
|
||||
mappings.add(myModes, ["P"],
|
||||
mappings.add(myModes, ["P", "<tab-open-clipboard-url>"],
|
||||
"Open (put) a URL based on the current clipboard contents in a new buffer",
|
||||
function () {
|
||||
let url = dactyl.clipboardRead();
|
||||
@@ -1825,16 +1825,16 @@ var Buffer = Module("buffer", {
|
||||
});
|
||||
|
||||
// reloading
|
||||
mappings.add(myModes, ["r"],
|
||||
mappings.add(myModes, ["r", "<reload>"],
|
||||
"Reload the current web page",
|
||||
function () { tabs.reload(tabs.getTab(), false); });
|
||||
|
||||
mappings.add(myModes, ["R"],
|
||||
mappings.add(myModes, ["R", "<full-reload>"],
|
||||
"Reload while skipping the cache",
|
||||
function () { tabs.reload(tabs.getTab(), true); });
|
||||
|
||||
// yanking
|
||||
mappings.add(myModes, ["Y"],
|
||||
mappings.add(myModes, ["Y", "<yank-word>"],
|
||||
"Copy selected text or current word",
|
||||
function () {
|
||||
let sel = buffer.getCurrentWord();
|
||||
@@ -1843,62 +1843,62 @@ var Buffer = Module("buffer", {
|
||||
});
|
||||
|
||||
// zooming
|
||||
mappings.add(myModes, ["zi", "+"],
|
||||
mappings.add(myModes, ["zi", "+", "<text-zoom-in>"],
|
||||
"Enlarge text zoom of current web page",
|
||||
function (args) { buffer.zoomIn(Math.max(args.count, 1), false); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["zm"],
|
||||
mappings.add(myModes, ["zm", "<text-zoom-more>"],
|
||||
"Enlarge text zoom of current web page by a larger amount",
|
||||
function (args) { buffer.zoomIn(Math.max(args.count, 1) * 3, false); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["zo", "-"],
|
||||
mappings.add(myModes, ["zo", "-", "<text-zoom-out>"],
|
||||
"Reduce text zoom of current web page",
|
||||
function (args) { buffer.zoomOut(Math.max(args.count, 1), false); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["zr"],
|
||||
mappings.add(myModes, ["zr", "<text-zoom-reduce>"],
|
||||
"Reduce text zoom of current web page by a larger amount",
|
||||
function (args) { buffer.zoomOut(Math.max(args.count, 1) * 3, false); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["zz"],
|
||||
mappings.add(myModes, ["zz", "<text-zoom>"],
|
||||
"Set text zoom value of current web page",
|
||||
function (args) { buffer.setZoom(args.count > 1 ? args.count : 100, false); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["ZI", "zI"],
|
||||
mappings.add(myModes, ["ZI", "zI", "<full-zoom-in>"],
|
||||
"Enlarge full zoom of current web page",
|
||||
function (args) { buffer.zoomIn(Math.max(args.count, 1), true); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["ZM", "zM"],
|
||||
mappings.add(myModes, ["ZM", "zM", "<full-zoom-more>"],
|
||||
"Enlarge full zoom of current web page by a larger amount",
|
||||
function (args) { buffer.zoomIn(Math.max(args.count, 1) * 3, true); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["ZO", "zO"],
|
||||
mappings.add(myModes, ["ZO", "zO", "<full-zoom-out>"],
|
||||
"Reduce full zoom of current web page",
|
||||
function (args) { buffer.zoomOut(Math.max(args.count, 1), true); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["ZR", "zR"],
|
||||
mappings.add(myModes, ["ZR", "zR", "<full-zoom-reduce>"],
|
||||
"Reduce full zoom of current web page by a larger amount",
|
||||
function (args) { buffer.zoomOut(Math.max(args.count, 1) * 3, true); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add(myModes, ["zZ"],
|
||||
mappings.add(myModes, ["zZ", "<full-zoom>"],
|
||||
"Set full zoom value of current web page",
|
||||
function (args) { buffer.setZoom(args.count > 1 ? args.count : 100, true); },
|
||||
{ count: true });
|
||||
|
||||
// page info
|
||||
mappings.add(myModes, ["<C-g>"],
|
||||
mappings.add(myModes, ["<C-g>", "<page-info>"],
|
||||
"Print the current file name",
|
||||
function () { buffer.showPageInfo(false); });
|
||||
|
||||
mappings.add(myModes, ["g<C-g>"],
|
||||
mappings.add(myModes, ["g<C-g>", "<more-page-info>"],
|
||||
"Print file information",
|
||||
function () { buffer.showPageInfo(true); });
|
||||
},
|
||||
|
||||
@@ -148,12 +148,6 @@ var CommandWidgets = Class("CommandWidgets", {
|
||||
return this.commandbar;
|
||||
}
|
||||
});
|
||||
|
||||
let fontSize = util.computedStyle(document.documentElement).fontSize;
|
||||
styles.system.add("font-size", "dactyl://content/buffer.xhtml",
|
||||
"body { font-size: " + fontSize + "; } \
|
||||
html|html > xul|scrollbar { visibility: collapse !important; }",
|
||||
true);
|
||||
},
|
||||
addElement: function addElement(obj) {
|
||||
const self = this;
|
||||
@@ -301,18 +295,10 @@ var CommandMode = Class("CommandMode", {
|
||||
this.keepCommand = userContext.hidden_option_command_afterimage;
|
||||
|
||||
if (this.historyKey)
|
||||
this.history = CommandLine.History(commandline.widgets.active.command.inputField, this.historyKey);
|
||||
this.history = CommandLine.History(commandline.widgets.active.command.inputField, this.historyKey, this);
|
||||
|
||||
if (this.complete)
|
||||
this.completions = CommandLine.Completions(commandline.widgets.active.command.inputField);
|
||||
|
||||
this.autocompleteTimer = Timer(200, 500, function autocompleteTell(tabPressed) {
|
||||
if (!events.feedingKeys && this.completions && options["autocomplete"].length) {
|
||||
this.completions.complete(true, false);
|
||||
if (this.completions)
|
||||
this.completions.itemList.visible = true;
|
||||
}
|
||||
}, this);
|
||||
this.completions = CommandLine.Completions(commandline.widgets.active.command.inputField, this);
|
||||
},
|
||||
|
||||
open: function (command) {
|
||||
@@ -335,17 +321,14 @@ var CommandMode = Class("CommandMode", {
|
||||
commandline.commandSession = this;
|
||||
if (this.command || stack.pop && commandline.command) {
|
||||
this.onChange(commandline.command);
|
||||
this.autocompleteTimer.flush(true);
|
||||
if (this.completions)
|
||||
this.completions.autocompleteTimer.flush(true);
|
||||
}
|
||||
},
|
||||
|
||||
leave: function (stack) {
|
||||
this.autocompleteTimer.reset();
|
||||
|
||||
if (this.completions) {
|
||||
this.completions.previewClear();
|
||||
this.completions.tabTimer.reset();
|
||||
}
|
||||
if (this.completions)
|
||||
this.completions.cleanup();
|
||||
|
||||
if (this.history)
|
||||
this.history.save();
|
||||
@@ -368,9 +351,9 @@ var CommandMode = Class("CommandMode", {
|
||||
if (this.completions) {
|
||||
this.resetCompletions();
|
||||
|
||||
this.autocompleteTimer.tell(false);
|
||||
this.completions.autocompleteTimer.tell(false);
|
||||
if (!this.completions.itemList.visible)
|
||||
this.autocompleteTimer.flush();
|
||||
this.completions.autocompleteTimer.flush();
|
||||
}
|
||||
this.onChange(commandline.command);
|
||||
},
|
||||
@@ -614,8 +597,10 @@ var CommandLine = Module("commandline", {
|
||||
if (this.widgets.message && this.widgets.message[1] === this._lastClearable)
|
||||
this.widgets.message = null;
|
||||
|
||||
if (modes.main != modes.COMMAND_LINE)
|
||||
if (!this.commandSession) {
|
||||
this.widgets.command = null;
|
||||
this.hideCompletions();
|
||||
}
|
||||
|
||||
if (modes.main == modes.OUTPUT_MULTILINE && !mow.isScrollable(1))
|
||||
modes.pop();
|
||||
@@ -866,10 +851,11 @@ var CommandLine = Module("commandline", {
|
||||
* @param {string} mode The mode for which we need history.
|
||||
*/
|
||||
History: Class("History", {
|
||||
init: function init(inputField, mode) {
|
||||
init: function init(inputField, mode, session) {
|
||||
this.mode = mode;
|
||||
this.input = inputField;
|
||||
this.reset();
|
||||
this.session = session;
|
||||
},
|
||||
get store() commandline._store.get(this.mode, []),
|
||||
set store(ary) { commandline._store.set(this.mode, ary); },
|
||||
@@ -915,8 +901,9 @@ var CommandLine = Module("commandline", {
|
||||
*/
|
||||
replace: function replace(val) {
|
||||
delete this.input.dactylKeyPress;
|
||||
if (this.completions)
|
||||
this.completions.previewClear();
|
||||
this.input.value = val;
|
||||
commandline.commandSession.onChange(val, "history");
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -928,8 +915,8 @@ var CommandLine = Module("commandline", {
|
||||
*/
|
||||
select: function select(backward, matchCurrent) {
|
||||
// always reset the tab completion if we use up/down keys
|
||||
if (commandline._completions)
|
||||
commandline._completions.reset();
|
||||
if (this.session.completions)
|
||||
this.session.completions.reset();
|
||||
|
||||
let diff = backward ? -1 : 1;
|
||||
|
||||
@@ -976,22 +963,36 @@ var CommandLine = Module("commandline", {
|
||||
* @param {Object} input
|
||||
*/
|
||||
Completions: Class("Completions", {
|
||||
init: function init(input) {
|
||||
init: function init(input, session) {
|
||||
this.context = CompletionContext(input.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
|
||||
this.context.onUpdate = this.closure._reset;
|
||||
this.editor = input.editor;
|
||||
this.input = input;
|
||||
this.session = session;
|
||||
this.selected = null;
|
||||
this.wildmode = options.get("wildmode");
|
||||
this.wildtypes = this.wildmode.value;
|
||||
this.itemList = commandline.completionList;
|
||||
this.itemList.setItems(this.context);
|
||||
|
||||
this.autocompleteTimer = Timer(200, 500, function autocompleteTell(tabPressed) {
|
||||
if (!events.feedingKeys && options["autocomplete"].length) {
|
||||
this.complete(true, false);
|
||||
this.itemList.visible = true;
|
||||
}
|
||||
}, this);
|
||||
this.tabTimer = Timer(0, 0, function tabTell(event) {
|
||||
this.tab(event.shiftKey, event.altKey && options["altwildmode"]);
|
||||
}, this);
|
||||
},
|
||||
|
||||
cleanup: function () {
|
||||
this.previewClear();
|
||||
this.tabTimer.reset();
|
||||
this.autocompleteTimer.reset();
|
||||
this.itemList.visible = false;
|
||||
},
|
||||
|
||||
UP: {},
|
||||
DOWN: {},
|
||||
PAGE_UP: {},
|
||||
@@ -1038,7 +1039,7 @@ var CommandLine = Module("commandline", {
|
||||
complete: function complete(show, tabPressed) {
|
||||
this.context.reset();
|
||||
this.context.tabPressed = tabPressed;
|
||||
commandline.commandSession.complete(this.context);
|
||||
this.session.complete(this.context);
|
||||
this.context.updateAsync = true;
|
||||
this.reset(show, tabPressed);
|
||||
this.wildIndex = 0;
|
||||
@@ -1204,7 +1205,7 @@ var CommandLine = Module("commandline", {
|
||||
tabs: [],
|
||||
|
||||
tab: function tab(reverse, wildmode) {
|
||||
commandline.commandSession.autocompleteTimer.flush();
|
||||
this.autocompleteTimer.flush();
|
||||
|
||||
if (this._caret != this.caret)
|
||||
this.reset();
|
||||
|
||||
@@ -110,10 +110,10 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
get menuItems() Dactyl.getMenuItems(),
|
||||
|
||||
// Global constants
|
||||
CURRENT_TAB: [],
|
||||
NEW_TAB: [],
|
||||
NEW_BACKGROUND_TAB: [],
|
||||
NEW_WINDOW: [],
|
||||
CURRENT_TAB: "here",
|
||||
NEW_TAB: "tab",
|
||||
NEW_BACKGROUND_TAB: "background-tab",
|
||||
NEW_WINDOW: "window",
|
||||
|
||||
forceNewTab: false,
|
||||
forceNewWindow: false,
|
||||
@@ -173,7 +173,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
|
||||
let filters = args.map(function (arg) RegExp("\\b" + util.regexp.escape(arg) + "\\b", "i"));
|
||||
if (filters.length)
|
||||
results = results.filter(function (item) filters.every(function (re) re.test(item.name + item.description)));
|
||||
results = results.filter(function (item) filters.every(function (re) re.test(item.name + " " + item.description)));
|
||||
|
||||
commandline.commandOutput(
|
||||
template.usage(results, params.format));
|
||||
@@ -380,15 +380,16 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
},
|
||||
|
||||
userEval: function (str, context, fileName, lineNumber) {
|
||||
let ctxt;
|
||||
if (jsmodules.__proto__ != window)
|
||||
str = "with (window) { with (modules) { (this.eval || eval)(" + str.quote() + ") } }";
|
||||
|
||||
if (fileName == null)
|
||||
if (io.sourcing && io.sourcing.file[0] !== "[")
|
||||
({ file: fileName, line: lineNumber }) = io.sourcing;
|
||||
({ file: fileName, line: lineNumber, context: ctxt }) = io.sourcing;
|
||||
else try {
|
||||
if (!context)
|
||||
context = userContext;
|
||||
context = userContext || ctxt;
|
||||
|
||||
context[EVAL_ERROR] = null;
|
||||
context[EVAL_STRING] = str;
|
||||
@@ -411,7 +412,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
}
|
||||
|
||||
if (!context)
|
||||
context = _userContext;
|
||||
context = _userContext || ctxt;
|
||||
return Cu.evalInSandbox(str, context, "1.8", fileName, lineNumber);
|
||||
},
|
||||
|
||||
@@ -560,9 +561,14 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
* @private
|
||||
*/
|
||||
initDocument: function initDocument(doc) {
|
||||
if (doc.location.protocol === "dactyl:") {
|
||||
dactyl.initHelp();
|
||||
config.styleHelp();
|
||||
try {
|
||||
if (doc.location.protocol === "dactyl:") {
|
||||
dactyl.initHelp();
|
||||
config.styleHelp();
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
util.reportError(e);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -662,9 +668,9 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
|
||||
let re = util.regexp(<![CDATA[
|
||||
^ (?P<space> \s*)
|
||||
(?P<char> [-*+]) \x20
|
||||
(?P<char> [-*+]) \ //
|
||||
(?P<content> .*\n
|
||||
(?: \1\x20\x20.*\n | \s*\n)* )
|
||||
(?: \1\ \ .*\n | \s*\n)* )
|
||||
|
|
||||
(?P<par>
|
||||
(?: ^ [^\S\n]*
|
||||
@@ -676,30 +682,55 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
(?: ^ [^\S\n]* \n) +
|
||||
]]>, "gmy");
|
||||
|
||||
let betas = util.regexp(/\[(b\d)\]/, "g");
|
||||
|
||||
let beta = array(betas.iterate(NEWS))
|
||||
.map(function (m) m[1]).uniq().slice(-1)[0];
|
||||
|
||||
default xml namespace = NS;
|
||||
function rec(text, level) {
|
||||
function rec(text, level, li) {
|
||||
let res = <></>;
|
||||
let list, space;
|
||||
let list, space, i = 0;
|
||||
|
||||
for (let match in re.iterate(text)) {
|
||||
if (match.char) {
|
||||
if (!list)
|
||||
res += list = <ul/>;
|
||||
list.* += <li>{rec(match.content.replace(RegExp("^" + match.space, "gm"), ""), level + 1)}</li>;
|
||||
let li = <li/>;
|
||||
li.* += rec(match.content.replace(RegExp("^" + match.space, "gm"), ""), level + 1, li)
|
||||
list.* += li;
|
||||
}
|
||||
else if (match.par) {
|
||||
let [, par, tags] = /([^]*?)\s*((?:\[[^\]]+\])*)\n*$/.exec(match.par);
|
||||
let t = tags;
|
||||
tags = array(betas.iterate(tags)).map(function (m) m[1]);
|
||||
|
||||
let group = tags.length && !tags.some(function (t) t == beta) ? "HelpNewsOld" : "";
|
||||
if (i === 0 && li) {
|
||||
li.@highlight = group;
|
||||
group = "";
|
||||
}
|
||||
|
||||
list = null;
|
||||
if (level == 0 && /^.*:\n$/.test(match.par))
|
||||
res += <h2>{template.linkifyHelp(match.par.slice(0, -1), true)}</h2>;
|
||||
if (level == 0 && /^.*:\n$/.test())
|
||||
var elem = <h2>{template.linkifyHelp(par.slice(0, -1), true)}</h2>;
|
||||
else {
|
||||
let [, a, b] = /^(IMPORTANT:?)?([^]*)/.exec(match.par);
|
||||
res += <p>{
|
||||
let [, a, b] = /^(IMPORTANT:?)?([^]*)/.exec(par);
|
||||
res += <p highlight={group + " HelpNews"}>{
|
||||
!tags.length ? "" :
|
||||
<hl key="HelpNewsTag">{tags.join(" ")}</hl>
|
||||
}{
|
||||
a ? <hl key="HelpWarning">{a}</hl> : ""
|
||||
}{
|
||||
template.linkifyHelp(b, true)
|
||||
}</p>;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
for each (let attr in res..@highlight) {
|
||||
attr.parent().@NS::highlight = attr;
|
||||
delete attr.parent().@highlight;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -710,7 +741,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
|
||||
'<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>\n' +
|
||||
'<!DOCTYPE document SYSTEM "resource://dactyl-content/dactyl.dtd">\n' +
|
||||
unescape(encodeURI( // UTF-8 handling hack.
|
||||
<document xmlns={NS}
|
||||
<document xmlns={NS} xmlns:dactyl={NS}
|
||||
name="versions" title={config.appName + " Versions"}>
|
||||
<h1 tag="versions news">{config.appName} Versions</h1>
|
||||
<toc start="2"/>
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
var ProcessorStack = Class("ProcessorStack", {
|
||||
init: function (mode, hives, keyModes) {
|
||||
this.main = mode.main;
|
||||
this._actions = [];
|
||||
this.actions = [];
|
||||
this.buffer = "";
|
||||
this.events = [];
|
||||
|
||||
this.processors = keyModes.map(function (m) hives.map(function (h) KeyProcessor(m, h)))
|
||||
.flatten().array;
|
||||
this.ownsBuffer = !this.processors.some(function (p) p.main.ownsBuffer);
|
||||
|
||||
for (let [i, input] in Iterator(this.processors)) {
|
||||
let params = input.main.params;
|
||||
@@ -31,9 +33,70 @@ var ProcessorStack = Class("ProcessorStack", {
|
||||
}
|
||||
},
|
||||
|
||||
notify: function () {
|
||||
this.execute(Events.KILL, true);
|
||||
},
|
||||
|
||||
execute: function execute(result, force) {
|
||||
|
||||
if (force && this.actions.length)
|
||||
this.processors.length = 0;
|
||||
|
||||
if (this.ownsBuffer)
|
||||
statusline.updateInputBuffer(this.processors.length ? this.buffer : "");
|
||||
|
||||
if (this.processors.length) {
|
||||
result = Events.KILL;
|
||||
if (this.actions.length && options["timeout"])
|
||||
this.timer = services.Timer(this, options["timeoutlen"], services.Timer.TYPE_ONE_SHOT);
|
||||
}
|
||||
else if (this.actions.length) {
|
||||
if (this._actions.length == 0) {
|
||||
dactyl.beep();
|
||||
events.feedingKeys = false;
|
||||
}
|
||||
|
||||
for (var res = this.actions[0]; callable(res);)
|
||||
res = res();
|
||||
result = res === Events.PASS ? Events.PASS : Events.KILL;
|
||||
}
|
||||
else if (result !== Events.KILL && !this.actions.length &&
|
||||
this.processors.some(function (p) !p.main.passUnknown)) {
|
||||
result = Events.KILL;
|
||||
dactyl.beep();
|
||||
events.feedingKeys = false;
|
||||
}
|
||||
else if (result === undefined)
|
||||
result = Events.PASS;
|
||||
|
||||
if (result !== Events.PASS)
|
||||
Events.kill(this.events[this.events.length - 1]);
|
||||
|
||||
if (result === Events.PASS || result === Events.ABORT)
|
||||
this.events.filter(function (e) e.getPreventDefault())
|
||||
.forEach(function (event, i) {
|
||||
let elem = event.originalTarget;
|
||||
if (event.originalTarget) {
|
||||
let doc = elem.ownerDocument || elem.document || elem;
|
||||
let evt = events.create(doc, event.type, event);
|
||||
events.dispatch(elem, evt, { skipmap: true, isMacro: true, isReplay: true });
|
||||
}
|
||||
else if (i > 0)
|
||||
events.events.keypress.call(events, event);
|
||||
});
|
||||
|
||||
if (force && this.processors.length === 0)
|
||||
events.processor = null;
|
||||
|
||||
return this.processors.length == 0;
|
||||
},
|
||||
|
||||
process: function process(event) {
|
||||
function dbg() {}
|
||||
|
||||
if (this.timer)
|
||||
this.timer.cancel();
|
||||
|
||||
let key = events.toString(event);
|
||||
this.events.push(event);
|
||||
|
||||
@@ -70,9 +133,7 @@ var ProcessorStack = Class("ProcessorStack", {
|
||||
dbg("ACTIONS: " + actions.length + " " + this.actions.length);
|
||||
dbg("PROCESSORS:", processors);
|
||||
|
||||
if (!processors.some(function (p) p.main.ownsBuffer))
|
||||
statusline.updateInputBuffer(processors.length ? this.buffer : "");
|
||||
|
||||
this._actions = actions;
|
||||
this.actions = actions.concat(this.actions);
|
||||
|
||||
if (result === Events.KILL)
|
||||
@@ -87,42 +148,7 @@ var ProcessorStack = Class("ProcessorStack", {
|
||||
|
||||
this.processors = processors;
|
||||
|
||||
if (processors.length)
|
||||
result = Events.KILL;
|
||||
else if (this.actions.length) {
|
||||
if (actions.length == 0)
|
||||
dactyl.beep();
|
||||
|
||||
if (modes.replaying && !events.waitForPageLoad())
|
||||
result = Events.KILL;
|
||||
else {
|
||||
for (var res = this.actions[0]; callable(res);)
|
||||
res = res();
|
||||
result = res === Events.PASS ? Events.PASS : Events.KILL;
|
||||
}
|
||||
}
|
||||
else if (result !== Events.KILL && !this.actions.length &&
|
||||
processors.some(function (p) !p.main.passUnknown)) {
|
||||
result = Events.KILL;
|
||||
dactyl.beep();
|
||||
}
|
||||
else if (result === undefined)
|
||||
result = Events.PASS;
|
||||
|
||||
if (result !== Events.PASS)
|
||||
Events.kill(event);
|
||||
|
||||
if (result === Events.PASS || result === Events.ABORT)
|
||||
this.events.filter(function (e) e.getPreventDefault())
|
||||
.forEach(function (event, i) {
|
||||
if (event.originalTarget) {
|
||||
let evt = events.create(event.originalTarget.ownerDocument, event.type, event);
|
||||
events.dispatch(event.originalTarget, evt, { skipmap: true, isMacro: true });
|
||||
}
|
||||
else if (i > 0)
|
||||
events.events.keypress.call(events, event);
|
||||
});
|
||||
return this.processors.length == 0;
|
||||
return this.execute(result, options["timeout"] && options["timeoutlen"] === 0)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -491,6 +517,7 @@ var Events = Module("events", {
|
||||
util.threadYield(1, true);
|
||||
|
||||
for (let [, evt_obj] in Iterator(events.fromString(keys))) {
|
||||
let now = Date.now();
|
||||
for (let type in values(["keydown", "keyup", "keypress"])) {
|
||||
let evt = update({}, evt_obj, { type: type });
|
||||
|
||||
@@ -511,10 +538,6 @@ var Events = Module("events", {
|
||||
|
||||
if (!this.feedingKeys)
|
||||
break;
|
||||
|
||||
// Stop feeding keys if page loading failed.
|
||||
if (modes.replaying && !this.waitForPageLoad())
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
@@ -594,9 +617,14 @@ var Events = Module("events", {
|
||||
* of x.
|
||||
*
|
||||
* @param {string} keys Messy form.
|
||||
* @param {boolean} unknownOk Whether unknown keys are passed
|
||||
* through rather than being converted to <lt>keyname>.
|
||||
* @default false
|
||||
* @returns {string} Canonical form.
|
||||
*/
|
||||
canonicalKeys: function (keys, unknownOk) {
|
||||
if (arguments.length === 1)
|
||||
unknownOk = true;
|
||||
return events.fromString(keys, unknownOk).map(events.closure.toString).join("");
|
||||
},
|
||||
|
||||
@@ -651,11 +679,17 @@ var Events = Module("events", {
|
||||
* <S-@> where @ is a non-case-changeable, non-space character.
|
||||
*
|
||||
* @param {string} keys The string to parse.
|
||||
* @param {boolean} unknownOk Whether unknown keys are passed
|
||||
* through rather than being converted to <lt>keyname>.
|
||||
* @default false
|
||||
* @returns {Array[Object]}
|
||||
*/
|
||||
fromString: function (input, unknownOk) {
|
||||
let out = [];
|
||||
|
||||
if (arguments.length === 1)
|
||||
unknownOk = true;
|
||||
|
||||
let out = [];
|
||||
let re = RegExp("<.*?>?>|[^<]|<(?!.*>)", "g");
|
||||
let match;
|
||||
while ((match = re.exec(input))) {
|
||||
@@ -862,10 +896,7 @@ var Events = Module("events", {
|
||||
|
||||
isContentNode: function isContentNode(node) {
|
||||
let win = (node.ownerDocument || node).defaultView || node;
|
||||
for (; win; win = win.parent != win && win.parent)
|
||||
if (win == content)
|
||||
return true;
|
||||
return false;
|
||||
return XPCNativeWrapper(win).top == content;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -874,39 +905,24 @@ var Events = Module("events", {
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
waitForPageLoad: function () {
|
||||
waitForPageLoad: function (time) {
|
||||
util.threadYield(true); // clear queue
|
||||
|
||||
if (buffer.loaded == 1)
|
||||
if (buffer.loaded)
|
||||
return true;
|
||||
|
||||
const maxWaitTime = 25;
|
||||
dactyl.echo("Waiting for page to load...", commandline.DISALLOW_MULTILINE);
|
||||
|
||||
const maxWaitTime = (time || 25);
|
||||
let start = Date.now();
|
||||
let end = start + (maxWaitTime * 1000); // maximum time to wait - TODO: add option
|
||||
let now;
|
||||
while (now = Date.now(), now < end) {
|
||||
util.threadYield();
|
||||
let end = start + (maxWaitTime * 1000);
|
||||
|
||||
if (!events.feedingKeys)
|
||||
return false;
|
||||
|
||||
if (buffer.loaded > 0) {
|
||||
util.sleep(250);
|
||||
break;
|
||||
}
|
||||
else
|
||||
dactyl.echo("Waiting for page to load...", commandline.DISALLOW_MULTILINE);
|
||||
}
|
||||
util.waitFor(function () !events.feedingKeys || buffer.loaded || Date.now() > end);
|
||||
commandline.clear();
|
||||
|
||||
// TODO: allow macros to be continued when page does not fully load with an option
|
||||
if (!buffer.loaded)
|
||||
dactyl.echoerr("Page did not load completely in " + maxWaitTime + " seconds. Macro stopped.");
|
||||
|
||||
// sometimes the input widget had focus when replaying a macro
|
||||
// maybe this call should be moved somewhere else?
|
||||
// dactyl.focusContent(true);
|
||||
|
||||
return buffer.loaded;
|
||||
},
|
||||
|
||||
@@ -1000,7 +1016,8 @@ var Events = Module("events", {
|
||||
*/
|
||||
|
||||
input: function onInput(event) {
|
||||
delete event.originalTarget.dactylKeyPress;
|
||||
if ("dactylKeyPress" in event.originalTarget)
|
||||
delete event.originalTarget.dactylKeyPress;
|
||||
},
|
||||
|
||||
// this keypress handler gets always called first, even if e.g.
|
||||
@@ -1024,18 +1041,17 @@ var Events = Module("events", {
|
||||
let duringFeed = this.duringFeed || [];
|
||||
this.duringFeed = [];
|
||||
try {
|
||||
if (this.feedingEvent && [!(k in event) || event[k] === v for ([k, v] in Iterator(this.feedingEvent))].every(util.identity)) {
|
||||
if (this.feedingEvent)
|
||||
for (let [k, v] in Iterator(this.feedingEvent))
|
||||
if (!(k in event))
|
||||
event[k] = v;
|
||||
this.feedingEvent = null;
|
||||
}
|
||||
this.feedingEvent = null;
|
||||
|
||||
let key = events.toString(event);
|
||||
if (!key)
|
||||
return null;
|
||||
|
||||
if (modes.recording && (!this._input || !mappings.user.hasMap(modes.main, this._input.buffer + key)))
|
||||
if (modes.recording && !event.isReplay)
|
||||
events._macroKeys.push(key);
|
||||
|
||||
// feedingKeys needs to be separate from interrupted so
|
||||
@@ -1043,8 +1059,6 @@ var Events = Module("events", {
|
||||
// interrupting whatever it's started and a real <C-c>
|
||||
// interrupting our playback.
|
||||
if (events.feedingKeys && !event.isMacro) {
|
||||
if (!event.originalTarget)
|
||||
util.dumpStack();
|
||||
if (key == "<C-c>") {
|
||||
events.feedingKeys = false;
|
||||
if (modes.replaying) {
|
||||
@@ -1177,10 +1191,6 @@ var Events = Module("events", {
|
||||
// access to the real focus target
|
||||
// Huh? --djk
|
||||
onFocusChange: function onFocusChange(event) {
|
||||
// command line has its own focus change handler
|
||||
if (modes.main.input)
|
||||
return;
|
||||
|
||||
function hasHTMLDocument(win) win && win.document && win.document instanceof HTMLDocument
|
||||
|
||||
let win = window.document.commandDispatcher.focusedWindow;
|
||||
@@ -1202,7 +1212,7 @@ var Events = Module("events", {
|
||||
}
|
||||
|
||||
if (Events.isInputElement(elem)) {
|
||||
if (!(modes.main & (modes.INSERT | modes.TEXT_EDIT | modes.VISUAL)))
|
||||
if (!modes.main.input)
|
||||
modes.push(modes.INSERT);
|
||||
|
||||
if (hasHTMLDocument(win))
|
||||
@@ -1216,7 +1226,7 @@ var Events = Module("events", {
|
||||
if (modes.main == modes.VISUAL && elem.selectionEnd == elem.selectionStart)
|
||||
modes.pop();
|
||||
|
||||
if (!(modes.main & (modes.INSERT | modes.TEXT_EDIT | modes.VISUAL)))
|
||||
if (!modes.main.input)
|
||||
if (options["insertmode"])
|
||||
modes.push(modes.INSERT);
|
||||
else {
|
||||
@@ -1323,11 +1333,11 @@ var Events = Module("events", {
|
||||
},
|
||||
mappings: function () {
|
||||
mappings.add(modes.all,
|
||||
["<C-z>"], "Temporarily ignore all " + config.appName + " key bindings",
|
||||
["<C-z>", "<pass-all-keys>"], "Temporarily ignore all " + config.appName + " key bindings",
|
||||
function () { modes.push(modes.PASS_THROUGH); });
|
||||
|
||||
mappings.add(modes.all,
|
||||
["<C-v>"], "Pass through next key",
|
||||
["<C-v>", "<pass-next-key>"], "Pass through next key",
|
||||
function () {
|
||||
if (modes.main == modes.QUOTE)
|
||||
return Events.PASS;
|
||||
@@ -1340,7 +1350,7 @@ var Events = Module("events", {
|
||||
|
||||
// macros
|
||||
mappings.add([modes.NORMAL, modes.TEXT_AREA, modes.PLAYER].filter(util.identity),
|
||||
["q"], "Record a key sequence into a macro",
|
||||
["q", "<record-macro>"], "Record a key sequence into a macro",
|
||||
function ({ arg }) {
|
||||
events._macroKeys.pop();
|
||||
events[modes.recording ? "finishRecording" : "startRecording"](arg);
|
||||
@@ -1348,13 +1358,33 @@ var Events = Module("events", {
|
||||
{ get arg() !modes.recording });
|
||||
|
||||
mappings.add([modes.NORMAL, modes.TEXT_AREA, modes.PLAYER].filter(util.identity),
|
||||
["@"], "Play a macro",
|
||||
["@", "<play-macro>"], "Play a macro",
|
||||
function ({ arg, count }) {
|
||||
count = Math.max(count, 1);
|
||||
while (count-- && events.playMacro(arg))
|
||||
;
|
||||
},
|
||||
{ arg: true, count: true });
|
||||
|
||||
mappings.add([modes.COMMAND],
|
||||
["<A-m>s", "<sleep>"], "Sleep for {count} milliseconds before continuing macro playback",
|
||||
function ({ command, count }) {
|
||||
let now = Date.now();
|
||||
dactyl.assert(count, "Count required for " + command);
|
||||
if (events.feedingKeys)
|
||||
util.sleep(count);
|
||||
},
|
||||
{ count: true });
|
||||
|
||||
mappings.add([modes.COMMAND],
|
||||
["<A-m>l", "<wait-for-page-load>"], "Wait for the current page to finish loading before continuing macro playback",
|
||||
function ({ count }) {
|
||||
if (events.feedingKeys && !events.waitForPageLoad(count)) {
|
||||
util.interrupted = true;
|
||||
throw Error("Interrupted");
|
||||
}
|
||||
},
|
||||
{ count: true });
|
||||
},
|
||||
options: function () {
|
||||
options.add(["passkeys", "pk"],
|
||||
@@ -1375,9 +1405,18 @@ var Events = Module("events", {
|
||||
return values;
|
||||
}
|
||||
});
|
||||
|
||||
options.add(["strictfocus", "sf"],
|
||||
"Prevent scripts from focusing input elements without user intervention",
|
||||
"boolean", true);
|
||||
|
||||
options.add(["timeout", "tmo"],
|
||||
"Whether to execute a shorter key command after a timeout when a longer command exists",
|
||||
"boolean", true);
|
||||
|
||||
options.add(["timeoutlen", "tmol"],
|
||||
"Maximum time (milliseconds) to wait for a longer key command when a shorter one exists",
|
||||
"number", 1000);
|
||||
},
|
||||
sanitizer: function () {
|
||||
sanitizer.addItem("macros", {
|
||||
|
||||
@@ -113,9 +113,17 @@ var Map = Class("Map", {
|
||||
if (this.executing)
|
||||
util.dumpStack("Attempt to execute mapping recursively: " + args.command);
|
||||
dactyl.assert(!this.executing, "Attempt to execute mapping recursively: " + args.command);
|
||||
this.executing = true;
|
||||
let res = dactyl.trapErrors(repeat);
|
||||
this.executing = false;
|
||||
|
||||
try {
|
||||
this.executing = true;
|
||||
var res = repeat();
|
||||
}
|
||||
catch (e) {
|
||||
events.feedingKeys = false;
|
||||
}
|
||||
finally {
|
||||
this.executing = false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -507,7 +515,7 @@ var Mappings = Module("mappings", {
|
||||
description: "Accept a count before the requisite key press"
|
||||
},
|
||||
{
|
||||
names: ["-description", "-d"],
|
||||
names: ["-description", "-desc", "-d"],
|
||||
description: "A description of this mapping",
|
||||
default: "User-defined mapping",
|
||||
type: CommandOption.STRING
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
var MOW = Module("mow", {
|
||||
init: function () {
|
||||
|
||||
let fontSize = util.computedStyle(document.documentElement).fontSize;
|
||||
styles.system.add("font-size", "dactyl://content/buffer.xhtml",
|
||||
"body { font-size: " + fontSize + "; } \
|
||||
html|html > xul|scrollbar { visibility: collapse !important; }",
|
||||
true);
|
||||
|
||||
XML.ignoreWhitespace = true;
|
||||
util.overlayWindow(window, {
|
||||
objects: {
|
||||
|
||||
@@ -867,9 +867,11 @@ var Tabs = Module("tabs", {
|
||||
},
|
||||
events: function () {
|
||||
let tabContainer = config.tabbrowser.mTabContainer;
|
||||
["TabMove", "TabOpen", "TabClose"].forEach(function (event) {
|
||||
events.addSessionListener(tabContainer, event, this.closure.updateTabCount, false);
|
||||
}, this);
|
||||
function callback() {
|
||||
tabs.timeout(function () { this.updateTabCount(); });
|
||||
}
|
||||
for (let event in values(["TabMove", "TabOpen", "TabClose"]))
|
||||
events.addSessionListener(tabContainer, event, callback, false);
|
||||
events.addSessionListener(tabContainer, "TabSelect", this.closure._onTabSelect, false);
|
||||
},
|
||||
mappings: function () {
|
||||
|
||||
Reference in New Issue
Block a user