mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-22 14:18:00 +01:00
Fix some major mode changing bugs. Closes issue #55.
--HG-- branch : mode-refactoring
This commit is contained in:
@@ -30,14 +30,42 @@ const Modes = Module("modes", {
|
||||
this.boundProperties = {};
|
||||
|
||||
// main modes, only one should ever be active
|
||||
this.addMode("NORMAL", { char: "n", display: null });
|
||||
this.addMode("INSERT", { char: "i", input: true });
|
||||
this.addMode("VISUAL", { char: "v", display: function () "VISUAL" + (this._extended & modes.LINE ? " LINE" : "") });
|
||||
this.addMode("NORMAL", { char: "n", display: function () null });
|
||||
this.addMode("INSERT", { char: "i", input: true, ownsFocus: true });
|
||||
this.addMode("VISUAL", { char: "v", ownsFocus: true, display: function () "VISUAL" + (this._extended & modes.LINE ? " LINE" : "") }, {
|
||||
leave: function (stack, newMode) {
|
||||
if (newMode.main == modes.CARET) {
|
||||
let selection = window.content.getSelection();
|
||||
if (selection && !selection.isCollapsed)
|
||||
selection.collapseToStart();
|
||||
}
|
||||
else
|
||||
editor.unselectText();
|
||||
}
|
||||
});
|
||||
this.addMode("COMMAND_LINE", { char: "c", input: true });
|
||||
this.addMode("CARET"); // text cursor is visible
|
||||
this.addMode("TEXTAREA", { char: "i" });
|
||||
this.addMode("EMBED", { input: true });
|
||||
this.addMode("CUSTOM", { display: function () plugins.mode });
|
||||
this.addMode("CARET", {}, {
|
||||
get pref() options.getPref("accessibility.browsewithcaret"),
|
||||
set pref(val) options.setPref("accessibility.browsewithcaret", val),
|
||||
enter: function (stack) {
|
||||
if (stack.pop && !this.pref)
|
||||
modes.pop();
|
||||
else if (!stack.pop && !this.pref)
|
||||
this.pref = true;
|
||||
},
|
||||
leave: function (stack) {
|
||||
if (!stack.push && this.pref)
|
||||
this.pref = false;
|
||||
}
|
||||
});
|
||||
this.addMode("TEXTAREA", { char: "i", ownsFocus: true });
|
||||
this.addMode("EMBED", { input: true, ownsFocus: true });
|
||||
this.addMode("PASS_THROUGH");
|
||||
this.addMode("QUOTE", {
|
||||
display: function () modes.getStack(1).main == modes.PASS_THROUGH
|
||||
? (modes.getStack(2).mainMode.display() || modes.getStack(2).mainMode.name) + " (next)"
|
||||
: "PASS THROUGH (next)"
|
||||
});
|
||||
// this._extended modes, can include multiple modes, and even main modes
|
||||
this.addMode("EX", true);
|
||||
this.addMode("HINTS", true);
|
||||
@@ -45,30 +73,31 @@ const Modes = Module("modes", {
|
||||
this.addMode("OUTPUT_MULTILINE", true);
|
||||
this.addMode("SEARCH_FORWARD", true);
|
||||
this.addMode("SEARCH_BACKWARD", true);
|
||||
this.addMode("SEARCH_VIEW_FORWARD", true);
|
||||
this.addMode("SEARCH_VIEW_BACKWARD", true);
|
||||
this.addMode("MENU", true); // a popupmenu is active
|
||||
this.addMode("LINE", true); // linewise visual mode
|
||||
this.addMode("PROMPT", true);
|
||||
|
||||
this.push(this.NORMAL, 0, {
|
||||
restore: function (prev) {
|
||||
// disable caret mode when we want to switch to normal mode
|
||||
enter: function (stack, prev) {
|
||||
if (options.getPref("accessibility.browsewithcaret"))
|
||||
options.setPref("accessibility.browsewithcaret", false);
|
||||
|
||||
statusline.updateUrl();
|
||||
dactyl.focusContent(true);
|
||||
if (prev.mainMode.input || prev.mainMode.ownsFocus)
|
||||
dactyl.focusContent(true);
|
||||
if (prev.main === modes.NORMAL) {
|
||||
dactyl.focusContent(true);
|
||||
// clear any selection made
|
||||
let selection = window.content.getSelection();
|
||||
if (selection && !selection.isCollapsed)
|
||||
selection.collapseToStart();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_getModeMessage: function () {
|
||||
if (this._passNextKey && !this._passAllKeys)
|
||||
return "-- PASS THROUGH (next) --";
|
||||
else if (this._passAllKeys && !this._passNextKey)
|
||||
return "-- PASS THROUGH --";
|
||||
|
||||
// when recording a macro
|
||||
let macromode = "";
|
||||
if (modes.isRecording)
|
||||
@@ -81,7 +110,8 @@ const Modes = Module("modes", {
|
||||
ext += " (menu)";
|
||||
ext += " --" + macromode;
|
||||
|
||||
if (this._main in this._modeMap && typeof this._modeMap[this._main].display == "function")
|
||||
let val = this._modeMap[this._main].display();
|
||||
if (val)
|
||||
return "-- " + this._modeMap[this._main].display() + ext;
|
||||
return macromode;
|
||||
},
|
||||
@@ -98,27 +128,31 @@ const Modes = Module("modes", {
|
||||
|
||||
get topOfStack() this._modeStack[this._modeStack.length - 1],
|
||||
|
||||
addMode: function (name, extended, options) {
|
||||
addMode: function (name, extended, options, params) {
|
||||
let disp = name.replace("_", " ", "g");
|
||||
this[name] = 1 << this._lastMode++;
|
||||
|
||||
if (typeof extended == "object") {
|
||||
params = options;
|
||||
options = extended;
|
||||
extended = false;
|
||||
}
|
||||
|
||||
let mode = util.extend({
|
||||
extended: extended,
|
||||
count: true,
|
||||
disp: disp,
|
||||
extended: extended,
|
||||
input: false,
|
||||
mask: this[name],
|
||||
name: name,
|
||||
disp: disp
|
||||
params: params || {}
|
||||
}, options);
|
||||
if (mode.char) {
|
||||
this.modeChars[mode.char] = this.modeChars[mode.char] || [];
|
||||
this.modeChars[mode.char].push(mode);
|
||||
}
|
||||
|
||||
if (mode.display !== null)
|
||||
if (mode.display == null)
|
||||
mode.display = function () disp;
|
||||
this._modeMap[name] = mode;
|
||||
this._modeMap[this[name]] = mode;
|
||||
@@ -129,6 +163,8 @@ const Modes = Module("modes", {
|
||||
|
||||
getMode: function (name) this._modeMap[name],
|
||||
|
||||
getStack: function (idx) this._modeStack[this._modeStack.length - idx - 1] || this._modeStack[0],
|
||||
|
||||
getCharModes: function (chr) [m for (m in values(this._modeMap)) if (m.char == chr)],
|
||||
|
||||
matchModes: function (obj)
|
||||
@@ -158,7 +194,7 @@ const Modes = Module("modes", {
|
||||
// helper function to set both modes in one go
|
||||
// if silent == true, you also need to take care of the mode handling changes yourself
|
||||
set: function (mainMode, extendedMode, params, stack) {
|
||||
params = params || {};
|
||||
params = params || this.getMode(mainMode || this.main).params;
|
||||
|
||||
if (!stack && mainMode != null && this._modeStack.length > 1)
|
||||
this.reset();
|
||||
@@ -166,9 +202,8 @@ const Modes = Module("modes", {
|
||||
let push = mainMode != null && !(stack && stack.pop) &&
|
||||
Modes.StackElem(mainMode, extendedMode || this.NONE, params, {});
|
||||
if (push && this.topOfStack) {
|
||||
if (this.topOfStack.params.save)
|
||||
this.topOfStack.params.save(push);
|
||||
|
||||
if (this.topOfStack.params.leave)
|
||||
this.topOfStack.params.leave({ push: push }, push);
|
||||
for (let [id, { obj, prop }] in Iterator(this.boundProperties)) {
|
||||
if (!obj.get())
|
||||
delete this.boundProperties(id);
|
||||
@@ -189,8 +224,12 @@ const Modes = Module("modes", {
|
||||
this._extended = this.NONE;
|
||||
}
|
||||
|
||||
let prev = stack && stack.pop || this.topOfStack;
|
||||
if (push)
|
||||
this._modeStack.push(push);
|
||||
if (this.topOfStack.params.enter && prev)
|
||||
this.topOfStack.params.enter(push ? { push: push } : stack || {},
|
||||
prev);
|
||||
|
||||
dactyl.triggerObserver("modeChange", [oldMain, oldExtended], [this._main, this._extended], stack);
|
||||
|
||||
@@ -202,22 +241,31 @@ const Modes = Module("modes", {
|
||||
this.set(mainMode, extendedMode, params, { push: this.topOfStack });
|
||||
},
|
||||
|
||||
pop: function () {
|
||||
let a = this._modeStack.pop();
|
||||
if (a.params.leave)
|
||||
a.params.leave(this.topOfStack);
|
||||
pop: function (mode) {
|
||||
while (this._modeStack.length > 1 && this.main != mode) {
|
||||
let a = this._modeStack.pop();
|
||||
if (a.params.leave)
|
||||
a.params.leave({ pop: a }, this.topOfStack);
|
||||
|
||||
this.set(this.topOfStack.main, this.topOfStack.extended, this.topOfStack.params, { pop: a });
|
||||
if (this.topOfStack.params.restore)
|
||||
this.topOfStack.params.restore(a);
|
||||
this.set(this.topOfStack.main, this.topOfStack.extended, this.topOfStack.params, { pop: a });
|
||||
|
||||
for (let [k, { obj, prop, value }] in Iterator(this.topOfStack.saved))
|
||||
obj[prop] = value;
|
||||
for (let [k, { obj, prop, value }] in Iterator(this.topOfStack.saved))
|
||||
obj[prop] = value;
|
||||
|
||||
if (mode == null)
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
replace: function (mode, oldMode) {
|
||||
// TODO: This should really be done in one step.
|
||||
this.pop(oldMode);
|
||||
this.push(mode);
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
if (this._modeStack.length == 1 && this.topOfStack.params.restore)
|
||||
this.topOfStack.params.restore(this.topOfStack);
|
||||
if (this._modeStack.length == 1 && this.topOfStack.params.enter)
|
||||
this.topOfStack.params.enter({}, this.topOfStack);
|
||||
while (this._modeStack.length > 1)
|
||||
this.pop();
|
||||
},
|
||||
@@ -229,12 +277,6 @@ const Modes = Module("modes", {
|
||||
}
|
||||
},
|
||||
|
||||
get passNextKey() this._passNextKey,
|
||||
set passNextKey(value) { this._passNextKey = value; this.show(); },
|
||||
|
||||
get passAllKeys() this._passAllKeys,
|
||||
set passAllKeys(value) { this._passAllKeys = value; this.show(); },
|
||||
|
||||
get isRecording() this._isRecording,
|
||||
set isRecording(value) { this._isRecording = value; this.show(); },
|
||||
|
||||
@@ -247,7 +289,17 @@ const Modes = Module("modes", {
|
||||
get extended() this._extended,
|
||||
set extended(value) { this.set(null, value); }
|
||||
}, {
|
||||
StackElem: Struct("main", "extended", "params", "saved"),
|
||||
StackElem: (function () {
|
||||
let struct = Struct("main", "extended", "params", "saved");
|
||||
struct.prototype.__defineGetter__("mainMode", function () modes.getMode(this.main));
|
||||
struct.prototype.toString = function () !loaded.modes ? this.main : "[mode " +
|
||||
modes.getMode(this.main).name +
|
||||
(!this.extended ? "" :
|
||||
"(" +
|
||||
[modes.getMode(1<<i).name for (i in util.range(0, 32)) if (this.extended & (1<<i))].join("|") +
|
||||
")") + "]";
|
||||
return struct;
|
||||
})(),
|
||||
cacheId: 0,
|
||||
boundProperty: function boundProperty(desc) {
|
||||
desc = desc || {};
|
||||
@@ -270,6 +322,15 @@ const Modes = Module("modes", {
|
||||
})
|
||||
}, desc));
|
||||
}
|
||||
}, {
|
||||
options: function () {
|
||||
options.observePref("accessibility.browsewithcaret", function (value) {
|
||||
if (!value && modes.topOfStack.main === modes.CARET)
|
||||
modes.pop();
|
||||
if (value && modes.main === modes.NORMAL)
|
||||
modes.push(modes.CARET);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// vim: set fdm=marker sw=4 ts=4 et:
|
||||
|
||||
Reference in New Issue
Block a user