Path: blob/master/web-gui/buildyourownbotnet/assets/js/codemirror/test/vim_test.js
1293 views
var code = '' +1' wOrd1 (#%\n' +2' word3] \n' +3'aopop pop 0 1 2 3 4\n' +4' (a) [b] {c} \n' +5'int getchar(void) {\n' +6' static char buf[BUFSIZ];\n' +7' static char *bufp = buf;\n' +8' if (n == 0) { /* buffer is empty */\n' +9' n = read(0, buf, sizeof buf);\n' +10' bufp = buf;\n' +11' }\n' +12'\n' +13' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' +14' \n' +15'}\n';1617var lines = (function() {18lineText = code.split('\n');19var ret = [];20for (var i = 0; i < lineText.length; i++) {21ret[i] = {22line: i,23length: lineText[i].length,24lineText: lineText[i],25textStart: /^\s*/.exec(lineText[i])[0].length26};27}28return ret;29})();30var endOfDocument = makeCursor(lines.length - 1,31lines[lines.length - 1].length);32var wordLine = lines[0];33var bigWordLine = lines[1];34var charLine = lines[2];35var bracesLine = lines[3];36var seekBraceLine = lines[4];3738var word1 = {39start: { line: wordLine.line, ch: 1 },40end: { line: wordLine.line, ch: 5 }41};42var word2 = {43start: { line: wordLine.line, ch: word1.end.ch + 2 },44end: { line: wordLine.line, ch: word1.end.ch + 4 }45};46var word3 = {47start: { line: bigWordLine.line, ch: 1 },48end: { line: bigWordLine.line, ch: 5 }49};50var bigWord1 = word1;51var bigWord2 = word2;52var bigWord3 = {53start: { line: bigWordLine.line, ch: 1 },54end: { line: bigWordLine.line, ch: 7 }55};56var bigWord4 = {57start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 },58end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 }59};6061var oChars = [ { line: charLine.line, ch: 1 },62{ line: charLine.line, ch: 3 },63{ line: charLine.line, ch: 7 } ];64var pChars = [ { line: charLine.line, ch: 2 },65{ line: charLine.line, ch: 4 },66{ line: charLine.line, ch: 6 },67{ line: charLine.line, ch: 8 } ];68var numChars = [ { line: charLine.line, ch: 10 },69{ line: charLine.line, ch: 12 },70{ line: charLine.line, ch: 14 },71{ line: charLine.line, ch: 16 },72{ line: charLine.line, ch: 18 }];73var parens1 = {74start: { line: bracesLine.line, ch: 1 },75end: { line: bracesLine.line, ch: 3 }76};77var squares1 = {78start: { line: bracesLine.line, ch: 5 },79end: { line: bracesLine.line, ch: 7 }80};81var curlys1 = {82start: { line: bracesLine.line, ch: 9 },83end: { line: bracesLine.line, ch: 11 }84};85var seekOutside = {86start: { line: seekBraceLine.line, ch: 1 },87end: { line: seekBraceLine.line, ch: 16 }88};89var seekInside = {90start: { line: seekBraceLine.line, ch: 14 },91end: { line: seekBraceLine.line, ch: 11 }92};9394function copyCursor(cur) {95return { ch: cur.ch, line: cur.line };96}9798function forEach(arr, func) {99for (var i = 0; i < arr.length; i++) {100func(arr[i]);101}102}103104function testVim(name, run, opts, expectedFail) {105var vimOpts = {106lineNumbers: true,107vimMode: true,108showCursorWhenSelecting: true,109value: code110};111for (var prop in opts) {112if (opts.hasOwnProperty(prop)) {113vimOpts[prop] = opts[prop];114}115}116return test('vim_' + name, function() {117var place = document.getElementById("testground");118var cm = CodeMirror(place, vimOpts);119var vim = CodeMirror.Vim.maybeInitVimState_(cm);120121function doKeysFn(cm) {122return function(args) {123if (args instanceof Array) {124arguments = args;125}126for (var i = 0; i < arguments.length; i++) {127CodeMirror.Vim.handleKey(cm, arguments[i]);128}129}130}131function doInsertModeKeysFn(cm) {132return function(args) {133if (args instanceof Array) { arguments = args; }134function executeHandler(handler) {135if (typeof handler == 'string') {136CodeMirror.commands[handler](cm);137} else {138handler(cm);139}140return true;141}142for (var i = 0; i < arguments.length; i++) {143var key = arguments[i];144// Find key in keymap and handle.145var handled = CodeMirror.lookupKey(key, ['vim-insert'], executeHandler);146// Record for insert mode.147if (handled === true && cm.state.vim.insertMode && arguments[i] != 'Esc') {148var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;149if (lastChange) {150lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));151}152}153}154}155}156function doExFn(cm) {157return function(command) {158cm.openDialog = helpers.fakeOpenDialog(command);159helpers.doKeys(':');160}161}162function assertCursorAtFn(cm) {163return function(line, ch) {164var pos;165if (ch == null && typeof line.line == 'number') {166pos = line;167} else {168pos = makeCursor(line, ch);169}170eqPos(pos, cm.getCursor());171}172}173function fakeOpenDialog(result) {174return function(text, callback) {175return callback(result);176}177}178var helpers = {179doKeys: doKeysFn(cm),180// Warning: Only emulates keymap events, not character insertions. Use181// replaceRange to simulate character insertions.182// Keys are in CodeMirror format, NOT vim format.183doInsertModeKeys: doInsertModeKeysFn(cm),184doEx: doExFn(cm),185assertCursorAt: assertCursorAtFn(cm),186fakeOpenDialog: fakeOpenDialog,187getRegisterController: function() {188return CodeMirror.Vim.getRegisterController();189}190}191CodeMirror.Vim.resetVimGlobalState_();192var successful = false;193try {194run(cm, vim, helpers);195successful = true;196} finally {197if (!successful || verbose) {198place.style.visibility = "visible";199} else {200place.removeChild(cm.getWrapperElement());201}202}203}, expectedFail);204};205testVim('qq@q', function(cm, vim, helpers) {206cm.setCursor(0, 0);207helpers.doKeys('q', 'q', 'l', 'l', 'q');208helpers.assertCursorAt(0,2);209helpers.doKeys('@', 'q');210helpers.assertCursorAt(0,4);211}, { value: ' '});212testVim('@@', function(cm, vim, helpers) {213cm.setCursor(0, 0);214helpers.doKeys('q', 'q', 'l', 'l', 'q');215helpers.assertCursorAt(0,2);216helpers.doKeys('@', 'q');217helpers.assertCursorAt(0,4);218helpers.doKeys('@', '@');219helpers.assertCursorAt(0,6);220}, { value: ' '});221var jumplistScene = ''+222'word\n'+223'(word)\n'+224'{word\n'+225'word.\n'+226'\n'+227'word search\n'+228'}word\n'+229'word\n'+230'word\n';231function testJumplist(name, keys, endPos, startPos, dialog) {232endPos = makeCursor(endPos[0], endPos[1]);233startPos = makeCursor(startPos[0], startPos[1]);234testVim(name, function(cm, vim, helpers) {235CodeMirror.Vim.resetVimGlobalState_();236if(dialog)cm.openDialog = helpers.fakeOpenDialog('word');237cm.setCursor(startPos);238helpers.doKeys.apply(null, keys);239helpers.assertCursorAt(endPos);240}, {value: jumplistScene});241};242testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]);243testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]);244testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]);245testJumplist('jumplist_[[', ['[', '[', '<C-o>'], [5,2], [5,2]);246testJumplist('jumplist_]]', [']', ']', '<C-o>'], [2,2], [2,2]);247testJumplist('jumplist_G', ['G', '<C-o>'], [5,2], [5,2]);248testJumplist('jumplist_gg', ['g', 'g', '<C-o>'], [5,2], [5,2]);249testJumplist('jumplist_%', ['%', '<C-o>'], [1,5], [1,5]);250testJumplist('jumplist_{', ['{', '<C-o>'], [1,5], [1,5]);251testJumplist('jumplist_}', ['}', '<C-o>'], [1,5], [1,5]);252testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', '<C-i>'], [1,5], [1,5]);253testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', '<C-i>'], [1,5], [1,5]);254testJumplist('jumplist_*_cachedCursor', ['*', '<C-o>'], [1,3], [1,3]);255testJumplist('jumplist_#_cachedCursor', ['#', '<C-o>'], [1,3], [1,3]);256testJumplist('jumplist_n', ['#', 'n', '<C-o>'], [1,1], [2,3]);257testJumplist('jumplist_N', ['#', 'N', '<C-o>'], [1,1], [2,3]);258testJumplist('jumplist_repeat_<c-o>', ['*', '*', '*', '3', '<C-o>'], [2,3], [2,3]);259testJumplist('jumplist_repeat_<c-i>', ['*', '*', '*', '3', '<C-o>', '2', '<C-i>'], [5,0], [2,3]);260testJumplist('jumplist_repeated_motion', ['3', '*', '<C-o>'], [2,3], [2,3]);261testJumplist('jumplist_/', ['/', '<C-o>'], [2,3], [2,3], 'dialog');262testJumplist('jumplist_?', ['?', '<C-o>'], [2,3], [2,3], 'dialog');263testJumplist('jumplist_skip_delted_mark<c-o>',264['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-o>', '<C-o>'],265[0,2], [0,2]);266testJumplist('jumplist_skip_delted_mark<c-i>',267['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-i>', '<C-i>'],268[1,0], [0,2]);269/**270* @param name Name of the test271* @param keys An array of keys or a string with a single key to simulate.272* @param endPos The expected end position of the cursor.273* @param startPos The position the cursor should start at, defaults to 0, 0.274*/275function testMotion(name, keys, endPos, startPos) {276testVim(name, function(cm, vim, helpers) {277if (!startPos) {278startPos = { line: 0, ch: 0 };279}280cm.setCursor(startPos);281helpers.doKeys(keys);282helpers.assertCursorAt(endPos);283});284};285286function makeCursor(line, ch) {287return { line: line, ch: ch };288};289290function offsetCursor(cur, offsetLine, offsetCh) {291return { line: cur.line + offsetLine, ch: cur.ch + offsetCh };292};293294// Motion tests295testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4));296testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4));297testMotion('h', 'h', makeCursor(0, 0), word1.start);298testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end);299testMotion('l', 'l', makeCursor(0, 1));300testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2));301testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end);302testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end);303testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument);304testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end);305testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4));306testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4));307testMotion('w', 'w', word1.start);308testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2));309testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51));310testMotion('w_repeat', ['2', 'w'], word2.start);311testMotion('w_wrap', ['w'], word3.start, word2.start);312testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument);313testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0));314testMotion('W', 'W', bigWord1.start);315testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start);316testMotion('e', 'e', word1.end);317testMotion('e_repeat', ['2', 'e'], word2.end);318testMotion('e_wrap', 'e', word3.end, word2.end);319testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument);320testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0));321testMotion('b', 'b', word3.start, word3.end);322testMotion('b_repeat', ['2', 'b'], word2.start, word3.end);323testMotion('b_wrap', 'b', word2.start, word3.start);324testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0));325testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument);326testMotion('ge', ['g', 'e'], word2.end, word3.end);327testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start);328testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start);329testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0),330makeCursor(0, 0));331testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument);332testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart),333makeCursor(3, 1));334testMotion('gg_repeat', ['3', 'g', 'g'],335makeCursor(lines[2].line, lines[2].textStart));336testMotion('G', 'G',337makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart),338makeCursor(3, 1));339testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line,340lines[2].textStart));341// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B.342testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8));343testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8));344testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8));345testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4));346testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8));347testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1));348testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1),349makeCursor(0, 3));350testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0));351testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]);352testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0));353testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1),354makeCursor(charLine.line, 0));355testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1),356pChars[0]);357testMotion('F', ['F', 'p'], pChars[0], pChars[1]);358testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]);359testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]);360testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]);361testMotion('%_parens', ['%'], parens1.end, parens1.start);362testMotion('%_squares', ['%'], squares1.end, squares1.start);363testMotion('%_braces', ['%'], curlys1.end, curlys1.start);364testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start);365testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start);366testVim('%_seek_skip', function(cm, vim, helpers) {367cm.setCursor(0,0);368helpers.doKeys(['%']);369helpers.assertCursorAt(0,9);370}, {value:'01234"("()'});371testVim('%_skip_string', function(cm, vim, helpers) {372cm.setCursor(0,0);373helpers.doKeys(['%']);374helpers.assertCursorAt(0,4);375cm.setCursor(0,2);376helpers.doKeys(['%']);377helpers.assertCursorAt(0,0);378}, {value:'(")")'});379(')')380testVim('%_skip_comment', function(cm, vim, helpers) {381cm.setCursor(0,0);382helpers.doKeys(['%']);383helpers.assertCursorAt(0,6);384cm.setCursor(0,3);385helpers.doKeys(['%']);386helpers.assertCursorAt(0,0);387}, {value:'(/*)*/)'});388// Make sure that moving down after going to the end of a line always leaves you389// at the end of a line, but preserves the offset in other cases390testVim('Changing lines after Eol operation', function(cm, vim, helpers) {391cm.setCursor(0,0);392helpers.doKeys(['$']);393helpers.doKeys(['j']);394// After moving to Eol and then down, we should be at Eol of line 2395helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 });396helpers.doKeys(['j']);397// After moving down, we should be at Eol of line 3398helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 });399helpers.doKeys(['h']);400helpers.doKeys(['j']);401// After moving back one space and then down, since line 4 is shorter than line 2, we should402// be at Eol of line 2 - 1403helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 });404helpers.doKeys(['j']);405helpers.doKeys(['j']);406// After moving down again, since line 3 has enough characters, we should be back to the407// same place we were at on line 1408helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 });409});410//making sure gj and gk recover from clipping411testVim('gj_gk_clipping', function(cm,vim,helpers){412cm.setCursor(0, 1);413helpers.doKeys('g','j','g','j');414helpers.assertCursorAt(2, 1);415helpers.doKeys('g','k','g','k');416helpers.assertCursorAt(0, 1);417},{value: 'line 1\n\nline 2'});418//testing a mix of j/k and gj/gk419testVim('j_k_and_gj_gk', function(cm,vim,helpers){420cm.setSize(120);421cm.setCursor(0, 0);422//go to the last character on the first line423helpers.doKeys('$');424//move up/down on the column within the wrapped line425//side-effect: cursor is not locked to eol anymore426helpers.doKeys('g','k');427var cur=cm.getCursor();428eq(cur.line,0);429is((cur.ch<176),'gk didn\'t move cursor back (1)');430helpers.doKeys('g','j');431helpers.assertCursorAt(0, 176);432//should move to character 177 on line 2 (j/k preserve character index within line)433helpers.doKeys('j');434//due to different line wrapping, the cursor can be on a different screen-x now435//gj and gk preserve screen-x on movement, much like moveV436helpers.doKeys('3','g','k');437cur=cm.getCursor();438eq(cur.line,1);439is((cur.ch<176),'gk didn\'t move cursor back (2)');440helpers.doKeys('g','j','2','g','j');441//should return to the same character-index442helpers.doKeys('k');443helpers.assertCursorAt(0, 176);444},{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'});445testVim('gj_gk', function(cm, vim, helpers) {446if (phantom) return;447cm.setSize(120);448// Test top of document edge case.449cm.setCursor(0, 4);450helpers.doKeys('g', 'j');451helpers.doKeys('10', 'g', 'k');452helpers.assertCursorAt(0, 4);453454// Test moving down preserves column position.455helpers.doKeys('g', 'j');456var pos1 = cm.getCursor();457var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4};458helpers.doKeys('g', 'j');459helpers.assertCursorAt(expectedPos2);460461// Move to the last character462cm.setCursor(0, 0);463// Move left to reset HSPos464helpers.doKeys('h');465// Test bottom of document edge case.466helpers.doKeys('100', 'g', 'j');467var endingPos = cm.getCursor();468is(endingPos != 0, 'gj should not be on wrapped line 0');469var topLeftCharCoords = cm.charCoords(makeCursor(0, 0));470var endingCharCoords = cm.charCoords(endingPos);471is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0');472},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' });473testVim('}', function(cm, vim, helpers) {474cm.setCursor(0, 0);475helpers.doKeys('}');476helpers.assertCursorAt(1, 0);477cm.setCursor(0, 0);478helpers.doKeys('2', '}');479helpers.assertCursorAt(4, 0);480cm.setCursor(0, 0);481helpers.doKeys('6', '}');482helpers.assertCursorAt(5, 0);483}, { value: 'a\n\nb\nc\n\nd' });484testVim('{', function(cm, vim, helpers) {485cm.setCursor(5, 0);486helpers.doKeys('{');487helpers.assertCursorAt(4, 0);488cm.setCursor(5, 0);489helpers.doKeys('2', '{');490helpers.assertCursorAt(1, 0);491cm.setCursor(5, 0);492helpers.doKeys('6', '{');493helpers.assertCursorAt(0, 0);494}, { value: 'a\n\nb\nc\n\nd' });495496// Operator tests497testVim('dl', function(cm, vim, helpers) {498var curStart = makeCursor(0, 0);499cm.setCursor(curStart);500helpers.doKeys('d', 'l');501eq('word1 ', cm.getValue());502var register = helpers.getRegisterController().getRegister();503eq(' ', register.text);504is(!register.linewise);505eqPos(curStart, cm.getCursor());506}, { value: ' word1 ' });507testVim('dl_eol', function(cm, vim, helpers) {508cm.setCursor(0, 6);509helpers.doKeys('d', 'l');510eq(' word1', cm.getValue());511var register = helpers.getRegisterController().getRegister();512eq(' ', register.text);513is(!register.linewise);514helpers.assertCursorAt(0, 5);515}, { value: ' word1 ' });516testVim('dl_repeat', function(cm, vim, helpers) {517var curStart = makeCursor(0, 0);518cm.setCursor(curStart);519helpers.doKeys('2', 'd', 'l');520eq('ord1 ', cm.getValue());521var register = helpers.getRegisterController().getRegister();522eq(' w', register.text);523is(!register.linewise);524eqPos(curStart, cm.getCursor());525}, { value: ' word1 ' });526testVim('dh', function(cm, vim, helpers) {527var curStart = makeCursor(0, 3);528cm.setCursor(curStart);529helpers.doKeys('d', 'h');530eq(' wrd1 ', cm.getValue());531var register = helpers.getRegisterController().getRegister();532eq('o', register.text);533is(!register.linewise);534eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor());535}, { value: ' word1 ' });536testVim('dj', function(cm, vim, helpers) {537var curStart = makeCursor(0, 3);538cm.setCursor(curStart);539helpers.doKeys('d', 'j');540eq(' word3', cm.getValue());541var register = helpers.getRegisterController().getRegister();542eq(' word1\nword2\n', register.text);543is(register.linewise);544helpers.assertCursorAt(0, 1);545}, { value: ' word1\nword2\n word3' });546testVim('dj_end_of_document', function(cm, vim, helpers) {547var curStart = makeCursor(0, 3);548cm.setCursor(curStart);549helpers.doKeys('d', 'j');550eq(' word1 ', cm.getValue());551var register = helpers.getRegisterController().getRegister();552eq('', register.text);553is(!register.linewise);554helpers.assertCursorAt(0, 3);555}, { value: ' word1 ' });556testVim('dk', function(cm, vim, helpers) {557var curStart = makeCursor(1, 3);558cm.setCursor(curStart);559helpers.doKeys('d', 'k');560eq(' word3', cm.getValue());561var register = helpers.getRegisterController().getRegister();562eq(' word1\nword2\n', register.text);563is(register.linewise);564helpers.assertCursorAt(0, 1);565}, { value: ' word1\nword2\n word3' });566testVim('dk_start_of_document', function(cm, vim, helpers) {567var curStart = makeCursor(0, 3);568cm.setCursor(curStart);569helpers.doKeys('d', 'k');570eq(' word1 ', cm.getValue());571var register = helpers.getRegisterController().getRegister();572eq('', register.text);573is(!register.linewise);574helpers.assertCursorAt(0, 3);575}, { value: ' word1 ' });576testVim('dw_space', function(cm, vim, helpers) {577var curStart = makeCursor(0, 0);578cm.setCursor(curStart);579helpers.doKeys('d', 'w');580eq('word1 ', cm.getValue());581var register = helpers.getRegisterController().getRegister();582eq(' ', register.text);583is(!register.linewise);584eqPos(curStart, cm.getCursor());585}, { value: ' word1 ' });586testVim('dw_word', function(cm, vim, helpers) {587var curStart = makeCursor(0, 1);588cm.setCursor(curStart);589helpers.doKeys('d', 'w');590eq(' word2', cm.getValue());591var register = helpers.getRegisterController().getRegister();592eq('word1 ', register.text);593is(!register.linewise);594eqPos(curStart, cm.getCursor());595}, { value: ' word1 word2' });596testVim('dw_only_word', function(cm, vim, helpers) {597// Test that if there is only 1 word left, dw deletes till the end of the598// line.599cm.setCursor(0, 1);600helpers.doKeys('d', 'w');601eq(' ', cm.getValue());602var register = helpers.getRegisterController().getRegister();603eq('word1 ', register.text);604is(!register.linewise);605helpers.assertCursorAt(0, 0);606}, { value: ' word1 ' });607testVim('dw_eol', function(cm, vim, helpers) {608// Assert that dw does not delete the newline if last word to delete is at end609// of line.610cm.setCursor(0, 1);611helpers.doKeys('d', 'w');612eq(' \nword2', cm.getValue());613var register = helpers.getRegisterController().getRegister();614eq('word1', register.text);615is(!register.linewise);616helpers.assertCursorAt(0, 0);617}, { value: ' word1\nword2' });618testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {619// Assert that dw does not delete the newline if last word to delete is at end620// of line and it is followed by multiple newlines.621cm.setCursor(0, 1);622helpers.doKeys('d', 'w');623eq(' \n\nword2', cm.getValue());624var register = helpers.getRegisterController().getRegister();625eq('word1', register.text);626is(!register.linewise);627helpers.assertCursorAt(0, 0);628}, { value: ' word1\n\nword2' });629testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) {630cm.setCursor(0, 0);631helpers.doKeys('d', 'w');632eq(' \nword', cm.getValue());633}, { value: '\n \nword' });634testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) {635cm.setCursor(0, 0);636helpers.doKeys('d', 'w');637eq('word', cm.getValue());638}, { value: '\nword' });639testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) {640cm.setCursor(0, 0);641helpers.doKeys('d', 'w');642eq('\n', cm.getValue());643}, { value: '\n\n' });644testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) {645cm.setCursor(0, 0);646helpers.doKeys('d', 'w');647eq('\n \n', cm.getValue());648}, { value: ' \n \n' });649testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) {650cm.setCursor(0, 0);651helpers.doKeys('d', 'w');652eq('\n\n', cm.getValue());653}, { value: ' \n\n' });654testVim('dw_word_whitespace_word', function(cm, vim, helpers) {655cm.setCursor(0, 0);656helpers.doKeys('d', 'w');657eq('\n \nword2', cm.getValue());658}, { value: 'word1\n \nword2'})659testVim('dw_end_of_document', function(cm, vim, helpers) {660cm.setCursor(1, 2);661helpers.doKeys('d', 'w');662eq('\nab', cm.getValue());663}, { value: '\nabc' });664testVim('dw_repeat', function(cm, vim, helpers) {665// Assert that dw does delete newline if it should go to the next line, and666// that repeat works properly.667cm.setCursor(0, 1);668helpers.doKeys('d', '2', 'w');669eq(' ', cm.getValue());670var register = helpers.getRegisterController().getRegister();671eq('word1\nword2', register.text);672is(!register.linewise);673helpers.assertCursorAt(0, 0);674}, { value: ' word1\nword2' });675testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) {676cm.setCursor(0, 0);677helpers.doKeys('d', 'e');678eq('\n\n', cm.getValue());679}, { value: 'word\n\n' });680testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) {681cm.setCursor(0, 3);682helpers.doKeys('d', 'e');683eq('wor', cm.getValue());684}, { value: 'word\n\n\n' });685testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) {686cm.setCursor(0, 0);687helpers.doKeys('d', 'e');688eq('', cm.getValue());689}, { value: ' \n\n\n' });690testVim('de_end_of_document', function(cm, vim, helpers) {691cm.setCursor(1, 2);692helpers.doKeys('d', 'e');693eq('\nab', cm.getValue());694}, { value: '\nabc' });695testVim('db_empty_lines', function(cm, vim, helpers) {696cm.setCursor(2, 0);697helpers.doKeys('d', 'b');698eq('\n\n', cm.getValue());699}, { value: '\n\n\n' });700testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) {701cm.setCursor(2, 0);702helpers.doKeys('d', 'b');703eq('\nword', cm.getValue());704}, { value: '\n\nword' });705testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) {706cm.setCursor(2, 3);707helpers.doKeys('d', 'b');708eq('\n\nd', cm.getValue());709}, { value: '\n\nword' });710testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) {711cm.setCursor(2, 0);712helpers.doKeys('d', 'b');713eq('', cm.getValue());714}, { value: '\n \n' });715testVim('db_start_of_document', function(cm, vim, helpers) {716cm.setCursor(0, 0);717helpers.doKeys('d', 'b');718eq('abc\n', cm.getValue());719}, { value: 'abc\n' });720testVim('dge_empty_lines', function(cm, vim, helpers) {721cm.setCursor(1, 0);722helpers.doKeys('d', 'g', 'e');723// Note: In real VIM the result should be '', but it's not quite consistent,724// since 2 newlines are deleted. But in the similar case of word\n\n, only725// 1 newline is deleted. We'll diverge from VIM's behavior since it's much726// easier this way.727eq('\n', cm.getValue());728}, { value: '\n\n' });729testVim('dge_word_and_empty_lines', function(cm, vim, helpers) {730cm.setCursor(1, 0);731helpers.doKeys('d', 'g', 'e');732eq('wor\n', cm.getValue());733}, { value: 'word\n\n'});734testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) {735cm.setCursor(2, 0);736helpers.doKeys('d', 'g', 'e');737eq('', cm.getValue());738}, { value: '\n \n' });739testVim('dge_start_of_document', function(cm, vim, helpers) {740cm.setCursor(0, 0);741helpers.doKeys('d', 'g', 'e');742eq('bc\n', cm.getValue());743}, { value: 'abc\n' });744testVim('d_inclusive', function(cm, vim, helpers) {745// Assert that when inclusive is set, the character the cursor is on gets746// deleted too.747var curStart = makeCursor(0, 1);748cm.setCursor(curStart);749helpers.doKeys('d', 'e');750eq(' ', cm.getValue());751var register = helpers.getRegisterController().getRegister();752eq('word1', register.text);753is(!register.linewise);754eqPos(curStart, cm.getCursor());755}, { value: ' word1 ' });756testVim('d_reverse', function(cm, vim, helpers) {757// Test that deleting in reverse works.758cm.setCursor(1, 0);759helpers.doKeys('d', 'b');760eq(' word2 ', cm.getValue());761var register = helpers.getRegisterController().getRegister();762eq('word1\n', register.text);763is(!register.linewise);764helpers.assertCursorAt(0, 1);765}, { value: ' word1\nword2 ' });766testVim('dd', function(cm, vim, helpers) {767cm.setCursor(0, 3);768var expectedBuffer = cm.getRange({ line: 0, ch: 0 },769{ line: 1, ch: 0 });770var expectedLineCount = cm.lineCount() - 1;771helpers.doKeys('d', 'd');772eq(expectedLineCount, cm.lineCount());773var register = helpers.getRegisterController().getRegister();774eq(expectedBuffer, register.text);775is(register.linewise);776helpers.assertCursorAt(0, lines[1].textStart);777});778testVim('dd_prefix_repeat', function(cm, vim, helpers) {779cm.setCursor(0, 3);780var expectedBuffer = cm.getRange({ line: 0, ch: 0 },781{ line: 2, ch: 0 });782var expectedLineCount = cm.lineCount() - 2;783helpers.doKeys('2', 'd', 'd');784eq(expectedLineCount, cm.lineCount());785var register = helpers.getRegisterController().getRegister();786eq(expectedBuffer, register.text);787is(register.linewise);788helpers.assertCursorAt(0, lines[2].textStart);789});790testVim('dd_motion_repeat', function(cm, vim, helpers) {791cm.setCursor(0, 3);792var expectedBuffer = cm.getRange({ line: 0, ch: 0 },793{ line: 2, ch: 0 });794var expectedLineCount = cm.lineCount() - 2;795helpers.doKeys('d', '2', 'd');796eq(expectedLineCount, cm.lineCount());797var register = helpers.getRegisterController().getRegister();798eq(expectedBuffer, register.text);799is(register.linewise);800helpers.assertCursorAt(0, lines[2].textStart);801});802testVim('dd_multiply_repeat', function(cm, vim, helpers) {803cm.setCursor(0, 3);804var expectedBuffer = cm.getRange({ line: 0, ch: 0 },805{ line: 6, ch: 0 });806var expectedLineCount = cm.lineCount() - 6;807helpers.doKeys('2', 'd', '3', 'd');808eq(expectedLineCount, cm.lineCount());809var register = helpers.getRegisterController().getRegister();810eq(expectedBuffer, register.text);811is(register.linewise);812helpers.assertCursorAt(0, lines[6].textStart);813});814testVim('dd_lastline', function(cm, vim, helpers) {815cm.setCursor(cm.lineCount(), 0);816var expectedLineCount = cm.lineCount() - 1;817helpers.doKeys('d', 'd');818eq(expectedLineCount, cm.lineCount());819helpers.assertCursorAt(cm.lineCount() - 1, 0);820});821// Yank commands should behave the exact same as d commands, expect that nothing822// gets deleted.823testVim('yw_repeat', function(cm, vim, helpers) {824// Assert that yw does yank newline if it should go to the next line, and825// that repeat works properly.826var curStart = makeCursor(0, 1);827cm.setCursor(curStart);828helpers.doKeys('y', '2', 'w');829eq(' word1\nword2', cm.getValue());830var register = helpers.getRegisterController().getRegister();831eq('word1\nword2', register.text);832is(!register.linewise);833eqPos(curStart, cm.getCursor());834}, { value: ' word1\nword2' });835testVim('yy_multiply_repeat', function(cm, vim, helpers) {836var curStart = makeCursor(0, 3);837cm.setCursor(curStart);838var expectedBuffer = cm.getRange({ line: 0, ch: 0 },839{ line: 6, ch: 0 });840var expectedLineCount = cm.lineCount();841helpers.doKeys('2', 'y', '3', 'y');842eq(expectedLineCount, cm.lineCount());843var register = helpers.getRegisterController().getRegister();844eq(expectedBuffer, register.text);845is(register.linewise);846eqPos(curStart, cm.getCursor());847});848// Change commands behave like d commands except that it also enters insert849// mode. In addition, when the change is linewise, an additional newline is850// inserted so that insert mode starts on that line.851testVim('cw', function(cm, vim, helpers) {852cm.setCursor(0, 0);853helpers.doKeys('c', '2', 'w');854eq(' word3', cm.getValue());855helpers.assertCursorAt(0, 0);856}, { value: 'word1 word2 word3'});857testVim('cw_repeat', function(cm, vim, helpers) {858// Assert that cw does delete newline if it should go to the next line, and859// that repeat works properly.860var curStart = makeCursor(0, 1);861cm.setCursor(curStart);862helpers.doKeys('c', '2', 'w');863eq(' ', cm.getValue());864var register = helpers.getRegisterController().getRegister();865eq('word1\nword2', register.text);866is(!register.linewise);867eqPos(curStart, cm.getCursor());868eq('vim-insert', cm.getOption('keyMap'));869}, { value: ' word1\nword2' });870testVim('cc_multiply_repeat', function(cm, vim, helpers) {871cm.setCursor(0, 3);872var expectedBuffer = cm.getRange({ line: 0, ch: 0 },873{ line: 6, ch: 0 });874var expectedLineCount = cm.lineCount() - 5;875helpers.doKeys('2', 'c', '3', 'c');876eq(expectedLineCount, cm.lineCount());877var register = helpers.getRegisterController().getRegister();878eq(expectedBuffer, register.text);879is(register.linewise);880eq('vim-insert', cm.getOption('keyMap'));881});882testVim('cc_append', function(cm, vim, helpers) {883var expectedLineCount = cm.lineCount();884cm.setCursor(cm.lastLine(), 0);885helpers.doKeys('c', 'c');886eq(expectedLineCount, cm.lineCount());887});888// Swapcase commands edit in place and do not modify registers.889testVim('g~w_repeat', function(cm, vim, helpers) {890// Assert that dw does delete newline if it should go to the next line, and891// that repeat works properly.892var curStart = makeCursor(0, 1);893cm.setCursor(curStart);894helpers.doKeys('g', '~', '2', 'w');895eq(' WORD1\nWORD2', cm.getValue());896var register = helpers.getRegisterController().getRegister();897eq('', register.text);898is(!register.linewise);899eqPos(curStart, cm.getCursor());900}, { value: ' word1\nword2' });901testVim('g~g~', function(cm, vim, helpers) {902var curStart = makeCursor(0, 3);903cm.setCursor(curStart);904var expectedLineCount = cm.lineCount();905var expectedValue = cm.getValue().toUpperCase();906helpers.doKeys('2', 'g', '~', '3', 'g', '~');907eq(expectedValue, cm.getValue());908var register = helpers.getRegisterController().getRegister();909eq('', register.text);910is(!register.linewise);911eqPos(curStart, cm.getCursor());912}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' });913testVim('>{motion}', function(cm, vim, helpers) {914cm.setCursor(1, 3);915var expectedLineCount = cm.lineCount();916var expectedValue = ' word1\n word2\nword3 ';917helpers.doKeys('>', 'k');918eq(expectedValue, cm.getValue());919var register = helpers.getRegisterController().getRegister();920eq('', register.text);921is(!register.linewise);922helpers.assertCursorAt(0, 3);923}, { value: ' word1\nword2\nword3 ', indentUnit: 2 });924testVim('>>', function(cm, vim, helpers) {925cm.setCursor(0, 3);926var expectedLineCount = cm.lineCount();927var expectedValue = ' word1\n word2\nword3 ';928helpers.doKeys('2', '>', '>');929eq(expectedValue, cm.getValue());930var register = helpers.getRegisterController().getRegister();931eq('', register.text);932is(!register.linewise);933helpers.assertCursorAt(0, 3);934}, { value: ' word1\nword2\nword3 ', indentUnit: 2 });935testVim('<{motion}', function(cm, vim, helpers) {936cm.setCursor(1, 3);937var expectedLineCount = cm.lineCount();938var expectedValue = ' word1\nword2\nword3 ';939helpers.doKeys('<', 'k');940eq(expectedValue, cm.getValue());941var register = helpers.getRegisterController().getRegister();942eq('', register.text);943is(!register.linewise);944helpers.assertCursorAt(0, 1);945}, { value: ' word1\n word2\nword3 ', indentUnit: 2 });946testVim('<<', function(cm, vim, helpers) {947cm.setCursor(0, 3);948var expectedLineCount = cm.lineCount();949var expectedValue = ' word1\nword2\nword3 ';950helpers.doKeys('2', '<', '<');951eq(expectedValue, cm.getValue());952var register = helpers.getRegisterController().getRegister();953eq('', register.text);954is(!register.linewise);955helpers.assertCursorAt(0, 1);956}, { value: ' word1\n word2\nword3 ', indentUnit: 2 });957958// Edit tests959function testEdit(name, before, pos, edit, after) {960return testVim(name, function(cm, vim, helpers) {961cm.setCursor(0, before.search(pos));962helpers.doKeys.apply(this, edit.split(''));963eq(after, cm.getValue());964}, {value: before});965}966967// These Delete tests effectively cover word-wise Change, Visual & Yank.968// Tabs are used as differentiated whitespace to catch edge cases.969// Normal word:970testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz');971testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz');972testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz');973testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz');974testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz');975testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz');976testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz');977testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz');978testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz');979testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz');980testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t');981testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo');982testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.');983testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.');984// Big word:985testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz');986testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz');987testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz');988testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz');989testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz');990testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz');991testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz');992testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz');993testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz');994testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz');995testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t');996testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo');997testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t');998testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo');9991000// Operator-motion tests1001testVim('D', function(cm, vim, helpers) {1002cm.setCursor(0, 3);1003helpers.doKeys('D');1004eq(' wo\nword2\n word3', cm.getValue());1005var register = helpers.getRegisterController().getRegister();1006eq('rd1', register.text);1007is(!register.linewise);1008helpers.assertCursorAt(0, 2);1009}, { value: ' word1\nword2\n word3' });1010testVim('C', function(cm, vim, helpers) {1011var curStart = makeCursor(0, 3);1012cm.setCursor(curStart);1013helpers.doKeys('C');1014eq(' wo\nword2\n word3', cm.getValue());1015var register = helpers.getRegisterController().getRegister();1016eq('rd1', register.text);1017is(!register.linewise);1018eqPos(curStart, cm.getCursor());1019eq('vim-insert', cm.getOption('keyMap'));1020}, { value: ' word1\nword2\n word3' });1021testVim('Y', function(cm, vim, helpers) {1022var curStart = makeCursor(0, 3);1023cm.setCursor(curStart);1024helpers.doKeys('Y');1025eq(' word1\nword2\n word3', cm.getValue());1026var register = helpers.getRegisterController().getRegister();1027eq('rd1', register.text);1028is(!register.linewise);1029helpers.assertCursorAt(0, 3);1030}, { value: ' word1\nword2\n word3' });1031testVim('~', function(cm, vim, helpers) {1032helpers.doKeys('3', '~');1033eq('ABCdefg', cm.getValue());1034helpers.assertCursorAt(0, 3);1035}, { value: 'abcdefg' });10361037// Action tests1038testVim('ctrl-a', function(cm, vim, helpers) {1039cm.setCursor(0, 0);1040helpers.doKeys('<C-a>');1041eq('-9', cm.getValue());1042helpers.assertCursorAt(0, 1);1043helpers.doKeys('2','<C-a>');1044eq('-7', cm.getValue());1045}, {value: '-10'});1046testVim('ctrl-x', function(cm, vim, helpers) {1047cm.setCursor(0, 0);1048helpers.doKeys('<C-x>');1049eq('-1', cm.getValue());1050helpers.assertCursorAt(0, 1);1051helpers.doKeys('2','<C-x>');1052eq('-3', cm.getValue());1053}, {value: '0'});1054testVim('<C-x>/<C-a> search forward', function(cm, vim, helpers) {1055forEach(['<C-x>', '<C-a>'], function(key) {1056cm.setCursor(0, 0);1057helpers.doKeys(key);1058helpers.assertCursorAt(0, 5);1059helpers.doKeys('l');1060helpers.doKeys(key);1061helpers.assertCursorAt(0, 10);1062cm.setCursor(0, 11);1063helpers.doKeys(key);1064helpers.assertCursorAt(0, 11);1065});1066}, {value: '__jmp1 jmp2 jmp'});1067testVim('a', function(cm, vim, helpers) {1068cm.setCursor(0, 1);1069helpers.doKeys('a');1070helpers.assertCursorAt(0, 2);1071eq('vim-insert', cm.getOption('keyMap'));1072});1073testVim('a_eol', function(cm, vim, helpers) {1074cm.setCursor(0, lines[0].length - 1);1075helpers.doKeys('a');1076helpers.assertCursorAt(0, lines[0].length);1077eq('vim-insert', cm.getOption('keyMap'));1078});1079testVim('i', function(cm, vim, helpers) {1080cm.setCursor(0, 1);1081helpers.doKeys('i');1082helpers.assertCursorAt(0, 1);1083eq('vim-insert', cm.getOption('keyMap'));1084});1085testVim('i_repeat', function(cm, vim, helpers) {1086helpers.doKeys('3', 'i');1087cm.replaceRange('test', cm.getCursor());1088helpers.doInsertModeKeys('Esc');1089eq('testtesttest', cm.getValue());1090helpers.assertCursorAt(0, 11);1091}, { value: '' });1092testVim('i_repeat_delete', function(cm, vim, helpers) {1093cm.setCursor(0, 4);1094helpers.doKeys('2', 'i');1095cm.replaceRange('z', cm.getCursor());1096helpers.doInsertModeKeys('Backspace', 'Backspace', 'Esc');1097eq('abe', cm.getValue());1098helpers.assertCursorAt(0, 1);1099}, { value: 'abcde' });1100testVim('A', function(cm, vim, helpers) {1101helpers.doKeys('A');1102helpers.assertCursorAt(0, lines[0].length);1103eq('vim-insert', cm.getOption('keyMap'));1104});1105testVim('I', function(cm, vim, helpers) {1106cm.setCursor(0, 4);1107helpers.doKeys('I');1108helpers.assertCursorAt(0, lines[0].textStart);1109eq('vim-insert', cm.getOption('keyMap'));1110});1111testVim('I_repeat', function(cm, vim, helpers) {1112cm.setCursor(0, 1);1113helpers.doKeys('3', 'I');1114cm.replaceRange('test', cm.getCursor());1115helpers.doInsertModeKeys('Esc');1116eq('testtesttestblah', cm.getValue());1117helpers.assertCursorAt(0, 11);1118}, { value: 'blah' });1119testVim('o', function(cm, vim, helpers) {1120cm.setCursor(0, 4);1121helpers.doKeys('o');1122eq('word1\n\nword2', cm.getValue());1123helpers.assertCursorAt(1, 0);1124eq('vim-insert', cm.getOption('keyMap'));1125}, { value: 'word1\nword2' });1126testVim('o_repeat', function(cm, vim, helpers) {1127cm.setCursor(0, 0);1128helpers.doKeys('3', 'o');1129cm.replaceRange('test', cm.getCursor());1130helpers.doInsertModeKeys('Esc');1131eq('\ntest\ntest\ntest', cm.getValue());1132helpers.assertCursorAt(3, 3);1133}, { value: '' });1134testVim('O', function(cm, vim, helpers) {1135cm.setCursor(0, 4);1136helpers.doKeys('O');1137eq('\nword1\nword2', cm.getValue());1138helpers.assertCursorAt(0, 0);1139eq('vim-insert', cm.getOption('keyMap'));1140}, { value: 'word1\nword2' });1141testVim('J', function(cm, vim, helpers) {1142cm.setCursor(0, 4);1143helpers.doKeys('J');1144var expectedValue = 'word1 word2\nword3\n word4';1145eq(expectedValue, cm.getValue());1146helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1);1147}, { value: 'word1 \n word2\nword3\n word4' });1148testVim('J_repeat', function(cm, vim, helpers) {1149cm.setCursor(0, 4);1150helpers.doKeys('3', 'J');1151var expectedValue = 'word1 word2 word3\n word4';1152eq(expectedValue, cm.getValue());1153helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1);1154}, { value: 'word1 \n word2\nword3\n word4' });1155testVim('p', function(cm, vim, helpers) {1156cm.setCursor(0, 1);1157helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);1158helpers.doKeys('p');1159eq('__abc\ndef_', cm.getValue());1160helpers.assertCursorAt(1, 2);1161}, { value: '___' });1162testVim('p_register', function(cm, vim, helpers) {1163cm.setCursor(0, 1);1164helpers.getRegisterController().getRegister('a').set('abc\ndef', false);1165helpers.doKeys('"', 'a', 'p');1166eq('__abc\ndef_', cm.getValue());1167helpers.assertCursorAt(1, 2);1168}, { value: '___' });1169testVim('p_wrong_register', function(cm, vim, helpers) {1170cm.setCursor(0, 1);1171helpers.getRegisterController().getRegister('a').set('abc\ndef', false);1172helpers.doKeys('p');1173eq('___', cm.getValue());1174helpers.assertCursorAt(0, 1);1175}, { value: '___' });1176testVim('p_line', function(cm, vim, helpers) {1177cm.setCursor(0, 1);1178helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);1179helpers.doKeys('2', 'p');1180eq('___\n a\nd\n a\nd', cm.getValue());1181helpers.assertCursorAt(1, 2);1182}, { value: '___' });1183testVim('p_lastline', function(cm, vim, helpers) {1184cm.setCursor(0, 1);1185helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true);1186helpers.doKeys('2', 'p');1187eq('___\n a\nd\n a\nd', cm.getValue());1188helpers.assertCursorAt(1, 2);1189}, { value: '___' });1190testVim('P', function(cm, vim, helpers) {1191cm.setCursor(0, 1);1192helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);1193helpers.doKeys('P');1194eq('_abc\ndef__', cm.getValue());1195helpers.assertCursorAt(1, 3);1196}, { value: '___' });1197testVim('P_line', function(cm, vim, helpers) {1198cm.setCursor(0, 1);1199helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);1200helpers.doKeys('2', 'P');1201eq(' a\nd\n a\nd\n___', cm.getValue());1202helpers.assertCursorAt(0, 2);1203}, { value: '___' });1204testVim('r', function(cm, vim, helpers) {1205cm.setCursor(0, 1);1206helpers.doKeys('3', 'r', 'u');1207eq('wuuuet\nanother', cm.getValue(),'3r failed');1208helpers.assertCursorAt(0, 3);1209cm.setCursor(0, 4);1210helpers.doKeys('v', 'j', 'h', 'r', '<Space>');1211eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed');1212}, { value: 'wordet\nanother' });1213testVim('R', function(cm, vim, helpers) {1214cm.setCursor(0, 1);1215helpers.doKeys('R');1216helpers.assertCursorAt(0, 1);1217eq('vim-replace', cm.getOption('keyMap'));1218is(cm.state.overwrite, 'Setting overwrite state failed');1219});1220testVim('mark', function(cm, vim, helpers) {1221cm.setCursor(2, 2);1222helpers.doKeys('m', 't');1223cm.setCursor(0, 0);1224helpers.doKeys('\'', 't');1225helpers.assertCursorAt(2, 2);1226cm.setCursor(0, 0);1227helpers.doKeys('`', 't');1228helpers.assertCursorAt(2, 2);1229});1230testVim('jumpToMark_next', function(cm, vim, helpers) {1231cm.setCursor(2, 2);1232helpers.doKeys('m', 't');1233cm.setCursor(0, 0);1234helpers.doKeys(']', '`');1235helpers.assertCursorAt(2, 2);1236cm.setCursor(0, 0);1237helpers.doKeys(']', '\'');1238helpers.assertCursorAt(2, 0);1239});1240testVim('jumpToMark_next_repeat', function(cm, vim, helpers) {1241cm.setCursor(2, 2);1242helpers.doKeys('m', 'a');1243cm.setCursor(3, 2);1244helpers.doKeys('m', 'b');1245cm.setCursor(4, 2);1246helpers.doKeys('m', 'c');1247cm.setCursor(0, 0);1248helpers.doKeys('2', ']', '`');1249helpers.assertCursorAt(3, 2);1250cm.setCursor(0, 0);1251helpers.doKeys('2', ']', '\'');1252helpers.assertCursorAt(3, 1);1253});1254testVim('jumpToMark_next_sameline', function(cm, vim, helpers) {1255cm.setCursor(2, 0);1256helpers.doKeys('m', 'a');1257cm.setCursor(2, 4);1258helpers.doKeys('m', 'b');1259cm.setCursor(2, 2);1260helpers.doKeys(']', '`');1261helpers.assertCursorAt(2, 4);1262});1263testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) {1264cm.setCursor(2, 0);1265helpers.doKeys('m', 'a');1266cm.setCursor(4, 0);1267helpers.doKeys(']', '`');1268helpers.assertCursorAt(4, 0);1269});1270testVim('jumpToMark_next_nomark', function(cm, vim, helpers) {1271cm.setCursor(2, 2);1272helpers.doKeys(']', '`');1273helpers.assertCursorAt(2, 2);1274helpers.doKeys(']', '\'');1275helpers.assertCursorAt(2, 0);1276});1277testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) {1278cm.setCursor(2, 2);1279helpers.doKeys('m', 'a');1280cm.setCursor(3, 4);1281helpers.doKeys('m', 'b');1282cm.setCursor(2, 1);1283helpers.doKeys(']', '\'');1284helpers.assertCursorAt(3, 1);1285});1286testVim('jumpToMark_next_action', function(cm, vim, helpers) {1287cm.setCursor(2, 2);1288helpers.doKeys('m', 't');1289cm.setCursor(0, 0);1290helpers.doKeys('d', ']', '`');1291helpers.assertCursorAt(0, 0);1292var actual = cm.getLine(0);1293var expected = 'pop pop 0 1 2 3 4';1294eq(actual, expected, "Deleting while jumping to the next mark failed.");1295});1296testVim('jumpToMark_next_line_action', function(cm, vim, helpers) {1297cm.setCursor(2, 2);1298helpers.doKeys('m', 't');1299cm.setCursor(0, 0);1300helpers.doKeys('d', ']', '\'');1301helpers.assertCursorAt(0, 1);1302var actual = cm.getLine(0);1303var expected = ' (a) [b] {c} '1304eq(actual, expected, "Deleting while jumping to the next mark line failed.");1305});1306testVim('jumpToMark_prev', function(cm, vim, helpers) {1307cm.setCursor(2, 2);1308helpers.doKeys('m', 't');1309cm.setCursor(4, 0);1310helpers.doKeys('[', '`');1311helpers.assertCursorAt(2, 2);1312cm.setCursor(4, 0);1313helpers.doKeys('[', '\'');1314helpers.assertCursorAt(2, 0);1315});1316testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) {1317cm.setCursor(2, 2);1318helpers.doKeys('m', 'a');1319cm.setCursor(3, 2);1320helpers.doKeys('m', 'b');1321cm.setCursor(4, 2);1322helpers.doKeys('m', 'c');1323cm.setCursor(5, 0);1324helpers.doKeys('2', '[', '`');1325helpers.assertCursorAt(3, 2);1326cm.setCursor(5, 0);1327helpers.doKeys('2', '[', '\'');1328helpers.assertCursorAt(3, 1);1329});1330testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) {1331cm.setCursor(2, 0);1332helpers.doKeys('m', 'a');1333cm.setCursor(2, 4);1334helpers.doKeys('m', 'b');1335cm.setCursor(2, 2);1336helpers.doKeys('[', '`');1337helpers.assertCursorAt(2, 0);1338});1339testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) {1340cm.setCursor(4, 4);1341helpers.doKeys('m', 'a');1342cm.setCursor(2, 0);1343helpers.doKeys('[', '`');1344helpers.assertCursorAt(2, 0);1345});1346testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) {1347cm.setCursor(2, 2);1348helpers.doKeys('[', '`');1349helpers.assertCursorAt(2, 2);1350helpers.doKeys('[', '\'');1351helpers.assertCursorAt(2, 0);1352});1353testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) {1354cm.setCursor(2, 2);1355helpers.doKeys('m', 'a');1356cm.setCursor(3, 4);1357helpers.doKeys('m', 'b');1358cm.setCursor(3, 6);1359helpers.doKeys('[', '\'');1360helpers.assertCursorAt(2, 0);1361});1362testVim('delmark_single', function(cm, vim, helpers) {1363cm.setCursor(1, 2);1364helpers.doKeys('m', 't');1365helpers.doEx('delmarks t');1366cm.setCursor(0, 0);1367helpers.doKeys('`', 't');1368helpers.assertCursorAt(0, 0);1369});1370testVim('delmark_range', function(cm, vim, helpers) {1371cm.setCursor(1, 2);1372helpers.doKeys('m', 'a');1373cm.setCursor(2, 2);1374helpers.doKeys('m', 'b');1375cm.setCursor(3, 2);1376helpers.doKeys('m', 'c');1377cm.setCursor(4, 2);1378helpers.doKeys('m', 'd');1379cm.setCursor(5, 2);1380helpers.doKeys('m', 'e');1381helpers.doEx('delmarks b-d');1382cm.setCursor(0, 0);1383helpers.doKeys('`', 'a');1384helpers.assertCursorAt(1, 2);1385helpers.doKeys('`', 'b');1386helpers.assertCursorAt(1, 2);1387helpers.doKeys('`', 'c');1388helpers.assertCursorAt(1, 2);1389helpers.doKeys('`', 'd');1390helpers.assertCursorAt(1, 2);1391helpers.doKeys('`', 'e');1392helpers.assertCursorAt(5, 2);1393});1394testVim('delmark_multi', function(cm, vim, helpers) {1395cm.setCursor(1, 2);1396helpers.doKeys('m', 'a');1397cm.setCursor(2, 2);1398helpers.doKeys('m', 'b');1399cm.setCursor(3, 2);1400helpers.doKeys('m', 'c');1401cm.setCursor(4, 2);1402helpers.doKeys('m', 'd');1403cm.setCursor(5, 2);1404helpers.doKeys('m', 'e');1405helpers.doEx('delmarks bcd');1406cm.setCursor(0, 0);1407helpers.doKeys('`', 'a');1408helpers.assertCursorAt(1, 2);1409helpers.doKeys('`', 'b');1410helpers.assertCursorAt(1, 2);1411helpers.doKeys('`', 'c');1412helpers.assertCursorAt(1, 2);1413helpers.doKeys('`', 'd');1414helpers.assertCursorAt(1, 2);1415helpers.doKeys('`', 'e');1416helpers.assertCursorAt(5, 2);1417});1418testVim('delmark_multi_space', function(cm, vim, helpers) {1419cm.setCursor(1, 2);1420helpers.doKeys('m', 'a');1421cm.setCursor(2, 2);1422helpers.doKeys('m', 'b');1423cm.setCursor(3, 2);1424helpers.doKeys('m', 'c');1425cm.setCursor(4, 2);1426helpers.doKeys('m', 'd');1427cm.setCursor(5, 2);1428helpers.doKeys('m', 'e');1429helpers.doEx('delmarks b c d');1430cm.setCursor(0, 0);1431helpers.doKeys('`', 'a');1432helpers.assertCursorAt(1, 2);1433helpers.doKeys('`', 'b');1434helpers.assertCursorAt(1, 2);1435helpers.doKeys('`', 'c');1436helpers.assertCursorAt(1, 2);1437helpers.doKeys('`', 'd');1438helpers.assertCursorAt(1, 2);1439helpers.doKeys('`', 'e');1440helpers.assertCursorAt(5, 2);1441});1442testVim('delmark_all', function(cm, vim, helpers) {1443cm.setCursor(1, 2);1444helpers.doKeys('m', 'a');1445cm.setCursor(2, 2);1446helpers.doKeys('m', 'b');1447cm.setCursor(3, 2);1448helpers.doKeys('m', 'c');1449cm.setCursor(4, 2);1450helpers.doKeys('m', 'd');1451cm.setCursor(5, 2);1452helpers.doKeys('m', 'e');1453helpers.doEx('delmarks a b-de');1454cm.setCursor(0, 0);1455helpers.doKeys('`', 'a');1456helpers.assertCursorAt(0, 0);1457helpers.doKeys('`', 'b');1458helpers.assertCursorAt(0, 0);1459helpers.doKeys('`', 'c');1460helpers.assertCursorAt(0, 0);1461helpers.doKeys('`', 'd');1462helpers.assertCursorAt(0, 0);1463helpers.doKeys('`', 'e');1464helpers.assertCursorAt(0, 0);1465});1466testVim('visual', function(cm, vim, helpers) {1467helpers.doKeys('l', 'v', 'l', 'l');1468helpers.assertCursorAt(0, 3);1469eqPos(makeCursor(0, 1), cm.getCursor('anchor'));1470helpers.doKeys('d');1471eq('15', cm.getValue());1472}, { value: '12345' });1473testVim('visual_line', function(cm, vim, helpers) {1474helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd');1475eq(' 4\n 5', cm.getValue());1476}, { value: ' 1\n 2\n 3\n 4\n 5' });1477testVim('visual_marks', function(cm, vim, helpers) {1478helpers.doKeys('l', 'v', 'l', 'l', 'v');1479// Test visual mode marks1480cm.setCursor(0, 0);1481helpers.doKeys('\'', '<');1482helpers.assertCursorAt(0, 1);1483helpers.doKeys('\'', '>');1484helpers.assertCursorAt(0, 3);1485});1486testVim('visual_join', function(cm, vim, helpers) {1487helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J');1488eq(' 1 2 3\n 4\n 5', cm.getValue());1489}, { value: ' 1\n 2\n 3\n 4\n 5' });1490testVim('visual_blank', function(cm, vim, helpers) {1491helpers.doKeys('v', 'k');1492eq(vim.visualMode, true);1493}, { value: '\n' });1494testVim('s_normal', function(cm, vim, helpers) {1495cm.setCursor(0, 1);1496helpers.doKeys('s');1497helpers.doInsertModeKeys('Esc');1498helpers.assertCursorAt(0, 0);1499eq('ac', cm.getValue());1500}, { value: 'abc'});1501testVim('s_visual', function(cm, vim, helpers) {1502cm.setCursor(0, 1);1503helpers.doKeys('v', 's');1504helpers.doInsertModeKeys('Esc');1505helpers.assertCursorAt(0, 0);1506eq('ac', cm.getValue());1507}, { value: 'abc'});1508testVim('S_normal', function(cm, vim, helpers) {1509cm.setCursor(0, 1);1510helpers.doKeys('j', 'S');1511helpers.doInsertModeKeys('Esc');1512helpers.assertCursorAt(1, 0);1513eq('aa\n\ncc', cm.getValue());1514}, { value: 'aa\nbb\ncc'});1515testVim('S_visual', function(cm, vim, helpers) {1516cm.setCursor(0, 1);1517helpers.doKeys('v', 'j', 'S');1518helpers.doInsertModeKeys('Esc');1519helpers.assertCursorAt(0, 0);1520eq('\ncc', cm.getValue());1521}, { value: 'aa\nbb\ncc'});1522testVim('/ and n/N', function(cm, vim, helpers) {1523cm.openDialog = helpers.fakeOpenDialog('match');1524helpers.doKeys('/');1525helpers.assertCursorAt(0, 11);1526helpers.doKeys('n');1527helpers.assertCursorAt(1, 6);1528helpers.doKeys('N');1529helpers.assertCursorAt(0, 11);15301531cm.setCursor(0, 0);1532helpers.doKeys('2', '/');1533helpers.assertCursorAt(1, 6);1534}, { value: 'match nope match \n nope Match' });1535testVim('/_case', function(cm, vim, helpers) {1536cm.openDialog = helpers.fakeOpenDialog('Match');1537helpers.doKeys('/');1538helpers.assertCursorAt(1, 6);1539}, { value: 'match nope match \n nope Match' });1540testVim('/_nongreedy', function(cm, vim, helpers) {1541cm.openDialog = helpers.fakeOpenDialog('aa');1542helpers.doKeys('/');1543helpers.assertCursorAt(0, 4);1544helpers.doKeys('n');1545helpers.assertCursorAt(1, 3);1546helpers.doKeys('n');1547helpers.assertCursorAt(0, 0);1548}, { value: 'aaa aa \n a aa'});1549testVim('?_nongreedy', function(cm, vim, helpers) {1550cm.openDialog = helpers.fakeOpenDialog('aa');1551helpers.doKeys('?');1552helpers.assertCursorAt(1, 3);1553helpers.doKeys('n');1554helpers.assertCursorAt(0, 4);1555helpers.doKeys('n');1556helpers.assertCursorAt(0, 0);1557}, { value: 'aaa aa \n a aa'});1558testVim('/_greedy', function(cm, vim, helpers) {1559cm.openDialog = helpers.fakeOpenDialog('a+');1560helpers.doKeys('/');1561helpers.assertCursorAt(0, 4);1562helpers.doKeys('n');1563helpers.assertCursorAt(1, 1);1564helpers.doKeys('n');1565helpers.assertCursorAt(1, 3);1566helpers.doKeys('n');1567helpers.assertCursorAt(0, 0);1568}, { value: 'aaa aa \n a aa'});1569testVim('?_greedy', function(cm, vim, helpers) {1570cm.openDialog = helpers.fakeOpenDialog('a+');1571helpers.doKeys('?');1572helpers.assertCursorAt(1, 3);1573helpers.doKeys('n');1574helpers.assertCursorAt(1, 1);1575helpers.doKeys('n');1576helpers.assertCursorAt(0, 4);1577helpers.doKeys('n');1578helpers.assertCursorAt(0, 0);1579}, { value: 'aaa aa \n a aa'});1580testVim('/_greedy_0_or_more', function(cm, vim, helpers) {1581cm.openDialog = helpers.fakeOpenDialog('a*');1582helpers.doKeys('/');1583helpers.assertCursorAt(0, 3);1584helpers.doKeys('n');1585helpers.assertCursorAt(0, 4);1586helpers.doKeys('n');1587helpers.assertCursorAt(0, 5);1588helpers.doKeys('n');1589helpers.assertCursorAt(1, 0);1590helpers.doKeys('n');1591helpers.assertCursorAt(1, 1);1592helpers.doKeys('n');1593helpers.assertCursorAt(0, 0);1594}, { value: 'aaa aa\n aa'});1595testVim('?_greedy_0_or_more', function(cm, vim, helpers) {1596cm.openDialog = helpers.fakeOpenDialog('a*');1597helpers.doKeys('?');1598helpers.assertCursorAt(1, 1);1599helpers.doKeys('n');1600helpers.assertCursorAt(1, 0);1601helpers.doKeys('n');1602helpers.assertCursorAt(0, 5);1603helpers.doKeys('n');1604helpers.assertCursorAt(0, 4);1605helpers.doKeys('n');1606helpers.assertCursorAt(0, 3);1607helpers.doKeys('n');1608helpers.assertCursorAt(0, 0);1609}, { value: 'aaa aa\n aa'});1610testVim('? and n/N', function(cm, vim, helpers) {1611cm.openDialog = helpers.fakeOpenDialog('match');1612helpers.doKeys('?');1613helpers.assertCursorAt(1, 6);1614helpers.doKeys('n');1615helpers.assertCursorAt(0, 11);1616helpers.doKeys('N');1617helpers.assertCursorAt(1, 6);16181619cm.setCursor(0, 0);1620helpers.doKeys('2', '?');1621helpers.assertCursorAt(0, 11);1622}, { value: 'match nope match \n nope Match' });1623testVim('*', function(cm, vim, helpers) {1624cm.setCursor(0, 9);1625helpers.doKeys('*');1626helpers.assertCursorAt(0, 22);16271628cm.setCursor(0, 9);1629helpers.doKeys('2', '*');1630helpers.assertCursorAt(1, 8);1631}, { value: 'nomatch match nomatch match \nnomatch Match' });1632testVim('*_no_word', function(cm, vim, helpers) {1633cm.setCursor(0, 0);1634helpers.doKeys('*');1635helpers.assertCursorAt(0, 0);1636}, { value: ' \n match \n' });1637testVim('*_symbol', function(cm, vim, helpers) {1638cm.setCursor(0, 0);1639helpers.doKeys('*');1640helpers.assertCursorAt(1, 0);1641}, { value: ' /}\n/} match \n' });1642testVim('#', function(cm, vim, helpers) {1643cm.setCursor(0, 9);1644helpers.doKeys('#');1645helpers.assertCursorAt(1, 8);16461647cm.setCursor(0, 9);1648helpers.doKeys('2', '#');1649helpers.assertCursorAt(0, 22);1650}, { value: 'nomatch match nomatch match \nnomatch Match' });1651testVim('*_seek', function(cm, vim, helpers) {1652// Should skip over space and symbols.1653cm.setCursor(0, 3);1654helpers.doKeys('*');1655helpers.assertCursorAt(0, 22);1656}, { value: ' := match nomatch match \nnomatch Match' });1657testVim('#', function(cm, vim, helpers) {1658// Should skip over space and symbols.1659cm.setCursor(0, 3);1660helpers.doKeys('#');1661helpers.assertCursorAt(1, 8);1662}, { value: ' := match nomatch match \nnomatch Match' });1663testVim('.', function(cm, vim, helpers) {1664cm.setCursor(0, 0);1665helpers.doKeys('2', 'd', 'w');1666helpers.doKeys('.');1667eq('5 6', cm.getValue());1668}, { value: '1 2 3 4 5 6'});1669testVim('._repeat', function(cm, vim, helpers) {1670cm.setCursor(0, 0);1671helpers.doKeys('2', 'd', 'w');1672helpers.doKeys('3', '.');1673eq('6', cm.getValue());1674}, { value: '1 2 3 4 5 6'});1675testVim('._insert', function(cm, vim, helpers) {1676helpers.doKeys('i');1677cm.replaceRange('test', cm.getCursor());1678helpers.doInsertModeKeys('Esc');1679helpers.doKeys('.');1680eq('testestt', cm.getValue());1681helpers.assertCursorAt(0, 6);1682}, { value: ''});1683testVim('._insert_repeat', function(cm, vim, helpers) {1684helpers.doKeys('i');1685cm.replaceRange('test', cm.getCursor());1686cm.setCursor(0, 4);1687helpers.doInsertModeKeys('Esc');1688helpers.doKeys('2', '.');1689eq('testesttestt', cm.getValue());1690helpers.assertCursorAt(0, 10);1691}, { value: ''});1692testVim('._repeat_insert', function(cm, vim, helpers) {1693helpers.doKeys('3', 'i');1694cm.replaceRange('te', cm.getCursor());1695cm.setCursor(0, 2);1696helpers.doInsertModeKeys('Esc');1697helpers.doKeys('.');1698eq('tetettetetee', cm.getValue());1699helpers.assertCursorAt(0, 10);1700}, { value: ''});1701testVim('._insert_o', function(cm, vim, helpers) {1702helpers.doKeys('o');1703cm.replaceRange('z', cm.getCursor());1704cm.setCursor(1, 1);1705helpers.doInsertModeKeys('Esc');1706helpers.doKeys('.');1707eq('\nz\nz', cm.getValue());1708helpers.assertCursorAt(2, 0);1709}, { value: ''});1710testVim('._insert_o_repeat', function(cm, vim, helpers) {1711helpers.doKeys('o');1712cm.replaceRange('z', cm.getCursor());1713helpers.doInsertModeKeys('Esc');1714cm.setCursor(1, 0);1715helpers.doKeys('2', '.');1716eq('\nz\nz\nz', cm.getValue());1717helpers.assertCursorAt(3, 0);1718}, { value: ''});1719testVim('._insert_o_indent', function(cm, vim, helpers) {1720helpers.doKeys('o');1721cm.replaceRange('z', cm.getCursor());1722helpers.doInsertModeKeys('Esc');1723cm.setCursor(1, 2);1724helpers.doKeys('.');1725eq('{\n z\n z', cm.getValue());1726helpers.assertCursorAt(2, 2);1727}, { value: '{'});1728testVim('._insert_cw', function(cm, vim, helpers) {1729helpers.doKeys('c', 'w');1730cm.replaceRange('test', cm.getCursor());1731helpers.doInsertModeKeys('Esc');1732cm.setCursor(0, 3);1733helpers.doKeys('2', 'l');1734helpers.doKeys('.');1735eq('test test word3', cm.getValue());1736helpers.assertCursorAt(0, 8);1737}, { value: 'word1 word2 word3' });1738testVim('._insert_cw_repeat', function(cm, vim, helpers) {1739// For some reason, repeat cw in desktop VIM will does not repeat insert mode1740// changes. Will conform to that behavior.1741helpers.doKeys('c', 'w');1742cm.replaceRange('test', cm.getCursor());1743helpers.doInsertModeKeys('Esc');1744cm.setCursor(0, 4);1745helpers.doKeys('l');1746helpers.doKeys('2', '.');1747eq('test test', cm.getValue());1748helpers.assertCursorAt(0, 8);1749}, { value: 'word1 word2 word3' });1750testVim('._delete', function(cm, vim, helpers) {1751cm.setCursor(0, 5);1752helpers.doKeys('i');1753helpers.doInsertModeKeys('Backspace', 'Esc');1754helpers.doKeys('.');1755eq('zace', cm.getValue());1756helpers.assertCursorAt(0, 1);1757}, { value: 'zabcde'});1758testVim('._delete_repeat', function(cm, vim, helpers) {1759cm.setCursor(0, 6);1760helpers.doKeys('i');1761helpers.doInsertModeKeys('Backspace', 'Esc');1762helpers.doKeys('2', '.');1763eq('zzce', cm.getValue());1764helpers.assertCursorAt(0, 1);1765}, { value: 'zzabcde'});1766testVim('f;', function(cm, vim, helpers) {1767cm.setCursor(0, 0);1768helpers.doKeys('f', 'x');1769helpers.doKeys(';');1770helpers.doKeys('2', ';');1771eq(9, cm.getCursor().ch);1772}, { value: '01x3xx678x'});1773testVim('F;', function(cm, vim, helpers) {1774cm.setCursor(0, 8);1775helpers.doKeys('F', 'x');1776helpers.doKeys(';');1777helpers.doKeys('2', ';');1778eq(2, cm.getCursor().ch);1779}, { value: '01x3xx6x8x'});1780testVim('t;', function(cm, vim, helpers) {1781cm.setCursor(0, 0);1782helpers.doKeys('t', 'x');1783helpers.doKeys(';');1784helpers.doKeys('2', ';');1785eq(8, cm.getCursor().ch);1786}, { value: '01x3xx678x'});1787testVim('T;', function(cm, vim, helpers) {1788cm.setCursor(0, 9);1789helpers.doKeys('T', 'x');1790helpers.doKeys(';');1791helpers.doKeys('2', ';');1792eq(2, cm.getCursor().ch);1793}, { value: '0xx3xx678x'});1794testVim('f,', function(cm, vim, helpers) {1795cm.setCursor(0, 6);1796helpers.doKeys('f', 'x');1797helpers.doKeys(',');1798helpers.doKeys('2', ',');1799eq(2, cm.getCursor().ch);1800}, { value: '01x3xx678x'});1801testVim('F,', function(cm, vim, helpers) {1802cm.setCursor(0, 3);1803helpers.doKeys('F', 'x');1804helpers.doKeys(',');1805helpers.doKeys('2', ',');1806eq(9, cm.getCursor().ch);1807}, { value: '01x3xx678x'});1808testVim('t,', function(cm, vim, helpers) {1809cm.setCursor(0, 6);1810helpers.doKeys('t', 'x');1811helpers.doKeys(',');1812helpers.doKeys('2', ',');1813eq(3, cm.getCursor().ch);1814}, { value: '01x3xx678x'});1815testVim('T,', function(cm, vim, helpers) {1816cm.setCursor(0, 4);1817helpers.doKeys('T', 'x');1818helpers.doKeys(',');1819helpers.doKeys('2', ',');1820eq(8, cm.getCursor().ch);1821}, { value: '01x3xx67xx'});1822testVim('fd,;', function(cm, vim, helpers) {1823cm.setCursor(0, 0);1824helpers.doKeys('f', '4');1825cm.setCursor(0, 0);1826helpers.doKeys('d', ';');1827eq('56789', cm.getValue());1828helpers.doKeys('u');1829cm.setCursor(0, 9);1830helpers.doKeys('d', ',');1831eq('01239', cm.getValue());1832}, { value: '0123456789'});1833testVim('Fd,;', function(cm, vim, helpers) {1834cm.setCursor(0, 9);1835helpers.doKeys('F', '4');1836cm.setCursor(0, 9);1837helpers.doKeys('d', ';');1838eq('01239', cm.getValue());1839helpers.doKeys('u');1840cm.setCursor(0, 0);1841helpers.doKeys('d', ',');1842eq('56789', cm.getValue());1843}, { value: '0123456789'});1844testVim('td,;', function(cm, vim, helpers) {1845cm.setCursor(0, 0);1846helpers.doKeys('t', '4');1847cm.setCursor(0, 0);1848helpers.doKeys('d', ';');1849eq('456789', cm.getValue());1850helpers.doKeys('u');1851cm.setCursor(0, 9);1852helpers.doKeys('d', ',');1853eq('012349', cm.getValue());1854}, { value: '0123456789'});1855testVim('Td,;', function(cm, vim, helpers) {1856cm.setCursor(0, 9);1857helpers.doKeys('T', '4');1858cm.setCursor(0, 9);1859helpers.doKeys('d', ';');1860eq('012349', cm.getValue());1861helpers.doKeys('u');1862cm.setCursor(0, 0);1863helpers.doKeys('d', ',');1864eq('456789', cm.getValue());1865}, { value: '0123456789'});1866testVim('fc,;', function(cm, vim, helpers) {1867cm.setCursor(0, 0);1868helpers.doKeys('f', '4');1869cm.setCursor(0, 0);1870helpers.doKeys('c', ';', 'Esc');1871eq('56789', cm.getValue());1872helpers.doKeys('u');1873cm.setCursor(0, 9);1874helpers.doKeys('c', ',');1875eq('01239', cm.getValue());1876}, { value: '0123456789'});1877testVim('Fc,;', function(cm, vim, helpers) {1878cm.setCursor(0, 9);1879helpers.doKeys('F', '4');1880cm.setCursor(0, 9);1881helpers.doKeys('c', ';', 'Esc');1882eq('01239', cm.getValue());1883helpers.doKeys('u');1884cm.setCursor(0, 0);1885helpers.doKeys('c', ',');1886eq('56789', cm.getValue());1887}, { value: '0123456789'});1888testVim('tc,;', function(cm, vim, helpers) {1889cm.setCursor(0, 0);1890helpers.doKeys('t', '4');1891cm.setCursor(0, 0);1892helpers.doKeys('c', ';', 'Esc');1893eq('456789', cm.getValue());1894helpers.doKeys('u');1895cm.setCursor(0, 9);1896helpers.doKeys('c', ',');1897eq('012349', cm.getValue());1898}, { value: '0123456789'});1899testVim('Tc,;', function(cm, vim, helpers) {1900cm.setCursor(0, 9);1901helpers.doKeys('T', '4');1902cm.setCursor(0, 9);1903helpers.doKeys('c', ';', 'Esc');1904eq('012349', cm.getValue());1905helpers.doKeys('u');1906cm.setCursor(0, 0);1907helpers.doKeys('c', ',');1908eq('456789', cm.getValue());1909}, { value: '0123456789'});1910testVim('fy,;', function(cm, vim, helpers) {1911cm.setCursor(0, 0);1912helpers.doKeys('f', '4');1913cm.setCursor(0, 0);1914helpers.doKeys('y', ';', 'P');1915eq('012340123456789', cm.getValue());1916helpers.doKeys('u');1917cm.setCursor(0, 9);1918helpers.doKeys('y', ',', 'P');1919eq('012345678456789', cm.getValue());1920}, { value: '0123456789'});1921testVim('Fy,;', function(cm, vim, helpers) {1922cm.setCursor(0, 9);1923helpers.doKeys('F', '4');1924cm.setCursor(0, 9);1925helpers.doKeys('y', ';', 'p');1926eq('012345678945678', cm.getValue());1927helpers.doKeys('u');1928cm.setCursor(0, 0);1929helpers.doKeys('y', ',', 'P');1930eq('012340123456789', cm.getValue());1931}, { value: '0123456789'});1932testVim('ty,;', function(cm, vim, helpers) {1933cm.setCursor(0, 0);1934helpers.doKeys('t', '4');1935cm.setCursor(0, 0);1936helpers.doKeys('y', ';', 'P');1937eq('01230123456789', cm.getValue());1938helpers.doKeys('u');1939cm.setCursor(0, 9);1940helpers.doKeys('y', ',', 'p');1941eq('01234567895678', cm.getValue());1942}, { value: '0123456789'});1943testVim('Ty,;', function(cm, vim, helpers) {1944cm.setCursor(0, 9);1945helpers.doKeys('T', '4');1946cm.setCursor(0, 9);1947helpers.doKeys('y', ';', 'p');1948eq('01234567895678', cm.getValue());1949helpers.doKeys('u');1950cm.setCursor(0, 0);1951helpers.doKeys('y', ',', 'P');1952eq('01230123456789', cm.getValue());1953}, { value: '0123456789'});1954testVim('HML', function(cm, vim, helpers) {1955var lines = 35;1956var textHeight = cm.defaultTextHeight();1957cm.setSize(600, lines*textHeight);1958cm.setCursor(120, 0);1959helpers.doKeys('H');1960helpers.assertCursorAt(86, 2);1961helpers.doKeys('L');1962helpers.assertCursorAt(120, 4);1963helpers.doKeys('M');1964helpers.assertCursorAt(103,4);1965}, { value: (function(){1966var lines = new Array(100);1967var upper = ' xx\n';1968var lower = ' xx\n';1969upper = lines.join(upper);1970lower = lines.join(lower);1971return upper + lower;1972})()});19731974var zVals = ['zb','zz','zt','z-','z.','z<CR>'].map(function(e, idx){1975var lineNum = 250;1976var lines = 35;1977testVim(e, function(cm, vim, helpers) {1978var k1 = e[0];1979var k2 = e.substring(1);1980var textHeight = cm.defaultTextHeight();1981cm.setSize(600, lines*textHeight);1982cm.setCursor(lineNum, 0);1983helpers.doKeys(k1, k2);1984zVals[idx] = cm.getScrollInfo().top;1985}, { value: (function(){1986return new Array(500).join('\n');1987})()});1988});1989testVim('zb<zz', function(cm, vim, helpers){1990eq(zVals[0]<zVals[1], true);1991});1992testVim('zz<zt', function(cm, vim, helpers){1993eq(zVals[1]<zVals[2], true);1994});1995testVim('zb==z-', function(cm, vim, helpers){1996eq(zVals[0], zVals[3]);1997});1998testVim('zz==z.', function(cm, vim, helpers){1999eq(zVals[1], zVals[4]);2000});2001testVim('zt==z<CR>', function(cm, vim, helpers){2002eq(zVals[2], zVals[5]);2003});20042005var scrollMotionSandbox =2006'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'2007'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'2008'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'2009'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n';2010testVim('scrollMotion', function(cm, vim, helpers){2011var prevCursor, prevScrollInfo;2012cm.setCursor(0, 0);2013// ctrl-y at the top of the file should have no effect.2014helpers.doKeys('<C-y>');2015eq(0, cm.getCursor().line);2016prevScrollInfo = cm.getScrollInfo();2017helpers.doKeys('<C-e>');2018eq(1, cm.getCursor().line);2019eq(true, prevScrollInfo.top < cm.getScrollInfo().top);2020// Jump to the end of the sandbox.2021cm.setCursor(1000, 0);2022prevCursor = cm.getCursor();2023// ctrl-e at the bottom of the file should have no effect.2024helpers.doKeys('<C-e>');2025eq(prevCursor.line, cm.getCursor().line);2026prevScrollInfo = cm.getScrollInfo();2027helpers.doKeys('<C-y>');2028eq(prevCursor.line - 1, cm.getCursor().line);2029eq(true, prevScrollInfo.top > cm.getScrollInfo().top);2030}, { value: scrollMotionSandbox});20312032var squareBracketMotionSandbox = ''+2033'({\n'+//02034' ({\n'+//112035' /*comment {\n'+//22036' */(\n'+//32037'#else \n'+//42038' /* )\n'+//52039'#if }\n'+//62040' )}*/\n'+//72041')}\n'+//82042'{}\n'+//92043'#else {{\n'+//102044'{}\n'+//112045'}\n'+//122046'{\n'+//132047'#endif\n'+//142048'}\n'+//152049'}\n'+//162050'#else';//172051testVim('[[, ]]', function(cm, vim, helpers) {2052cm.setCursor(0, 0);2053helpers.doKeys(']', ']');2054helpers.assertCursorAt(9,0);2055helpers.doKeys('2', ']', ']');2056helpers.assertCursorAt(13,0);2057helpers.doKeys(']', ']');2058helpers.assertCursorAt(17,0);2059helpers.doKeys('[', '[');2060helpers.assertCursorAt(13,0);2061helpers.doKeys('2', '[', '[');2062helpers.assertCursorAt(9,0);2063helpers.doKeys('[', '[');2064helpers.assertCursorAt(0,0);2065}, { value: squareBracketMotionSandbox});2066testVim('[], ][', function(cm, vim, helpers) {2067cm.setCursor(0, 0);2068helpers.doKeys(']', '[');2069helpers.assertCursorAt(12,0);2070helpers.doKeys('2', ']', '[');2071helpers.assertCursorAt(16,0);2072helpers.doKeys(']', '[');2073helpers.assertCursorAt(17,0);2074helpers.doKeys('[', ']');2075helpers.assertCursorAt(16,0);2076helpers.doKeys('2', '[', ']');2077helpers.assertCursorAt(12,0);2078helpers.doKeys('[', ']');2079helpers.assertCursorAt(0,0);2080}, { value: squareBracketMotionSandbox});2081testVim('[{, ]}', function(cm, vim, helpers) {2082cm.setCursor(4, 10);2083helpers.doKeys('[', '{');2084helpers.assertCursorAt(2,12);2085helpers.doKeys('2', '[', '{');2086helpers.assertCursorAt(0,1);2087cm.setCursor(4, 10);2088helpers.doKeys(']', '}');2089helpers.assertCursorAt(6,11);2090helpers.doKeys('2', ']', '}');2091helpers.assertCursorAt(8,1);2092cm.setCursor(0,1);2093helpers.doKeys(']', '}');2094helpers.assertCursorAt(8,1);2095helpers.doKeys('[', '{');2096helpers.assertCursorAt(0,1);2097}, { value: squareBracketMotionSandbox});2098testVim('[(, ])', function(cm, vim, helpers) {2099cm.setCursor(4, 10);2100helpers.doKeys('[', '(');2101helpers.assertCursorAt(3,14);2102helpers.doKeys('2', '[', '(');2103helpers.assertCursorAt(0,0);2104cm.setCursor(4, 10);2105helpers.doKeys(']', ')');2106helpers.assertCursorAt(5,11);2107helpers.doKeys('2', ']', ')');2108helpers.assertCursorAt(8,0);2109helpers.doKeys('[', '(');2110helpers.assertCursorAt(0,0);2111helpers.doKeys(']', ')');2112helpers.assertCursorAt(8,0);2113}, { value: squareBracketMotionSandbox});2114testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) {2115forEach(['*', '/'], function(key){2116cm.setCursor(7, 0);2117helpers.doKeys('2', '[', key);2118helpers.assertCursorAt(2,2);2119helpers.doKeys('2', ']', key);2120helpers.assertCursorAt(7,5);2121});2122}, { value: squareBracketMotionSandbox});2123testVim('[#, ]#', function(cm, vim, helpers) {2124cm.setCursor(10, 3);2125helpers.doKeys('2', '[', '#');2126helpers.assertCursorAt(4,0);2127helpers.doKeys('5', ']', '#');2128helpers.assertCursorAt(17,0);2129cm.setCursor(10, 3);2130helpers.doKeys(']', '#');2131helpers.assertCursorAt(14,0);2132}, { value: squareBracketMotionSandbox});2133testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) {2134cm.setCursor(11, 0);2135helpers.doKeys('[', 'm');2136helpers.assertCursorAt(10,7);2137helpers.doKeys('4', '[', 'm');2138helpers.assertCursorAt(1,3);2139helpers.doKeys('5', ']', 'm');2140helpers.assertCursorAt(11,0);2141helpers.doKeys('[', 'M');2142helpers.assertCursorAt(9,1);2143helpers.doKeys('3', ']', 'M');2144helpers.assertCursorAt(15,0);2145helpers.doKeys('5', '[', 'M');2146helpers.assertCursorAt(7,3);2147}, { value: squareBracketMotionSandbox});21482149// Ex mode tests2150testVim('ex_go_to_line', function(cm, vim, helpers) {2151cm.setCursor(0, 0);2152helpers.doEx('4');2153helpers.assertCursorAt(3, 0);2154}, { value: 'a\nb\nc\nd\ne\n'});2155testVim('ex_write', function(cm, vim, helpers) {2156var tmp = CodeMirror.commands.save;2157var written;2158var actualCm;2159CodeMirror.commands.save = function(cm) {2160written = true;2161actualCm = cm;2162};2163// Test that w, wr, wri ... write all trigger :write.2164var command = 'write';2165for (var i = 1; i < command.length; i++) {2166written = false;2167actualCm = null;2168helpers.doEx(command.substring(0, i));2169eq(written, true);2170eq(actualCm, cm);2171}2172CodeMirror.commands.save = tmp;2173});2174testVim('ex_sort', function(cm, vim, helpers) {2175helpers.doEx('sort');2176eq('Z\na\nb\nc\nd', cm.getValue());2177}, { value: 'b\nZ\nd\nc\na'});2178testVim('ex_sort_reverse', function(cm, vim, helpers) {2179helpers.doEx('sort!');2180eq('d\nc\nb\na', cm.getValue());2181}, { value: 'b\nd\nc\na'});2182testVim('ex_sort_range', function(cm, vim, helpers) {2183helpers.doEx('2,3sort');2184eq('b\nc\nd\na', cm.getValue());2185}, { value: 'b\nd\nc\na'});2186testVim('ex_sort_oneline', function(cm, vim, helpers) {2187helpers.doEx('2sort');2188// Expect no change.2189eq('b\nd\nc\na', cm.getValue());2190}, { value: 'b\nd\nc\na'});2191testVim('ex_sort_ignoreCase', function(cm, vim, helpers) {2192helpers.doEx('sort i');2193eq('a\nb\nc\nd\nZ', cm.getValue());2194}, { value: 'b\nZ\nd\nc\na'});2195testVim('ex_sort_unique', function(cm, vim, helpers) {2196helpers.doEx('sort u');2197eq('Z\na\nb\nc\nd', cm.getValue());2198}, { value: 'b\nZ\na\na\nd\na\nc\na'});2199testVim('ex_sort_decimal', function(cm, vim, helpers) {2200helpers.doEx('sort d');2201eq('d3\n s5\n6\n.9', cm.getValue());2202}, { value: '6\nd3\n s5\n.9'});2203testVim('ex_sort_decimal_negative', function(cm, vim, helpers) {2204helpers.doEx('sort d');2205eq('z-9\nd3\n s5\n6\n.9', cm.getValue());2206}, { value: '6\nd3\n s5\n.9\nz-9'});2207testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) {2208helpers.doEx('sort! d');2209eq('.9\n6\n s5\nd3', cm.getValue());2210}, { value: '6\nd3\n s5\n.9'});2211testVim('ex_sort_hex', function(cm, vim, helpers) {2212helpers.doEx('sort x');2213eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue());2214}, { value: '6\nd3\n s5\n&0xB\n.9'});2215testVim('ex_sort_octal', function(cm, vim, helpers) {2216helpers.doEx('sort o');2217eq('.8\n.9\nd3\n s5\n6', cm.getValue());2218}, { value: '6\nd3\n s5\n.9\n.8'});2219testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) {2220helpers.doEx('sort d');2221eq('y\nz\nc1\nb2\na3', cm.getValue());2222}, { value: 'a3\nz\nc1\ny\nb2'});2223testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) {2224helpers.doEx('sort! d');2225eq('a3\nb2\nc1\nz\ny', cm.getValue());2226}, { value: 'a3\nz\nc1\ny\nb2'});2227testVim('ex_substitute_same_line', function(cm, vim, helpers) {2228cm.setCursor(1, 0);2229helpers.doEx('s/one/two');2230eq('one one\n two two', cm.getValue());2231}, { value: 'one one\n one one'});2232testVim('ex_substitute_global', function(cm, vim, helpers) {2233cm.setCursor(1, 0);2234helpers.doEx('%s/one/two');2235eq('two two\n two two', cm.getValue());2236}, { value: 'one one\n one one'});2237testVim('ex_substitute_input_range', function(cm, vim, helpers) {2238cm.setCursor(1, 0);2239helpers.doEx('1,3s/\\d/0');2240eq('0\n0\n0\n4', cm.getValue());2241}, { value: '1\n2\n3\n4' });2242testVim('ex_substitute_visual_range', function(cm, vim, helpers) {2243cm.setCursor(1, 0);2244// Set last visual mode selection marks '< and '> at lines 2 and 42245helpers.doKeys('V', '2', 'j', 'v');2246helpers.doEx('\'<,\'>s/\\d/0');2247eq('1\n0\n0\n0\n5', cm.getValue());2248}, { value: '1\n2\n3\n4\n5' });2249testVim('ex_substitute_capture', function(cm, vim, helpers) {2250cm.setCursor(1, 0);2251helpers.doEx('s/(\\d+)/$1$1/')2252eq('a1111 a1212 a1313', cm.getValue());2253}, { value: 'a11 a12 a13' });2254testVim('ex_substitute_empty_query', function(cm, vim, helpers) {2255// If the query is empty, use last query.2256cm.setCursor(1, 0);2257cm.openDialog = helpers.fakeOpenDialog('1');2258helpers.doKeys('/');2259helpers.doEx('s//b');2260eq('abb ab2 ab3', cm.getValue());2261}, { value: 'a11 a12 a13' });2262testVim('ex_substitute_count', function(cm, vim, helpers) {2263cm.setCursor(1, 0);2264helpers.doEx('s/\\d/0/i 2');2265eq('1\n0\n0\n4', cm.getValue());2266}, { value: '1\n2\n3\n4' });2267testVim('ex_substitute_count_with_range', function(cm, vim, helpers) {2268cm.setCursor(1, 0);2269helpers.doEx('1,3s/\\d/0/ 3');2270eq('1\n2\n0\n0', cm.getValue());2271}, { value: '1\n2\n3\n4' });2272function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) {2273testVim(name, function(cm, vim, helpers) {2274var savedOpenDialog = cm.openDialog;2275var savedKeyName = CodeMirror.keyName;2276var onKeyDown;2277var recordedCallback;2278var closed = true; // Start out closed, set false on second openDialog.2279function close() {2280closed = true;2281}2282// First openDialog should save callback.2283cm.openDialog = function(template, callback, options) {2284recordedCallback = callback;2285}2286// Do first openDialog.2287helpers.doKeys(':');2288// Second openDialog should save keyDown handler.2289cm.openDialog = function(template, callback, options) {2290onKeyDown = options.onKeyDown;2291closed = false;2292};2293// Return the command to Vim and trigger second openDialog.2294recordedCallback(command);2295// The event should really use keyCode, but here just mock it out and use2296// key and replace keyName to just return key.2297CodeMirror.keyName = function (e) { return e.key; }2298keys = keys.toUpperCase();2299for (var i = 0; i < keys.length; i++) {2300is(!closed);2301onKeyDown({ key: keys.charAt(i) }, '', close);2302}2303try {2304eq(expectedValue, cm.getValue());2305helpers.assertCursorAt(finalPos);2306is(closed);2307} catch(e) {2308throw e2309} finally {2310// Restore overriden functions.2311CodeMirror.keyName = savedKeyName;2312cm.openDialog = savedOpenDialog;2313}2314}, { value: initialValue });2315};2316testSubstituteConfirm('ex_substitute_confirm_emptydoc',2317'%s/x/b/c', '', '', '', makeCursor(0, 0));2318testSubstituteConfirm('ex_substitute_confirm_nomatch',2319'%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0));2320testSubstituteConfirm('ex_substitute_confirm_accept',2321'%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1));2322testSubstituteConfirm('ex_substitute_confirm_random_keys',2323'%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1));2324testSubstituteConfirm('ex_substitute_confirm_some',2325'%s/a/b/c', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1));2326testSubstituteConfirm('ex_substitute_confirm_all',2327'%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1));2328testSubstituteConfirm('ex_substitute_confirm_accept_then_all',2329'%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1));2330testSubstituteConfirm('ex_substitute_confirm_quit',2331'%s/a/b/c', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3));2332testSubstituteConfirm('ex_substitute_confirm_last',2333'%s/a/b/c', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));2334testSubstituteConfirm('ex_substitute_confirm_oneline',2335'1s/a/b/c', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));2336testSubstituteConfirm('ex_substitute_confirm_range_accept',2337'1,2s/a/b/c', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0));2338testSubstituteConfirm('ex_substitute_confirm_range_some',2339'1,3s/a/b/c', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0));2340testSubstituteConfirm('ex_substitute_confirm_range_all',2341'1,3s/a/b/c', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0));2342testSubstituteConfirm('ex_substitute_confirm_range_last',2343'1,3s/a/b/c', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0));2344//:noh should clear highlighting of search-results but allow to resume search through n2345testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) {2346cm.openDialog = helpers.fakeOpenDialog('match');2347helpers.doKeys('?');2348helpers.doEx('noh');2349eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared');2350helpers.doKeys('n');2351helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting');2352}, { value: 'match nope match \n nope Match' });2353// TODO: Reset key maps after each test.2354testVim('ex_map_key2key', function(cm, vim, helpers) {2355helpers.doEx('map a x');2356helpers.doKeys('a');2357helpers.assertCursorAt(0, 0);2358eq('bc', cm.getValue());2359}, { value: 'abc' });2360testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) {2361helpers.doEx('map ; :');2362var dialogOpened = false;2363cm.openDialog = function() {2364dialogOpened = true;2365}2366helpers.doKeys(';');2367eq(dialogOpened, true);2368});2369testVim('ex_map_ex2key:', function(cm, vim, helpers) {2370helpers.doEx('map :del x');2371helpers.doEx('del');2372helpers.assertCursorAt(0, 0);2373eq('bc', cm.getValue());2374}, { value: 'abc' });2375testVim('ex_map_ex2ex', function(cm, vim, helpers) {2376helpers.doEx('map :del :w');2377var tmp = CodeMirror.commands.save;2378var written = false;2379var actualCm;2380CodeMirror.commands.save = function(cm) {2381written = true;2382actualCm = cm;2383};2384helpers.doEx('del');2385CodeMirror.commands.save = tmp;2386eq(written, true);2387eq(actualCm, cm);2388});2389testVim('ex_map_key2ex', function(cm, vim, helpers) {2390helpers.doEx('map a :w');2391var tmp = CodeMirror.commands.save;2392var written = false;2393var actualCm;2394CodeMirror.commands.save = function(cm) {2395written = true;2396actualCm = cm;2397};2398helpers.doKeys('a');2399CodeMirror.commands.save = tmp;2400eq(written, true);2401eq(actualCm, cm);2402});2403testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) {2404CodeMirror.Vim.map('b', ':w', 'visual');2405var tmp = CodeMirror.commands.save;2406var written = false;2407var actualCm;2408CodeMirror.commands.save = function(cm) {2409written = true;2410actualCm = cm;2411};2412// Mapping should not work in normal mode.2413helpers.doKeys('b');2414eq(written, false);2415// Mapping should work in visual mode.2416helpers.doKeys('v', 'b');2417eq(written, true);2418eq(actualCm, cm);24192420CodeMirror.commands.save = tmp;2421});24222423// Testing registration of functions as ex-commands and mapping to <Key>-keys2424testVim('ex_api_test', function(cm, vim, helpers) {2425var res=false;2426var val='from';2427CodeMirror.Vim.defineEx('extest','ext',function(cm,params){2428if(params.args)val=params.args[0];2429else res=true;2430});2431helpers.doEx(':ext to');2432eq(val,'to','Defining ex-command failed');2433CodeMirror.Vim.map('<C-CR><Space>',':ext');2434helpers.doKeys('<C-CR>','<Space>');2435is(res,'Mapping to key failed');2436});2437// For now, this test needs to be last because it messes up : for future tests.2438testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) {2439helpers.doEx('map : x');2440helpers.doKeys(':');2441helpers.assertCursorAt(0, 0);2442eq('bc', cm.getValue());2443}, { value: 'abc' });244424452446