summaryrefslogtreecommitdiff
path: root/common/content
diff options
context:
space:
mode:
authorKris Maglione <maglione.k@gmail.com>2011-08-05 16:50:00 -0400
committerKris Maglione <maglione.k@gmail.com>2011-08-05 16:50:00 -0400
commitf502617a8460ba807ae726577195656707185882 (patch)
tree96aed1adbed89cc93f8d8947da6ce16b91fbecd0 /common/content
parent55f5f9292b18a7b6ff2f6d70cb45a530b81e3862 (diff)
downloadpentadactyl-f502617a8460ba807ae726577195656707185882.tar.gz
Add operator mode per Vim. Wrap most editor commands in transactions. And stuff. Closes issue #439.
Diffstat (limited to 'common/content')
-rw-r--r--common/content/buffer.js28
-rw-r--r--common/content/editor.js317
-rw-r--r--common/content/mappings.js29
-rw-r--r--common/content/modes.js13
4 files changed, 193 insertions, 194 deletions
diff --git a/common/content/buffer.js b/common/content/buffer.js
index d1577935..ace57af8 100644
--- a/common/content/buffer.js
+++ b/common/content/buffer.js
@@ -1688,12 +1688,12 @@ var Buffer = Module("buffer", {
function () { ex.stop(); });
// scrolling
- mappings.add([modes.COMMAND], ["j", "<Down>", "<C-e>", "<scroll-down-line>"],
+ mappings.add([modes.NORMAL], ["j", "<Down>", "<C-e>", "<scroll-down-line>"],
"Scroll document down",
function (args) { buffer.scrollVertical("lines", Math.max(args.count, 1)); },
{ count: true });
- mappings.add([modes.COMMAND], ["k", "<Up>", "<C-y>", "<scroll-up-line>"],
+ mappings.add([modes.NORMAL], ["k", "<Up>", "<C-y>", "<scroll-up-line>"],
"Scroll document up",
function (args) { buffer.scrollVertical("lines", -Math.max(args.count, 1)); },
{ count: true });
@@ -1703,30 +1703,30 @@ var Buffer = Module("buffer", {
function (args) { buffer.scrollHorizontal("columns", -Math.max(args.count, 1)); },
{ count: true });
- mappings.add([modes.COMMAND], dactyl.has("mail") ? ["l", "<scroll-right-column>"] : ["l", "<Right>", "<scroll-right-column>"],
+ mappings.add([modes.NORMAL], 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([modes.COMMAND], ["0", "^", "<scroll-begin>"],
+ mappings.add([modes.NORMAL], ["0", "^", "<scroll-begin>"],
"Scroll to the absolute left of the document",
function () { buffer.scrollToPercent(0, null); });
- mappings.add([modes.COMMAND], ["$", "<scroll-end>"],
+ mappings.add([modes.NORMAL], ["$", "<scroll-end>"],
"Scroll to the absolute right of the document",
function () { buffer.scrollToPercent(100, null); });
- mappings.add([modes.COMMAND], ["gg", "<Home>", "<scroll-top>"],
+ mappings.add([modes.NORMAL], ["gg", "<Home>", "<scroll-top>"],
"Go to the top of the document",
function (args) { buffer.scrollToPercent(null, args.count != null ? args.count : 0); },
{ count: true });
- mappings.add([modes.COMMAND], ["G", "<End>", "<scroll-bottom>"],
+ mappings.add([modes.NORMAL], ["G", "<End>", "<scroll-bottom>"],
"Go to the end of the document",
function (args) { buffer.scrollToPercent(null, args.count != null ? args.count : 100); },
{ count: true });
- mappings.add([modes.COMMAND], ["%", "<scroll-percent>"],
+ mappings.add([modes.NORMAL], ["%", "<scroll-percent>"],
"Scroll to {count} percent of the document",
function (args) {
dactyl.assert(args.count > 0 && args.count <= 100);
@@ -1734,22 +1734,22 @@ var Buffer = Module("buffer", {
},
{ count: true });
- mappings.add([modes.COMMAND], ["<C-d>", "<scroll-down>"],
+ mappings.add([modes.NORMAL], ["<C-d>", "<scroll-down>"],
"Scroll window downwards in the buffer",
function (args) { buffer._scrollByScrollSize(args.count, true); },
{ count: true });
- mappings.add([modes.COMMAND], ["<C-u>", "<scroll-up>"],
+ mappings.add([modes.NORMAL], ["<C-u>", "<scroll-up>"],
"Scroll window upwards in the buffer",
function (args) { buffer._scrollByScrollSize(args.count, false); },
{ count: true });
- mappings.add([modes.COMMAND], ["<C-b>", "<PageUp>", "<S-Space>", "<scroll-up-page>"],
+ mappings.add([modes.NORMAL], ["<C-b>", "<PageUp>", "<S-Space>", "<scroll-up-page>"],
"Scroll up a full page",
function (args) { buffer.scrollVertical("pages", -Math.max(args.count, 1)); },
{ count: true });
- mappings.add([modes.COMMAND], ["<Space>"],
+ mappings.add([modes.NORMAL], ["<Space>"],
"Scroll down a full page",
function (args) {
if (isinstance(content.document.activeElement, [HTMLInputElement, HTMLButtonElement]))
@@ -1758,7 +1758,7 @@ var Buffer = Module("buffer", {
},
{ count: true });
- mappings.add([modes.COMMAND], ["<C-f>", "<PageDown>", "<scroll-down-page>"],
+ mappings.add([modes.NORMAL], ["<C-f>", "<PageDown>", "<scroll-down-page>"],
"Scroll down a full page",
function (args) { buffer.scrollVertical("pages", Math.max(args.count, 1)); },
{ count: true });
@@ -1969,7 +1969,7 @@ var Buffer = Module("buffer", {
try {
config.browser.docShell.QueryInterface(Ci.nsIDocCharset).charset = val;
PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, val);
- getWebNavigation().reload(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
+ window.getWebNavigation().reload(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
}
catch (e) { dactyl.reportError(e); }
return null;
diff --git a/common/content/editor.js b/common/content/editor.js
index d2fe3224..1ea8a272 100644
--- a/common/content/editor.js
+++ b/common/content/editor.js
@@ -92,68 +92,6 @@ var Editor = Module("editor", {
}
},
- // cmd = y, d, c
- // motion = b, 0, gg, G, etc.
- selectMotion: function selectMotion(cmd, motion, count) {
- // XXX: better as a precondition
- if (count == null)
- count = 1;
-
- if (cmd == motion) {
- motion = "j";
- count--;
- }
-
- if (modes.main != modes.VISUAL)
- modes.push(modes.VISUAL);
-
- switch (motion) {
- case "j":
- this.executeCommand("cmd_beginLine", 1);
- this.executeCommand("cmd_selectLineNext", count + 1);
- break;
- case "k":
- this.executeCommand("cmd_beginLine", 1);
- this.executeCommand("cmd_lineNext", 1);
- this.executeCommand("cmd_selectLinePrevious", count + 1);
- break;
- case "h":
- this.executeCommand("cmd_selectCharPrevious", count);
- break;
- case "l":
- this.executeCommand("cmd_selectCharNext", count);
- break;
- case "e":
- case "w":
- this.executeCommand("cmd_selectWordNext", count);
- break;
- case "b":
- this.executeCommand("cmd_selectWordPrevious", count);
- break;
- case "0":
- case "^":
- this.executeCommand("cmd_selectBeginLine", 1);
- break;
- case "$":
- this.executeCommand("cmd_selectEndLine", 1);
- break;
- case "gg":
- this.executeCommand("cmd_endLine", 1);
- this.executeCommand("cmd_selectTop", 1);
- this.executeCommand("cmd_selectBeginLine", 1);
- break;
- case "G":
- this.executeCommand("cmd_beginLine", 1);
- this.executeCommand("cmd_selectBottom", 1);
- this.executeCommand("cmd_selectEndLine", 1);
- break;
-
- default:
- dactyl.beep();
- return;
- }
- },
-
// This function will move/select up to given "pos"
// Simple setSelectionRange() would be better, but we want to maintain the correct
// order of selectionStart/End (a Gecko bug always makes selectionStart <= selectionEnd)
@@ -427,11 +365,27 @@ var Editor = Module("editor", {
}, {
mappings: function () {
+ Map.types["editor"] = {
+ preExecute: function preExecute(args) {
+ Editor.getEditor(null).beginTransaction();
+ },
+ postExecute: function preExecute(args) {
+ Editor.getEditor(null).endTransaction();
+ },
+ };
+ Map.types["operator"] = {
+ postExecute: function preExecute(args) {
+ if (modes.main == modes.OPERATOR)
+ modes.pop();
+ },
+ };
+
// add mappings for commands like h,j,k,l,etc. in CARET, VISUAL and TEXT_EDIT mode
function addMovementMap(keys, description, hasCount, caretModeMethod, caretModeArg, textEditCommand, visualTextEditCommand) {
- let extraInfo = {};
- if (hasCount)
- extraInfo.count = true;
+ let extraInfo = {
+ count: !!hasCount,
+ type: "operator"
+ };
function caretExecute(arg, again) {
function fixSelection() {
@@ -486,7 +440,7 @@ var Editor = Module("editor", {
},
extraInfo);
- mappings.add([modes.TEXT_EDIT], keys, description,
+ mappings.add([modes.OPERATOR], keys, description,
function ({ count }) {
if (!count)
count = 1;
@@ -503,7 +457,8 @@ var Editor = Module("editor", {
commands.forEach(function (cmd)
editor.executeCommand(cmd, 1));
modes.push(modes.INSERT);
- });
+ },
+ { type: "editor" });
}
function selectPreviousLine() {
@@ -582,77 +537,89 @@ var Editor = Module("editor", {
addBeginInsertModeMap(["S"], ["cmd_deleteToEndOfLine", "cmd_deleteToBeginningOfLine"], "Delete the current line and start insert");
addBeginInsertModeMap(["C"], ["cmd_deleteToEndOfLine"], "Delete from the cursor to the end of the line and start insert");
- function addMotionMap(key, desc, cmd, mode) {
- mappings.add([modes.TEXT_EDIT], [key],
+ function addMotionMap(key, desc, select, cmd, mode) {
+ mappings.add([modes.OPERATOR], [key],
desc,
- function ({ count, motion }) {
- editor.selectMotion(key, motion, Math.max(count, 1));
- if (callable(cmd))
- cmd.call(events, Editor.getEditor(null));
- else {
- editor.executeCommand(cmd, 1);
- modes.pop(modes.TEXT_EDIT);
- }
- if (mode)
- modes.push(mode);
+ function ({ count, motion, command }) {
+ modes.push(modes.OPERATOR, null, {
+ leave: function leave(stack) {
+ if (stack.push)
+ return;
+
+ try {
+ editor.beginTransaction();
+
+ let range = RangeFind.union(start, sel.getRangeAt(0));
+ sel.removeAllRanges();
+ sel.addRange(select ? range : start);
+ cmd(editor, range);
+ }
+ finally {
+ editor.endTransaction();
+ }
+
+ modes.delay(function () {
+ if (mode)
+ modes.push(mode);
+ });
+ }
+ });
+
+ let editor = Editor.getEditor(null);
+ let sel = editor.selection;
+ let start = sel.getRangeAt(0).cloneRange();
},
- { count: true, motion: true });
+ { count: true, type: "motion" });
}
- addMotionMap("d", "Delete motion", "cmd_delete");
- addMotionMap("c", "Change motion", "cmd_delete", modes.INSERT);
- addMotionMap("y", "Yank motion", "cmd_copy");
+ addMotionMap("d", "Delete motion", true, function (editor) { editor.cut(); });
+ addMotionMap("c", "Change motion", true, function (editor) { editor.cut(); }, modes.INSERT);
+ addMotionMap("y", "Yank motion", false, function (editor, range) { dactyl.clipboardWrite(util.domToString(range)) });
- mappings.add([modes.INPUT],
- ["<C-w>"], "Delete previous word",
- function () { editor.executeCommand("cmd_deleteWordBackward", 1); });
+ let bind = function bind(names, description, action, params)
+ mappings.add([modes.INPUT], names, description,
+ action, update({ type: "editor" }, params));
- mappings.add([modes.INPUT],
- ["<C-u>"], "Delete until beginning of current line",
- function () {
- // Deletes the whole line. What the hell.
- // editor.executeCommand("cmd_deleteToBeginningOfLine", 1);
+ bind(["<C-w>"], "Delete previous word",
+ function () { editor.executeCommand("cmd_deleteWordBackward", 1); });
- editor.executeCommand("cmd_selectBeginLine", 1);
- if (Editor.getController().isCommandEnabled("cmd_delete"))
- editor.executeCommand("cmd_delete", 1);
- });
+ bind(["<C-u>"], "Delete until beginning of current line",
+ function () {
+ // Deletes the whole line. What the hell.
+ // editor.executeCommand("cmd_deleteToBeginningOfLine", 1);
- mappings.add([modes.INPUT],
- ["<C-k>"], "Delete until end of current line",
- function () { editor.executeCommand("cmd_deleteToEndOfLine", 1); });
+ editor.executeCommand("cmd_selectBeginLine", 1);
+ if (Editor.getController().isCommandEnabled("cmd_delete"))
+ editor.executeCommand("cmd_delete", 1);
+ });
- mappings.add([modes.INPUT],
- ["<C-a>"], "Move cursor to beginning of current line",
- function () { editor.executeCommand("cmd_beginLine", 1); });
+ bind(["<C-k>"], "Delete until end of current line",
+ function () { editor.executeCommand("cmd_deleteToEndOfLine", 1); });
- mappings.add([modes.INPUT],
- ["<C-e>"], "Move cursor to end of current line",
- function () { editor.executeCommand("cmd_endLine", 1); });
+ bind(["<C-a>"], "Move cursor to beginning of current line",
+ function () { editor.executeCommand("cmd_beginLine", 1); });
- mappings.add([modes.INPUT],
- ["<C-h>"], "Delete character to the left",
- function () { events.feedkeys("<BS>", true); });
+ bind(["<C-e>"], "Move cursor to end of current line",
+ function () { editor.executeCommand("cmd_endLine", 1); });
- mappings.add([modes.INPUT],
- ["<C-d>"], "Delete character to the right",
- function () { editor.executeCommand("cmd_deleteCharForward", 1); });
+ bind(["<C-h>"], "Delete character to the left",
+ function () { events.feedkeys("<BS>", true); });
- mappings.add([modes.INPUT],
- ["<S-Insert>"], "Insert clipboard/selection",
- function () { editor.pasteClipboard(); });
+ bind(["<C-d>"], "Delete character to the right",
+ function () { editor.executeCommand("cmd_deleteCharForward", 1); });
- mappings.add([modes.INPUT, modes.TEXT_EDIT],
- ["<C-i>"], "Edit text field with an external editor",
- function () { editor.editFieldExternally(); });
+ bind(["<S-Insert>"], "Insert clipboard/selection",
+ function () { editor.pasteClipboard(); });
- mappings.add([modes.INPUT],
- ["<C-t>"], "Edit text field in Vi mode",
- function () {
- dactyl.assert(dactyl.focusedElement);
- dactyl.assert(!editor.isTextEdit);
- modes.push(modes.TEXT_EDIT);
- });
+ bind(["<C-i>"], "Edit text field with an external editor",
+ function () { editor.editFieldExternally(); });
+
+ bind(["<C-t>"], "Edit text field in Vi mode",
+ function () {
+ dactyl.assert(dactyl.focusedElement);
+ dactyl.assert(!editor.isTextEdit);
+ modes.push(modes.TEXT_EDIT);
+ });
// Ugh.
mappings.add([modes.INPUT, modes.CARET],
@@ -673,6 +640,10 @@ var Editor = Module("editor", {
["<C-]>", "<C-5>"], "Expand Insert mode abbreviation",
function () { editor.expandAbbreviation(modes.INSERT); });
+ let bind = function bind(names, description, action, params)
+ mappings.add([modes.TEXT_EDIT], names, description,
+ action, update({ type: "editor" }, params));
+
// text edit mode
mappings.add([modes.TEXT_EDIT],
["u"], "Undo changes",
@@ -690,9 +661,8 @@ var Editor = Module("editor", {
},
{ count: true });
- mappings.add([modes.TEXT_EDIT],
- ["D"], "Delete the characters under the cursor until the end of the line",
- function () { editor.executeCommand("cmd_deleteToEndOfLine"); });
+ bind(["D"], "Delete the characters under the cursor until the end of the line",
+ function () { editor.executeCommand("cmd_deleteToEndOfLine"); });
mappings.add([modes.TEXT_EDIT],
["o"], "Open line below current",
@@ -711,14 +681,12 @@ var Editor = Module("editor", {
editor.executeCommand("cmd_linePrevious", 1);
});
- mappings.add([modes.TEXT_EDIT],
- ["X"], "Delete character to the left",
- function (args) { editor.executeCommand("cmd_deleteCharBackward", Math.max(args.count, 1)); },
+ bind(["X"], "Delete character to the left",
+ function (args) { editor.executeCommand("cmd_deleteCharBackward", Math.max(args.count, 1)); },
{ count: true });
- mappings.add([modes.TEXT_EDIT],
- ["x"], "Delete character to the right",
- function (args) { editor.executeCommand("cmd_deleteCharForward", Math.max(args.count, 1)); },
+ bind(["x"], "Delete character to the right",
+ function (args) { editor.executeCommand("cmd_deleteCharForward", Math.max(args.count, 1)); },
{ count: true });
// visual mode
@@ -764,51 +732,58 @@ var Editor = Module("editor", {
dactyl.clipboardWrite(buffer.currentWord, true);
});
- mappings.add([modes.VISUAL, modes.TEXT_EDIT],
- ["p"], "Paste clipboard contents",
- function ({ count }) {
+ bind(["p"], "Paste clipboard contents",
+ function ({ count }) {
dactyl.assert(!editor.isCaret);
editor.executeCommand("cmd_paste", count || 1);
modes.pop(modes.TEXT_EDIT);
},
{ count: true });
- // finding characters
- mappings.add([modes.TEXT_EDIT, modes.VISUAL],
- ["f"], "Move to a character on the current line after the cursor",
- function ({ arg, count }) {
- let pos = editor.findChar(arg, Math.max(count, 1));
- if (pos >= 0)
- editor.moveToPosition(pos, true, modes.main == modes.VISUAL);
- },
- { arg: true, count: true });
+ let bind = function bind(names, description, action, params)
+ mappings.add([modes.OPERATOR], names, description,
+ action, update({ type: "editor" }, params));
- mappings.add([modes.TEXT_EDIT, modes.VISUAL],
- ["F"], "Move to a character on the current line before the cursor",
- function ({ arg, count }) {
- let pos = editor.findChar(arg, Math.max(count, 1), true);
- if (pos >= 0)
- editor.moveToPosition(pos, false, modes.main == modes.VISUAL);
- },
- { arg: true, count: true });
-
- mappings.add([modes.TEXT_EDIT, modes.VISUAL],
- ["t"], "Move before a character on the current line",
- function ({ arg, count }) {
- let pos = editor.findChar(arg, Math.max(count, 1));
- if (pos >= 0)
- editor.moveToPosition(pos - 1, true, modes.main == modes.VISUAL);
- },
- { arg: true, count: true });
+ // finding characters
+ function offset(backward, before, pos) {
+ if (!backward && modes.main != modes.TEXT_EDIT)
+ pos += 1;
+ if (before)
+ pos += backward ? +1 : -1;
+ return pos;
+ }
- mappings.add([modes.TEXT_EDIT, modes.VISUAL],
- ["T"], "Move before a character on the current line, backwards",
- function ({ arg, count }) {
- let pos = editor.findChar(arg, Math.max(count, 1), true);
- if (pos >= 0)
- editor.moveToPosition(pos + 1, false, modes.main == modes.VISUAL);
- },
- { arg: true, count: true });
+ bind(["f"], "Move to a character on the current line after the cursor",
+ function ({ arg, count }) {
+ let pos = editor.findChar(arg, Math.max(count, 1));
+ if (pos >= 0)
+ editor.moveToPosition(offset(false, false, pos), true, modes.main == modes.VISUAL);
+ },
+ { arg: true, count: true, type: "operator" });
+
+ bind(["F"], "Move to a character on the current line before the cursor",
+ function ({ arg, count }) {
+ let pos = editor.findChar(arg, Math.max(count, 1), true);
+ if (pos >= 0)
+ editor.moveToPosition(offset(true, false, pos), false, modes.main == modes.VISUAL);
+ },
+ { arg: true, count: true, type: "operator" });
+
+ bind(["t"], "Move before a character on the current line",
+ function ({ arg, count }) {
+ let pos = editor.findChar(arg, Math.max(count, 1));
+ if (pos >= 0)
+ editor.moveToPosition(offset(false, true, pos), true, modes.main == modes.VISUAL);
+ },
+ { arg: true, count: true, type: "operator" });
+
+ bind(["T"], "Move before a character on the current line, backwards",
+ function ({ arg, count }) {
+ let pos = editor.findChar(arg, Math.max(count, 1), true);
+ if (pos >= 0)
+ editor.moveToPosition(offset(true, true, pos), false, modes.main == modes.VISUAL);
+ },
+ { arg: true, count: true, type: "operator" });
// text edit and visual mode
mappings.add([modes.TEXT_EDIT, modes.VISUAL],
@@ -834,8 +809,8 @@ var Editor = Module("editor", {
},
{ count: true });
- function bind() mappings.add.apply(mappings,
- [[modes.AUTOCOMPLETE]].concat(Array.slice(arguments)))
+ let bind = function bind() mappings.add.apply(mappings,
+ [[modes.AUTOCOMPLETE]].concat(Array.slice(arguments)))
bind(["<Esc>"], "Return to Insert mode",
function () Events.PASS_THROUGH);
diff --git a/common/content/mappings.js b/common/content/mappings.js
index 155849e4..c58ba3eb 100644
--- a/common/content/mappings.js
+++ b/common/content/mappings.js
@@ -17,7 +17,7 @@
* *action*.
* @param {string} description A short one line description of the key mapping.
* @param {function} action The action invoked by each key sequence.
- * @param {Object} extraInfo An optional extra configuration hash. The
+ * @param {Object} info An optional extra configuration hash. The
* following properties are supported.
* arg - see {@link Map#arg}
* count - see {@link Map#count}
@@ -29,7 +29,7 @@
* @private
*/
var Map = Class("Map", {
- init: function (modes, keys, description, action, extraInfo) {
+ init: function (modes, keys, description, action, info) {
this.id = ++Map.id;
this.modes = modes;
this._keys = keys;
@@ -38,8 +38,11 @@ var Map = Class("Map", {
Object.freeze(this.modes);
- if (extraInfo)
- this.update(extraInfo);
+ if (info) {
+ if (Set.has(Map.types, info.type))
+ this.update(Map.types[info.type]);
+ this.update(info);
+ }
},
name: Class.memoize(function () this.names[0]),
@@ -69,12 +72,24 @@ var Map = Class("Map", {
* as an argument.
*/
motion: false,
+
/** @property {boolean} Whether the RHS of the mapping should expand mappings recursively. */
noremap: false,
+
+ /** @property {function(object)} A function to be executed before this mapping. */
+ preExecute: function preExecute(args) {},
+ /** @property {function(object)} A function to be executed after this mapping. */
+ postExecute: function postExecute(args) {},
+
/** @property {boolean} Whether any output from the mapping should be echoed on the command line. */
silent: false,
+
/** @property {string} The literal RHS expansion of this mapping. */
rhs: null,
+
+ /** @property {string} The type of this mapping. */
+ type: "",
+
/**
* @property {boolean} Specifies whether this is a user mapping. User
* mappings may be created by plugins, or directly by users. Users and
@@ -118,6 +133,7 @@ var Map = Class("Map", {
dactyl.assert(!this.executing, _("map.recursive", args.command));
try {
+ this.preExecute(args);
this.executing = true;
var res = repeat();
}
@@ -127,12 +143,15 @@ var Map = Class("Map", {
}
finally {
this.executing = false;
+ this.postExecute(args);
}
return res;
}
}, {
- id: 0
+ id: 0,
+
+ types: {}
});
var MapHive = Class("MapHive", Contexts.Hive, {
diff --git a/common/content/modes.js b/common/content/modes.js
index c4988309..1bc25320 100644
--- a/common/content/modes.js
+++ b/common/content/modes.js
@@ -57,11 +57,16 @@ var Modes = Module("modes", {
description: "Active when nothing is focused",
bases: [this.COMMAND]
});
+ this.addMode("OPERATOR", {
+ char: "o",
+ description: "Mappings which move the cursor",
+ bases: []
+ });
this.addMode("VISUAL", {
char: "v",
description: "Active when text is selected",
display: function () "VISUAL" + (this._extended & modes.LINE ? " LINE" : ""),
- bases: [this.COMMAND],
+ bases: [this.COMMAND, this.OPERATOR],
ownsFocus: true
}, {
leave: function (stack, newMode) {
@@ -97,7 +102,7 @@ var Modes = Module("modes", {
this.addMode("TEXT_EDIT", {
char: "t",
description: "Vim-like editing of input elements",
- bases: [this.COMMAND],
+ bases: [this.OPERATOR, this.COMMAND],
ownsFocus: true
}, {
onKeyPress: function (eventList) {
@@ -489,7 +494,7 @@ var Modes = Module("modes", {
init: function init(name, options, params) {
if (options.bases)
util.assert(options.bases.every(function (m) m instanceof this, this.constructor),
- _("mode.invalidBases"), true);
+ _("mode.invalidBases"), false);
this.update({
id: 1 << Modes.Mode._id++,
@@ -647,7 +652,7 @@ var Modes = Module("modes", {
options.add(["showmode", "smd"],
"Show the current mode in the command line when it matches this expression",
- "stringlist", "caret,output_multiline,!normal,base",
+ "stringlist", "caret,output_multiline,!normal,base,operator",
opts);
},
prefs: function initPrefs() {