update vim mode
This commit is contained in:
parent
f0d01b93d4
commit
094b8a147a
4 changed files with 289 additions and 33 deletions
|
|
@ -2684,6 +2684,7 @@ config.defineOptions(Editor.prototype, "editor", {
|
||||||
useSoftTabs: "session",
|
useSoftTabs: "session",
|
||||||
tabSize: "session",
|
tabSize: "session",
|
||||||
wrap: "session",
|
wrap: "session",
|
||||||
|
indentedSoftWrap: "session",
|
||||||
foldStyle: "session",
|
foldStyle: "session",
|
||||||
mode: "session"
|
mode: "session"
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ var themeData = [
|
||||||
["Dreamweaver" ],
|
["Dreamweaver" ],
|
||||||
["Eclipse" ],
|
["Eclipse" ],
|
||||||
["GitHub" ],
|
["GitHub" ],
|
||||||
|
["IPlastic" ],
|
||||||
["Solarized Light"],
|
["Solarized Light"],
|
||||||
["TextMate" ],
|
["TextMate" ],
|
||||||
["Tomorrow" ],
|
["Tomorrow" ],
|
||||||
|
|
|
||||||
|
|
@ -654,6 +654,9 @@ define(function(require, exports, module) {
|
||||||
this.refresh = function() {
|
this.refresh = function() {
|
||||||
return this.ace.resize(true);
|
return this.ace.resize(true);
|
||||||
};
|
};
|
||||||
|
this.getMode = function() {
|
||||||
|
return { name : this.getOption("mode") };
|
||||||
|
}
|
||||||
}).call(CodeMirror.prototype);
|
}).call(CodeMirror.prototype);
|
||||||
function toAcePos(cmPos) {
|
function toAcePos(cmPos) {
|
||||||
return {row: cmPos.line, column: cmPos.ch};
|
return {row: cmPos.line, column: cmPos.ch};
|
||||||
|
|
@ -1185,18 +1188,30 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = {};
|
var options = {};
|
||||||
function defineOption(name, defaultValue, type) {
|
function defineOption(name, defaultValue, type, aliases, callback) {
|
||||||
if (defaultValue === undefined) { throw Error('defaultValue is required'); }
|
if (defaultValue === undefined && !callback) {
|
||||||
|
throw Error('defaultValue is required unless callback is provided');
|
||||||
|
}
|
||||||
if (!type) { type = 'string'; }
|
if (!type) { type = 'string'; }
|
||||||
options[name] = {
|
options[name] = {
|
||||||
type: type,
|
type: type,
|
||||||
defaultValue: defaultValue
|
defaultValue: defaultValue,
|
||||||
|
callback: callback
|
||||||
};
|
};
|
||||||
|
if (aliases) {
|
||||||
|
for (var i = 0; i < aliases.length; i++) {
|
||||||
|
options[aliases[i]] = options[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (defaultValue) {
|
||||||
setOption(name, defaultValue);
|
setOption(name, defaultValue);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setOption(name, value, cm) {
|
function setOption(name, value, cm, cfg) {
|
||||||
var option = options[name];
|
var option = options[name];
|
||||||
|
cfg = cfg || {};
|
||||||
|
var scope = cfg.scope;
|
||||||
if (!option) {
|
if (!option) {
|
||||||
throw Error('Unknown option: ' + name);
|
throw Error('Unknown option: ' + name);
|
||||||
}
|
}
|
||||||
|
|
@ -1208,16 +1223,59 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
value = true;
|
value = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (option.callback) {
|
||||||
|
if (scope !== 'local') {
|
||||||
|
option.callback(value, undefined);
|
||||||
|
}
|
||||||
|
if (scope !== 'global' && cm) {
|
||||||
|
option.callback(value, cm);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (scope !== 'local') {
|
||||||
option.value = option.type == 'boolean' ? !!value : value;
|
option.value = option.type == 'boolean' ? !!value : value;
|
||||||
}
|
}
|
||||||
|
if (scope !== 'global' && cm) {
|
||||||
|
cm.state.vim.options[name] = {value: value};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getOption(name) {
|
function getOption(name, cm, cfg) {
|
||||||
var option = options[name];
|
var option = options[name];
|
||||||
|
cfg = cfg || {};
|
||||||
|
var scope = cfg.scope;
|
||||||
if (!option) {
|
if (!option) {
|
||||||
throw Error('Unknown option: ' + name);
|
throw Error('Unknown option: ' + name);
|
||||||
}
|
}
|
||||||
return option.value;
|
if (option.callback) {
|
||||||
|
var local = cm && option.callback(undefined, cm);
|
||||||
|
if (scope !== 'global' && local !== undefined) {
|
||||||
|
return local;
|
||||||
}
|
}
|
||||||
|
if (scope !== 'local') {
|
||||||
|
return option.callback();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
var local = (scope !== 'global') && (cm && cm.state.vim.options[name]);
|
||||||
|
return (local || (scope !== 'local') && option || {}).value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineOption('filetype', undefined, 'string', ['ft'], function(name, cm) {
|
||||||
|
// Option is local. Do nothing for global.
|
||||||
|
if (cm === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The 'filetype' option proxies to the CodeMirror 'mode' option.
|
||||||
|
if (name === undefined) {
|
||||||
|
var mode = cm.getMode().name;
|
||||||
|
return mode == 'null' ? '' : mode;
|
||||||
|
} else {
|
||||||
|
var mode = name == '' ? 'null' : name;
|
||||||
|
cm.setOption('mode', mode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var createCircularJumpList = function() {
|
var createCircularJumpList = function() {
|
||||||
var size = 100;
|
var size = 100;
|
||||||
|
|
@ -1371,8 +1429,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
visualBlock: false,
|
visualBlock: false,
|
||||||
lastSelection: null,
|
lastSelection: null,
|
||||||
lastPastedText: null,
|
lastPastedText: null,
|
||||||
sel: {
|
sel: {},
|
||||||
}
|
// Buffer-local/window-local values of vim options.
|
||||||
|
options: {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return cm.state.vim;
|
return cm.state.vim;
|
||||||
|
|
@ -1434,6 +1493,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
// remove user defined key bindings.
|
// remove user defined key bindings.
|
||||||
exCommandDispatcher.unmap(lhs, ctx);
|
exCommandDispatcher.unmap(lhs, ctx);
|
||||||
},
|
},
|
||||||
|
// TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace
|
||||||
|
// them, or somehow make them work with the existing CodeMirror setOption/getOption API.
|
||||||
setOption: setOption,
|
setOption: setOption,
|
||||||
getOption: getOption,
|
getOption: getOption,
|
||||||
defineOption: defineOption,
|
defineOption: defineOption,
|
||||||
|
|
@ -1985,7 +2046,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
}
|
}
|
||||||
function onPromptKeyDown(e, query, close) {
|
function onPromptKeyDown(e, query, close) {
|
||||||
var keyName = CodeMirror.keyName(e);
|
var keyName = CodeMirror.keyName(e);
|
||||||
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') {
|
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
|
||||||
|
(keyName == 'Backspace' && query == '')) {
|
||||||
vimGlobalState.searchHistoryController.pushInput(query);
|
vimGlobalState.searchHistoryController.pushInput(query);
|
||||||
vimGlobalState.searchHistoryController.reset();
|
vimGlobalState.searchHistoryController.reset();
|
||||||
updateSearchQuery(cm, originalQuery);
|
updateSearchQuery(cm, originalQuery);
|
||||||
|
|
@ -1995,6 +2057,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
clearInputState(cm);
|
clearInputState(cm);
|
||||||
close();
|
close();
|
||||||
cm.focus();
|
cm.focus();
|
||||||
|
} else if (keyName == 'Ctrl-U') {
|
||||||
|
// Ctrl-U clears input.
|
||||||
|
CodeMirror.e_stop(e);
|
||||||
|
close('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (command.searchArgs.querySrc) {
|
switch (command.searchArgs.querySrc) {
|
||||||
|
|
@ -2055,7 +2121,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
}
|
}
|
||||||
function onPromptKeyDown(e, input, close) {
|
function onPromptKeyDown(e, input, close) {
|
||||||
var keyName = CodeMirror.keyName(e), up;
|
var keyName = CodeMirror.keyName(e), up;
|
||||||
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') {
|
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
|
||||||
|
(keyName == 'Backspace' && input == '')) {
|
||||||
vimGlobalState.exCommandHistoryController.pushInput(input);
|
vimGlobalState.exCommandHistoryController.pushInput(input);
|
||||||
vimGlobalState.exCommandHistoryController.reset();
|
vimGlobalState.exCommandHistoryController.reset();
|
||||||
CodeMirror.e_stop(e);
|
CodeMirror.e_stop(e);
|
||||||
|
|
@ -2067,6 +2134,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
up = keyName == 'Up' ? true : false;
|
up = keyName == 'Up' ? true : false;
|
||||||
input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || '';
|
input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || '';
|
||||||
close(input);
|
close(input);
|
||||||
|
} else if (keyName == 'Ctrl-U') {
|
||||||
|
// Ctrl-U clears input.
|
||||||
|
CodeMirror.e_stop(e);
|
||||||
|
close('');
|
||||||
} else {
|
} else {
|
||||||
if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
|
if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
|
||||||
vimGlobalState.exCommandHistoryController.reset();
|
vimGlobalState.exCommandHistoryController.reset();
|
||||||
|
|
@ -2096,8 +2167,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
var registerName = inputState.registerName;
|
var registerName = inputState.registerName;
|
||||||
var sel = vim.sel;
|
var sel = vim.sel;
|
||||||
// TODO: Make sure cm and vim selections are identical outside visual mode.
|
// TODO: Make sure cm and vim selections are identical outside visual mode.
|
||||||
var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor('head'));
|
var origHead = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.head): cm.getCursor('head'));
|
||||||
var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor('anchor'));
|
var origAnchor = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.anchor) : cm.getCursor('anchor'));
|
||||||
var oldHead = copyCursor(origHead);
|
var oldHead = copyCursor(origHead);
|
||||||
var oldAnchor = copyCursor(origAnchor);
|
var oldAnchor = copyCursor(origAnchor);
|
||||||
var newHead, newAnchor;
|
var newHead, newAnchor;
|
||||||
|
|
@ -2672,10 +2743,11 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
var anchor = ranges[0].anchor,
|
var anchor = ranges[0].anchor,
|
||||||
head = ranges[0].head;
|
head = ranges[0].head;
|
||||||
text = cm.getRange(anchor, head);
|
text = cm.getRange(anchor, head);
|
||||||
if (!isWhiteSpaceString(text)) {
|
var lastState = vim.lastEditInputState || {};
|
||||||
|
if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) {
|
||||||
// Exclude trailing whitespace if the range is not all whitespace.
|
// Exclude trailing whitespace if the range is not all whitespace.
|
||||||
var match = (/\s+$/).exec(text);
|
var match = (/\s+$/).exec(text);
|
||||||
if (match) {
|
if (match && lastState.motionArgs && lastState.motionArgs.forward) {
|
||||||
head = offsetCursor(head, 0, - match[0].length);
|
head = offsetCursor(head, 0, - match[0].length);
|
||||||
text = text.slice(0, - match[0].length);
|
text = text.slice(0, - match[0].length);
|
||||||
}
|
}
|
||||||
|
|
@ -4307,7 +4379,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
function dialog(cm, template, shortText, onClose, options) {
|
function dialog(cm, template, shortText, onClose, options) {
|
||||||
if (cm.openDialog) {
|
if (cm.openDialog) {
|
||||||
cm.openDialog(template, onClose, { bottom: true, value: options.value,
|
cm.openDialog(template, onClose, { bottom: true, value: options.value,
|
||||||
onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp, select: options.select });
|
onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp,
|
||||||
|
selectValueOnOpen: false});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
onClose(prompt(shortText, ''));
|
onClose(prompt(shortText, ''));
|
||||||
|
|
@ -4662,6 +4735,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
// pair of commands that have a shared prefix, at least one of their
|
// pair of commands that have a shared prefix, at least one of their
|
||||||
// shortNames must not match the prefix of the other command.
|
// shortNames must not match the prefix of the other command.
|
||||||
var defaultExCommandMap = [
|
var defaultExCommandMap = [
|
||||||
|
{ name: 'colorscheme', shortName: 'colo' },
|
||||||
{ name: 'map' },
|
{ name: 'map' },
|
||||||
{ name: 'imap', shortName: 'im' },
|
{ name: 'imap', shortName: 'im' },
|
||||||
{ name: 'nmap', shortName: 'nm' },
|
{ name: 'nmap', shortName: 'nm' },
|
||||||
|
|
@ -4670,7 +4744,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
{ name: 'write', shortName: 'w' },
|
{ name: 'write', shortName: 'w' },
|
||||||
{ name: 'undo', shortName: 'u' },
|
{ name: 'undo', shortName: 'u' },
|
||||||
{ name: 'redo', shortName: 'red' },
|
{ name: 'redo', shortName: 'red' },
|
||||||
{ name: 'set', shortName: 'set' },
|
{ name: 'set', shortName: 'se' },
|
||||||
|
{ name: 'set', shortName: 'se' },
|
||||||
|
{ name: 'setlocal', shortName: 'setl' },
|
||||||
|
{ name: 'setglobal', shortName: 'setg' },
|
||||||
{ name: 'sort', shortName: 'sor' },
|
{ name: 'sort', shortName: 'sor' },
|
||||||
{ name: 'substitute', shortName: 's', possiblyAsync: true },
|
{ name: 'substitute', shortName: 's', possiblyAsync: true },
|
||||||
{ name: 'nohlsearch', shortName: 'noh' },
|
{ name: 'nohlsearch', shortName: 'noh' },
|
||||||
|
|
@ -4683,6 +4760,13 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
};
|
};
|
||||||
ExCommandDispatcher.prototype = {
|
ExCommandDispatcher.prototype = {
|
||||||
processCommand: function(cm, input, opt_params) {
|
processCommand: function(cm, input, opt_params) {
|
||||||
|
var that = this;
|
||||||
|
cm.operation(function () {
|
||||||
|
cm.curOp.isVimOp = true;
|
||||||
|
that._processCommand(cm, input, opt_params);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_processCommand: function(cm, input, opt_params) {
|
||||||
var vim = cm.state.vim;
|
var vim = cm.state.vim;
|
||||||
var commandHistoryRegister = vimGlobalState.registerController.getRegister(':');
|
var commandHistoryRegister = vimGlobalState.registerController.getRegister(':');
|
||||||
var previousCommand = commandHistoryRegister.toString();
|
var previousCommand = commandHistoryRegister.toString();
|
||||||
|
|
@ -4895,6 +4979,13 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
};
|
};
|
||||||
|
|
||||||
var exCommands = {
|
var exCommands = {
|
||||||
|
colorscheme: function(cm, params) {
|
||||||
|
if (!params.args || params.args.length < 1) {
|
||||||
|
showConfirm(cm, cm.getOption('theme'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cm.setOption('theme', params.args[0]);
|
||||||
|
},
|
||||||
map: function(cm, params, ctx) {
|
map: function(cm, params, ctx) {
|
||||||
var mapArgs = params.args;
|
var mapArgs = params.args;
|
||||||
if (!mapArgs || mapArgs.length < 2) {
|
if (!mapArgs || mapArgs.length < 2) {
|
||||||
|
|
@ -4928,6 +5019,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
},
|
},
|
||||||
set: function(cm, params) {
|
set: function(cm, params) {
|
||||||
var setArgs = params.args;
|
var setArgs = params.args;
|
||||||
|
// Options passed through to the setOption/getOption calls. May be passed in by the
|
||||||
|
// local/global versions of the set command
|
||||||
|
var setCfg = params.setCfg || {};
|
||||||
if (!setArgs || setArgs.length < 1) {
|
if (!setArgs || setArgs.length < 1) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
showConfirm(cm, 'Invalid mapping: ' + params.input);
|
showConfirm(cm, 'Invalid mapping: ' + params.input);
|
||||||
|
|
@ -4951,23 +5045,34 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
optionName = optionName.substring(2);
|
optionName = optionName.substring(2);
|
||||||
value = false;
|
value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean';
|
var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean';
|
||||||
if (optionIsBoolean && value == undefined) {
|
if (optionIsBoolean && value == undefined) {
|
||||||
// Calling set with a boolean option sets it to true.
|
// Calling set with a boolean option sets it to true.
|
||||||
value = true;
|
value = true;
|
||||||
}
|
}
|
||||||
if (!optionIsBoolean && !value || forceGet) {
|
|
||||||
var oldValue = getOption(optionName);
|
|
||||||
// If no value is provided, then we assume this is a get.
|
// If no value is provided, then we assume this is a get.
|
||||||
|
if (!optionIsBoolean && value === undefined || forceGet) {
|
||||||
|
var oldValue = getOption(optionName, cm, setCfg);
|
||||||
if (oldValue === true || oldValue === false) {
|
if (oldValue === true || oldValue === false) {
|
||||||
showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName);
|
showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName);
|
||||||
} else {
|
} else {
|
||||||
showConfirm(cm, ' ' + optionName + '=' + oldValue);
|
showConfirm(cm, ' ' + optionName + '=' + oldValue);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setOption(optionName, value, cm);
|
setOption(optionName, value, cm, setCfg);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setlocal: function (cm, params) {
|
||||||
|
// setCfg is passed through to setOption
|
||||||
|
params.setCfg = {scope: 'local'};
|
||||||
|
this.set(cm, params);
|
||||||
|
},
|
||||||
|
setglobal: function (cm, params) {
|
||||||
|
// setCfg is passed through to setOption
|
||||||
|
params.setCfg = {scope: 'global'};
|
||||||
|
this.set(cm, params);
|
||||||
|
},
|
||||||
registers: function(cm, params) {
|
registers: function(cm, params) {
|
||||||
var regArgs = params.args;
|
var regArgs = params.args;
|
||||||
var registers = vimGlobalState.registerController.registers;
|
var registers = vimGlobalState.registerController.registers;
|
||||||
|
|
@ -5590,7 +5695,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
}
|
}
|
||||||
function updateFakeCursor(cm) {
|
function updateFakeCursor(cm) {
|
||||||
var vim = cm.state.vim;
|
var vim = cm.state.vim;
|
||||||
var from = copyCursor(vim.sel.head);
|
var from = clipCursorToContent(cm, copyCursor(vim.sel.head));
|
||||||
var to = offsetCursor(from, 0, 1);
|
var to = offsetCursor(from, 0, 1);
|
||||||
if (vim.fakeCursor) {
|
if (vim.fakeCursor) {
|
||||||
vim.fakeCursor.clear();
|
vim.fakeCursor.clear();
|
||||||
|
|
@ -5601,7 +5706,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
||||||
var anchor = cm.getCursor('anchor');
|
var anchor = cm.getCursor('anchor');
|
||||||
var head = cm.getCursor('head');
|
var head = cm.getCursor('head');
|
||||||
// Enter or exit visual mode to match mouse selection.
|
// Enter or exit visual mode to match mouse selection.
|
||||||
if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) {
|
if (vim.visualMode && !cm.somethingSelected()) {
|
||||||
exitVisualMode(cm, false);
|
exitVisualMode(cm, false);
|
||||||
} else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) {
|
} else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) {
|
||||||
vim.visualMode = true;
|
vim.visualMode = true;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ editor.session.setMode(new JavaScriptMode());
|
||||||
function CodeMirror(place, opts) {
|
function CodeMirror(place, opts) {
|
||||||
if (opts.value != null)
|
if (opts.value != null)
|
||||||
editor.session.setValue(opts.value);
|
editor.session.setValue(opts.value);
|
||||||
|
editor.setOption("indentedSoftWrap", false);
|
||||||
editor.setOption("wrap", opts.lineWrapping);
|
editor.setOption("wrap", opts.lineWrapping);
|
||||||
editor.setOption("useSoftTabs", !opts.indentWithTabs);
|
editor.setOption("useSoftTabs", !opts.indentWithTabs);
|
||||||
editor.setKeyboardHandler(null);
|
editor.setKeyboardHandler(null);
|
||||||
|
|
@ -58,6 +59,7 @@ function CodeMirror(place, opts) {
|
||||||
cm.setSize(500, 300);
|
cm.setSize(500, 300);
|
||||||
return cm;
|
return cm;
|
||||||
}
|
}
|
||||||
|
CodeMirror.defineMode = function() {}
|
||||||
for (var key in vim.CodeMirror)
|
for (var key in vim.CodeMirror)
|
||||||
CodeMirror[key] = vim.CodeMirror[key];
|
CodeMirror[key] = vim.CodeMirror[key];
|
||||||
var editor;
|
var editor;
|
||||||
|
|
@ -595,7 +597,7 @@ testVim('{', function(cm, vim, helpers) {
|
||||||
helpers.doKeys('6', '{');
|
helpers.doKeys('6', '{');
|
||||||
helpers.assertCursorAt(0, 0);
|
helpers.assertCursorAt(0, 0);
|
||||||
}, { value: 'a\n\nb\nc\n\nd' });
|
}, { value: 'a\n\nb\nc\n\nd' });
|
||||||
testVim('paragraph motions', function(cm, vim, helpers) {
|
testVim('paragraph_motions', function(cm, vim, helpers) {
|
||||||
cm.setCursor(10, 0);
|
cm.setCursor(10, 0);
|
||||||
helpers.doKeys('{');
|
helpers.doKeys('{');
|
||||||
helpers.assertCursorAt(4, 0);
|
helpers.assertCursorAt(4, 0);
|
||||||
|
|
@ -1075,6 +1077,17 @@ testVim('cc_multiply_repeat', function(cm, vim, helpers) {
|
||||||
is(register.linewise);
|
is(register.linewise);
|
||||||
eq('vim-insert', cm.getOption('keyMap'));
|
eq('vim-insert', cm.getOption('keyMap'));
|
||||||
});
|
});
|
||||||
|
testVim('ct', function(cm, vim, helpers) {
|
||||||
|
cm.setCursor(0, 9);
|
||||||
|
helpers.doKeys('c', 't', 'w');
|
||||||
|
eq(' word1 word3', cm.getValue());
|
||||||
|
helpers.doKeys('<Esc>', 'c', '|');
|
||||||
|
eq(' word3', cm.getValue());
|
||||||
|
helpers.assertCursorAt(0, 0);
|
||||||
|
helpers.doKeys('<Esc>', '2', 'u', 'w', 'h');
|
||||||
|
helpers.doKeys('c', '2', 'g', 'e');
|
||||||
|
eq(' wordword3', cm.getValue());
|
||||||
|
}, { value: ' word1 word2 word3'});
|
||||||
testVim('cc_should_not_append_to_document', function(cm, vim, helpers) {
|
testVim('cc_should_not_append_to_document', function(cm, vim, helpers) {
|
||||||
var expectedLineCount = cm.lineCount();
|
var expectedLineCount = cm.lineCount();
|
||||||
cm.setCursor(cm.lastLine(), 0);
|
cm.setCursor(cm.lastLine(), 0);
|
||||||
|
|
@ -1975,7 +1988,11 @@ testVim('visual_block_move_to_eol', function(cm, vim, helpers) {
|
||||||
cm.setCursor(0, 0);
|
cm.setCursor(0, 0);
|
||||||
helpers.doKeys('<C-v>', 'G', '$');
|
helpers.doKeys('<C-v>', 'G', '$');
|
||||||
var selections = cm.getSelections().join();
|
var selections = cm.getSelections().join();
|
||||||
eq("123,45,6", selections);
|
eq('123,45,6', selections);
|
||||||
|
// Checks that with cursor at Infinity, finding words backwards still works.
|
||||||
|
helpers.doKeys('2', 'k', 'b');
|
||||||
|
selections = cm.getSelections().join();
|
||||||
|
eq('1', selections);
|
||||||
}, {value: '123\n45\n6'});
|
}, {value: '123\n45\n6'});
|
||||||
testVim('visual_block_different_line_lengths', function(cm, vim, helpers) {
|
testVim('visual_block_different_line_lengths', function(cm, vim, helpers) {
|
||||||
// test the block selection with lines of different length
|
// test the block selection with lines of different length
|
||||||
|
|
@ -2803,6 +2820,44 @@ testVim('exCommand_history', function(cm, vim, helpers) {
|
||||||
onKeyDown({keyCode: keyCodes.Up}, input, close);
|
onKeyDown({keyCode: keyCodes.Up}, input, close);
|
||||||
eq(input, 'sort');
|
eq(input, 'sort');
|
||||||
}, {value: ''});
|
}, {value: ''});
|
||||||
|
testVim('search_clear', function(cm, vim, helpers) {
|
||||||
|
var onKeyDown;
|
||||||
|
var input = '';
|
||||||
|
var keyCodes = {
|
||||||
|
Ctrl: 17,
|
||||||
|
u: 85
|
||||||
|
};
|
||||||
|
cm.openDialog = function(template, callback, options) {
|
||||||
|
onKeyDown = options.onKeyDown;
|
||||||
|
};
|
||||||
|
var close = function(newVal) {
|
||||||
|
if (typeof newVal == 'string') input = newVal;
|
||||||
|
}
|
||||||
|
helpers.doKeys('/');
|
||||||
|
input = 'foo';
|
||||||
|
onKeyDown({keyCode: keyCodes.Ctrl}, input, close);
|
||||||
|
onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close);
|
||||||
|
eq(input, '');
|
||||||
|
});
|
||||||
|
testVim('exCommand_clear', function(cm, vim, helpers) {
|
||||||
|
var onKeyDown;
|
||||||
|
var input = '';
|
||||||
|
var keyCodes = {
|
||||||
|
Ctrl: 17,
|
||||||
|
u: 85
|
||||||
|
};
|
||||||
|
cm.openDialog = function(template, callback, options) {
|
||||||
|
onKeyDown = options.onKeyDown;
|
||||||
|
};
|
||||||
|
var close = function(newVal) {
|
||||||
|
if (typeof newVal == 'string') input = newVal;
|
||||||
|
}
|
||||||
|
helpers.doKeys(':');
|
||||||
|
input = 'foo';
|
||||||
|
onKeyDown({keyCode: keyCodes.Ctrl}, input, close);
|
||||||
|
onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close);
|
||||||
|
eq(input, '');
|
||||||
|
});
|
||||||
testVim('.', function(cm, vim, helpers) {
|
testVim('.', function(cm, vim, helpers) {
|
||||||
cm.setCursor(0, 0);
|
cm.setCursor(0, 0);
|
||||||
helpers.doKeys('2', 'd', 'w');
|
helpers.doKeys('2', 'd', 'w');
|
||||||
|
|
@ -3753,17 +3808,111 @@ testVim('set_string', function(cm, vim, helpers) {
|
||||||
eq('c', CodeMirror.Vim.getOption('testoption'));
|
eq('c', CodeMirror.Vim.getOption('testoption'));
|
||||||
});
|
});
|
||||||
testVim('ex_set_string', function(cm, vim, helpers) {
|
testVim('ex_set_string', function(cm, vim, helpers) {
|
||||||
CodeMirror.Vim.defineOption('testoption', 'a', 'string');
|
CodeMirror.Vim.defineOption('testopt', 'a', 'string');
|
||||||
// Test default value is set.
|
// Test default value is set.
|
||||||
eq('a', CodeMirror.Vim.getOption('testoption'));
|
eq('a', CodeMirror.Vim.getOption('testopt'));
|
||||||
try {
|
try {
|
||||||
// Test fail to set 'notestoption'
|
// Test fail to set 'notestopt'
|
||||||
helpers.doEx('set notestoption=b');
|
helpers.doEx('set notestopt=b');
|
||||||
fail();
|
fail();
|
||||||
} catch (expected) {};
|
} catch (expected) {};
|
||||||
// Test setOption
|
// Test setOption
|
||||||
helpers.doEx('set testoption=c')
|
helpers.doEx('set testopt=c')
|
||||||
eq('c', CodeMirror.Vim.getOption('testoption'));
|
eq('c', CodeMirror.Vim.getOption('testopt'));
|
||||||
|
helpers.doEx('set testopt=c')
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt')); // global
|
||||||
|
// Test setOption global
|
||||||
|
helpers.doEx('setg testopt=d')
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm));
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
|
||||||
|
eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
|
||||||
|
eq('d', CodeMirror.Vim.getOption('testopt'));
|
||||||
|
// Test setOption local
|
||||||
|
helpers.doEx('setl testopt=e')
|
||||||
|
eq('e', CodeMirror.Vim.getOption('testopt', cm));
|
||||||
|
eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
|
||||||
|
eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
|
||||||
|
eq('d', CodeMirror.Vim.getOption('testopt'));
|
||||||
|
});
|
||||||
|
testVim('ex_set_callback', function(cm, vim, helpers) {
|
||||||
|
var global;
|
||||||
|
|
||||||
|
function cb(val, cm, cfg) {
|
||||||
|
if (val === undefined) {
|
||||||
|
// Getter
|
||||||
|
if (cm) {
|
||||||
|
return cm._local;
|
||||||
|
} else {
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Setter
|
||||||
|
if (cm) {
|
||||||
|
cm._local = val;
|
||||||
|
} else {
|
||||||
|
global = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeMirror.Vim.defineOption('testopt', 'a', 'string', cb);
|
||||||
|
// Test default value is set.
|
||||||
|
eq('a', CodeMirror.Vim.getOption('testopt'));
|
||||||
|
try {
|
||||||
|
// Test fail to set 'notestopt'
|
||||||
|
helpers.doEx('set notestopt=b');
|
||||||
|
fail();
|
||||||
|
} catch (expected) {};
|
||||||
|
// Test setOption (Identical to the string tests, but via callback instead)
|
||||||
|
helpers.doEx('set testopt=c')
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt')); // global
|
||||||
|
// Test setOption global
|
||||||
|
helpers.doEx('setg testopt=d')
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm));
|
||||||
|
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
|
||||||
|
eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
|
||||||
|
eq('d', CodeMirror.Vim.getOption('testopt'));
|
||||||
|
// Test setOption local
|
||||||
|
helpers.doEx('setl testopt=e')
|
||||||
|
eq('e', CodeMirror.Vim.getOption('testopt', cm));
|
||||||
|
eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
|
||||||
|
eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
|
||||||
|
eq('d', CodeMirror.Vim.getOption('testopt'));
|
||||||
|
})
|
||||||
|
testVim('ex_set_filetype', function(cm, vim, helpers) {
|
||||||
|
CodeMirror.defineMode('test_mode', function() {
|
||||||
|
return {token: function(stream) {
|
||||||
|
stream.match(/^\s+|^\S+/);
|
||||||
|
}};
|
||||||
|
});
|
||||||
|
CodeMirror.defineMode('test_mode_2', function() {
|
||||||
|
return {token: function(stream) {
|
||||||
|
stream.match(/^\s+|^\S+/);
|
||||||
|
}};
|
||||||
|
});
|
||||||
|
// Test mode is set.
|
||||||
|
helpers.doEx('set filetype=test_mode');
|
||||||
|
eq('test_mode', cm.getMode().name);
|
||||||
|
// Test 'ft' alias also sets mode.
|
||||||
|
helpers.doEx('set ft=test_mode_2');
|
||||||
|
eq('test_mode_2', cm.getMode().name);
|
||||||
|
});
|
||||||
|
testVim('ex_set_filetype_null', function(cm, vim, helpers) {
|
||||||
|
CodeMirror.defineMode('test_mode', function() {
|
||||||
|
return {token: function(stream) {
|
||||||
|
stream.match(/^\s+|^\S+/);
|
||||||
|
}};
|
||||||
|
});
|
||||||
|
cm.setOption('mode', 'test_mode');
|
||||||
|
// Test mode is set to null.
|
||||||
|
helpers.doEx('set filetype=');
|
||||||
|
eq('null', cm.getMode().name);
|
||||||
});
|
});
|
||||||
// TODO: Reset key maps after each test.
|
// TODO: Reset key maps after each test.
|
||||||
testVim('ex_map_key2key', function(cm, vim, helpers) {
|
testVim('ex_map_key2key', function(cm, vim, helpers) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue