summaryrefslogtreecommitdiff
path: root/public/vendor/codemirror/keymap/vim.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/vendor/codemirror/keymap/vim.js')
-rwxr-xr-xpublic/vendor/codemirror/keymap/vim.js158
1 files changed, 88 insertions, 70 deletions
diff --git a/public/vendor/codemirror/keymap/vim.js b/public/vendor/codemirror/keymap/vim.js
index ef5dd8c0..d50cc4af 100755
--- a/public/vendor/codemirror/keymap/vim.js
+++ b/public/vendor/codemirror/keymap/vim.js
@@ -3,42 +3,16 @@
/**
* Supported keybindings:
+ * Too many to list. Refer to defaultKeyMap below.
*
- * Motion:
- * h, j, k, l
- * gj, gk
- * e, E, w, W, b, B, ge, gE
- * f<character>, F<character>, t<character>, T<character>
- * $, ^, 0, -, +, _
- * gg, G
- * %
- * '<character>, `<character>
- *
- * Operator:
- * d, y, c
- * dd, yy, cc
- * g~, g~g~
- * >, <, >>, <<
- *
- * Operator-Motion:
- * x, X, D, Y, C, ~
- *
- * Action:
- * a, i, s, A, I, S, o, O
- * zz, z., z<CR>, zt, zb, z-
- * J
- * u, Ctrl-r
- * m<character>
- * r<character>
- *
- * Modes:
- * ESC - leave insert mode, visual mode, and clear input state.
- * Ctrl-[, Ctrl-c - same as ESC.
+ * Supported Ex commands:
+ * Refer to defaultExCommandMap below.
*
* Registers: unnamed, -, a-z, A-Z, 0-9
* (Does not respect the special case for number registers when delete
* operator is made with these commands: %, (, ), , /, ?, n, N, {, } )
* TODO: Implement the remaining registers.
+ *
* Marks: a-z, A-Z, and 0-9
* TODO: Implement the remaining special marks. They have more complex
* behavior.
@@ -57,6 +31,7 @@
* 6. Motion, operator, and action implementations
* 7. Helper functions for the key handler, motions, operators, and actions
* 8. Set up Vim to work as a keymap for CodeMirror.
+ * 9. Ex command implementations.
*/
(function(mod) {
@@ -227,6 +202,34 @@
{ keys: ':', type: 'ex' }
];
+ /**
+ * Ex commands
+ * Care must be taken when adding to the default Ex command map. For any
+ * pair of commands that have a shared prefix, at least one of their
+ * shortNames must not match the prefix of the other command.
+ */
+ var defaultExCommandMap = [
+ { name: 'colorscheme', shortName: 'colo' },
+ { name: 'map' },
+ { name: 'imap', shortName: 'im' },
+ { name: 'nmap', shortName: 'nm' },
+ { name: 'vmap', shortName: 'vm' },
+ { name: 'unmap' },
+ { name: 'write', shortName: 'w' },
+ { name: 'undo', shortName: 'u' },
+ { name: 'redo', shortName: 'red' },
+ { name: 'set', shortName: 'se' },
+ { name: 'set', shortName: 'se' },
+ { name: 'setlocal', shortName: 'setl' },
+ { name: 'setglobal', shortName: 'setg' },
+ { name: 'sort', shortName: 'sor' },
+ { name: 'substitute', shortName: 's', possiblyAsync: true },
+ { name: 'nohlsearch', shortName: 'noh' },
+ { name: 'delmarks', shortName: 'delm' },
+ { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },
+ { name: 'global', shortName: 'g' }
+ ];
+
var Pos = CodeMirror.Pos;
var Vim = function() {
@@ -463,7 +466,7 @@
}
// The 'filetype' option proxies to the CodeMirror 'mode' option.
if (name === undefined) {
- var mode = cm.getMode().name;
+ var mode = cm.getOption('mode');
return mode == 'null' ? '' : mode;
} else {
var mode = name == '' ? 'null' : name;
@@ -689,7 +692,9 @@
getOption: getOption,
defineOption: defineOption,
defineEx: function(name, prefix, func){
- if (name.indexOf(prefix) !== 0) {
+ if (!prefix) {
+ prefix = name;
+ } else if (name.indexOf(prefix) !== 0) {
throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered');
}
exCommands[name]=func;
@@ -846,6 +851,8 @@
mapCommand: mapCommand,
_mapCommand: _mapCommand,
+ defineRegister: defineRegister,
+
exitVisualMode: exitVisualMode,
exitInsertMode: exitInsertMode
};
@@ -935,6 +942,25 @@
}
};
+ /**
+ * Defines an external register.
+ *
+ * The name should be a single character that will be used to reference the register.
+ * The register should support setText, pushText, clear, and toString(). See Register
+ * for a reference implementation.
+ */
+ function defineRegister(name, register) {
+ var registers = vimGlobalState.registerController.registers[name];
+ if (!name || name.length != 1) {
+ throw Error('Register name must be 1 character');
+ }
+ if (registers[name]) {
+ throw Error('Register already defined ' + name);
+ }
+ registers[name] = register;
+ validRegisters.push(name);
+ }
+
/*
* vim registers allow you to keep many independent copy and paste buffers.
* See http://usevim.com/2012/04/13/registers/ for an introduction.
@@ -3635,13 +3661,17 @@
// Translates the replace part of a search and replace from ex (vim) syntax into
// javascript form. Similar to translateRegex, but additionally fixes back references
// (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'.
+ var charUnescapes = {'\\n': '\n', '\\r': '\r', '\\t': '\t'};
function translateRegexReplace(str) {
var escapeNextChar = false;
var out = [];
for (var i = -1; i < str.length; i++) {
var c = str.charAt(i) || '';
var n = str.charAt(i+1) || '';
- if (escapeNextChar) {
+ if (charUnescapes[c + n]) {
+ out.push(charUnescapes[c+n]);
+ i++;
+ } else if (escapeNextChar) {
// At any point in the loop, escapeNextChar is true if the previous
// character was a '\' and was not escaped.
out.push(c);
@@ -3669,6 +3699,7 @@
}
// Unescape \ and / in the replace part, for PCRE mode.
+ var unescapes = {'\\/': '/', '\\\\': '\\', '\\n': '\n', '\\r': '\r', '\\t': '\t'};
function unescapeRegexReplace(str) {
var stream = new CodeMirror.StringStream(str);
var output = [];
@@ -3677,13 +3708,15 @@
while (stream.peek() && stream.peek() != '\\') {
output.push(stream.next());
}
- if (stream.match('\\/', true)) {
- // \/ => /
- output.push('/');
- } else if (stream.match('\\\\', true)) {
- // \\ => \
- output.push('\\');
- } else {
+ var matched = false;
+ for (var matcher in unescapes) {
+ if (stream.match(matcher, true)) {
+ matched = true;
+ output.push(unescapes[matcher]);
+ break;
+ }
+ }
+ if (!matched) {
// Don't change anything
output.push(stream.next());
}
@@ -3913,31 +3946,6 @@
return {top: from.line, bottom: to.line};
}
- // Ex command handling
- // Care must be taken when adding to the default Ex command map. For any
- // pair of commands that have a shared prefix, at least one of their
- // shortNames must not match the prefix of the other command.
- var defaultExCommandMap = [
- { name: 'colorscheme', shortName: 'colo' },
- { name: 'map' },
- { name: 'imap', shortName: 'im' },
- { name: 'nmap', shortName: 'nm' },
- { name: 'vmap', shortName: 'vm' },
- { name: 'unmap' },
- { name: 'write', shortName: 'w' },
- { name: 'undo', shortName: 'u' },
- { name: 'redo', shortName: 'red' },
- { name: 'set', shortName: 'se' },
- { name: 'set', shortName: 'se' },
- { name: 'setlocal', shortName: 'setl' },
- { name: 'setglobal', shortName: 'setg' },
- { name: 'sort', shortName: 'sor' },
- { name: 'substitute', shortName: 's', possiblyAsync: true },
- { name: 'nohlsearch', shortName: 'noh' },
- { name: 'delmarks', shortName: 'delm' },
- { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },
- { name: 'global', shortName: 'g' }
- ];
var ExCommandDispatcher = function() {
this.buildCommandMap_();
};
@@ -4483,6 +4491,9 @@
var query = state.getQuery();
var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line;
var lineEnd = params.lineEnd || lineStart;
+ if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) {
+ lineEnd = Infinity;
+ }
if (count) {
lineStart = lineEnd;
lineEnd = lineStart + count - 1;
@@ -4601,10 +4612,9 @@
searchCursor.replace(newText);
}
function next() {
- var found;
// The below only loops to skip over multiple occurrences on the same
// line when 'global' is not true.
- while(found = searchCursor.findNext() &&
+ while(searchCursor.findNext() &&
isInRange(searchCursor.from(), lineStart, lineEnd)) {
if (!global && lastPos && searchCursor.from().line == lastPos.line) {
continue;
@@ -4737,7 +4747,7 @@
}
function _mapCommand(command) {
- defaultKeymap.push(command);
+ defaultKeymap.unshift(command);
}
function mapCommand(keys, type, name, args, extra) {
@@ -4779,6 +4789,14 @@
function executeMacroRegister(cm, vim, macroModeState, registerName) {
var register = vimGlobalState.registerController.getRegister(registerName);
+ if (registerName == ':') {
+ // Read-only register containing last Ex command.
+ if (register.keyBuffer[0]) {
+ exCommandDispatcher.processCommand(cm, register.keyBuffer[0]);
+ }
+ macroModeState.isPlaying = false;
+ return;
+ }
var keyBuffer = register.keyBuffer;
var imc = 0;
macroModeState.isPlaying = true;
@@ -4818,7 +4836,7 @@
if (macroModeState.isPlaying) { return; }
var registerName = macroModeState.latestRegister;
var register = vimGlobalState.registerController.getRegister(registerName);
- if (register) {
+ if (register && register.pushInsertModeChanges) {
register.pushInsertModeChanges(macroModeState.lastInsertModeChanges);
}
}
@@ -4827,7 +4845,7 @@
if (macroModeState.isPlaying) { return; }
var registerName = macroModeState.latestRegister;
var register = vimGlobalState.registerController.getRegister(registerName);
- if (register) {
+ if (register && register.pushSearchQuery) {
register.pushSearchQuery(query);
}
}