mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 08:27:59 +01:00
Begin replacing the key processing rat's nest.
--HG-- branch : key-processing
This commit is contained in:
@@ -1115,9 +1115,9 @@ var CommandLine = Module("commandline", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Wouldn't multiple handlers be cleaner? --djk
|
// TODO: Wouldn't multiple handlers be cleaner? --djk
|
||||||
if (event.type == "click" && (event.target instanceof HTMLAnchorElement ||
|
if (event.type == "click" && event.target instanceof HTMLAnchorElement) {
|
||||||
event.originalTarget.hasAttributeNS(NS, "command"))) {
|
|
||||||
|
|
||||||
|
util.dump(event.getPreventDefault(), event.target);
|
||||||
if (event.getPreventDefault())
|
if (event.getPreventDefault())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,219 @@
|
|||||||
|
|
||||||
/** @scope modules */
|
/** @scope modules */
|
||||||
|
|
||||||
|
var ProcessorStack = Class("ProcessorStack", {
|
||||||
|
init: function (mode, hives, keyModes) {
|
||||||
|
this.main = mode.main;
|
||||||
|
this.actions = [];
|
||||||
|
this.buffer = "";
|
||||||
|
this.events = [];
|
||||||
|
|
||||||
|
this.processors = keyModes.map(function (m) hives.map(function (h) KeyProcessor(m, h)))
|
||||||
|
.flatten().array;
|
||||||
|
|
||||||
|
for (let [i, input] in Iterator(this.processors)) {
|
||||||
|
let params = input.main == mode.main ? mode.params : input.main.params;
|
||||||
|
if (params.preExecute)
|
||||||
|
input.preExecute = params.preExecute;
|
||||||
|
if (params.postExecute)
|
||||||
|
input.postExecute = params.postExecute;
|
||||||
|
if (params.onEvent && input.hive === mappings.builtin)
|
||||||
|
input.fallthrough = function (event) {
|
||||||
|
return params.onEvent(event) === false ? Events.KILL : Events.PASS;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
process: function process(event) {
|
||||||
|
function dbg() {}
|
||||||
|
|
||||||
|
let key = events.toString(event);
|
||||||
|
this.events.push(event);
|
||||||
|
|
||||||
|
this.buffer += key;
|
||||||
|
|
||||||
|
let actions = [];
|
||||||
|
let processors = [];
|
||||||
|
|
||||||
|
dbg("\n\n");
|
||||||
|
dbg("KEY: " + key + " skipmap: " + event.skipmap + " macro: " + event.isMacro);
|
||||||
|
|
||||||
|
for (let [i, input] in Iterator(this.processors)) {
|
||||||
|
let res = input.process(event);
|
||||||
|
if (res !== Events.ABORT)
|
||||||
|
var result = res;
|
||||||
|
|
||||||
|
dbg("RES: " + input + " " + (callable(res) ? {}.toString.call(res) : res));
|
||||||
|
|
||||||
|
if (res === Events.KILL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
buffer = buffer || input.inputBuffer;
|
||||||
|
|
||||||
|
if (callable(res))
|
||||||
|
actions.push(res);
|
||||||
|
|
||||||
|
if (isinstance(res, KeyProcessor))
|
||||||
|
processors.push(res);
|
||||||
|
if (res === Events.WAIT || input.waiting)
|
||||||
|
processors.push(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("RESULT: " + (callable(result) ? {}.toString.call(result) : result) + " " + event.getPreventDefault());
|
||||||
|
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.concat(this.actions);
|
||||||
|
|
||||||
|
if (result === Events.KILL)
|
||||||
|
this.actions = [];
|
||||||
|
else if (!this.actions.length)
|
||||||
|
for (let input in values(this.processors))
|
||||||
|
if (input.fallthrough) {
|
||||||
|
if (result === Events.KILL)
|
||||||
|
break;
|
||||||
|
result = dactyl.trapErrors(input.fallthrough, input, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.processors = processors;
|
||||||
|
|
||||||
|
if (processors.length)
|
||||||
|
result = Events.KILL;
|
||||||
|
else if (this.actions.length) {
|
||||||
|
if (actions.length == 0)
|
||||||
|
dactyl.beep();
|
||||||
|
result = this.actions[0]() === Events.PASS ? Events.PASS : Events.KILL;
|
||||||
|
}
|
||||||
|
else if (result !== Events.KILL && 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.onKeyPress(event);
|
||||||
|
});
|
||||||
|
return this.processors.length == 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var KeyProcessor = Class("KeyProcessor", {
|
||||||
|
init: function init(main, hive) {
|
||||||
|
this.main = main;
|
||||||
|
this.events = [];
|
||||||
|
this.hive = hive;
|
||||||
|
this.wantCount = this.main.count;
|
||||||
|
},
|
||||||
|
|
||||||
|
get toStringParams() [this.main.name, this.hive.name],
|
||||||
|
|
||||||
|
countStr: "",
|
||||||
|
command: "",
|
||||||
|
get count() this.countStr ? Number(this.countStr) : null,
|
||||||
|
|
||||||
|
append: function append(event) {
|
||||||
|
this.events.push(event);
|
||||||
|
let key = events.toString(event);
|
||||||
|
|
||||||
|
if (this.wantCount && !this.command &&
|
||||||
|
(this.countStr ? /^[0-9]$/ : /^[1-9]$/).test(key))
|
||||||
|
this.countStr += key;
|
||||||
|
else
|
||||||
|
this.command += key;
|
||||||
|
return this.events;
|
||||||
|
},
|
||||||
|
|
||||||
|
process: function process(event) {
|
||||||
|
this.append(event);
|
||||||
|
this.waiting = false;
|
||||||
|
return this.onKeyPress(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
execute: function execute(map)
|
||||||
|
let (self = this, args = arguments)
|
||||||
|
function execute() {
|
||||||
|
if (self.preExecute)
|
||||||
|
self.preExecute.apply(self, args);
|
||||||
|
let res = map.execute.apply(map, Array.slice(args, 1));
|
||||||
|
if (self.postExecute)
|
||||||
|
self.postExecute.apply(self, args);
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
|
onKeyPress: function onKeyPress(event) {
|
||||||
|
if (event.skipmap)
|
||||||
|
return Events.ABORT;
|
||||||
|
|
||||||
|
if (!this.command)
|
||||||
|
return Events.WAIT;
|
||||||
|
|
||||||
|
var map = this.hive.get(this.main, this.command);
|
||||||
|
this.waiting = this.hive.getCandidates(this.main, this.command);
|
||||||
|
if (map) {
|
||||||
|
if (map.arg)
|
||||||
|
return KeyArgProcessor(this, map, false, "arg");
|
||||||
|
else if (map.motion)
|
||||||
|
return KeyArgProcessor(this, map, true, "motion");
|
||||||
|
else if (modes.replaying && !events.waitForPageLoad())
|
||||||
|
return Events.KILL;
|
||||||
|
|
||||||
|
return this.execute(map, { count: this.count, command: this.command, events: this.events });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.waiting)
|
||||||
|
return this.main.input ? Events.PASS : Events.ABORT;
|
||||||
|
|
||||||
|
return Events.WAIT;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var KeyArgProcessor = Class("KeyArgProcessor", KeyProcessor, {
|
||||||
|
init: function init(input, map, wantCount, argName) {
|
||||||
|
init.supercall(this, input.main, input.hive);
|
||||||
|
this.map = map;
|
||||||
|
this.parent = input;
|
||||||
|
this.argName = argName;
|
||||||
|
this.wantCount = wantCount;
|
||||||
|
},
|
||||||
|
|
||||||
|
onKeyPress: function onKeyPress(event) {
|
||||||
|
if (Events.isEscape(event))
|
||||||
|
return Events.KILL;
|
||||||
|
if (!this.command)
|
||||||
|
return Events.WAIT;
|
||||||
|
|
||||||
|
let args = {
|
||||||
|
command: this.parent.command,
|
||||||
|
count: this.count || this.parent.count,
|
||||||
|
events: this.parent.events.concat(this.events)
|
||||||
|
};
|
||||||
|
args[this.argName] = this.command;
|
||||||
|
|
||||||
|
return this.execute(this.map, args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @instance events
|
* @instance events
|
||||||
*/
|
*/
|
||||||
var Events = Module("events", {
|
var Events = Module("events", {
|
||||||
init: function () {
|
init: function () {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
util.overlayWindow(window, {
|
util.overlayWindow(window, {
|
||||||
append: <e4x xmlns={XUL}>
|
append: <e4x xmlns={XUL}>
|
||||||
<window id={document.documentElement.id}>
|
<window id={document.documentElement.id}>
|
||||||
@@ -32,7 +240,6 @@ var Events = Module("events", {
|
|||||||
this._currentMacro = "";
|
this._currentMacro = "";
|
||||||
this._macroKeys = [];
|
this._macroKeys = [];
|
||||||
this._lastMacro = "";
|
this._lastMacro = "";
|
||||||
this._processors = [];
|
|
||||||
|
|
||||||
this.sessionListeners = [];
|
this.sessionListeners = [];
|
||||||
|
|
||||||
@@ -103,6 +310,10 @@ var Events = Module("events", {
|
|||||||
this.addSessionListener(window, "popuphidden", this.onPopupHidden, true);
|
this.addSessionListener(window, "popuphidden", this.onPopupHidden, true);
|
||||||
this.addSessionListener(window, "popupshown", this.onPopupShown, true);
|
this.addSessionListener(window, "popupshown", this.onPopupShown, true);
|
||||||
this.addSessionListener(window, "resize", this.onResize, true);
|
this.addSessionListener(window, "resize", this.onResize, true);
|
||||||
|
|
||||||
|
dactyl.registerObserver("modeChange", function () {
|
||||||
|
delete this.processor;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
@@ -863,15 +1074,6 @@ var Events = Module("events", {
|
|||||||
onKeyPress: function onKeyPress(event) {
|
onKeyPress: function onKeyPress(event) {
|
||||||
event.dactylDefaultPrevented = event.getPreventDefault();
|
event.dactylDefaultPrevented = event.getPreventDefault();
|
||||||
|
|
||||||
function kill(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldPass()
|
|
||||||
(!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement)) &&
|
|
||||||
options.get("passkeys").has(events.toString(event));
|
|
||||||
|
|
||||||
let duringFeed = this.duringFeed || [];
|
let duringFeed = this.duringFeed || [];
|
||||||
this.duringFeed = [];
|
this.duringFeed = [];
|
||||||
try {
|
try {
|
||||||
@@ -906,16 +1108,14 @@ var Events = Module("events", {
|
|||||||
else
|
else
|
||||||
duringFeed.push(event);
|
duringFeed.push(event);
|
||||||
|
|
||||||
return kill(event);
|
return Events.kill(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.processor) {
|
||||||
let mode = modes.getStack(0);
|
let mode = modes.getStack(0);
|
||||||
if (event.dactylMode)
|
if (event.dactylMode)
|
||||||
mode = Modes.StackElement(event.dactylMode);
|
mode = Modes.StackElement(event.dactylMode);
|
||||||
|
|
||||||
let processors = this._processors;
|
|
||||||
this._processors = [];
|
|
||||||
if (!processors.length) {
|
|
||||||
let ignore = false;
|
let ignore = false;
|
||||||
let overrideMode = null;
|
let overrideMode = null;
|
||||||
|
|
||||||
@@ -930,7 +1130,7 @@ var Events = Module("events", {
|
|||||||
mode.params.mainMode = modes.getStack(2).main;
|
mode.params.mainMode = modes.getStack(2).main;
|
||||||
ignore = Events.isEscape(key);
|
ignore = Events.isEscape(key);
|
||||||
}
|
}
|
||||||
else if (shouldPass())
|
else if (events.shouldPass(event))
|
||||||
mode.params.mainMode = modes.getStack(1).main;
|
mode.params.mainMode = modes.getStack(1).main;
|
||||||
else
|
else
|
||||||
ignore = true;
|
ignore = true;
|
||||||
@@ -938,7 +1138,7 @@ var Events = Module("events", {
|
|||||||
if (ignore && !Events.isEscape(key))
|
if (ignore && !Events.isEscape(key))
|
||||||
modes.pop();
|
modes.pop();
|
||||||
}
|
}
|
||||||
else if (!event.isMacro && !event.noremap && shouldPass())
|
else if (!event.isMacro && !event.noremap && events.shouldPass(event))
|
||||||
ignore = true;
|
ignore = true;
|
||||||
|
|
||||||
if (ignore)
|
if (ignore)
|
||||||
@@ -957,78 +1157,14 @@ var Events = Module("events", {
|
|||||||
|
|
||||||
let hives = mappings.hives.slice(event.noremap ? -1 : 0);
|
let hives = mappings.hives.slice(event.noremap ? -1 : 0);
|
||||||
|
|
||||||
processors = keyModes.map(function (m) hives.map(function (h) Events.KeyProcessor(m, h)))
|
this.processor = ProcessorStack(mode, hives, keyModes);
|
||||||
.flatten().array;
|
|
||||||
|
|
||||||
for (let [i, input] in Iterator(processors)) {
|
|
||||||
let params = input.main == mode.main ? mode.params : input.main.params;
|
|
||||||
if (params.preExecute)
|
|
||||||
input.preExecute = params.preExecute;
|
|
||||||
if (params.postExecute)
|
|
||||||
input.postExecute = params.postExecute;
|
|
||||||
if (params.onEvent && input.hive === mappings.builtin)
|
|
||||||
input.fallthrough = function (event) {
|
|
||||||
return params.onEvent(event) === false ? Events.KILL : Events.PASS;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let refeed, buffer, waiting = 0, action;
|
let processor = this.processor;
|
||||||
for (let input in values(processors)) {
|
this.processor = null;
|
||||||
var res = input.process(event);
|
if (!processor.process(event))
|
||||||
waiting += res == Events.WAIT;
|
this.processor = processor;
|
||||||
buffer = buffer || input.inputBuffer;
|
|
||||||
if (callable(res))
|
|
||||||
action = action || res;
|
|
||||||
|
|
||||||
if (isArray(res) && !waiting)
|
|
||||||
refeed = res;
|
|
||||||
if (res === Events.KILL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!refeed || refeed.length == 1)
|
|
||||||
for (let input in values(processors))
|
|
||||||
if (input.fallthrough) {
|
|
||||||
if (res === Events.KILL)
|
|
||||||
break;
|
|
||||||
res = dactyl.trapErrors(input.fallthrough, input, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!processors.some(function (p) p.main.ownsBuffer))
|
|
||||||
statusline.updateInputBuffer(buffer);
|
|
||||||
|
|
||||||
if (waiting) {
|
|
||||||
res = Events.KILL;
|
|
||||||
this._processors = processors;
|
|
||||||
}
|
|
||||||
else if (action)
|
|
||||||
res = action(res) === Events.PASS ? Events.PASS : Events.KILL;
|
|
||||||
|
|
||||||
if (res !== Events.KILL && (mode.main & (modes.TEXT_EDIT | modes.VISUAL))) {
|
|
||||||
res = Events.KILL;
|
|
||||||
dactyl.beep();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res !== Events.PASS && !isArray(res))
|
|
||||||
refeed = null;
|
|
||||||
|
|
||||||
if (refeed && refeed[0] && (!refeed[0].getPreventDefault() || refeed[0].dactylDefaultPrevented)) {
|
|
||||||
res = Events.PASS;
|
|
||||||
refeed.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res !== Events.PASS)
|
|
||||||
kill(event);
|
|
||||||
|
|
||||||
if (refeed)
|
|
||||||
for (let [i, event] in Iterator(refeed))
|
|
||||||
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.onKeyPress(event);
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
dactyl.reportError(e);
|
dactyl.reportError(e);
|
||||||
@@ -1053,15 +1189,11 @@ var Events = Module("events", {
|
|||||||
// before we get a chance to process our key bindings on the
|
// before we get a chance to process our key bindings on the
|
||||||
// "keypress" event.
|
// "keypress" event.
|
||||||
|
|
||||||
function shouldPass() // FIXME.
|
|
||||||
(!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement)) &&
|
|
||||||
options.get("passkeys").has(events.toString(event));
|
|
||||||
|
|
||||||
if (modes.main == modes.PASS_THROUGH ||
|
if (modes.main == modes.PASS_THROUGH ||
|
||||||
modes.main == modes.QUOTE
|
modes.main == modes.QUOTE
|
||||||
&& modes.getStack(1).main !== modes.PASS_THROUGH
|
&& modes.getStack(1).main !== modes.PASS_THROUGH
|
||||||
&& !shouldPass() ||
|
&& !events.shouldPass(event) ||
|
||||||
!modes.passThrough && shouldPass())
|
!modes.passThrough && events.shouldPass(event))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!Events.isInputElement(dactyl.focusedElement))
|
if (!Events.isInputElement(dactyl.focusedElement))
|
||||||
@@ -1110,137 +1242,17 @@ var Events = Module("events", {
|
|||||||
else if (modes.main == modes.CARET)
|
else if (modes.main == modes.CARET)
|
||||||
modes.push(modes.VISUAL);
|
modes.push(modes.VISUAL);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
shouldPass: function shouldPass(event)
|
||||||
|
(!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement)) &&
|
||||||
|
options.get("passkeys").has(events.toString(event))
|
||||||
}, {
|
}, {
|
||||||
|
ABORT: {},
|
||||||
KILL: true,
|
KILL: true,
|
||||||
PASS: false,
|
PASS: false,
|
||||||
WAIT: null,
|
WAIT: null,
|
||||||
|
|
||||||
|
|
||||||
KeyProcessor: Class("KeyProcessor", {
|
|
||||||
init: function init(main, hive) {
|
|
||||||
this.main = main;
|
|
||||||
this.events = [];
|
|
||||||
this.hive = hive;
|
|
||||||
},
|
|
||||||
|
|
||||||
get toStringParams() [this.main.name, this.hive.name],
|
|
||||||
|
|
||||||
buffer: "", // partial command storage
|
|
||||||
pendingMotionMap: null, // e.g. "d{motion}" if we wait for a motion of the "d" command
|
|
||||||
pendingArgMap: null, // pending map storage for commands like m{a-z}
|
|
||||||
count: null, // parsed count from the input buffer
|
|
||||||
motionCount: null,
|
|
||||||
|
|
||||||
append: function append(event) {
|
|
||||||
this.events.push(event);
|
|
||||||
this.buffer += events.toString(event);
|
|
||||||
return this.events;
|
|
||||||
},
|
|
||||||
|
|
||||||
process: function process(event) {
|
|
||||||
function kill(event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = this.onKeyPress(event);
|
|
||||||
|
|
||||||
if (res != Events.WAIT)
|
|
||||||
this.inputBuffer = "";
|
|
||||||
else {
|
|
||||||
let motionMap = (this.pendingMotionMap && this.pendingMotionMap.names[0]) || "";
|
|
||||||
this.inputBuffer = motionMap + this.buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
|
|
||||||
execute: function execute(map)
|
|
||||||
let (self = this, args = arguments)
|
|
||||||
function execute() {
|
|
||||||
if (self.preExecute)
|
|
||||||
self.preExecute.apply(self, args);
|
|
||||||
let res = map.execute.apply(map, Array.slice(args, 1));
|
|
||||||
if (self.postExecute) // To do: get rid of self.
|
|
||||||
self.postExecute.apply(self, args);
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
|
|
||||||
onKeyPress: function onKeyPress(event) {
|
|
||||||
// This all needs to go. It's horrible. --Kris
|
|
||||||
|
|
||||||
let key = events.toString(event);
|
|
||||||
let [, countStr, command] = /^((?:[1-9][0-9]*)?)(.*)/.exec(this.buffer + key);
|
|
||||||
|
|
||||||
var map = this.hive.get(this.main, command);
|
|
||||||
|
|
||||||
let candidates = this.hive.getCandidates(this.main, command);
|
|
||||||
if (candidates == 0 && !map) {
|
|
||||||
[map] = this.pendingMap || [];
|
|
||||||
this.pendingMap = null;
|
|
||||||
if (map && map.arg)
|
|
||||||
this.pendingArgMap = [map, command];
|
|
||||||
}
|
|
||||||
|
|
||||||
// counts must be at the start of a complete mapping (10j -> go 10 lines down)
|
|
||||||
if (countStr && !command) {
|
|
||||||
// no count for insert mode mappings
|
|
||||||
if (!this.main.count)
|
|
||||||
return this.append(event);
|
|
||||||
else if (this.main.input)
|
|
||||||
return Events.PASS;
|
|
||||||
else
|
|
||||||
this.append(event);
|
|
||||||
}
|
|
||||||
else if (this.pendingArgMap) {
|
|
||||||
let [map, command] = this.pendingArgMap;
|
|
||||||
if (!Events.isEscape(key))
|
|
||||||
return this.execute(map, null, this.count, key, command);
|
|
||||||
return Events.KILL;
|
|
||||||
}
|
|
||||||
else if (!event.skipmap && map && candidates == 0) {
|
|
||||||
this.pendingMap = null;
|
|
||||||
|
|
||||||
let count = this.pendingMotionMap ? "motionCount" : "count";
|
|
||||||
this[count] = parseInt(countStr, 10);
|
|
||||||
|
|
||||||
if (isNaN(this[count]))
|
|
||||||
this[count] = null;
|
|
||||||
|
|
||||||
if (map.arg) {
|
|
||||||
this.append(event);
|
|
||||||
this.pendingArgMap = [map, command];
|
|
||||||
}
|
|
||||||
else if (this.pendingMotionMap) {
|
|
||||||
let [map, command] = this.pendingMotionMap;
|
|
||||||
if (!Events.isEscape(key))
|
|
||||||
return this.execute(map, command, this.motionCount || this.count, null, command);
|
|
||||||
return Events.KILL;
|
|
||||||
}
|
|
||||||
else if (map.motion) {
|
|
||||||
this.buffer = "";
|
|
||||||
this.pendingMotionMap = [map, command];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (modes.replaying && !events.waitForPageLoad())
|
|
||||||
return Events.KILL;
|
|
||||||
|
|
||||||
return this.execute(map, null, this.count, null, command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!event.skipmap && this.hive.getCandidates(this.main, command) > 0) {
|
|
||||||
this.append(event);
|
|
||||||
this.pendingMap = [map, command];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.append(event);
|
|
||||||
return this.events;
|
|
||||||
}
|
|
||||||
return Events.WAIT;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
isEscape: function isEscape(event)
|
isEscape: function isEscape(event)
|
||||||
let (key = isString(event) ? event : events.toString(event))
|
let (key = isString(event) ? event : events.toString(event))
|
||||||
key === "<Esc>" || key === "<C-[>",
|
key === "<Esc>" || key === "<C-[>",
|
||||||
@@ -1252,6 +1264,11 @@ var Events = Module("events", {
|
|||||||
HTMLTextAreaElement,
|
HTMLTextAreaElement,
|
||||||
Ci.nsIDOMXULTreeElement, Ci.nsIDOMXULTextBoxElement]) ||
|
Ci.nsIDOMXULTreeElement, Ci.nsIDOMXULTextBoxElement]) ||
|
||||||
elem instanceof Window && Editor.getEditor(elem);
|
elem instanceof Window && Editor.getEditor(elem);
|
||||||
|
},
|
||||||
|
|
||||||
|
kill: function kill(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
commands: function () {
|
commands: function () {
|
||||||
|
|||||||
@@ -95,22 +95,20 @@ var Map = Class("Map", {
|
|||||||
/**
|
/**
|
||||||
* Execute the action for this mapping.
|
* Execute the action for this mapping.
|
||||||
*
|
*
|
||||||
* @param {string} motion The motion argument if accepted by this mapping.
|
* @param {object} args The arguments object for the given mapping.
|
||||||
* E.g. "w" for "dw"
|
|
||||||
* @param {number} count The associated count. E.g. "5" for "5j"
|
|
||||||
* @default -1
|
|
||||||
* @param {string} argument The normal argument if accepted by this
|
|
||||||
* mapping. E.g. "a" for "ma"
|
|
||||||
*/
|
*/
|
||||||
execute: function (motion, count, argument, command) {
|
execute: function (args) {
|
||||||
let args = { count: count, arg: argument, motion: motion, command: command };
|
if (!isObject(args)) // Backwards compatibility :(
|
||||||
|
args = iter(["motion", "count", "arg", "command"])
|
||||||
|
.map(function ([i, prop]) [prop, this[i]], arguments)
|
||||||
|
.toObject()
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
function repeat() self.action(args)
|
function repeat() self.action(args)
|
||||||
if (this.names[0] != ".") // FIXME: Kludge.
|
if (this.names[0] != ".") // FIXME: Kludge.
|
||||||
mappings.repeat = repeat;
|
mappings.repeat = repeat;
|
||||||
|
|
||||||
dactyl.assert(!this.executing, "Attempt to execute mapping recursively");
|
dactyl.assert(!this.executing, "Attempt to execute mapping recursively: " + args.command);
|
||||||
this.executing = true;
|
this.executing = true;
|
||||||
let res = dactyl.trapErrors(repeat);
|
let res = dactyl.trapErrors(repeat);
|
||||||
this.executing = false;
|
this.executing = false;
|
||||||
@@ -382,7 +380,7 @@ var Mappings = Module("mappings", {
|
|||||||
* @returns {Map}
|
* @returns {Map}
|
||||||
*/
|
*/
|
||||||
get: function get(mode, cmd) {
|
get: function get(mode, cmd) {
|
||||||
return this.hives.nth(function (h) h.get(mode, command), 0);
|
return this.hives.nth(function (h) h.get(mode, cmd), 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -60,9 +60,10 @@ var Modes = Module("modes", {
|
|||||||
this.addMode("VISUAL", {
|
this.addMode("VISUAL", {
|
||||||
char: "v",
|
char: "v",
|
||||||
description: "Active when text is selected",
|
description: "Active when text is selected",
|
||||||
|
display: function () "VISUAL" + (this._extended & modes.LINE ? " LINE" : ""),
|
||||||
bases: [this.COMMAND],
|
bases: [this.COMMAND],
|
||||||
ownsFocus: true,
|
ownsFocus: true,
|
||||||
display: function () "VISUAL" + (this._extended & modes.LINE ? " LINE" : "")
|
passUnknown: false
|
||||||
}, {
|
}, {
|
||||||
leave: function (stack, newMode) {
|
leave: function (stack, newMode) {
|
||||||
if (newMode.main == modes.CARET) {
|
if (newMode.main == modes.CARET) {
|
||||||
@@ -98,7 +99,8 @@ var Modes = Module("modes", {
|
|||||||
char: "t",
|
char: "t",
|
||||||
description: "Vim-like editing of input elements",
|
description: "Vim-like editing of input elements",
|
||||||
bases: [this.COMMAND],
|
bases: [this.COMMAND],
|
||||||
ownsFocus: true
|
ownsFocus: true,
|
||||||
|
passUnknown: false
|
||||||
});
|
});
|
||||||
this.addMode("OUTPUT_MULTILINE", {
|
this.addMode("OUTPUT_MULTILINE", {
|
||||||
description: "Active when the multi-line output buffer is open",
|
description: "Active when the multi-line output buffer is open",
|
||||||
@@ -432,11 +434,7 @@ var Modes = Module("modes", {
|
|||||||
|
|
||||||
get bases() this.input ? [modes.INPUT] : [modes.MAIN],
|
get bases() this.input ? [modes.INPUT] : [modes.MAIN],
|
||||||
|
|
||||||
get toStringParams() [this.name],
|
get count() !this.input,
|
||||||
|
|
||||||
valueOf: function () this.id,
|
|
||||||
|
|
||||||
count: true,
|
|
||||||
|
|
||||||
get description() this._display,
|
get description() this._display,
|
||||||
|
|
||||||
@@ -450,7 +448,13 @@ var Modes = Module("modes", {
|
|||||||
|
|
||||||
input: false,
|
input: false,
|
||||||
|
|
||||||
get mask() this
|
passUnknown: false,
|
||||||
|
|
||||||
|
get mask() this,
|
||||||
|
|
||||||
|
get toStringParams() [this.name],
|
||||||
|
|
||||||
|
valueOf: function () this.id
|
||||||
}, {
|
}, {
|
||||||
_id: 0
|
_id: 0
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ function isinstance(object, interfaces) {
|
|||||||
if (objproto.toString.call(object) === "[object " + interfaces[i] + "]")
|
if (objproto.toString.call(object) === "[object " + interfaces[i] + "]")
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if ("isinstance" in object && object.isinstance !== isinstance) {
|
else if (typeof object === "object" && "isinstance" in object && object.isinstance !== isinstance) {
|
||||||
if (object.isinstance(interfaces[i]))
|
if (object.isinstance(interfaces[i]))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user