4 'aopop pop 0 1 2 3 4\n' +
6 'int getchar(void) {\n' +
7 ' static char buf[BUFSIZ];\n' +
8 ' static char *bufp = buf;\n' +
9 ' if (n == 0) { /* buffer is empty */\n' +
10 ' n = read(0, buf, sizeof buf);\n' +
14 ' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' +
18 var lines = (function() {
19 lineText = code.split('\n');
21 for (var i = 0; i < lineText.length; i++) {
24 length: lineText[i].length,
25 lineText: lineText[i],
26 textStart: /^\s*/.exec(lineText[i])[0].length
31 var endOfDocument = makeCursor(lines.length - 1,
32 lines[lines.length - 1].length);
33 var wordLine = lines[0];
34 var bigWordLine = lines[1];
35 var charLine = lines[2];
36 var bracesLine = lines[3];
37 var seekBraceLine = lines[4];
40 start: { line: wordLine.line, ch: 1 },
41 end: { line: wordLine.line, ch: 5 }
44 start: { line: wordLine.line, ch: word1.end.ch + 2 },
45 end: { line: wordLine.line, ch: word1.end.ch + 4 }
48 start: { line: bigWordLine.line, ch: 1 },
49 end: { line: bigWordLine.line, ch: 5 }
54 start: { line: bigWordLine.line, ch: 1 },
55 end: { line: bigWordLine.line, ch: 7 }
58 start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 },
59 end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 }
62 var oChars = [ { line: charLine.line, ch: 1 },
63 { line: charLine.line, ch: 3 },
64 { line: charLine.line, ch: 7 } ];
65 var pChars = [ { line: charLine.line, ch: 2 },
66 { line: charLine.line, ch: 4 },
67 { line: charLine.line, ch: 6 },
68 { line: charLine.line, ch: 8 } ];
69 var numChars = [ { line: charLine.line, ch: 10 },
70 { line: charLine.line, ch: 12 },
71 { line: charLine.line, ch: 14 },
72 { line: charLine.line, ch: 16 },
73 { line: charLine.line, ch: 18 }];
75 start: { line: bracesLine.line, ch: 1 },
76 end: { line: bracesLine.line, ch: 3 }
79 start: { line: bracesLine.line, ch: 5 },
80 end: { line: bracesLine.line, ch: 7 }
83 start: { line: bracesLine.line, ch: 9 },
84 end: { line: bracesLine.line, ch: 11 }
87 start: { line: seekBraceLine.line, ch: 1 },
88 end: { line: seekBraceLine.line, ch: 16 }
91 start: { line: seekBraceLine.line, ch: 14 },
92 end: { line: seekBraceLine.line, ch: 11 }
95 function copyCursor(cur) {
96 return { ch: cur.ch, line: cur.line };
99 function testVim(name, run, opts, expectedFail) {
103 showCursorWhenSelecting: true,
106 for (var prop in opts) {
107 if (opts.hasOwnProperty(prop)) {
108 vimOpts[prop] = opts[prop];
111 return test('vim_' + name, function() {
112 var place = document.getElementById("testground");
113 var cm = CodeMirror(place, vimOpts);
114 var vim = CodeMirror.Vim.maybeInitVimState_(cm);
116 function doKeysFn(cm) {
117 return function(args) {
118 if (args instanceof Array) {
121 for (var i = 0; i < arguments.length; i++) {
122 CodeMirror.Vim.handleKey(cm, arguments[i]);
126 function doInsertModeKeysFn(cm) {
127 return function(args) {
128 if (args instanceof Array) { arguments = args; }
129 function executeHandler(handler) {
130 if (typeof handler == 'string') {
131 CodeMirror.commands[handler](cm);
137 for (var i = 0; i < arguments.length; i++) {
138 var key = arguments[i];
139 // Find key in keymap and handle.
140 var handled = CodeMirror.lookupKey(key, ['vim-insert'], executeHandler);
141 // Record for insert mode.
142 if (handled === true && cm.state.vim.insertMode && arguments[i] != 'Esc') {
143 var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;
145 lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));
151 function doExFn(cm) {
152 return function(command) {
153 cm.openDialog = helpers.fakeOpenDialog(command);
157 function assertCursorAtFn(cm) {
158 return function(line, ch) {
160 if (ch == null && typeof line.line == 'number') {
163 pos = makeCursor(line, ch);
165 eqPos(pos, cm.getCursor());
168 function fakeOpenDialog(result) {
169 return function(text, callback) {
170 return callback(result);
174 doKeys: doKeysFn(cm),
175 // Warning: Only emulates keymap events, not character insertions. Use
176 // replaceRange to simulate character insertions.
177 // Keys are in CodeMirror format, NOT vim format.
178 doInsertModeKeys: doInsertModeKeysFn(cm),
180 assertCursorAt: assertCursorAtFn(cm),
181 fakeOpenDialog: fakeOpenDialog,
182 getRegisterController: function() {
183 return CodeMirror.Vim.getRegisterController();
186 CodeMirror.Vim.resetVimGlobalState_();
187 var successful = false;
189 run(cm, vim, helpers);
192 if ((debug && !successful) || verbose) {
193 place.style.visibility = "visible";
195 place.removeChild(cm.getWrapperElement());
200 testVim('qq@q', function(cm, vim, helpers) {
202 helpers.doKeys('q', 'q', 'l', 'l', 'q');
203 helpers.assertCursorAt(0,2);
204 helpers.doKeys('@', 'q');
205 helpers.assertCursorAt(0,4);
207 testVim('@@', function(cm, vim, helpers) {
209 helpers.doKeys('q', 'q', 'l', 'l', 'q');
210 helpers.assertCursorAt(0,2);
211 helpers.doKeys('@', 'q');
212 helpers.assertCursorAt(0,4);
213 helpers.doKeys('@', '@');
214 helpers.assertCursorAt(0,6);
216 var jumplistScene = ''+
226 function testJumplist(name, keys, endPos, startPos, dialog) {
227 endPos = makeCursor(endPos[0], endPos[1]);
228 startPos = makeCursor(startPos[0], startPos[1]);
229 testVim(name, function(cm, vim, helpers) {
230 CodeMirror.Vim.resetVimGlobalState_();
231 if(dialog)cm.openDialog = helpers.fakeOpenDialog('word');
232 cm.setCursor(startPos);
233 helpers.doKeys.apply(null, keys);
234 helpers.assertCursorAt(endPos);
235 }, {value: jumplistScene});
237 testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]);
238 testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]);
239 testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]);
240 testJumplist('jumplist_[[', ['[', '[', '<C-o>'], [5,2], [5,2]);
241 testJumplist('jumplist_]]', [']', ']', '<C-o>'], [2,2], [2,2]);
242 testJumplist('jumplist_G', ['G', '<C-o>'], [5,2], [5,2]);
243 testJumplist('jumplist_gg', ['g', 'g', '<C-o>'], [5,2], [5,2]);
244 testJumplist('jumplist_%', ['%', '<C-o>'], [1,5], [1,5]);
245 testJumplist('jumplist_{', ['{', '<C-o>'], [1,5], [1,5]);
246 testJumplist('jumplist_}', ['}', '<C-o>'], [1,5], [1,5]);
247 testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', '<C-i>'], [1,5], [1,5]);
248 testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', '<C-i>'], [1,5], [1,5]);
249 testJumplist('jumplist_*_cachedCursor', ['*', '<C-o>'], [1,3], [1,3]);
250 testJumplist('jumplist_#_cachedCursor', ['#', '<C-o>'], [1,3], [1,3]);
251 testJumplist('jumplist_n', ['#', 'n', '<C-o>'], [1,1], [2,3]);
252 testJumplist('jumplist_N', ['#', 'N', '<C-o>'], [1,1], [2,3]);
253 testJumplist('jumplist_repeat_<c-o>', ['*', '*', '*', '3', '<C-o>'], [2,3], [2,3]);
254 testJumplist('jumplist_repeat_<c-i>', ['*', '*', '*', '3', '<C-o>', '2', '<C-i>'], [5,0], [2,3]);
255 testJumplist('jumplist_repeated_motion', ['3', '*', '<C-o>'], [2,3], [2,3]);
256 testJumplist('jumplist_/', ['/', '<C-o>'], [2,3], [2,3], 'dialog');
257 testJumplist('jumplist_?', ['?', '<C-o>'], [2,3], [2,3], 'dialog');
258 testJumplist('jumplist_skip_delted_mark<c-o>',
259 ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-o>', '<C-o>'],
261 testJumplist('jumplist_skip_delted_mark<c-i>',
262 ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-i>', '<C-i>'],
265 * @param name Name of the test
266 * @param keys An array of keys or a string with a single key to simulate.
267 * @param endPos The expected end position of the cursor.
268 * @param startPos The position the cursor should start at, defaults to 0, 0.
270 function testMotion(name, keys, endPos, startPos) {
271 testVim(name, function(cm, vim, helpers) {
273 startPos = { line: 0, ch: 0 };
275 cm.setCursor(startPos);
276 helpers.doKeys(keys);
277 helpers.assertCursorAt(endPos);
281 function makeCursor(line, ch) {
282 return { line: line, ch: ch };
285 function offsetCursor(cur, offsetLine, offsetCh) {
286 return { line: cur.line + offsetLine, ch: cur.ch + offsetCh };
290 testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4));
291 testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4));
292 testMotion('h', 'h', makeCursor(0, 0), word1.start);
293 testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end);
294 testMotion('l', 'l', makeCursor(0, 1));
295 testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2));
296 testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end);
297 testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end);
298 testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument);
299 testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end);
300 testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4));
301 testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4));
302 testMotion('w', 'w', word1.start);
303 testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2));
304 testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51));
305 testMotion('w_repeat', ['2', 'w'], word2.start);
306 testMotion('w_wrap', ['w'], word3.start, word2.start);
307 testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument);
308 testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0));
309 testMotion('W', 'W', bigWord1.start);
310 testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start);
311 testMotion('e', 'e', word1.end);
312 testMotion('e_repeat', ['2', 'e'], word2.end);
313 testMotion('e_wrap', 'e', word3.end, word2.end);
314 testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument);
315 testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0));
316 testMotion('b', 'b', word3.start, word3.end);
317 testMotion('b_repeat', ['2', 'b'], word2.start, word3.end);
318 testMotion('b_wrap', 'b', word2.start, word3.start);
319 testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0));
320 testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument);
321 testMotion('ge', ['g', 'e'], word2.end, word3.end);
322 testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start);
323 testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start);
324 testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0),
326 testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument);
327 testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart),
329 testMotion('gg_repeat', ['3', 'g', 'g'],
330 makeCursor(lines[2].line, lines[2].textStart));
332 makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart),
334 testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line,
335 lines[2].textStart));
336 // TODO: Make the test code long enough to test Ctrl-F and Ctrl-B.
337 testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8));
338 testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8));
339 testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8));
340 testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4));
341 testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8));
342 testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1));
343 testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1),
345 testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0));
346 testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]);
347 testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0));
348 testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1),
349 makeCursor(charLine.line, 0));
350 testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1),
352 testMotion('F', ['F', 'p'], pChars[0], pChars[1]);
353 testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]);
354 testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]);
355 testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]);
356 testMotion('%_parens', ['%'], parens1.end, parens1.start);
357 testMotion('%_squares', ['%'], squares1.end, squares1.start);
358 testMotion('%_braces', ['%'], curlys1.end, curlys1.start);
359 testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start);
360 testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start);
361 testVim('%_seek_skip', function(cm, vim, helpers) {
363 helpers.doKeys(['%']);
364 helpers.assertCursorAt(0,9);
365 }, {value:'01234"("()'});
366 testVim('%_skip_string', function(cm, vim, helpers) {
368 helpers.doKeys(['%']);
369 helpers.assertCursorAt(0,4);
371 helpers.doKeys(['%']);
372 helpers.assertCursorAt(0,0);
375 testVim('%_skip_comment', function(cm, vim, helpers) {
377 helpers.doKeys(['%']);
378 helpers.assertCursorAt(0,6);
380 helpers.doKeys(['%']);
381 helpers.assertCursorAt(0,0);
382 }, {value:'(/*)*/)'});
383 // Make sure that moving down after going to the end of a line always leaves you
384 // at the end of a line, but preserves the offset in other cases
385 testVim('Changing lines after Eol operation', function(cm, vim, helpers) {
387 helpers.doKeys(['$']);
388 helpers.doKeys(['j']);
389 // After moving to Eol and then down, we should be at Eol of line 2
390 helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 });
391 helpers.doKeys(['j']);
392 // After moving down, we should be at Eol of line 3
393 helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 });
394 helpers.doKeys(['h']);
395 helpers.doKeys(['j']);
396 // After moving back one space and then down, since line 4 is shorter than line 2, we should
397 // be at Eol of line 2 - 1
398 helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 });
399 helpers.doKeys(['j']);
400 helpers.doKeys(['j']);
401 // After moving down again, since line 3 has enough characters, we should be back to the
402 // same place we were at on line 1
403 helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 });
405 //making sure gj and gk recover from clipping
406 testVim('gj_gk_clipping', function(cm,vim,helpers){
408 helpers.doKeys('g','j','g','j');
409 helpers.assertCursorAt(2, 1);
410 helpers.doKeys('g','k','g','k');
411 helpers.assertCursorAt(0, 1);
412 },{value: 'line 1\n\nline 2'});
413 //testing a mix of j/k and gj/gk
414 testVim('j_k_and_gj_gk', function(cm,vim,helpers){
417 //go to the last character on the first line
419 //move up/down on the column within the wrapped line
420 //side-effect: cursor is not locked to eol anymore
421 helpers.doKeys('g','k');
422 var cur=cm.getCursor();
424 is((cur.ch<176),'gk didn\'t move cursor back (1)');
425 helpers.doKeys('g','j');
426 helpers.assertCursorAt(0, 176);
427 //should move to character 177 on line 2 (j/k preserve character index within line)
429 //due to different line wrapping, the cursor can be on a different screen-x now
430 //gj and gk preserve screen-x on movement, much like moveV
431 helpers.doKeys('3','g','k');
434 is((cur.ch<176),'gk didn\'t move cursor back (2)');
435 helpers.doKeys('g','j','2','g','j');
436 //should return to the same character-index
438 helpers.assertCursorAt(0, 176);
439 },{ 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.'});
440 testVim('gj_gk', function(cm, vim, helpers) {
443 // Test top of document edge case.
445 helpers.doKeys('g', 'j');
446 helpers.doKeys('10', 'g', 'k');
447 helpers.assertCursorAt(0, 4);
449 // Test moving down preserves column position.
450 helpers.doKeys('g', 'j');
451 var pos1 = cm.getCursor();
452 var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4};
453 helpers.doKeys('g', 'j');
454 helpers.assertCursorAt(expectedPos2);
456 // Move to the last character
458 // Move left to reset HSPos
460 // Test bottom of document edge case.
461 helpers.doKeys('100', 'g', 'j');
462 var endingPos = cm.getCursor();
463 is(endingPos != 0, 'gj should not be on wrapped line 0');
464 var topLeftCharCoords = cm.charCoords(makeCursor(0, 0));
465 var endingCharCoords = cm.charCoords(endingPos);
466 is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0');
467 },{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' });
468 testVim('}', function(cm, vim, helpers) {
471 helpers.assertCursorAt(1, 0);
473 helpers.doKeys('2', '}');
474 helpers.assertCursorAt(4, 0);
476 helpers.doKeys('6', '}');
477 helpers.assertCursorAt(5, 0);
478 }, { value: 'a\n\nb\nc\n\nd' });
479 testVim('{', function(cm, vim, helpers) {
482 helpers.assertCursorAt(4, 0);
484 helpers.doKeys('2', '{');
485 helpers.assertCursorAt(1, 0);
487 helpers.doKeys('6', '{');
488 helpers.assertCursorAt(0, 0);
489 }, { value: 'a\n\nb\nc\n\nd' });
492 testVim('dl', function(cm, vim, helpers) {
493 var curStart = makeCursor(0, 0);
494 cm.setCursor(curStart);
495 helpers.doKeys('d', 'l');
496 eq('word1 ', cm.getValue());
497 var register = helpers.getRegisterController().getRegister();
498 eq(' ', register.text);
499 is(!register.linewise);
500 eqPos(curStart, cm.getCursor());
501 }, { value: ' word1 ' });
502 testVim('dl_eol', function(cm, vim, helpers) {
504 helpers.doKeys('d', 'l');
505 eq(' word1', cm.getValue());
506 var register = helpers.getRegisterController().getRegister();
507 eq(' ', register.text);
508 is(!register.linewise);
509 helpers.assertCursorAt(0, 5);
510 }, { value: ' word1 ' });
511 testVim('dl_repeat', function(cm, vim, helpers) {
512 var curStart = makeCursor(0, 0);
513 cm.setCursor(curStart);
514 helpers.doKeys('2', 'd', 'l');
515 eq('ord1 ', cm.getValue());
516 var register = helpers.getRegisterController().getRegister();
517 eq(' w', register.text);
518 is(!register.linewise);
519 eqPos(curStart, cm.getCursor());
520 }, { value: ' word1 ' });
521 testVim('dh', function(cm, vim, helpers) {
522 var curStart = makeCursor(0, 3);
523 cm.setCursor(curStart);
524 helpers.doKeys('d', 'h');
525 eq(' wrd1 ', cm.getValue());
526 var register = helpers.getRegisterController().getRegister();
527 eq('o', register.text);
528 is(!register.linewise);
529 eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor());
530 }, { value: ' word1 ' });
531 testVim('dj', function(cm, vim, helpers) {
532 var curStart = makeCursor(0, 3);
533 cm.setCursor(curStart);
534 helpers.doKeys('d', 'j');
535 eq(' word3', cm.getValue());
536 var register = helpers.getRegisterController().getRegister();
537 eq(' word1\nword2\n', register.text);
538 is(register.linewise);
539 helpers.assertCursorAt(0, 1);
540 }, { value: ' word1\nword2\n word3' });
541 testVim('dj_end_of_document', function(cm, vim, helpers) {
542 var curStart = makeCursor(0, 3);
543 cm.setCursor(curStart);
544 helpers.doKeys('d', 'j');
545 eq(' word1 ', cm.getValue());
546 var register = helpers.getRegisterController().getRegister();
547 eq('', register.text);
548 is(!register.linewise);
549 helpers.assertCursorAt(0, 3);
550 }, { value: ' word1 ' });
551 testVim('dk', function(cm, vim, helpers) {
552 var curStart = makeCursor(1, 3);
553 cm.setCursor(curStart);
554 helpers.doKeys('d', 'k');
555 eq(' word3', cm.getValue());
556 var register = helpers.getRegisterController().getRegister();
557 eq(' word1\nword2\n', register.text);
558 is(register.linewise);
559 helpers.assertCursorAt(0, 1);
560 }, { value: ' word1\nword2\n word3' });
561 testVim('dk_start_of_document', function(cm, vim, helpers) {
562 var curStart = makeCursor(0, 3);
563 cm.setCursor(curStart);
564 helpers.doKeys('d', 'k');
565 eq(' word1 ', cm.getValue());
566 var register = helpers.getRegisterController().getRegister();
567 eq('', register.text);
568 is(!register.linewise);
569 helpers.assertCursorAt(0, 3);
570 }, { value: ' word1 ' });
571 testVim('dw_space', function(cm, vim, helpers) {
572 var curStart = makeCursor(0, 0);
573 cm.setCursor(curStart);
574 helpers.doKeys('d', 'w');
575 eq('word1 ', cm.getValue());
576 var register = helpers.getRegisterController().getRegister();
577 eq(' ', register.text);
578 is(!register.linewise);
579 eqPos(curStart, cm.getCursor());
580 }, { value: ' word1 ' });
581 testVim('dw_word', function(cm, vim, helpers) {
582 var curStart = makeCursor(0, 1);
583 cm.setCursor(curStart);
584 helpers.doKeys('d', 'w');
585 eq(' word2', cm.getValue());
586 var register = helpers.getRegisterController().getRegister();
587 eq('word1 ', register.text);
588 is(!register.linewise);
589 eqPos(curStart, cm.getCursor());
590 }, { value: ' word1 word2' });
591 testVim('dw_only_word', function(cm, vim, helpers) {
592 // Test that if there is only 1 word left, dw deletes till the end of the
595 helpers.doKeys('d', 'w');
596 eq(' ', cm.getValue());
597 var register = helpers.getRegisterController().getRegister();
598 eq('word1 ', register.text);
599 is(!register.linewise);
600 helpers.assertCursorAt(0, 0);
601 }, { value: ' word1 ' });
602 testVim('dw_eol', function(cm, vim, helpers) {
603 // Assert that dw does not delete the newline if last word to delete is at end
606 helpers.doKeys('d', 'w');
607 eq(' \nword2', cm.getValue());
608 var register = helpers.getRegisterController().getRegister();
609 eq('word1', register.text);
610 is(!register.linewise);
611 helpers.assertCursorAt(0, 0);
612 }, { value: ' word1\nword2' });
613 testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {
614 // Assert that dw does not delete the newline if last word to delete is at end
615 // of line and it is followed by multiple newlines.
617 helpers.doKeys('d', 'w');
618 eq(' \n\nword2', cm.getValue());
619 var register = helpers.getRegisterController().getRegister();
620 eq('word1', register.text);
621 is(!register.linewise);
622 helpers.assertCursorAt(0, 0);
623 }, { value: ' word1\n\nword2' });
624 testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) {
626 helpers.doKeys('d', 'w');
627 eq(' \nword', cm.getValue());
628 }, { value: '\n \nword' });
629 testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) {
631 helpers.doKeys('d', 'w');
632 eq('word', cm.getValue());
633 }, { value: '\nword' });
634 testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) {
636 helpers.doKeys('d', 'w');
637 eq('\n', cm.getValue());
638 }, { value: '\n\n' });
639 testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) {
641 helpers.doKeys('d', 'w');
642 eq('\n \n', cm.getValue());
643 }, { value: ' \n \n' });
644 testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) {
646 helpers.doKeys('d', 'w');
647 eq('\n\n', cm.getValue());
648 }, { value: ' \n\n' });
649 testVim('dw_word_whitespace_word', function(cm, vim, helpers) {
651 helpers.doKeys('d', 'w');
652 eq('\n \nword2', cm.getValue());
653 }, { value: 'word1\n \nword2'})
654 testVim('dw_end_of_document', function(cm, vim, helpers) {
656 helpers.doKeys('d', 'w');
657 eq('\nab', cm.getValue());
658 }, { value: '\nabc' });
659 testVim('dw_repeat', function(cm, vim, helpers) {
660 // Assert that dw does delete newline if it should go to the next line, and
661 // that repeat works properly.
663 helpers.doKeys('d', '2', 'w');
664 eq(' ', cm.getValue());
665 var register = helpers.getRegisterController().getRegister();
666 eq('word1\nword2', register.text);
667 is(!register.linewise);
668 helpers.assertCursorAt(0, 0);
669 }, { value: ' word1\nword2' });
670 testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) {
672 helpers.doKeys('d', 'e');
673 eq('\n\n', cm.getValue());
674 }, { value: 'word\n\n' });
675 testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) {
677 helpers.doKeys('d', 'e');
678 eq('wor', cm.getValue());
679 }, { value: 'word\n\n\n' });
680 testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) {
682 helpers.doKeys('d', 'e');
683 eq('', cm.getValue());
684 }, { value: ' \n\n\n' });
685 testVim('de_end_of_document', function(cm, vim, helpers) {
687 helpers.doKeys('d', 'e');
688 eq('\nab', cm.getValue());
689 }, { value: '\nabc' });
690 testVim('db_empty_lines', function(cm, vim, helpers) {
692 helpers.doKeys('d', 'b');
693 eq('\n\n', cm.getValue());
694 }, { value: '\n\n\n' });
695 testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) {
697 helpers.doKeys('d', 'b');
698 eq('\nword', cm.getValue());
699 }, { value: '\n\nword' });
700 testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) {
702 helpers.doKeys('d', 'b');
703 eq('\n\nd', cm.getValue());
704 }, { value: '\n\nword' });
705 testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) {
707 helpers.doKeys('d', 'b');
708 eq('', cm.getValue());
709 }, { value: '\n \n' });
710 testVim('db_start_of_document', function(cm, vim, helpers) {
712 helpers.doKeys('d', 'b');
713 eq('abc\n', cm.getValue());
714 }, { value: 'abc\n' });
715 testVim('dge_empty_lines', function(cm, vim, helpers) {
717 helpers.doKeys('d', 'g', 'e');
718 // Note: In real VIM the result should be '', but it's not quite consistent,
719 // since 2 newlines are deleted. But in the similar case of word\n\n, only
720 // 1 newline is deleted. We'll diverge from VIM's behavior since it's much
722 eq('\n', cm.getValue());
723 }, { value: '\n\n' });
724 testVim('dge_word_and_empty_lines', function(cm, vim, helpers) {
726 helpers.doKeys('d', 'g', 'e');
727 eq('wor\n', cm.getValue());
728 }, { value: 'word\n\n'});
729 testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) {
731 helpers.doKeys('d', 'g', 'e');
732 eq('', cm.getValue());
733 }, { value: '\n \n' });
734 testVim('dge_start_of_document', function(cm, vim, helpers) {
736 helpers.doKeys('d', 'g', 'e');
737 eq('bc\n', cm.getValue());
738 }, { value: 'abc\n' });
739 testVim('d_inclusive', function(cm, vim, helpers) {
740 // Assert that when inclusive is set, the character the cursor is on gets
742 var curStart = makeCursor(0, 1);
743 cm.setCursor(curStart);
744 helpers.doKeys('d', 'e');
745 eq(' ', cm.getValue());
746 var register = helpers.getRegisterController().getRegister();
747 eq('word1', register.text);
748 is(!register.linewise);
749 eqPos(curStart, cm.getCursor());
750 }, { value: ' word1 ' });
751 testVim('d_reverse', function(cm, vim, helpers) {
752 // Test that deleting in reverse works.
754 helpers.doKeys('d', 'b');
755 eq(' word2 ', cm.getValue());
756 var register = helpers.getRegisterController().getRegister();
757 eq('word1\n', register.text);
758 is(!register.linewise);
759 helpers.assertCursorAt(0, 1);
760 }, { value: ' word1\nword2 ' });
761 testVim('dd', function(cm, vim, helpers) {
763 var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
765 var expectedLineCount = cm.lineCount() - 1;
766 helpers.doKeys('d', 'd');
767 eq(expectedLineCount, cm.lineCount());
768 var register = helpers.getRegisterController().getRegister();
769 eq(expectedBuffer, register.text);
770 is(register.linewise);
771 helpers.assertCursorAt(0, lines[1].textStart);
773 testVim('dd_prefix_repeat', function(cm, vim, helpers) {
775 var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
777 var expectedLineCount = cm.lineCount() - 2;
778 helpers.doKeys('2', 'd', 'd');
779 eq(expectedLineCount, cm.lineCount());
780 var register = helpers.getRegisterController().getRegister();
781 eq(expectedBuffer, register.text);
782 is(register.linewise);
783 helpers.assertCursorAt(0, lines[2].textStart);
785 testVim('dd_motion_repeat', function(cm, vim, helpers) {
787 var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
789 var expectedLineCount = cm.lineCount() - 2;
790 helpers.doKeys('d', '2', 'd');
791 eq(expectedLineCount, cm.lineCount());
792 var register = helpers.getRegisterController().getRegister();
793 eq(expectedBuffer, register.text);
794 is(register.linewise);
795 helpers.assertCursorAt(0, lines[2].textStart);
797 testVim('dd_multiply_repeat', function(cm, vim, helpers) {
799 var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
801 var expectedLineCount = cm.lineCount() - 6;
802 helpers.doKeys('2', 'd', '3', 'd');
803 eq(expectedLineCount, cm.lineCount());
804 var register = helpers.getRegisterController().getRegister();
805 eq(expectedBuffer, register.text);
806 is(register.linewise);
807 helpers.assertCursorAt(0, lines[6].textStart);
809 testVim('dd_lastline', function(cm, vim, helpers) {
810 cm.setCursor(cm.lineCount(), 0);
811 var expectedLineCount = cm.lineCount() - 1;
812 helpers.doKeys('d', 'd');
813 eq(expectedLineCount, cm.lineCount());
814 helpers.assertCursorAt(cm.lineCount() - 1, 0);
816 // Yank commands should behave the exact same as d commands, expect that nothing
818 testVim('yw_repeat', function(cm, vim, helpers) {
819 // Assert that yw does yank newline if it should go to the next line, and
820 // that repeat works properly.
821 var curStart = makeCursor(0, 1);
822 cm.setCursor(curStart);
823 helpers.doKeys('y', '2', 'w');
824 eq(' word1\nword2', cm.getValue());
825 var register = helpers.getRegisterController().getRegister();
826 eq('word1\nword2', register.text);
827 is(!register.linewise);
828 eqPos(curStart, cm.getCursor());
829 }, { value: ' word1\nword2' });
830 testVim('yy_multiply_repeat', function(cm, vim, helpers) {
831 var curStart = makeCursor(0, 3);
832 cm.setCursor(curStart);
833 var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
835 var expectedLineCount = cm.lineCount();
836 helpers.doKeys('2', 'y', '3', 'y');
837 eq(expectedLineCount, cm.lineCount());
838 var register = helpers.getRegisterController().getRegister();
839 eq(expectedBuffer, register.text);
840 is(register.linewise);
841 eqPos(curStart, cm.getCursor());
843 // Change commands behave like d commands except that it also enters insert
844 // mode. In addition, when the change is linewise, an additional newline is
845 // inserted so that insert mode starts on that line.
846 testVim('cw', function(cm, vim, helpers) {
848 helpers.doKeys('c', '2', 'w');
849 eq(' word3', cm.getValue());
850 helpers.assertCursorAt(0, 0);
851 }, { value: 'word1 word2 word3'});
852 testVim('cw_repeat', function(cm, vim, helpers) {
853 // Assert that cw does delete newline if it should go to the next line, and
854 // that repeat works properly.
855 var curStart = makeCursor(0, 1);
856 cm.setCursor(curStart);
857 helpers.doKeys('c', '2', 'w');
858 eq(' ', cm.getValue());
859 var register = helpers.getRegisterController().getRegister();
860 eq('word1\nword2', register.text);
861 is(!register.linewise);
862 eqPos(curStart, cm.getCursor());
863 eq('vim-insert', cm.getOption('keyMap'));
864 }, { value: ' word1\nword2' });
865 testVim('cc_multiply_repeat', function(cm, vim, helpers) {
867 var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
869 var expectedLineCount = cm.lineCount() - 5;
870 helpers.doKeys('2', 'c', '3', 'c');
871 eq(expectedLineCount, cm.lineCount());
872 var register = helpers.getRegisterController().getRegister();
873 eq(expectedBuffer, register.text);
874 is(register.linewise);
875 eq('vim-insert', cm.getOption('keyMap'));
877 testVim('cc_append', function(cm, vim, helpers) {
878 var expectedLineCount = cm.lineCount();
879 cm.setCursor(cm.lastLine(), 0);
880 helpers.doKeys('c', 'c');
881 eq(expectedLineCount, cm.lineCount());
883 // Swapcase commands edit in place and do not modify registers.
884 testVim('g~w_repeat', function(cm, vim, helpers) {
885 // Assert that dw does delete newline if it should go to the next line, and
886 // that repeat works properly.
887 var curStart = makeCursor(0, 1);
888 cm.setCursor(curStart);
889 helpers.doKeys('g', '~', '2', 'w');
890 eq(' WORD1\nWORD2', cm.getValue());
891 var register = helpers.getRegisterController().getRegister();
892 eq('', register.text);
893 is(!register.linewise);
894 eqPos(curStart, cm.getCursor());
895 }, { value: ' word1\nword2' });
896 testVim('g~g~', function(cm, vim, helpers) {
897 var curStart = makeCursor(0, 3);
898 cm.setCursor(curStart);
899 var expectedLineCount = cm.lineCount();
900 var expectedValue = cm.getValue().toUpperCase();
901 helpers.doKeys('2', 'g', '~', '3', 'g', '~');
902 eq(expectedValue, cm.getValue());
903 var register = helpers.getRegisterController().getRegister();
904 eq('', register.text);
905 is(!register.linewise);
906 eqPos(curStart, cm.getCursor());
907 }, { value: ' word1\nword2\nword3\nword4\nword5\nword6' });
908 testVim('>{motion}', function(cm, vim, helpers) {
910 var expectedLineCount = cm.lineCount();
911 var expectedValue = ' word1\n word2\nword3 ';
912 helpers.doKeys('>', 'k');
913 eq(expectedValue, cm.getValue());
914 var register = helpers.getRegisterController().getRegister();
915 eq('', register.text);
916 is(!register.linewise);
917 helpers.assertCursorAt(0, 3);
918 }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
919 testVim('>>', function(cm, vim, helpers) {
921 var expectedLineCount = cm.lineCount();
922 var expectedValue = ' word1\n word2\nword3 ';
923 helpers.doKeys('2', '>', '>');
924 eq(expectedValue, cm.getValue());
925 var register = helpers.getRegisterController().getRegister();
926 eq('', register.text);
927 is(!register.linewise);
928 helpers.assertCursorAt(0, 3);
929 }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
930 testVim('<{motion}', function(cm, vim, helpers) {
932 var expectedLineCount = cm.lineCount();
933 var expectedValue = ' word1\nword2\nword3 ';
934 helpers.doKeys('<', 'k');
935 eq(expectedValue, cm.getValue());
936 var register = helpers.getRegisterController().getRegister();
937 eq('', register.text);
938 is(!register.linewise);
939 helpers.assertCursorAt(0, 1);
940 }, { value: ' word1\n word2\nword3 ', indentUnit: 2 });
941 testVim('<<', function(cm, vim, helpers) {
943 var expectedLineCount = cm.lineCount();
944 var expectedValue = ' word1\nword2\nword3 ';
945 helpers.doKeys('2', '<', '<');
946 eq(expectedValue, cm.getValue());
947 var register = helpers.getRegisterController().getRegister();
948 eq('', register.text);
949 is(!register.linewise);
950 helpers.assertCursorAt(0, 1);
951 }, { value: ' word1\n word2\nword3 ', indentUnit: 2 });
954 function testEdit(name, before, pos, edit, after) {
955 return testVim(name, function(cm, vim, helpers) {
956 cm.setCursor(0, before.search(pos));
957 helpers.doKeys.apply(this, edit.split(''));
958 eq(after, cm.getValue());
962 // These Delete tests effectively cover word-wise Change, Visual & Yank.
963 // Tabs are used as differentiated whitespace to catch edge cases.
965 testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz');
966 testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz');
967 testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz');
968 testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz');
969 testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz');
970 testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz');
971 testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz');
972 testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz');
973 testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz');
974 testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz');
975 testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t');
976 testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo');
977 testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.');
978 testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.');
980 testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz');
981 testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz');
982 testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz');
983 testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz');
984 testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz');
985 testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz');
986 testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz');
987 testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz');
988 testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz');
989 testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz');
990 testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t');
991 testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo');
992 testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t');
993 testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo');
995 // Operator-motion tests
996 testVim('D', function(cm, vim, helpers) {
999 eq(' wo\nword2\n word3', cm.getValue());
1000 var register = helpers.getRegisterController().getRegister();
1001 eq('rd1', register.text);
1002 is(!register.linewise);
1003 helpers.assertCursorAt(0, 2);
1004 }, { value: ' word1\nword2\n word3' });
1005 testVim('C', function(cm, vim, helpers) {
1006 var curStart = makeCursor(0, 3);
1007 cm.setCursor(curStart);
1008 helpers.doKeys('C');
1009 eq(' wo\nword2\n word3', cm.getValue());
1010 var register = helpers.getRegisterController().getRegister();
1011 eq('rd1', register.text);
1012 is(!register.linewise);
1013 eqPos(curStart, cm.getCursor());
1014 eq('vim-insert', cm.getOption('keyMap'));
1015 }, { value: ' word1\nword2\n word3' });
1016 testVim('Y', function(cm, vim, helpers) {
1017 var curStart = makeCursor(0, 3);
1018 cm.setCursor(curStart);
1019 helpers.doKeys('Y');
1020 eq(' word1\nword2\n word3', cm.getValue());
1021 var register = helpers.getRegisterController().getRegister();
1022 eq('rd1', register.text);
1023 is(!register.linewise);
1024 helpers.assertCursorAt(0, 3);
1025 }, { value: ' word1\nword2\n word3' });
1026 testVim('~', function(cm, vim, helpers) {
1027 helpers.doKeys('3', '~');
1028 eq('ABCdefg', cm.getValue());
1029 helpers.assertCursorAt(0, 3);
1030 }, { value: 'abcdefg' });
1033 testVim('ctrl-a', function(cm, vim, helpers) {
1035 helpers.doKeys('<C-a>');
1036 eq('-9', cm.getValue());
1037 helpers.assertCursorAt(0, 1);
1038 helpers.doKeys('2','<C-a>');
1039 eq('-7', cm.getValue());
1041 testVim('ctrl-x', function(cm, vim, helpers) {
1043 helpers.doKeys('<C-x>');
1044 eq('-1', cm.getValue());
1045 helpers.assertCursorAt(0, 1);
1046 helpers.doKeys('2','<C-x>');
1047 eq('-3', cm.getValue());
1049 testVim('<C-x>/<C-a> search forward', function(cm, vim, helpers) {
1050 ['<C-x>', '<C-a>'].forEach(function(key) {
1052 helpers.doKeys(key);
1053 helpers.assertCursorAt(0, 5);
1054 helpers.doKeys('l');
1055 helpers.doKeys(key);
1056 helpers.assertCursorAt(0, 10);
1057 cm.setCursor(0, 11);
1058 helpers.doKeys(key);
1059 helpers.assertCursorAt(0, 11);
1061 }, {value: '__jmp1 jmp2 jmp'});
1062 testVim('a', function(cm, vim, helpers) {
1064 helpers.doKeys('a');
1065 helpers.assertCursorAt(0, 2);
1066 eq('vim-insert', cm.getOption('keyMap'));
1068 testVim('a_eol', function(cm, vim, helpers) {
1069 cm.setCursor(0, lines[0].length - 1);
1070 helpers.doKeys('a');
1071 helpers.assertCursorAt(0, lines[0].length);
1072 eq('vim-insert', cm.getOption('keyMap'));
1074 testVim('i', function(cm, vim, helpers) {
1076 helpers.doKeys('i');
1077 helpers.assertCursorAt(0, 1);
1078 eq('vim-insert', cm.getOption('keyMap'));
1080 testVim('i_repeat', function(cm, vim, helpers) {
1081 helpers.doKeys('3', 'i');
1082 cm.replaceRange('test', cm.getCursor());
1083 helpers.doInsertModeKeys('Esc');
1084 eq('testtesttest', cm.getValue());
1085 helpers.assertCursorAt(0, 11);
1087 testVim('i_repeat_delete', function(cm, vim, helpers) {
1089 helpers.doKeys('2', 'i');
1090 cm.replaceRange('z', cm.getCursor());
1091 helpers.doInsertModeKeys('Backspace', 'Backspace', 'Esc');
1092 eq('abe', cm.getValue());
1093 helpers.assertCursorAt(0, 1);
1094 }, { value: 'abcde' });
1095 testVim('A', function(cm, vim, helpers) {
1096 helpers.doKeys('A');
1097 helpers.assertCursorAt(0, lines[0].length);
1098 eq('vim-insert', cm.getOption('keyMap'));
1100 testVim('I', function(cm, vim, helpers) {
1102 helpers.doKeys('I');
1103 helpers.assertCursorAt(0, lines[0].textStart);
1104 eq('vim-insert', cm.getOption('keyMap'));
1106 testVim('I_repeat', function(cm, vim, helpers) {
1108 helpers.doKeys('3', 'I');
1109 cm.replaceRange('test', cm.getCursor());
1110 helpers.doInsertModeKeys('Esc');
1111 eq('testtesttestblah', cm.getValue());
1112 helpers.assertCursorAt(0, 11);
1113 }, { value: 'blah' });
1114 testVim('o', function(cm, vim, helpers) {
1116 helpers.doKeys('o');
1117 eq('word1\n\nword2', cm.getValue());
1118 helpers.assertCursorAt(1, 0);
1119 eq('vim-insert', cm.getOption('keyMap'));
1120 }, { value: 'word1\nword2' });
1121 testVim('o_repeat', function(cm, vim, helpers) {
1123 helpers.doKeys('3', 'o');
1124 cm.replaceRange('test', cm.getCursor());
1125 helpers.doInsertModeKeys('Esc');
1126 eq('\ntest\ntest\ntest', cm.getValue());
1127 helpers.assertCursorAt(3, 3);
1129 testVim('O', function(cm, vim, helpers) {
1131 helpers.doKeys('O');
1132 eq('\nword1\nword2', cm.getValue());
1133 helpers.assertCursorAt(0, 0);
1134 eq('vim-insert', cm.getOption('keyMap'));
1135 }, { value: 'word1\nword2' });
1136 testVim('J', function(cm, vim, helpers) {
1138 helpers.doKeys('J');
1139 var expectedValue = 'word1 word2\nword3\n word4';
1140 eq(expectedValue, cm.getValue());
1141 helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1);
1142 }, { value: 'word1 \n word2\nword3\n word4' });
1143 testVim('J_repeat', function(cm, vim, helpers) {
1145 helpers.doKeys('3', 'J');
1146 var expectedValue = 'word1 word2 word3\n word4';
1147 eq(expectedValue, cm.getValue());
1148 helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1);
1149 }, { value: 'word1 \n word2\nword3\n word4' });
1150 testVim('p', function(cm, vim, helpers) {
1152 helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
1153 helpers.doKeys('p');
1154 eq('__abc\ndef_', cm.getValue());
1155 helpers.assertCursorAt(1, 2);
1156 }, { value: '___' });
1157 testVim('p_register', function(cm, vim, helpers) {
1159 helpers.getRegisterController().getRegister('a').set('abc\ndef', false);
1160 helpers.doKeys('"', 'a', 'p');
1161 eq('__abc\ndef_', cm.getValue());
1162 helpers.assertCursorAt(1, 2);
1163 }, { value: '___' });
1164 testVim('p_wrong_register', function(cm, vim, helpers) {
1166 helpers.getRegisterController().getRegister('a').set('abc\ndef', false);
1167 helpers.doKeys('p');
1168 eq('___', cm.getValue());
1169 helpers.assertCursorAt(0, 1);
1170 }, { value: '___' });
1171 testVim('p_line', function(cm, vim, helpers) {
1173 helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);
1174 helpers.doKeys('2', 'p');
1175 eq('___\n a\nd\n a\nd', cm.getValue());
1176 helpers.assertCursorAt(1, 2);
1177 }, { value: '___' });
1178 testVim('P', function(cm, vim, helpers) {
1180 helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
1181 helpers.doKeys('P');
1182 eq('_abc\ndef__', cm.getValue());
1183 helpers.assertCursorAt(1, 3);
1184 }, { value: '___' });
1185 testVim('P_line', function(cm, vim, helpers) {
1187 helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);
1188 helpers.doKeys('2', 'P');
1189 eq(' a\nd\n a\nd\n___', cm.getValue());
1190 helpers.assertCursorAt(0, 2);
1191 }, { value: '___' });
1192 testVim('r', function(cm, vim, helpers) {
1194 helpers.doKeys('3', 'r', 'u');
1195 eq('wuuuet\nanother', cm.getValue(),'3r failed');
1196 helpers.assertCursorAt(0, 3);
1198 helpers.doKeys('v', 'j', 'h', 'r', '<Space>');
1199 eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed');
1200 }, { value: 'wordet\nanother' });
1201 testVim('R', function(cm, vim, helpers) {
1203 helpers.doKeys('R');
1204 helpers.assertCursorAt(0, 1);
1205 eq('vim-replace', cm.getOption('keyMap'));
1206 is(cm.state.overwrite, 'Setting overwrite state failed');
1208 testVim('mark', function(cm, vim, helpers) {
1210 helpers.doKeys('m', 't');
1212 helpers.doKeys('\'', 't');
1213 helpers.assertCursorAt(2, 2);
1215 helpers.doKeys('`', 't');
1216 helpers.assertCursorAt(2, 2);
1218 testVim('jumpToMark_next', function(cm, vim, helpers) {
1220 helpers.doKeys('m', 't');
1222 helpers.doKeys(']', '`');
1223 helpers.assertCursorAt(2, 2);
1225 helpers.doKeys(']', '\'');
1226 helpers.assertCursorAt(2, 0);
1228 testVim('jumpToMark_next_repeat', function(cm, vim, helpers) {
1230 helpers.doKeys('m', 'a');
1232 helpers.doKeys('m', 'b');
1234 helpers.doKeys('m', 'c');
1236 helpers.doKeys('2', ']', '`');
1237 helpers.assertCursorAt(3, 2);
1239 helpers.doKeys('2', ']', '\'');
1240 helpers.assertCursorAt(3, 1);
1242 testVim('jumpToMark_next_sameline', function(cm, vim, helpers) {
1244 helpers.doKeys('m', 'a');
1246 helpers.doKeys('m', 'b');
1248 helpers.doKeys(']', '`');
1249 helpers.assertCursorAt(2, 4);
1251 testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) {
1253 helpers.doKeys('m', 'a');
1255 helpers.doKeys(']', '`');
1256 helpers.assertCursorAt(4, 0);
1258 testVim('jumpToMark_next_nomark', function(cm, vim, helpers) {
1260 helpers.doKeys(']', '`');
1261 helpers.assertCursorAt(2, 2);
1262 helpers.doKeys(']', '\'');
1263 helpers.assertCursorAt(2, 0);
1265 testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) {
1267 helpers.doKeys('m', 'a');
1269 helpers.doKeys('m', 'b');
1271 helpers.doKeys(']', '\'');
1272 helpers.assertCursorAt(3, 1);
1274 testVim('jumpToMark_next_action', function(cm, vim, helpers) {
1276 helpers.doKeys('m', 't');
1278 helpers.doKeys('d', ']', '`');
1279 helpers.assertCursorAt(0, 0);
1280 var actual = cm.getLine(0);
1281 var expected = 'pop pop 0 1 2 3 4';
1282 eq(actual, expected, "Deleting while jumping to the next mark failed.");
1284 testVim('jumpToMark_next_line_action', function(cm, vim, helpers) {
1286 helpers.doKeys('m', 't');
1288 helpers.doKeys('d', ']', '\'');
1289 helpers.assertCursorAt(0, 1);
1290 var actual = cm.getLine(0);
1291 var expected = ' (a) [b] {c} '
1292 eq(actual, expected, "Deleting while jumping to the next mark line failed.");
1294 testVim('jumpToMark_prev', function(cm, vim, helpers) {
1296 helpers.doKeys('m', 't');
1298 helpers.doKeys('[', '`');
1299 helpers.assertCursorAt(2, 2);
1301 helpers.doKeys('[', '\'');
1302 helpers.assertCursorAt(2, 0);
1304 testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) {
1306 helpers.doKeys('m', 'a');
1308 helpers.doKeys('m', 'b');
1310 helpers.doKeys('m', 'c');
1312 helpers.doKeys('2', '[', '`');
1313 helpers.assertCursorAt(3, 2);
1315 helpers.doKeys('2', '[', '\'');
1316 helpers.assertCursorAt(3, 1);
1318 testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) {
1320 helpers.doKeys('m', 'a');
1322 helpers.doKeys('m', 'b');
1324 helpers.doKeys('[', '`');
1325 helpers.assertCursorAt(2, 0);
1327 testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) {
1329 helpers.doKeys('m', 'a');
1331 helpers.doKeys('[', '`');
1332 helpers.assertCursorAt(2, 0);
1334 testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) {
1336 helpers.doKeys('[', '`');
1337 helpers.assertCursorAt(2, 2);
1338 helpers.doKeys('[', '\'');
1339 helpers.assertCursorAt(2, 0);
1341 testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) {
1343 helpers.doKeys('m', 'a');
1345 helpers.doKeys('m', 'b');
1347 helpers.doKeys('[', '\'');
1348 helpers.assertCursorAt(2, 0);
1350 testVim('delmark_single', function(cm, vim, helpers) {
1352 helpers.doKeys('m', 't');
1353 helpers.doEx('delmarks t');
1355 helpers.doKeys('`', 't');
1356 helpers.assertCursorAt(0, 0);
1358 testVim('delmark_range', function(cm, vim, helpers) {
1360 helpers.doKeys('m', 'a');
1362 helpers.doKeys('m', 'b');
1364 helpers.doKeys('m', 'c');
1366 helpers.doKeys('m', 'd');
1368 helpers.doKeys('m', 'e');
1369 helpers.doEx('delmarks b-d');
1371 helpers.doKeys('`', 'a');
1372 helpers.assertCursorAt(1, 2);
1373 helpers.doKeys('`', 'b');
1374 helpers.assertCursorAt(1, 2);
1375 helpers.doKeys('`', 'c');
1376 helpers.assertCursorAt(1, 2);
1377 helpers.doKeys('`', 'd');
1378 helpers.assertCursorAt(1, 2);
1379 helpers.doKeys('`', 'e');
1380 helpers.assertCursorAt(5, 2);
1382 testVim('delmark_multi', function(cm, vim, helpers) {
1384 helpers.doKeys('m', 'a');
1386 helpers.doKeys('m', 'b');
1388 helpers.doKeys('m', 'c');
1390 helpers.doKeys('m', 'd');
1392 helpers.doKeys('m', 'e');
1393 helpers.doEx('delmarks bcd');
1395 helpers.doKeys('`', 'a');
1396 helpers.assertCursorAt(1, 2);
1397 helpers.doKeys('`', 'b');
1398 helpers.assertCursorAt(1, 2);
1399 helpers.doKeys('`', 'c');
1400 helpers.assertCursorAt(1, 2);
1401 helpers.doKeys('`', 'd');
1402 helpers.assertCursorAt(1, 2);
1403 helpers.doKeys('`', 'e');
1404 helpers.assertCursorAt(5, 2);
1406 testVim('delmark_multi_space', function(cm, vim, helpers) {
1408 helpers.doKeys('m', 'a');
1410 helpers.doKeys('m', 'b');
1412 helpers.doKeys('m', 'c');
1414 helpers.doKeys('m', 'd');
1416 helpers.doKeys('m', 'e');
1417 helpers.doEx('delmarks b c d');
1419 helpers.doKeys('`', 'a');
1420 helpers.assertCursorAt(1, 2);
1421 helpers.doKeys('`', 'b');
1422 helpers.assertCursorAt(1, 2);
1423 helpers.doKeys('`', 'c');
1424 helpers.assertCursorAt(1, 2);
1425 helpers.doKeys('`', 'd');
1426 helpers.assertCursorAt(1, 2);
1427 helpers.doKeys('`', 'e');
1428 helpers.assertCursorAt(5, 2);
1430 testVim('delmark_all', function(cm, vim, helpers) {
1432 helpers.doKeys('m', 'a');
1434 helpers.doKeys('m', 'b');
1436 helpers.doKeys('m', 'c');
1438 helpers.doKeys('m', 'd');
1440 helpers.doKeys('m', 'e');
1441 helpers.doEx('delmarks a b-de');
1443 helpers.doKeys('`', 'a');
1444 helpers.assertCursorAt(0, 0);
1445 helpers.doKeys('`', 'b');
1446 helpers.assertCursorAt(0, 0);
1447 helpers.doKeys('`', 'c');
1448 helpers.assertCursorAt(0, 0);
1449 helpers.doKeys('`', 'd');
1450 helpers.assertCursorAt(0, 0);
1451 helpers.doKeys('`', 'e');
1452 helpers.assertCursorAt(0, 0);
1454 testVim('visual', function(cm, vim, helpers) {
1455 helpers.doKeys('l', 'v', 'l', 'l');
1456 helpers.assertCursorAt(0, 3);
1457 eqPos(makeCursor(0, 1), cm.getCursor('anchor'));
1458 helpers.doKeys('d');
1459 eq('15', cm.getValue());
1460 }, { value: '12345' });
1461 testVim('visual_line', function(cm, vim, helpers) {
1462 helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd');
1463 eq(' 4\n 5', cm.getValue());
1464 }, { value: ' 1\n 2\n 3\n 4\n 5' });
1465 testVim('visual_marks', function(cm, vim, helpers) {
1466 helpers.doKeys('l', 'v', 'l', 'l', 'v');
1467 // Test visual mode marks
1469 helpers.doKeys('\'', '<');
1470 helpers.assertCursorAt(0, 1);
1471 helpers.doKeys('\'', '>');
1472 helpers.assertCursorAt(0, 3);
1474 testVim('visual_join', function(cm, vim, helpers) {
1475 helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J');
1476 eq(' 1 2 3\n 4\n 5', cm.getValue());
1477 }, { value: ' 1\n 2\n 3\n 4\n 5' });
1478 testVim('visual_blank', function(cm, vim, helpers) {
1479 helpers.doKeys('v', 'k');
1480 eq(vim.visualMode, true);
1481 }, { value: '\n' });
1482 testVim('/ and n/N', function(cm, vim, helpers) {
1483 cm.openDialog = helpers.fakeOpenDialog('match');
1484 helpers.doKeys('/');
1485 helpers.assertCursorAt(0, 11);
1486 helpers.doKeys('n');
1487 helpers.assertCursorAt(1, 6);
1488 helpers.doKeys('N');
1489 helpers.assertCursorAt(0, 11);
1492 helpers.doKeys('2', '/');
1493 helpers.assertCursorAt(1, 6);
1494 }, { value: 'match nope match \n nope Match' });
1495 testVim('/_case', function(cm, vim, helpers) {
1496 cm.openDialog = helpers.fakeOpenDialog('Match');
1497 helpers.doKeys('/');
1498 helpers.assertCursorAt(1, 6);
1499 }, { value: 'match nope match \n nope Match' });
1500 testVim('/_nongreedy', function(cm, vim, helpers) {
1501 cm.openDialog = helpers.fakeOpenDialog('aa');
1502 helpers.doKeys('/');
1503 helpers.assertCursorAt(0, 4);
1504 helpers.doKeys('n');
1505 helpers.assertCursorAt(1, 3);
1506 helpers.doKeys('n');
1507 helpers.assertCursorAt(0, 0);
1508 }, { value: 'aaa aa \n a aa'});
1509 testVim('?_nongreedy', function(cm, vim, helpers) {
1510 cm.openDialog = helpers.fakeOpenDialog('aa');
1511 helpers.doKeys('?');
1512 helpers.assertCursorAt(1, 3);
1513 helpers.doKeys('n');
1514 helpers.assertCursorAt(0, 4);
1515 helpers.doKeys('n');
1516 helpers.assertCursorAt(0, 0);
1517 }, { value: 'aaa aa \n a aa'});
1518 testVim('/_greedy', function(cm, vim, helpers) {
1519 cm.openDialog = helpers.fakeOpenDialog('a+');
1520 helpers.doKeys('/');
1521 helpers.assertCursorAt(0, 4);
1522 helpers.doKeys('n');
1523 helpers.assertCursorAt(1, 1);
1524 helpers.doKeys('n');
1525 helpers.assertCursorAt(1, 3);
1526 helpers.doKeys('n');
1527 helpers.assertCursorAt(0, 0);
1528 }, { value: 'aaa aa \n a aa'});
1529 testVim('?_greedy', function(cm, vim, helpers) {
1530 cm.openDialog = helpers.fakeOpenDialog('a+');
1531 helpers.doKeys('?');
1532 helpers.assertCursorAt(1, 3);
1533 helpers.doKeys('n');
1534 helpers.assertCursorAt(1, 1);
1535 helpers.doKeys('n');
1536 helpers.assertCursorAt(0, 4);
1537 helpers.doKeys('n');
1538 helpers.assertCursorAt(0, 0);
1539 }, { value: 'aaa aa \n a aa'});
1540 testVim('/_greedy_0_or_more', function(cm, vim, helpers) {
1541 cm.openDialog = helpers.fakeOpenDialog('a*');
1542 helpers.doKeys('/');
1543 helpers.assertCursorAt(0, 3);
1544 helpers.doKeys('n');
1545 helpers.assertCursorAt(0, 4);
1546 helpers.doKeys('n');
1547 helpers.assertCursorAt(0, 5);
1548 helpers.doKeys('n');
1549 helpers.assertCursorAt(1, 0);
1550 helpers.doKeys('n');
1551 helpers.assertCursorAt(1, 1);
1552 helpers.doKeys('n');
1553 helpers.assertCursorAt(0, 0);
1554 }, { value: 'aaa aa\n aa'});
1555 testVim('?_greedy_0_or_more', function(cm, vim, helpers) {
1556 cm.openDialog = helpers.fakeOpenDialog('a*');
1557 helpers.doKeys('?');
1558 helpers.assertCursorAt(1, 1);
1559 helpers.doKeys('n');
1560 helpers.assertCursorAt(1, 0);
1561 helpers.doKeys('n');
1562 helpers.assertCursorAt(0, 5);
1563 helpers.doKeys('n');
1564 helpers.assertCursorAt(0, 4);
1565 helpers.doKeys('n');
1566 helpers.assertCursorAt(0, 3);
1567 helpers.doKeys('n');
1568 helpers.assertCursorAt(0, 0);
1569 }, { value: 'aaa aa\n aa'});
1570 testVim('? and n/N', function(cm, vim, helpers) {
1571 cm.openDialog = helpers.fakeOpenDialog('match');
1572 helpers.doKeys('?');
1573 helpers.assertCursorAt(1, 6);
1574 helpers.doKeys('n');
1575 helpers.assertCursorAt(0, 11);
1576 helpers.doKeys('N');
1577 helpers.assertCursorAt(1, 6);
1580 helpers.doKeys('2', '?');
1581 helpers.assertCursorAt(0, 11);
1582 }, { value: 'match nope match \n nope Match' });
1583 testVim('*', function(cm, vim, helpers) {
1585 helpers.doKeys('*');
1586 helpers.assertCursorAt(0, 22);
1589 helpers.doKeys('2', '*');
1590 helpers.assertCursorAt(1, 8);
1591 }, { value: 'nomatch match nomatch match \nnomatch Match' });
1592 testVim('*_no_word', function(cm, vim, helpers) {
1594 helpers.doKeys('*');
1595 helpers.assertCursorAt(0, 0);
1596 }, { value: ' \n match \n' });
1597 testVim('*_symbol', function(cm, vim, helpers) {
1599 helpers.doKeys('*');
1600 helpers.assertCursorAt(1, 0);
1601 }, { value: ' /}\n/} match \n' });
1602 testVim('#', function(cm, vim, helpers) {
1604 helpers.doKeys('#');
1605 helpers.assertCursorAt(1, 8);
1608 helpers.doKeys('2', '#');
1609 helpers.assertCursorAt(0, 22);
1610 }, { value: 'nomatch match nomatch match \nnomatch Match' });
1611 testVim('*_seek', function(cm, vim, helpers) {
1612 // Should skip over space and symbols.
1614 helpers.doKeys('*');
1615 helpers.assertCursorAt(0, 22);
1616 }, { value: ' := match nomatch match \nnomatch Match' });
1617 testVim('#', function(cm, vim, helpers) {
1618 // Should skip over space and symbols.
1620 helpers.doKeys('#');
1621 helpers.assertCursorAt(1, 8);
1622 }, { value: ' := match nomatch match \nnomatch Match' });
1623 testVim('.', function(cm, vim, helpers) {
1625 helpers.doKeys('2', 'd', 'w');
1626 helpers.doKeys('.');
1627 eq('5 6', cm.getValue());
1628 }, { value: '1 2 3 4 5 6'});
1629 testVim('._repeat', function(cm, vim, helpers) {
1631 helpers.doKeys('2', 'd', 'w');
1632 helpers.doKeys('3', '.');
1633 eq('6', cm.getValue());
1634 }, { value: '1 2 3 4 5 6'});
1635 testVim('._insert', function(cm, vim, helpers) {
1636 helpers.doKeys('i');
1637 cm.replaceRange('test', cm.getCursor());
1638 helpers.doInsertModeKeys('Esc');
1639 helpers.doKeys('.');
1640 eq('testestt', cm.getValue());
1641 helpers.assertCursorAt(0, 6);
1643 testVim('._insert_repeat', function(cm, vim, helpers) {
1644 helpers.doKeys('i');
1645 cm.replaceRange('test', cm.getCursor());
1647 helpers.doInsertModeKeys('Esc');
1648 helpers.doKeys('2', '.');
1649 eq('testesttestt', cm.getValue());
1650 helpers.assertCursorAt(0, 10);
1652 testVim('._repeat_insert', function(cm, vim, helpers) {
1653 helpers.doKeys('3', 'i');
1654 cm.replaceRange('te', cm.getCursor());
1656 helpers.doInsertModeKeys('Esc');
1657 helpers.doKeys('.');
1658 eq('tetettetetee', cm.getValue());
1659 helpers.assertCursorAt(0, 10);
1661 testVim('._insert_o', function(cm, vim, helpers) {
1662 helpers.doKeys('o');
1663 cm.replaceRange('z', cm.getCursor());
1665 helpers.doInsertModeKeys('Esc');
1666 helpers.doKeys('.');
1667 eq('\nz\nz', cm.getValue());
1668 helpers.assertCursorAt(2, 0);
1670 testVim('._insert_o_repeat', function(cm, vim, helpers) {
1671 helpers.doKeys('o');
1672 cm.replaceRange('z', cm.getCursor());
1673 helpers.doInsertModeKeys('Esc');
1675 helpers.doKeys('2', '.');
1676 eq('\nz\nz\nz', cm.getValue());
1677 helpers.assertCursorAt(3, 0);
1679 testVim('._insert_o_indent', function(cm, vim, helpers) {
1680 helpers.doKeys('o');
1681 cm.replaceRange('z', cm.getCursor());
1682 helpers.doInsertModeKeys('Esc');
1684 helpers.doKeys('.');
1685 eq('{\n z\n z', cm.getValue());
1686 helpers.assertCursorAt(2, 2);
1688 testVim('._insert_cw', function(cm, vim, helpers) {
1689 helpers.doKeys('c', 'w');
1690 cm.replaceRange('test', cm.getCursor());
1691 helpers.doInsertModeKeys('Esc');
1693 helpers.doKeys('2', 'l');
1694 helpers.doKeys('.');
1695 eq('test test word3', cm.getValue());
1696 helpers.assertCursorAt(0, 8);
1697 }, { value: 'word1 word2 word3' });
1698 testVim('._insert_cw_repeat', function(cm, vim, helpers) {
1699 // For some reason, repeat cw in desktop VIM will does not repeat insert mode
1700 // changes. Will conform to that behavior.
1701 helpers.doKeys('c', 'w');
1702 cm.replaceRange('test', cm.getCursor());
1703 helpers.doInsertModeKeys('Esc');
1705 helpers.doKeys('l');
1706 helpers.doKeys('2', '.');
1707 eq('test test', cm.getValue());
1708 helpers.assertCursorAt(0, 8);
1709 }, { value: 'word1 word2 word3' });
1710 testVim('._delete', function(cm, vim, helpers) {
1712 helpers.doKeys('i');
1713 helpers.doInsertModeKeys('Backspace', 'Esc');
1714 helpers.doKeys('.');
1715 eq('zace', cm.getValue());
1716 helpers.assertCursorAt(0, 1);
1717 }, { value: 'zabcde'});
1718 testVim('._delete_repeat', function(cm, vim, helpers) {
1720 helpers.doKeys('i');
1721 helpers.doInsertModeKeys('Backspace', 'Esc');
1722 helpers.doKeys('2', '.');
1723 eq('zzce', cm.getValue());
1724 helpers.assertCursorAt(0, 1);
1725 }, { value: 'zzabcde'});
1726 testVim('f;', function(cm, vim, helpers) {
1728 helpers.doKeys('f', 'x');
1729 helpers.doKeys(';');
1730 helpers.doKeys('2', ';');
1731 eq(9, cm.getCursor().ch);
1732 }, { value: '01x3xx678x'});
1733 testVim('F;', function(cm, vim, helpers) {
1735 helpers.doKeys('F', 'x');
1736 helpers.doKeys(';');
1737 helpers.doKeys('2', ';');
1738 eq(2, cm.getCursor().ch);
1739 }, { value: '01x3xx6x8x'});
1740 testVim('t;', function(cm, vim, helpers) {
1742 helpers.doKeys('t', 'x');
1743 helpers.doKeys(';');
1744 helpers.doKeys('2', ';');
1745 eq(8, cm.getCursor().ch);
1746 }, { value: '01x3xx678x'});
1747 testVim('T;', function(cm, vim, helpers) {
1749 helpers.doKeys('T', 'x');
1750 helpers.doKeys(';');
1751 helpers.doKeys('2', ';');
1752 eq(2, cm.getCursor().ch);
1753 }, { value: '0xx3xx678x'});
1754 testVim('f,', function(cm, vim, helpers) {
1756 helpers.doKeys('f', 'x');
1757 helpers.doKeys(',');
1758 helpers.doKeys('2', ',');
1759 eq(2, cm.getCursor().ch);
1760 }, { value: '01x3xx678x'});
1761 testVim('F,', function(cm, vim, helpers) {
1763 helpers.doKeys('F', 'x');
1764 helpers.doKeys(',');
1765 helpers.doKeys('2', ',');
1766 eq(9, cm.getCursor().ch);
1767 }, { value: '01x3xx678x'});
1768 testVim('t,', function(cm, vim, helpers) {
1770 helpers.doKeys('t', 'x');
1771 helpers.doKeys(',');
1772 helpers.doKeys('2', ',');
1773 eq(3, cm.getCursor().ch);
1774 }, { value: '01x3xx678x'});
1775 testVim('T,', function(cm, vim, helpers) {
1777 helpers.doKeys('T', 'x');
1778 helpers.doKeys(',');
1779 helpers.doKeys('2', ',');
1780 eq(8, cm.getCursor().ch);
1781 }, { value: '01x3xx67xx'});
1782 testVim('fd,;', function(cm, vim, helpers) {
1784 helpers.doKeys('f', '4');
1786 helpers.doKeys('d', ';');
1787 eq('56789', cm.getValue());
1788 helpers.doKeys('u');
1790 helpers.doKeys('d', ',');
1791 eq('01239', cm.getValue());
1792 }, { value: '0123456789'});
1793 testVim('Fd,;', function(cm, vim, helpers) {
1795 helpers.doKeys('F', '4');
1797 helpers.doKeys('d', ';');
1798 eq('01239', cm.getValue());
1799 helpers.doKeys('u');
1801 helpers.doKeys('d', ',');
1802 eq('56789', cm.getValue());
1803 }, { value: '0123456789'});
1804 testVim('td,;', function(cm, vim, helpers) {
1806 helpers.doKeys('t', '4');
1808 helpers.doKeys('d', ';');
1809 eq('456789', cm.getValue());
1810 helpers.doKeys('u');
1812 helpers.doKeys('d', ',');
1813 eq('012349', cm.getValue());
1814 }, { value: '0123456789'});
1815 testVim('Td,;', function(cm, vim, helpers) {
1817 helpers.doKeys('T', '4');
1819 helpers.doKeys('d', ';');
1820 eq('012349', cm.getValue());
1821 helpers.doKeys('u');
1823 helpers.doKeys('d', ',');
1824 eq('456789', cm.getValue());
1825 }, { value: '0123456789'});
1826 testVim('fc,;', function(cm, vim, helpers) {
1828 helpers.doKeys('f', '4');
1830 helpers.doKeys('c', ';', 'Esc');
1831 eq('56789', cm.getValue());
1832 helpers.doKeys('u');
1834 helpers.doKeys('c', ',');
1835 eq('01239', cm.getValue());
1836 }, { value: '0123456789'});
1837 testVim('Fc,;', function(cm, vim, helpers) {
1839 helpers.doKeys('F', '4');
1841 helpers.doKeys('c', ';', 'Esc');
1842 eq('01239', cm.getValue());
1843 helpers.doKeys('u');
1845 helpers.doKeys('c', ',');
1846 eq('56789', cm.getValue());
1847 }, { value: '0123456789'});
1848 testVim('tc,;', function(cm, vim, helpers) {
1850 helpers.doKeys('t', '4');
1852 helpers.doKeys('c', ';', 'Esc');
1853 eq('456789', cm.getValue());
1854 helpers.doKeys('u');
1856 helpers.doKeys('c', ',');
1857 eq('012349', cm.getValue());
1858 }, { value: '0123456789'});
1859 testVim('Tc,;', function(cm, vim, helpers) {
1861 helpers.doKeys('T', '4');
1863 helpers.doKeys('c', ';', 'Esc');
1864 eq('012349', cm.getValue());
1865 helpers.doKeys('u');
1867 helpers.doKeys('c', ',');
1868 eq('456789', cm.getValue());
1869 }, { value: '0123456789'});
1870 testVim('fy,;', function(cm, vim, helpers) {
1872 helpers.doKeys('f', '4');
1874 helpers.doKeys('y', ';', 'P');
1875 eq('012340123456789', cm.getValue());
1876 helpers.doKeys('u');
1878 helpers.doKeys('y', ',', 'P');
1879 eq('012345678456789', cm.getValue());
1880 }, { value: '0123456789'});
1881 testVim('Fy,;', function(cm, vim, helpers) {
1883 helpers.doKeys('F', '4');
1885 helpers.doKeys('y', ';', 'p');
1886 eq('012345678945678', cm.getValue());
1887 helpers.doKeys('u');
1889 helpers.doKeys('y', ',', 'P');
1890 eq('012340123456789', cm.getValue());
1891 }, { value: '0123456789'});
1892 testVim('ty,;', function(cm, vim, helpers) {
1894 helpers.doKeys('t', '4');
1896 helpers.doKeys('y', ';', 'P');
1897 eq('01230123456789', cm.getValue());
1898 helpers.doKeys('u');
1900 helpers.doKeys('y', ',', 'p');
1901 eq('01234567895678', cm.getValue());
1902 }, { value: '0123456789'});
1903 testVim('Ty,;', function(cm, vim, helpers) {
1905 helpers.doKeys('T', '4');
1907 helpers.doKeys('y', ';', 'p');
1908 eq('01234567895678', cm.getValue());
1909 helpers.doKeys('u');
1911 helpers.doKeys('y', ',', 'P');
1912 eq('01230123456789', cm.getValue());
1913 }, { value: '0123456789'});
1914 testVim('HML', function(cm, vim, helpers) {
1916 var textHeight = cm.defaultTextHeight();
1917 cm.setSize(600, lines*textHeight);
1918 cm.setCursor(120, 0);
1919 helpers.doKeys('H');
1920 helpers.assertCursorAt(86, 2);
1921 helpers.doKeys('L');
1922 helpers.assertCursorAt(120, 4);
1923 helpers.doKeys('M');
1924 helpers.assertCursorAt(103,4);
1925 }, { value: (function(){
1926 var lines = new Array(100);
1927 var upper = ' xx\n';
1928 var lower = ' xx\n';
1929 upper = lines.join(upper);
1930 lower = lines.join(lower);
1931 return upper + lower;
1934 var zVals = ['zb','zz','zt','z-','z.','z<CR>'].map(function(e, idx){
1937 testVim(e, function(cm, vim, helpers) {
1939 var k2 = e.substring(1);
1940 var textHeight = cm.defaultTextHeight();
1941 cm.setSize(600, lines*textHeight);
1942 cm.setCursor(lineNum, 0);
1943 helpers.doKeys(k1, k2);
1944 zVals[idx] = cm.getScrollInfo().top;
1945 }, { value: (function(){
1946 return new Array(500).join('\n');
1949 testVim('zb<zz', function(cm, vim, helpers){
1950 eq(zVals[0]<zVals[1], true);
1952 testVim('zz<zt', function(cm, vim, helpers){
1953 eq(zVals[1]<zVals[2], true);
1955 testVim('zb==z-', function(cm, vim, helpers){
1956 eq(zVals[0], zVals[3]);
1958 testVim('zz==z.', function(cm, vim, helpers){
1959 eq(zVals[1], zVals[4]);
1961 testVim('zt==z<CR>', function(cm, vim, helpers){
1962 eq(zVals[2], zVals[5]);
1965 var squareBracketMotionSandbox = ''+
1968 ' /*comment {\n'+//2
1984 testVim('[[, ]]', function(cm, vim, helpers) {
1986 helpers.doKeys(']', ']');
1987 helpers.assertCursorAt(9,0);
1988 helpers.doKeys('2', ']', ']');
1989 helpers.assertCursorAt(13,0);
1990 helpers.doKeys(']', ']');
1991 helpers.assertCursorAt(17,0);
1992 helpers.doKeys('[', '[');
1993 helpers.assertCursorAt(13,0);
1994 helpers.doKeys('2', '[', '[');
1995 helpers.assertCursorAt(9,0);
1996 helpers.doKeys('[', '[');
1997 helpers.assertCursorAt(0,0);
1998 }, { value: squareBracketMotionSandbox});
1999 testVim('[], ][', function(cm, vim, helpers) {
2001 helpers.doKeys(']', '[');
2002 helpers.assertCursorAt(12,0);
2003 helpers.doKeys('2', ']', '[');
2004 helpers.assertCursorAt(16,0);
2005 helpers.doKeys(']', '[');
2006 helpers.assertCursorAt(17,0);
2007 helpers.doKeys('[', ']');
2008 helpers.assertCursorAt(16,0);
2009 helpers.doKeys('2', '[', ']');
2010 helpers.assertCursorAt(12,0);
2011 helpers.doKeys('[', ']');
2012 helpers.assertCursorAt(0,0);
2013 }, { value: squareBracketMotionSandbox});
2014 testVim('[{, ]}', function(cm, vim, helpers) {
2015 cm.setCursor(4, 10);
2016 helpers.doKeys('[', '{');
2017 helpers.assertCursorAt(2,12);
2018 helpers.doKeys('2', '[', '{');
2019 helpers.assertCursorAt(0,1);
2020 cm.setCursor(4, 10);
2021 helpers.doKeys(']', '}');
2022 helpers.assertCursorAt(6,11);
2023 helpers.doKeys('2', ']', '}');
2024 helpers.assertCursorAt(8,1);
2026 helpers.doKeys(']', '}');
2027 helpers.assertCursorAt(8,1);
2028 helpers.doKeys('[', '{');
2029 helpers.assertCursorAt(0,1);
2030 }, { value: squareBracketMotionSandbox});
2031 testVim('[(, ])', function(cm, vim, helpers) {
2032 cm.setCursor(4, 10);
2033 helpers.doKeys('[', '(');
2034 helpers.assertCursorAt(3,14);
2035 helpers.doKeys('2', '[', '(');
2036 helpers.assertCursorAt(0,0);
2037 cm.setCursor(4, 10);
2038 helpers.doKeys(']', ')');
2039 helpers.assertCursorAt(5,11);
2040 helpers.doKeys('2', ']', ')');
2041 helpers.assertCursorAt(8,0);
2042 helpers.doKeys('[', '(');
2043 helpers.assertCursorAt(0,0);
2044 helpers.doKeys(']', ')');
2045 helpers.assertCursorAt(8,0);
2046 }, { value: squareBracketMotionSandbox});
2047 testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) {
2048 ['*', '/'].forEach(function(key){
2050 helpers.doKeys('2', '[', key);
2051 helpers.assertCursorAt(2,2);
2052 helpers.doKeys('2', ']', key);
2053 helpers.assertCursorAt(7,5);
2055 }, { value: squareBracketMotionSandbox});
2056 testVim('[#, ]#', function(cm, vim, helpers) {
2057 cm.setCursor(10, 3);
2058 helpers.doKeys('2', '[', '#');
2059 helpers.assertCursorAt(4,0);
2060 helpers.doKeys('5', ']', '#');
2061 helpers.assertCursorAt(17,0);
2062 cm.setCursor(10, 3);
2063 helpers.doKeys(']', '#');
2064 helpers.assertCursorAt(14,0);
2065 }, { value: squareBracketMotionSandbox});
2066 testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) {
2067 cm.setCursor(11, 0);
2068 helpers.doKeys('[', 'm');
2069 helpers.assertCursorAt(10,7);
2070 helpers.doKeys('4', '[', 'm');
2071 helpers.assertCursorAt(1,3);
2072 helpers.doKeys('5', ']', 'm');
2073 helpers.assertCursorAt(11,0);
2074 helpers.doKeys('[', 'M');
2075 helpers.assertCursorAt(9,1);
2076 helpers.doKeys('3', ']', 'M');
2077 helpers.assertCursorAt(15,0);
2078 helpers.doKeys('5', '[', 'M');
2079 helpers.assertCursorAt(7,3);
2080 }, { value: squareBracketMotionSandbox});
2083 testVim('ex_go_to_line', function(cm, vim, helpers) {
2086 helpers.assertCursorAt(3, 0);
2087 }, { value: 'a\nb\nc\nd\ne\n'});
2088 testVim('ex_write', function(cm, vim, helpers) {
2089 var tmp = CodeMirror.commands.save;
2092 CodeMirror.commands.save = function(cm) {
2096 // Test that w, wr, wri ... write all trigger :write.
2097 var command = 'write';
2098 for (var i = 1; i < command.length; i++) {
2101 helpers.doEx(command.substring(0, i));
2105 CodeMirror.commands.save = tmp;
2107 testVim('ex_sort', function(cm, vim, helpers) {
2108 helpers.doEx('sort');
2109 eq('Z\na\nb\nc\nd', cm.getValue());
2110 }, { value: 'b\nZ\nd\nc\na'});
2111 testVim('ex_sort_reverse', function(cm, vim, helpers) {
2112 helpers.doEx('sort!');
2113 eq('d\nc\nb\na', cm.getValue());
2114 }, { value: 'b\nd\nc\na'});
2115 testVim('ex_sort_range', function(cm, vim, helpers) {
2116 helpers.doEx('2,3sort');
2117 eq('b\nc\nd\na', cm.getValue());
2118 }, { value: 'b\nd\nc\na'});
2119 testVim('ex_sort_oneline', function(cm, vim, helpers) {
2120 helpers.doEx('2sort');
2121 // Expect no change.
2122 eq('b\nd\nc\na', cm.getValue());
2123 }, { value: 'b\nd\nc\na'});
2124 testVim('ex_sort_ignoreCase', function(cm, vim, helpers) {
2125 helpers.doEx('sort i');
2126 eq('a\nb\nc\nd\nZ', cm.getValue());
2127 }, { value: 'b\nZ\nd\nc\na'});
2128 testVim('ex_sort_unique', function(cm, vim, helpers) {
2129 helpers.doEx('sort u');
2130 eq('Z\na\nb\nc\nd', cm.getValue());
2131 }, { value: 'b\nZ\na\na\nd\na\nc\na'});
2132 testVim('ex_sort_decimal', function(cm, vim, helpers) {
2133 helpers.doEx('sort d');
2134 eq('d3\n s5\n6\n.9', cm.getValue());
2135 }, { value: '6\nd3\n s5\n.9'});
2136 testVim('ex_sort_decimal_negative', function(cm, vim, helpers) {
2137 helpers.doEx('sort d');
2138 eq('z-9\nd3\n s5\n6\n.9', cm.getValue());
2139 }, { value: '6\nd3\n s5\n.9\nz-9'});
2140 testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) {
2141 helpers.doEx('sort! d');
2142 eq('.9\n6\n s5\nd3', cm.getValue());
2143 }, { value: '6\nd3\n s5\n.9'});
2144 testVim('ex_sort_hex', function(cm, vim, helpers) {
2145 helpers.doEx('sort x');
2146 eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue());
2147 }, { value: '6\nd3\n s5\n&0xB\n.9'});
2148 testVim('ex_sort_octal', function(cm, vim, helpers) {
2149 helpers.doEx('sort o');
2150 eq('.8\n.9\nd3\n s5\n6', cm.getValue());
2151 }, { value: '6\nd3\n s5\n.9\n.8'});
2152 testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) {
2153 helpers.doEx('sort d');
2154 eq('y\nz\nc1\nb2\na3', cm.getValue());
2155 }, { value: 'a3\nz\nc1\ny\nb2'});
2156 testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) {
2157 helpers.doEx('sort! d');
2158 eq('a3\nb2\nc1\nz\ny', cm.getValue());
2159 }, { value: 'a3\nz\nc1\ny\nb2'});
2160 testVim('ex_substitute_same_line', function(cm, vim, helpers) {
2162 helpers.doEx('s/one/two');
2163 eq('one one\n two two', cm.getValue());
2164 }, { value: 'one one\n one one'});
2165 testVim('ex_substitute_global', function(cm, vim, helpers) {
2167 helpers.doEx('%s/one/two');
2168 eq('two two\n two two', cm.getValue());
2169 }, { value: 'one one\n one one'});
2170 testVim('ex_substitute_input_range', function(cm, vim, helpers) {
2172 helpers.doEx('1,3s/\\d/0');
2173 eq('0\n0\n0\n4', cm.getValue());
2174 }, { value: '1\n2\n3\n4' });
2175 testVim('ex_substitute_visual_range', function(cm, vim, helpers) {
2177 // Set last visual mode selection marks '< and '> at lines 2 and 4
2178 helpers.doKeys('V', '2', 'j', 'v');
2179 helpers.doEx('\'<,\'>s/\\d/0');
2180 eq('1\n0\n0\n0\n5', cm.getValue());
2181 }, { value: '1\n2\n3\n4\n5' });
2182 testVim('ex_substitute_capture', function(cm, vim, helpers) {
2184 helpers.doEx('s/(\\d+)/$1$1/')
2185 eq('a1111 a1212 a1313', cm.getValue());
2186 }, { value: 'a11 a12 a13' });
2187 testVim('ex_substitute_empty_query', function(cm, vim, helpers) {
2188 // If the query is empty, use last query.
2190 cm.openDialog = helpers.fakeOpenDialog('1');
2191 helpers.doKeys('/');
2192 helpers.doEx('s//b');
2193 eq('abb ab2 ab3', cm.getValue());
2194 }, { value: 'a11 a12 a13' });
2195 testVim('ex_substitute_count', function(cm, vim, helpers) {
2197 helpers.doEx('s/\\d/0/i 2');
2198 eq('1\n0\n0\n4', cm.getValue());
2199 }, { value: '1\n2\n3\n4' });
2200 testVim('ex_substitute_count_with_range', function(cm, vim, helpers) {
2202 helpers.doEx('1,3s/\\d/0/ 3');
2203 eq('1\n2\n0\n0', cm.getValue());
2204 }, { value: '1\n2\n3\n4' });
2205 function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) {
2206 testVim(name, function(cm, vim, helpers) {
2207 var savedOpenDialog = cm.openDialog;
2208 var savedKeyName = CodeMirror.keyName;
2210 var recordedCallback;
2211 var closed = true; // Start out closed, set false on second openDialog.
2215 // First openDialog should save callback.
2216 cm.openDialog = function(template, callback, options) {
2217 recordedCallback = callback;
2219 // Do first openDialog.
2220 helpers.doKeys(':');
2221 // Second openDialog should save keyDown handler.
2222 cm.openDialog = function(template, callback, options) {
2223 onKeyDown = options.onKeyDown;
2226 // Return the command to Vim and trigger second openDialog.
2227 recordedCallback(command);
2228 // The event should really use keyCode, but here just mock it out and use
2229 // key and replace keyName to just return key.
2230 CodeMirror.keyName = function (e) { return e.key; }
2231 keys = keys.toUpperCase();
2232 for (var i = 0; i < keys.length; i++) {
2234 onKeyDown({ key: keys.charAt(i) }, '', close);
2237 eq(expectedValue, cm.getValue());
2238 helpers.assertCursorAt(finalPos);
2243 // Restore overriden functions.
2244 CodeMirror.keyName = savedKeyName;
2245 cm.openDialog = savedOpenDialog;
2247 }, { value: initialValue });
2249 testSubstituteConfirm('ex_substitute_confirm_emptydoc',
2250 '%s/x/b/c', '', '', '', makeCursor(0, 0));
2251 testSubstituteConfirm('ex_substitute_confirm_nomatch',
2252 '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0));
2253 testSubstituteConfirm('ex_substitute_confirm_accept',
2254 '%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1));
2255 testSubstituteConfirm('ex_substitute_confirm_random_keys',
2256 '%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1));
2257 testSubstituteConfirm('ex_substitute_confirm_some',
2258 '%s/a/b/c', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1));
2259 testSubstituteConfirm('ex_substitute_confirm_all',
2260 '%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1));
2261 testSubstituteConfirm('ex_substitute_confirm_accept_then_all',
2262 '%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1));
2263 testSubstituteConfirm('ex_substitute_confirm_quit',
2264 '%s/a/b/c', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3));
2265 testSubstituteConfirm('ex_substitute_confirm_last',
2266 '%s/a/b/c', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
2267 testSubstituteConfirm('ex_substitute_confirm_oneline',
2268 '1s/a/b/c', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
2269 testSubstituteConfirm('ex_substitute_confirm_range_accept',
2270 '1,2s/a/b/c', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0));
2271 testSubstituteConfirm('ex_substitute_confirm_range_some',
2272 '1,3s/a/b/c', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0));
2273 testSubstituteConfirm('ex_substitute_confirm_range_all',
2274 '1,3s/a/b/c', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0));
2275 testSubstituteConfirm('ex_substitute_confirm_range_last',
2276 '1,3s/a/b/c', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0));
2277 //:noh should clear highlighting of search-results but allow to resume search through n
2278 testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) {
2279 cm.openDialog = helpers.fakeOpenDialog('match');
2280 helpers.doKeys('?');
2281 helpers.doEx('noh');
2282 eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared');
2283 helpers.doKeys('n');
2284 helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting');
2285 }, { value: 'match nope match \n nope Match' });
2286 // TODO: Reset key maps after each test.
2287 testVim('ex_map_key2key', function(cm, vim, helpers) {
2288 helpers.doEx('map a x');
2289 helpers.doKeys('a');
2290 helpers.assertCursorAt(0, 0);
2291 eq('bc', cm.getValue());
2292 }, { value: 'abc' });
2293 testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) {
2294 helpers.doEx('map ; :');
2295 var dialogOpened = false;
2296 cm.openDialog = function() {
2297 dialogOpened = true;
2299 helpers.doKeys(';');
2300 eq(dialogOpened, true);
2302 testVim('ex_map_ex2key:', function(cm, vim, helpers) {
2303 helpers.doEx('map :del x');
2304 helpers.doEx('del');
2305 helpers.assertCursorAt(0, 0);
2306 eq('bc', cm.getValue());
2307 }, { value: 'abc' });
2308 testVim('ex_map_ex2ex', function(cm, vim, helpers) {
2309 helpers.doEx('map :del :w');
2310 var tmp = CodeMirror.commands.save;
2311 var written = false;
2313 CodeMirror.commands.save = function(cm) {
2317 helpers.doEx('del');
2318 CodeMirror.commands.save = tmp;
2322 testVim('ex_map_key2ex', function(cm, vim, helpers) {
2323 helpers.doEx('map a :w');
2324 var tmp = CodeMirror.commands.save;
2325 var written = false;
2327 CodeMirror.commands.save = function(cm) {
2331 helpers.doKeys('a');
2332 CodeMirror.commands.save = tmp;
2336 // Testing registration of functions as ex-commands and mapping to <Key>-keys
2337 testVim('ex_api_test', function(cm, vim, helpers) {
2340 CodeMirror.Vim.defineEx('extest','ext',function(cm,params){
2341 if(params.args)val=params.args[0];
2344 helpers.doEx(':ext to');
2345 eq(val,'to','Defining ex-command failed');
2346 CodeMirror.Vim.map('<C-CR><Space>',':ext');
2347 helpers.doKeys('<C-CR>','<Space>');
2348 is(res,'Mapping to key failed');
2350 // For now, this test needs to be last because it messes up : for future tests.
2351 testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) {
2352 helpers.doEx('map : x');
2353 helpers.doKeys(':');
2354 helpers.assertCursorAt(0, 0);
2355 eq('bc', cm.getValue());
2356 }, { value: 'abc' });