vim_test.js (165600B)
1 var Pos = CodeMirror.Pos; 2 CodeMirror.Vim.suppressErrorLogging = true; 3 4 var code = '' + 5 ' wOrd1 (#%\n' + 6 ' word3] \n' + 7 'aopop pop 0 1 2 3 4\n' + 8 ' (a) [b] {c} \n' + 9 'int getchar(void) {\n' + 10 ' static char buf[BUFSIZ];\n' + 11 ' static char *bufp = buf;\n' + 12 ' if (n == 0) { /* buffer is empty */\n' + 13 ' n = read(0, buf, sizeof buf);\n' + 14 ' bufp = buf;\n' + 15 ' }\n' + 16 '\n' + 17 ' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' + 18 ' \n' + 19 '}\n'; 20 21 var lines = (function() { 22 lineText = code.split('\n'); 23 var ret = []; 24 for (var i = 0; i < lineText.length; i++) { 25 ret[i] = { 26 line: i, 27 length: lineText[i].length, 28 lineText: lineText[i], 29 textStart: /^\s*/.exec(lineText[i])[0].length 30 }; 31 } 32 return ret; 33 })(); 34 var endOfDocument = makeCursor(lines.length - 1, 35 lines[lines.length - 1].length); 36 var wordLine = lines[0]; 37 var bigWordLine = lines[1]; 38 var charLine = lines[2]; 39 var bracesLine = lines[3]; 40 var seekBraceLine = lines[4]; 41 42 var word1 = { 43 start: new Pos(wordLine.line, 1), 44 end: new Pos(wordLine.line, 5) 45 }; 46 var word2 = { 47 start: new Pos(wordLine.line, word1.end.ch + 2), 48 end: new Pos(wordLine.line, word1.end.ch + 4) 49 }; 50 var word3 = { 51 start: new Pos(bigWordLine.line, 1), 52 end: new Pos(bigWordLine.line, 5) 53 }; 54 var bigWord1 = word1; 55 var bigWord2 = word2; 56 var bigWord3 = { 57 start: new Pos(bigWordLine.line, 1), 58 end: new Pos(bigWordLine.line, 7) 59 }; 60 var bigWord4 = { 61 start: new Pos(bigWordLine.line, bigWord1.end.ch + 3), 62 end: new Pos(bigWordLine.line, bigWord1.end.ch + 7) 63 }; 64 65 var oChars = [ new Pos(charLine.line, 1), 66 new Pos(charLine.line, 3), 67 new Pos(charLine.line, 7) ]; 68 var pChars = [ new Pos(charLine.line, 2), 69 new Pos(charLine.line, 4), 70 new Pos(charLine.line, 6), 71 new Pos(charLine.line, 8) ]; 72 var numChars = [ new Pos(charLine.line, 10), 73 new Pos(charLine.line, 12), 74 new Pos(charLine.line, 14), 75 new Pos(charLine.line, 16), 76 new Pos(charLine.line, 18)]; 77 var parens1 = { 78 start: new Pos(bracesLine.line, 1), 79 end: new Pos(bracesLine.line, 3) 80 }; 81 var squares1 = { 82 start: new Pos(bracesLine.line, 5), 83 end: new Pos(bracesLine.line, 7) 84 }; 85 var curlys1 = { 86 start: new Pos(bracesLine.line, 9), 87 end: new Pos(bracesLine.line, 11) 88 }; 89 var seekOutside = { 90 start: new Pos(seekBraceLine.line, 1), 91 end: new Pos(seekBraceLine.line, 16) 92 }; 93 var seekInside = { 94 start: new Pos(seekBraceLine.line, 14), 95 end: new Pos(seekBraceLine.line, 11) 96 }; 97 98 function copyCursor(cur) { 99 return new Pos(cur.line, cur.ch); 100 } 101 102 function forEach(arr, func) { 103 for (var i = 0; i < arr.length; i++) { 104 func(arr[i], i, arr); 105 } 106 } 107 108 function expectFail(fn) { 109 try { 110 fn(); 111 } catch(expected) { 112 return; 113 }; 114 throw new Error("Expected to throw an error"); 115 } 116 117 function testVim(name, run, opts, expectedFail) { 118 var vimOpts = { 119 lineNumbers: true, 120 vimMode: true, 121 showCursorWhenSelecting: true, 122 value: code 123 }; 124 for (var prop in opts) { 125 if (opts.hasOwnProperty(prop)) { 126 vimOpts[prop] = opts[prop]; 127 } 128 } 129 return test('vim_' + name, function() { 130 var place = document.getElementById("testground"); 131 var cm = CodeMirror(place, vimOpts); 132 var vim = CodeMirror.Vim.maybeInitVimState_(cm); 133 134 function doKeysFn(cm) { 135 return function(args) { 136 if (args instanceof Array) { 137 arguments = args; 138 } 139 for (var i = 0; i < arguments.length; i++) { 140 var result = CodeMirror.Vim.handleKey(cm, arguments[i]); 141 if (!result && cm.state.vim.insertMode) { 142 cm.replaceSelections(fillArray(arguments[i], cm.listSelections().length)); 143 } 144 } 145 } 146 } 147 function doInsertModeKeysFn(cm) { 148 return function(args) { 149 if (args instanceof Array) { arguments = args; } 150 function executeHandler(handler) { 151 if (typeof handler == 'string') { 152 CodeMirror.commands[handler](cm); 153 } else { 154 handler(cm); 155 } 156 return true; 157 } 158 for (var i = 0; i < arguments.length; i++) { 159 var key = arguments[i]; 160 // Find key in keymap and handle. 161 var handled = CodeMirror.lookupKey(key, cm.getOption('keyMap'), executeHandler, cm); 162 // Record for insert mode. 163 if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { 164 var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; 165 if (lastChange && (key.indexOf('Delete') != -1 || key.indexOf('Backspace') != -1)) { 166 lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key)); 167 } 168 } 169 } 170 } 171 } 172 function doExFn(cm) { 173 return function(command) { 174 cm.openDialog = helpers.fakeOpenDialog(command); 175 helpers.doKeys(':'); 176 } 177 } 178 function assertCursorAtFn(cm) { 179 return function(line, ch) { 180 var pos; 181 if (ch == null && typeof line.line == 'number') { 182 pos = line; 183 } else { 184 pos = makeCursor(line, ch); 185 } 186 eqCursorPos(cm.getCursor(), pos); 187 } 188 } 189 function fakeOpenDialog(result) { 190 return function(text, callback) { 191 return callback(result); 192 } 193 } 194 function fakeOpenNotification(matcher) { 195 return function(text) { 196 matcher(text); 197 } 198 } 199 var helpers = { 200 doKeys: doKeysFn(cm), 201 // Warning: Only emulates keymap events, not character insertions. Use 202 // replaceRange to simulate character insertions. 203 // Keys are in CodeMirror format, NOT vim format. 204 doInsertModeKeys: doInsertModeKeysFn(cm), 205 doEx: doExFn(cm), 206 assertCursorAt: assertCursorAtFn(cm), 207 fakeOpenDialog: fakeOpenDialog, 208 fakeOpenNotification: fakeOpenNotification, 209 getRegisterController: function() { 210 return CodeMirror.Vim.getRegisterController(); 211 } 212 } 213 CodeMirror.Vim.resetVimGlobalState_(); 214 var successful = false; 215 var savedOpenNotification = cm.openNotification; 216 var savedOpenDialog = cm.openDialog; 217 try { 218 run(cm, vim, helpers); 219 successful = true; 220 } finally { 221 cm.openNotification = savedOpenNotification; 222 cm.openDialog = savedOpenDialog; 223 if (!successful || verbose) { 224 place.style.visibility = "visible"; 225 } else { 226 place.removeChild(cm.getWrapperElement()); 227 } 228 } 229 }, expectedFail); 230 }; 231 testVim('qq@q', function(cm, vim, helpers) { 232 cm.setCursor(0, 0); 233 helpers.doKeys('q', 'q', 'l', 'l', 'q'); 234 helpers.assertCursorAt(0,2); 235 helpers.doKeys('@', 'q'); 236 helpers.assertCursorAt(0,4); 237 }, { value: ' '}); 238 testVim('@@', function(cm, vim, helpers) { 239 cm.setCursor(0, 0); 240 helpers.doKeys('q', 'q', 'l', 'l', 'q'); 241 helpers.assertCursorAt(0,2); 242 helpers.doKeys('@', 'q'); 243 helpers.assertCursorAt(0,4); 244 helpers.doKeys('@', '@'); 245 helpers.assertCursorAt(0,6); 246 }, { value: ' '}); 247 var jumplistScene = ''+ 248 'word\n'+ 249 '(word)\n'+ 250 '{word\n'+ 251 'word.\n'+ 252 '\n'+ 253 'word search\n'+ 254 '}word\n'+ 255 'word\n'+ 256 'word\n'; 257 function testJumplist(name, keys, endPos, startPos, dialog) { 258 endPos = makeCursor(endPos[0], endPos[1]); 259 startPos = makeCursor(startPos[0], startPos[1]); 260 testVim(name, function(cm, vim, helpers) { 261 CodeMirror.Vim.resetVimGlobalState_(); 262 if(dialog)cm.openDialog = helpers.fakeOpenDialog('word'); 263 cm.setCursor(startPos); 264 helpers.doKeys.apply(null, keys); 265 helpers.assertCursorAt(endPos); 266 }, {value: jumplistScene}); 267 } 268 testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]); 269 testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]); 270 testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]); 271 testJumplist('jumplist_[[', ['[', '[', '<C-o>'], [5,2], [5,2]); 272 testJumplist('jumplist_]]', [']', ']', '<C-o>'], [2,2], [2,2]); 273 testJumplist('jumplist_G', ['G', '<C-o>'], [5,2], [5,2]); 274 testJumplist('jumplist_gg', ['g', 'g', '<C-o>'], [5,2], [5,2]); 275 testJumplist('jumplist_%', ['%', '<C-o>'], [1,5], [1,5]); 276 testJumplist('jumplist_{', ['{', '<C-o>'], [1,5], [1,5]); 277 testJumplist('jumplist_}', ['}', '<C-o>'], [1,5], [1,5]); 278 testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', '<C-i>'], [1,0], [1,5]); 279 testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', '<C-i>'], [1,5], [1,5]); 280 testJumplist('jumplist_*_cachedCursor', ['*', '<C-o>'], [1,3], [1,3]); 281 testJumplist('jumplist_#_cachedCursor', ['#', '<C-o>'], [1,3], [1,3]); 282 testJumplist('jumplist_n', ['#', 'n', '<C-o>'], [1,1], [2,3]); 283 testJumplist('jumplist_N', ['#', 'N', '<C-o>'], [1,1], [2,3]); 284 testJumplist('jumplist_repeat_<c-o>', ['*', '*', '*', '3', '<C-o>'], [2,3], [2,3]); 285 testJumplist('jumplist_repeat_<c-i>', ['*', '*', '*', '3', '<C-o>', '2', '<C-i>'], [5,0], [2,3]); 286 testJumplist('jumplist_repeated_motion', ['3', '*', '<C-o>'], [2,3], [2,3]); 287 testJumplist('jumplist_/', ['/', '<C-o>'], [2,3], [2,3], 'dialog'); 288 testJumplist('jumplist_?', ['?', '<C-o>'], [2,3], [2,3], 'dialog'); 289 testJumplist('jumplist_skip_deleted_mark<c-o>', 290 ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-o>', '<C-o>'], 291 [0,2], [0,2]); 292 testJumplist('jumplist_skip_deleted_mark<c-i>', 293 ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-i>', '<C-i>'], 294 [1,0], [0,2]); 295 296 /** 297 * @param name Name of the test 298 * @param keys An array of keys or a string with a single key to simulate. 299 * @param endPos The expected end position of the cursor. 300 * @param startPos The position the cursor should start at, defaults to 0, 0. 301 */ 302 function testMotion(name, keys, endPos, startPos) { 303 testVim(name, function(cm, vim, helpers) { 304 if (!startPos) { 305 startPos = new Pos(0, 0); 306 } 307 cm.setCursor(startPos); 308 helpers.doKeys(keys); 309 helpers.assertCursorAt(endPos); 310 }); 311 } 312 313 function makeCursor(line, ch) { 314 return new Pos(line, ch); 315 } 316 317 function offsetCursor(cur, offsetLine, offsetCh) { 318 return new Pos(cur.line + offsetLine, cur.ch + offsetCh); 319 } 320 321 // Motion tests 322 testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4)); 323 testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4)); 324 testMotion('h', 'h', makeCursor(0, 0), word1.start); 325 testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end); 326 testMotion('l', 'l', makeCursor(0, 1)); 327 testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2)); 328 testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end); 329 testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end); 330 testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument); 331 testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end); 332 testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4)); 333 testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4)); 334 testMotion('w', 'w', word1.start); 335 testMotion('keepHPos', ['5', 'j', 'j', '7', 'k'], makeCursor(8, 12), makeCursor(12, 12)); 336 testMotion('keepHPosEol', ['$', '2', 'j'], makeCursor(2, 18)); 337 testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2)); 338 testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51)); 339 testMotion('w_repeat', ['2', 'w'], word2.start); 340 testMotion('w_wrap', ['w'], word3.start, word2.start); 341 testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument); 342 testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0)); 343 testMotion('W', 'W', bigWord1.start); 344 testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start); 345 testMotion('e', 'e', word1.end); 346 testMotion('e_repeat', ['2', 'e'], word2.end); 347 testMotion('e_wrap', 'e', word3.end, word2.end); 348 testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument); 349 testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0)); 350 testMotion('b', 'b', word3.start, word3.end); 351 testMotion('b_repeat', ['2', 'b'], word2.start, word3.end); 352 testMotion('b_wrap', 'b', word2.start, word3.start); 353 testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0)); 354 testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument); 355 testMotion('ge', ['g', 'e'], word2.end, word3.end); 356 testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start); 357 testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start); 358 testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0), 359 makeCursor(0, 0)); 360 testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument); 361 testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart), 362 makeCursor(3, 1)); 363 testMotion('gg_repeat', ['3', 'g', 'g'], 364 makeCursor(lines[2].line, lines[2].textStart)); 365 testMotion('G', 'G', 366 makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart), 367 makeCursor(3, 1)); 368 testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line, 369 lines[2].textStart)); 370 // TODO: Make the test code long enough to test Ctrl-F and Ctrl-B. 371 testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8)); 372 testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8)); 373 testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8)); 374 testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4)); 375 testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8)); 376 testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1)); 377 testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1), 378 makeCursor(0, 3)); 379 testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0)); 380 testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]); 381 testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0)); 382 testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1), 383 makeCursor(charLine.line, 0)); 384 testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1), 385 pChars[0]); 386 testMotion('F', ['F', 'p'], pChars[0], pChars[1]); 387 testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]); 388 testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]); 389 testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]); 390 testMotion('%_parens', ['%'], parens1.end, parens1.start); 391 testMotion('%_squares', ['%'], squares1.end, squares1.start); 392 testMotion('%_braces', ['%'], curlys1.end, curlys1.start); 393 testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start); 394 testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start); 395 testVim('%_seek_skip', function(cm, vim, helpers) { 396 cm.setCursor(0,0); 397 helpers.doKeys(['%']); 398 helpers.assertCursorAt(0,9); 399 }, {value:'01234"("()'}); 400 testVim('%_skip_string', function(cm, vim, helpers) { 401 cm.setCursor(0,0); 402 helpers.doKeys(['%']); 403 helpers.assertCursorAt(0,4); 404 cm.setCursor(0,2); 405 helpers.doKeys(['%']); 406 helpers.assertCursorAt(0,0); 407 }, {value:'(")")'}); 408 testVim('%_skip_comment', function(cm, vim, helpers) { 409 cm.setCursor(0,0); 410 helpers.doKeys(['%']); 411 helpers.assertCursorAt(0,6); 412 cm.setCursor(0,3); 413 helpers.doKeys(['%']); 414 helpers.assertCursorAt(0,0); 415 }, {value:'(/*)*/)'}); 416 // Make sure that moving down after going to the end of a line always leaves you 417 // at the end of a line, but preserves the offset in other cases 418 testVim('Changing lines after Eol operation', function(cm, vim, helpers) { 419 cm.setCursor(0,0); 420 helpers.doKeys(['$']); 421 helpers.doKeys(['j']); 422 // After moving to Eol and then down, we should be at Eol of line 2 423 helpers.assertCursorAt(new Pos(1, lines[1].length - 1)); 424 helpers.doKeys(['j']); 425 // After moving down, we should be at Eol of line 3 426 helpers.assertCursorAt(new Pos(2, lines[2].length - 1)); 427 helpers.doKeys(['h']); 428 helpers.doKeys(['j']); 429 // After moving back one space and then down, since line 4 is shorter than line 2, we should 430 // be at Eol of line 2 - 1 431 helpers.assertCursorAt(new Pos(3, lines[3].length - 1)); 432 helpers.doKeys(['j']); 433 helpers.doKeys(['j']); 434 // After moving down again, since line 3 has enough characters, we should be back to the 435 // same place we were at on line 1 436 helpers.assertCursorAt(new Pos(5, lines[2].length - 2)); 437 }); 438 //making sure gj and gk recover from clipping 439 testVim('gj_gk_clipping', function(cm,vim,helpers){ 440 cm.setCursor(0, 1); 441 helpers.doKeys('g','j','g','j'); 442 helpers.assertCursorAt(2, 1); 443 helpers.doKeys('g','k','g','k'); 444 helpers.assertCursorAt(0, 1); 445 },{value: 'line 1\n\nline 2'}); 446 //testing a mix of j/k and gj/gk 447 testVim('j_k_and_gj_gk', function(cm,vim,helpers){ 448 cm.setSize(120); 449 cm.setCursor(0, 0); 450 //go to the last character on the first line 451 helpers.doKeys('$'); 452 //move up/down on the column within the wrapped line 453 //side-effect: cursor is not locked to eol anymore 454 helpers.doKeys('g','k'); 455 var cur=cm.getCursor(); 456 eq(cur.line,0); 457 is((cur.ch<176),'gk didn\'t move cursor back (1)'); 458 helpers.doKeys('g','j'); 459 helpers.assertCursorAt(0, 176); 460 //should move to character 177 on line 2 (j/k preserve character index within line) 461 helpers.doKeys('j'); 462 //due to different line wrapping, the cursor can be on a different screen-x now 463 //gj and gk preserve screen-x on movement, much like moveV 464 helpers.doKeys('3','g','k'); 465 cur=cm.getCursor(); 466 eq(cur.line,1); 467 is((cur.ch<176),'gk didn\'t move cursor back (2)'); 468 helpers.doKeys('g','j','2','g','j'); 469 //should return to the same character-index 470 helpers.doKeys('k'); 471 helpers.assertCursorAt(0, 176); 472 },{ 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.'}); 473 testVim('gj_gk', function(cm, vim, helpers) { 474 if (phantom) return; 475 cm.setSize(120); 476 // Test top of document edge case. 477 cm.setCursor(0, 4); 478 helpers.doKeys('g', 'j'); 479 helpers.doKeys('10', 'g', 'k'); 480 helpers.assertCursorAt(0, 4); 481 482 // Test moving down preserves column position. 483 helpers.doKeys('g', 'j'); 484 var pos1 = cm.getCursor(); 485 var expectedPos2 = new Pos(0, (pos1.ch - 4) * 2 + 4); 486 helpers.doKeys('g', 'j'); 487 helpers.assertCursorAt(expectedPos2); 488 489 // Move to the last character 490 cm.setCursor(0, 0); 491 // Move left to reset HSPos 492 helpers.doKeys('h'); 493 // Test bottom of document edge case. 494 helpers.doKeys('100', 'g', 'j'); 495 var endingPos = cm.getCursor(); 496 is(endingPos != 0, 'gj should not be on wrapped line 0'); 497 var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); 498 var endingCharCoords = cm.charCoords(endingPos); 499 is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); 500 },{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentionallylongtotestmovementofgjandgkoverwrappedlines.' }); 501 testVim('}', function(cm, vim, helpers) { 502 cm.setCursor(0, 0); 503 helpers.doKeys('}'); 504 helpers.assertCursorAt(1, 0); 505 cm.setCursor(0, 0); 506 helpers.doKeys('2', '}'); 507 helpers.assertCursorAt(4, 0); 508 cm.setCursor(0, 0); 509 helpers.doKeys('6', '}'); 510 helpers.assertCursorAt(5, 0); 511 }, { value: 'a\n\nb\nc\n\nd' }); 512 testVim('{', function(cm, vim, helpers) { 513 cm.setCursor(5, 0); 514 helpers.doKeys('{'); 515 helpers.assertCursorAt(4, 0); 516 cm.setCursor(5, 0); 517 helpers.doKeys('2', '{'); 518 helpers.assertCursorAt(1, 0); 519 cm.setCursor(5, 0); 520 helpers.doKeys('6', '{'); 521 helpers.assertCursorAt(0, 0); 522 }, { value: 'a\n\nb\nc\n\nd' }); 523 testVim('(', function(cm, vim, helpers) { 524 cm.setCursor(6, 23); 525 helpers.doKeys('('); 526 helpers.assertCursorAt(6, 14); 527 helpers.doKeys('2', '('); 528 helpers.assertCursorAt(5, 0); 529 helpers.doKeys('('); 530 helpers.assertCursorAt(4, 0); 531 helpers.doKeys('('); 532 helpers.assertCursorAt(3, 0); 533 helpers.doKeys('('); 534 helpers.assertCursorAt(2, 0); 535 helpers.doKeys('('); 536 helpers.assertCursorAt(0, 0); 537 helpers.doKeys('('); 538 helpers.assertCursorAt(0, 0); 539 }, { value: 'sentence1.\n\n\nsentence2\n\nsentence3. sentence4\n sentence5? sentence6!' }); 540 testVim(')', function(cm, vim, helpers) { 541 cm.setCursor(0, 0); 542 helpers.doKeys('2', ')'); 543 helpers.assertCursorAt(3, 0); 544 helpers.doKeys(')'); 545 helpers.assertCursorAt(4, 0); 546 helpers.doKeys(')'); 547 helpers.assertCursorAt(5, 0); 548 helpers.doKeys(')'); 549 helpers.assertCursorAt(5, 11); 550 helpers.doKeys(')'); 551 helpers.assertCursorAt(6, 14); 552 helpers.doKeys(')'); 553 helpers.assertCursorAt(6, 23); 554 helpers.doKeys(')'); 555 helpers.assertCursorAt(6, 23); 556 }, { value: 'sentence1.\n\n\nsentence2\n\nsentence3. sentence4\n sentence5? sentence6!' }); 557 testVim('paragraph_motions', function(cm, vim, helpers) { 558 cm.setCursor(10, 0); 559 helpers.doKeys('{'); 560 helpers.assertCursorAt(4, 0); 561 helpers.doKeys('{'); 562 helpers.assertCursorAt(0, 0); 563 helpers.doKeys('2', '}'); 564 helpers.assertCursorAt(7, 0); 565 helpers.doKeys('2', '}'); 566 helpers.assertCursorAt(16, 0); 567 568 cm.setCursor(9, 0); 569 helpers.doKeys('}'); 570 helpers.assertCursorAt(14, 0); 571 572 cm.setCursor(6, 0); 573 helpers.doKeys('}'); 574 helpers.assertCursorAt(7, 0); 575 576 // ip inside empty space 577 cm.setCursor(10, 0); 578 helpers.doKeys('v', 'i', 'p'); 579 eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); 580 eqCursorPos(Pos(12, 0), cm.getCursor('head')); 581 helpers.doKeys('i', 'p'); 582 eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); 583 eqCursorPos(Pos(13, 1), cm.getCursor('head')); 584 helpers.doKeys('2', 'i', 'p'); 585 eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); 586 eqCursorPos(Pos(16, 1), cm.getCursor('head')); 587 588 // should switch to visualLine mode 589 cm.setCursor(14, 0); 590 helpers.doKeys('<Esc>', 'v', 'i', 'p'); 591 helpers.assertCursorAt(14, 0); 592 593 cm.setCursor(14, 0); 594 helpers.doKeys('<Esc>', 'V', 'i', 'p'); 595 eqCursorPos(Pos(16, 1), cm.getCursor('head')); 596 597 // ap inside empty space 598 cm.setCursor(10, 0); 599 helpers.doKeys('<Esc>', 'v', 'a', 'p'); 600 eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); 601 eqCursorPos(Pos(13, 1), cm.getCursor('head')); 602 helpers.doKeys('a', 'p'); 603 eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); 604 eqCursorPos(Pos(16, 1), cm.getCursor('head')); 605 606 cm.setCursor(13, 0); 607 helpers.doKeys('v', 'a', 'p'); 608 eqCursorPos(Pos(13, 0), cm.getCursor('anchor')); 609 eqCursorPos(Pos(14, 0), cm.getCursor('head')); 610 611 cm.setCursor(16, 0); 612 helpers.doKeys('v', 'a', 'p'); 613 eqCursorPos(Pos(14, 0), cm.getCursor('anchor')); 614 eqCursorPos(Pos(16, 1), cm.getCursor('head')); 615 616 cm.setCursor(0, 0); 617 helpers.doKeys('v', 'a', 'p'); 618 eqCursorPos(Pos(0, 0), cm.getCursor('anchor')); 619 eqCursorPos(Pos(4, 0), cm.getCursor('head')); 620 621 cm.setCursor(0, 0); 622 helpers.doKeys('d', 'i', 'p'); 623 var register = helpers.getRegisterController().getRegister(); 624 eq('a\na\n', register.toString()); 625 is(register.linewise); 626 helpers.doKeys('3', 'j', 'p'); 627 helpers.doKeys('y', 'i', 'p'); 628 is(register.linewise); 629 eq('b\na\na\nc\n', register.toString()); 630 }, { value: 'a\na\n\n\n\nb\nc\n\n\n\n\n\n\nd\n\ne\nf' }); 631 632 // Operator tests 633 testVim('dl', function(cm, vim, helpers) { 634 var curStart = makeCursor(0, 0); 635 cm.setCursor(curStart); 636 helpers.doKeys('d', 'l'); 637 eq('word1 ', cm.getValue()); 638 var register = helpers.getRegisterController().getRegister(); 639 eq(' ', register.toString()); 640 is(!register.linewise); 641 eqCursorPos(curStart, cm.getCursor()); 642 }, { value: ' word1 ' }); 643 testVim('dl_eol', function(cm, vim, helpers) { 644 cm.setCursor(0, 6); 645 helpers.doKeys('d', 'l'); 646 eq(' word1', cm.getValue()); 647 var register = helpers.getRegisterController().getRegister(); 648 eq(' ', register.toString()); 649 is(!register.linewise); 650 helpers.assertCursorAt(0, 5); 651 }, { value: ' word1 ' }); 652 testVim('dl_repeat', function(cm, vim, helpers) { 653 var curStart = makeCursor(0, 0); 654 cm.setCursor(curStart); 655 helpers.doKeys('2', 'd', 'l'); 656 eq('ord1 ', cm.getValue()); 657 var register = helpers.getRegisterController().getRegister(); 658 eq(' w', register.toString()); 659 is(!register.linewise); 660 eqCursorPos(curStart, cm.getCursor()); 661 }, { value: ' word1 ' }); 662 testVim('dh', function(cm, vim, helpers) { 663 var curStart = makeCursor(0, 3); 664 cm.setCursor(curStart); 665 helpers.doKeys('d', 'h'); 666 eq(' wrd1 ', cm.getValue()); 667 var register = helpers.getRegisterController().getRegister(); 668 eq('o', register.toString()); 669 is(!register.linewise); 670 eqCursorPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); 671 }, { value: ' word1 ' }); 672 testVim('dj', function(cm, vim, helpers) { 673 var curStart = makeCursor(0, 3); 674 cm.setCursor(curStart); 675 helpers.doKeys('d', 'j'); 676 eq(' word3', cm.getValue()); 677 var register = helpers.getRegisterController().getRegister(); 678 eq(' word1\nword2\n', register.toString()); 679 is(register.linewise); 680 helpers.assertCursorAt(0, 1); 681 }, { value: ' word1\nword2\n word3' }); 682 testVim('dj_end_of_document', function(cm, vim, helpers) { 683 var curStart = makeCursor(0, 3); 684 cm.setCursor(curStart); 685 helpers.doKeys('d', 'j'); 686 eq('', cm.getValue()); 687 var register = helpers.getRegisterController().getRegister(); 688 eq(' word1 \n', register.toString()); 689 is(register.linewise); 690 helpers.assertCursorAt(0, 0); 691 }, { value: ' word1 ' }); 692 testVim('dk', function(cm, vim, helpers) { 693 var curStart = makeCursor(1, 3); 694 cm.setCursor(curStart); 695 helpers.doKeys('d', 'k'); 696 eq(' word3', cm.getValue()); 697 var register = helpers.getRegisterController().getRegister(); 698 eq(' word1\nword2\n', register.toString()); 699 is(register.linewise); 700 helpers.assertCursorAt(0, 1); 701 }, { value: ' word1\nword2\n word3' }); 702 testVim('dk_start_of_document', function(cm, vim, helpers) { 703 var curStart = makeCursor(0, 3); 704 cm.setCursor(curStart); 705 helpers.doKeys('d', 'k'); 706 eq('', cm.getValue()); 707 var register = helpers.getRegisterController().getRegister(); 708 eq(' word1 \n', register.toString()); 709 is(register.linewise); 710 helpers.assertCursorAt(0, 0); 711 }, { value: ' word1 ' }); 712 testVim('dw_space', function(cm, vim, helpers) { 713 var curStart = makeCursor(0, 0); 714 cm.setCursor(curStart); 715 helpers.doKeys('d', 'w'); 716 eq('word1 ', cm.getValue()); 717 var register = helpers.getRegisterController().getRegister(); 718 eq(' ', register.toString()); 719 is(!register.linewise); 720 eqCursorPos(curStart, cm.getCursor()); 721 }, { value: ' word1 ' }); 722 testVim('dw_word', function(cm, vim, helpers) { 723 var curStart = makeCursor(0, 1); 724 cm.setCursor(curStart); 725 helpers.doKeys('d', 'w'); 726 eq(' word2', cm.getValue()); 727 var register = helpers.getRegisterController().getRegister(); 728 eq('word1 ', register.toString()); 729 is(!register.linewise); 730 eqCursorPos(curStart, cm.getCursor()); 731 }, { value: ' word1 word2' }); 732 testVim('dw_unicode_word', function(cm, vim, helpers) { 733 helpers.doKeys('d', 'w'); 734 eq(cm.getValue().length, 10); 735 helpers.doKeys('d', 'w'); 736 eq(cm.getValue().length, 6); 737 helpers.doKeys('d', 'w'); 738 eq(cm.getValue().length, 5); 739 helpers.doKeys('d', 'e'); 740 eq(cm.getValue().length, 2); 741 }, { value: ' \u0562\u0561\u0580\u0587\xbbe\xb5g ' }); 742 testVim('dw_only_word', function(cm, vim, helpers) { 743 // Test that if there is only 1 word left, dw deletes till the end of the 744 // line. 745 cm.setCursor(0, 1); 746 helpers.doKeys('d', 'w'); 747 eq(' ', cm.getValue()); 748 var register = helpers.getRegisterController().getRegister(); 749 eq('word1 ', register.toString()); 750 is(!register.linewise); 751 helpers.assertCursorAt(0, 0); 752 }, { value: ' word1 ' }); 753 testVim('dw_eol', function(cm, vim, helpers) { 754 // Assert that dw does not delete the newline if last word to delete is at end 755 // of line. 756 cm.setCursor(0, 1); 757 helpers.doKeys('d', 'w'); 758 eq(' \nword2', cm.getValue()); 759 var register = helpers.getRegisterController().getRegister(); 760 eq('word1', register.toString()); 761 is(!register.linewise); 762 helpers.assertCursorAt(0, 0); 763 }, { value: ' word1\nword2' }); 764 testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) { 765 // Assert that dw does not delete the newline if last word to delete is at end 766 // of line and it is followed by multiple newlines. 767 cm.setCursor(0, 1); 768 helpers.doKeys('d', 'w'); 769 eq(' \n\nword2', cm.getValue()); 770 var register = helpers.getRegisterController().getRegister(); 771 eq('word1', register.toString()); 772 is(!register.linewise); 773 helpers.assertCursorAt(0, 0); 774 }, { value: ' word1\n\nword2' }); 775 testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) { 776 cm.setCursor(0, 0); 777 helpers.doKeys('d', 'w'); 778 eq(' \nword', cm.getValue()); 779 }, { value: '\n \nword' }); 780 testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) { 781 cm.setCursor(0, 0); 782 helpers.doKeys('d', 'w'); 783 eq('word', cm.getValue()); 784 }, { value: '\nword' }); 785 testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) { 786 cm.setCursor(0, 0); 787 helpers.doKeys('d', 'w'); 788 eq('\n', cm.getValue()); 789 }, { value: '\n\n' }); 790 testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) { 791 cm.setCursor(0, 0); 792 helpers.doKeys('d', 'w'); 793 eq('\n \n', cm.getValue()); 794 }, { value: ' \n \n' }); 795 testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) { 796 cm.setCursor(0, 0); 797 helpers.doKeys('d', 'w'); 798 eq('\n\n', cm.getValue()); 799 }, { value: ' \n\n' }); 800 testVim('dw_word_whitespace_word', function(cm, vim, helpers) { 801 cm.setCursor(0, 0); 802 helpers.doKeys('d', 'w'); 803 eq('\n \nword2', cm.getValue()); 804 }, { value: 'word1\n \nword2'}) 805 testVim('dw_end_of_document', function(cm, vim, helpers) { 806 cm.setCursor(1, 2); 807 helpers.doKeys('d', 'w'); 808 eq('\nab', cm.getValue()); 809 }, { value: '\nabc' }); 810 testVim('dw_repeat', function(cm, vim, helpers) { 811 // Assert that dw does delete newline if it should go to the next line, and 812 // that repeat works properly. 813 cm.setCursor(0, 1); 814 helpers.doKeys('d', '2', 'w'); 815 eq(' ', cm.getValue()); 816 var register = helpers.getRegisterController().getRegister(); 817 eq('word1\nword2', register.toString()); 818 is(!register.linewise); 819 helpers.assertCursorAt(0, 0); 820 }, { value: ' word1\nword2' }); 821 testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) { 822 cm.setCursor(0, 0); 823 helpers.doKeys('d', 'e'); 824 eq('\n\n', cm.getValue()); 825 }, { value: 'word\n\n' }); 826 testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) { 827 cm.setCursor(0, 3); 828 helpers.doKeys('d', 'e'); 829 eq('wor', cm.getValue()); 830 }, { value: 'word\n\n\n' }); 831 testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) { 832 cm.setCursor(0, 0); 833 helpers.doKeys('d', 'e'); 834 eq('', cm.getValue()); 835 }, { value: ' \n\n\n' }); 836 testVim('de_end_of_document', function(cm, vim, helpers) { 837 cm.setCursor(1, 2); 838 helpers.doKeys('d', 'e'); 839 eq('\nab', cm.getValue()); 840 }, { value: '\nabc' }); 841 testVim('db_empty_lines', function(cm, vim, helpers) { 842 cm.setCursor(2, 0); 843 helpers.doKeys('d', 'b'); 844 eq('\n\n', cm.getValue()); 845 }, { value: '\n\n\n' }); 846 testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) { 847 cm.setCursor(2, 0); 848 helpers.doKeys('d', 'b'); 849 eq('\nword', cm.getValue()); 850 }, { value: '\n\nword' }); 851 testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) { 852 cm.setCursor(2, 3); 853 helpers.doKeys('d', 'b'); 854 eq('\n\nd', cm.getValue()); 855 }, { value: '\n\nword' }); 856 testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) { 857 cm.setCursor(2, 0); 858 helpers.doKeys('d', 'b'); 859 eq('', cm.getValue()); 860 }, { value: '\n \n' }); 861 testVim('db_start_of_document', function(cm, vim, helpers) { 862 cm.setCursor(0, 0); 863 helpers.doKeys('d', 'b'); 864 eq('abc\n', cm.getValue()); 865 }, { value: 'abc\n' }); 866 testVim('dge_empty_lines', function(cm, vim, helpers) { 867 cm.setCursor(1, 0); 868 helpers.doKeys('d', 'g', 'e'); 869 // Note: In real VIM the result should be '', but it's not quite consistent, 870 // since 2 newlines are deleted. But in the similar case of word\n\n, only 871 // 1 newline is deleted. We'll diverge from VIM's behavior since it's much 872 // easier this way. 873 eq('\n', cm.getValue()); 874 }, { value: '\n\n' }); 875 testVim('dge_word_and_empty_lines', function(cm, vim, helpers) { 876 cm.setCursor(1, 0); 877 helpers.doKeys('d', 'g', 'e'); 878 eq('wor\n', cm.getValue()); 879 }, { value: 'word\n\n'}); 880 testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) { 881 cm.setCursor(2, 0); 882 helpers.doKeys('d', 'g', 'e'); 883 eq('', cm.getValue()); 884 }, { value: '\n \n' }); 885 testVim('dge_start_of_document', function(cm, vim, helpers) { 886 cm.setCursor(0, 0); 887 helpers.doKeys('d', 'g', 'e'); 888 eq('bc\n', cm.getValue()); 889 }, { value: 'abc\n' }); 890 testVim('d_inclusive', function(cm, vim, helpers) { 891 // Assert that when inclusive is set, the character the cursor is on gets 892 // deleted too. 893 var curStart = makeCursor(0, 1); 894 cm.setCursor(curStart); 895 helpers.doKeys('d', 'e'); 896 eq(' ', cm.getValue()); 897 var register = helpers.getRegisterController().getRegister(); 898 eq('word1', register.toString()); 899 is(!register.linewise); 900 eqCursorPos(curStart, cm.getCursor()); 901 }, { value: ' word1 ' }); 902 testVim('d_reverse', function(cm, vim, helpers) { 903 // Test that deleting in reverse works. 904 cm.setCursor(1, 0); 905 helpers.doKeys('d', 'b'); 906 eq(' word2 ', cm.getValue()); 907 var register = helpers.getRegisterController().getRegister(); 908 eq('word1\n', register.toString()); 909 is(!register.linewise); 910 helpers.assertCursorAt(0, 1); 911 }, { value: ' word1\nword2 ' }); 912 testVim('dd', function(cm, vim, helpers) { 913 cm.setCursor(0, 3); 914 var expectedBuffer = cm.getRange(new Pos(0, 0), 915 new Pos(1, 0)); 916 var expectedLineCount = cm.lineCount() - 1; 917 helpers.doKeys('d', 'd'); 918 eq(expectedLineCount, cm.lineCount()); 919 var register = helpers.getRegisterController().getRegister(); 920 eq(expectedBuffer, register.toString()); 921 is(register.linewise); 922 helpers.assertCursorAt(0, lines[1].textStart); 923 }); 924 testVim('dd_prefix_repeat', function(cm, vim, helpers) { 925 cm.setCursor(0, 3); 926 var expectedBuffer = cm.getRange(new Pos(0, 0), 927 new Pos(2, 0)); 928 var expectedLineCount = cm.lineCount() - 2; 929 helpers.doKeys('2', 'd', 'd'); 930 eq(expectedLineCount, cm.lineCount()); 931 var register = helpers.getRegisterController().getRegister(); 932 eq(expectedBuffer, register.toString()); 933 is(register.linewise); 934 helpers.assertCursorAt(0, lines[2].textStart); 935 }); 936 testVim('dd_motion_repeat', function(cm, vim, helpers) { 937 cm.setCursor(0, 3); 938 var expectedBuffer = cm.getRange(new Pos(0, 0), 939 new Pos(2, 0)); 940 var expectedLineCount = cm.lineCount() - 2; 941 helpers.doKeys('d', '2', 'd'); 942 eq(expectedLineCount, cm.lineCount()); 943 var register = helpers.getRegisterController().getRegister(); 944 eq(expectedBuffer, register.toString()); 945 is(register.linewise); 946 helpers.assertCursorAt(0, lines[2].textStart); 947 }); 948 testVim('dd_multiply_repeat', function(cm, vim, helpers) { 949 cm.setCursor(0, 3); 950 var expectedBuffer = cm.getRange(new Pos(0, 0), 951 new Pos(6, 0)); 952 var expectedLineCount = cm.lineCount() - 6; 953 helpers.doKeys('2', 'd', '3', 'd'); 954 eq(expectedLineCount, cm.lineCount()); 955 var register = helpers.getRegisterController().getRegister(); 956 eq(expectedBuffer, register.toString()); 957 is(register.linewise); 958 helpers.assertCursorAt(0, lines[6].textStart); 959 }); 960 testVim('dd_lastline', function(cm, vim, helpers) { 961 cm.setCursor(cm.lineCount(), 0); 962 var expectedLineCount = cm.lineCount() - 1; 963 helpers.doKeys('d', 'd'); 964 eq(expectedLineCount, cm.lineCount()); 965 helpers.assertCursorAt(cm.lineCount() - 1, 0); 966 }); 967 testVim('dd_only_line', function(cm, vim, helpers) { 968 cm.setCursor(0, 0); 969 var expectedRegister = cm.getValue() + "\n"; 970 helpers.doKeys('d','d'); 971 eq(1, cm.lineCount()); 972 eq('', cm.getValue()); 973 var register = helpers.getRegisterController().getRegister(); 974 eq(expectedRegister, register.toString()); 975 }, { value: "thisistheonlyline" }); 976 // Yank commands should behave the exact same as d commands, expect that nothing 977 // gets deleted. 978 testVim('yw_repeat', function(cm, vim, helpers) { 979 // Assert that yw does yank newline if it should go to the next line, and 980 // that repeat works properly. 981 var curStart = makeCursor(0, 1); 982 cm.setCursor(curStart); 983 helpers.doKeys('y', '2', 'w'); 984 eq(' word1\nword2', cm.getValue()); 985 var register = helpers.getRegisterController().getRegister(); 986 eq('word1\nword2', register.toString()); 987 is(!register.linewise); 988 eqCursorPos(curStart, cm.getCursor()); 989 }, { value: ' word1\nword2' }); 990 testVim('yy_multiply_repeat', function(cm, vim, helpers) { 991 var curStart = makeCursor(0, 3); 992 cm.setCursor(curStart); 993 var expectedBuffer = cm.getRange(new Pos(0, 0), 994 new Pos(6, 0)); 995 var expectedLineCount = cm.lineCount(); 996 helpers.doKeys('2', 'y', '3', 'y'); 997 eq(expectedLineCount, cm.lineCount()); 998 var register = helpers.getRegisterController().getRegister(); 999 eq(expectedBuffer, register.toString()); 1000 is(register.linewise); 1001 eqCursorPos(curStart, cm.getCursor()); 1002 }); 1003 testVim('2dd_blank_P', function(cm, vim, helpers) { 1004 helpers.doKeys('2', 'd', 'd', 'P'); 1005 eq('\na\n\n', cm.getValue()); 1006 }, { value: '\na\n\n' }); 1007 // Change commands behave like d commands except that it also enters insert 1008 // mode. In addition, when the change is linewise, an additional newline is 1009 // inserted so that insert mode starts on that line. 1010 testVim('cw', function(cm, vim, helpers) { 1011 cm.setCursor(0, 0); 1012 helpers.doKeys('c', '2', 'w'); 1013 eq(' word3', cm.getValue()); 1014 helpers.assertCursorAt(0, 0); 1015 }, { value: 'word1 word2 word3'}); 1016 testVim('cw_repeat', function(cm, vim, helpers) { 1017 // Assert that cw does delete newline if it should go to the next line, and 1018 // that repeat works properly. 1019 var curStart = makeCursor(0, 1); 1020 cm.setCursor(curStart); 1021 helpers.doKeys('c', '2', 'w'); 1022 eq(' ', cm.getValue()); 1023 var register = helpers.getRegisterController().getRegister(); 1024 eq('word1\nword2', register.toString()); 1025 is(!register.linewise); 1026 eqCursorPos(curStart, cm.getCursor()); 1027 eq('vim-insert', cm.getOption('keyMap')); 1028 }, { value: ' word1\nword2' }); 1029 testVim('cc_multiply_repeat', function(cm, vim, helpers) { 1030 cm.setCursor(0, 3); 1031 var expectedBuffer = cm.getRange(new Pos(0, 0), 1032 new Pos(6, 0)); 1033 var expectedLineCount = cm.lineCount() - 5; 1034 helpers.doKeys('2', 'c', '3', 'c'); 1035 eq(expectedLineCount, cm.lineCount()); 1036 var register = helpers.getRegisterController().getRegister(); 1037 eq(expectedBuffer, register.toString()); 1038 is(register.linewise); 1039 eq('vim-insert', cm.getOption('keyMap')); 1040 }); 1041 testVim('ct', function(cm, vim, helpers) { 1042 cm.setCursor(0, 9); 1043 helpers.doKeys('c', 't', 'w'); 1044 eq(' word1 word3', cm.getValue()); 1045 helpers.doKeys('<Esc>', 'c', '|'); 1046 eq(' word3', cm.getValue()); 1047 helpers.assertCursorAt(0, 0); 1048 helpers.doKeys('<Esc>', '2', 'u', 'w', 'h'); 1049 helpers.doKeys('c', '2', 'g', 'e'); 1050 eq(' wordword3', cm.getValue()); 1051 }, { value: ' word1 word2 word3'}); 1052 testVim('cc_should_not_append_to_document', function(cm, vim, helpers) { 1053 var expectedLineCount = cm.lineCount(); 1054 cm.setCursor(cm.lastLine(), 0); 1055 helpers.doKeys('c', 'c'); 1056 eq(expectedLineCount, cm.lineCount()); 1057 }); 1058 function fillArray(val, times) { 1059 var arr = []; 1060 for (var i = 0; i < times; i++) { 1061 arr.push(val); 1062 } 1063 return arr; 1064 } 1065 testVim('c_visual_block', function(cm, vim, helpers) { 1066 cm.setCursor(0, 1); 1067 helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'l', 'c'); 1068 helpers.doKeys('hello'); 1069 eq('1hello\n5hello\nahellofg', cm.getValue()); 1070 helpers.doKeys('<Esc>'); 1071 cm.setCursor(2, 3); 1072 helpers.doKeys('<C-v>', '2', 'k', 'h', 'C'); 1073 helpers.doKeys('world'); 1074 eq('1hworld\n5hworld\nahworld', cm.getValue()); 1075 }, {value: '1234\n5678\nabcdefg'}); 1076 testVim('c_visual_block_replay', function(cm, vim, helpers) { 1077 cm.setCursor(0, 1); 1078 helpers.doKeys('<C-v>', '2', 'j', 'l', 'c'); 1079 helpers.doKeys('fo'); 1080 eq('1fo4\n5fo8\nafodefg', cm.getValue()); 1081 helpers.doKeys('<Esc>'); 1082 cm.setCursor(0, 0); 1083 helpers.doKeys('.'); 1084 eq('foo4\nfoo8\nfoodefg', cm.getValue()); 1085 }, {value: '1234\n5678\nabcdefg'}); 1086 testVim('I_visual_block_replay', function(cm, vim, helpers) { 1087 cm.setCursor(0, 2); 1088 helpers.doKeys('<C-v>', '2', 'j', 'l', 'I'); 1089 helpers.doKeys('+-') 1090 eq('12+-34\n56+-78\nab+-cdefg\nxyz', cm.getValue()); 1091 helpers.doKeys('<Esc>'); 1092 // ensure that repeat location doesn't depend on last selection 1093 cm.setCursor(3, 2); 1094 helpers.doKeys('g', 'v') 1095 eq("+-34\n+-78\n+-cd", cm.getSelection()) 1096 cm.setCursor(0, 3); 1097 helpers.doKeys('<C-v>', '1', 'j', '2', 'l'); 1098 eq("-34\n-78", cm.getSelection()); 1099 cm.setCursor(0, 0); 1100 eq("", cm.getSelection()); 1101 helpers.doKeys('g', 'v'); 1102 eq("-34\n-78", cm.getSelection()); 1103 cm.setCursor(1, 1); 1104 helpers.doKeys('.'); 1105 eq('12+-34\n5+-6+-78\na+-b+-cdefg\nx+-yz', cm.getValue()); 1106 }, {value: '1234\n5678\nabcdefg\nxyz'}); 1107 1108 testVim('d_visual_block', function(cm, vim, helpers) { 1109 cm.setCursor(0, 1); 1110 helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'l', 'd'); 1111 eq('1\n5\nafg', cm.getValue()); 1112 }, {value: '1234\n5678\nabcdefg'}); 1113 testVim('D_visual_block', function(cm, vim, helpers) { 1114 cm.setCursor(0, 1); 1115 helpers.doKeys('<C-v>', '2', 'j', 'l', 'D'); 1116 eq('1\n5\na', cm.getValue()); 1117 }, {value: '1234\n5678\nabcdefg'}); 1118 1119 testVim('s_visual_block', function(cm, vim, helpers) { 1120 cm.setCursor(0, 1); 1121 helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'l', 's'); 1122 helpers.doKeys('hello{'); 1123 eq('1hello{\n5hello{\nahello{fg\n', cm.getValue()); 1124 helpers.doKeys('<Esc>'); 1125 cm.setCursor(2, 3); 1126 helpers.doKeys('<C-v>', '1', 'k', 'h', 'S'); 1127 helpers.doKeys('world'); 1128 eq('1hello{\n world\n', cm.getValue()); 1129 }, {value: '1234\n5678\nabcdefg\n'}); 1130 1131 // Swapcase commands edit in place and do not modify registers. 1132 testVim('g~w_repeat', function(cm, vim, helpers) { 1133 // Assert that dw does delete newline if it should go to the next line, and 1134 // that repeat works properly. 1135 var curStart = makeCursor(0, 1); 1136 cm.setCursor(curStart); 1137 helpers.doKeys('g', '~', '2', 'w'); 1138 eq(' WORD1\nWORD2', cm.getValue()); 1139 var register = helpers.getRegisterController().getRegister(); 1140 eq('', register.toString()); 1141 is(!register.linewise); 1142 eqCursorPos(curStart, cm.getCursor()); 1143 }, { value: ' word1\nword2' }); 1144 testVim('g~g~', function(cm, vim, helpers) { 1145 var curStart = makeCursor(0, 3); 1146 cm.setCursor(curStart); 1147 var expectedLineCount = cm.lineCount(); 1148 var expectedValue = cm.getValue().toUpperCase(); 1149 helpers.doKeys('2', 'g', '~', '3', 'g', '~'); 1150 eq(expectedValue, cm.getValue()); 1151 var register = helpers.getRegisterController().getRegister(); 1152 eq('', register.toString()); 1153 is(!register.linewise); 1154 eqCursorPos(curStart, cm.getCursor()); 1155 }, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); 1156 testVim('gu_and_gU', function(cm, vim, helpers) { 1157 var curStart = makeCursor(0, 7); 1158 var value = cm.getValue(); 1159 cm.setCursor(curStart); 1160 helpers.doKeys('2', 'g', 'U', 'w'); 1161 eq(cm.getValue(), 'wa wb xX WC wd'); 1162 eqCursorPos(curStart, cm.getCursor()); 1163 helpers.doKeys('2', 'g', 'u', 'w'); 1164 eq(cm.getValue(), value); 1165 1166 helpers.doKeys('2', 'g', 'U', 'B'); 1167 eq(cm.getValue(), 'wa WB Xx wc wd'); 1168 eqCursorPos(makeCursor(0, 3), cm.getCursor()); 1169 1170 cm.setCursor(makeCursor(0, 4)); 1171 helpers.doKeys('g', 'u', 'i', 'w'); 1172 eq(cm.getValue(), 'wa wb Xx wc wd'); 1173 eqCursorPos(makeCursor(0, 3), cm.getCursor()); 1174 1175 // TODO: support gUgU guu 1176 // eqCursorPos(makeCursor(0, 0), cm.getCursor()); 1177 1178 var register = helpers.getRegisterController().getRegister(); 1179 eq('', register.toString()); 1180 is(!register.linewise); 1181 }, { value: 'wa wb xx wc wd' }); 1182 testVim('visual_block_~', function(cm, vim, helpers) { 1183 cm.setCursor(1, 1); 1184 helpers.doKeys('<C-v>', 'l', 'l', 'j', '~'); 1185 helpers.assertCursorAt(1, 1); 1186 eq('hello\nwoRLd\naBCDe', cm.getValue()); 1187 cm.setCursor(2, 0); 1188 helpers.doKeys('v', 'l', 'l', '~'); 1189 helpers.assertCursorAt(2, 0); 1190 eq('hello\nwoRLd\nAbcDe', cm.getValue()); 1191 },{value: 'hello\nwOrld\nabcde' }); 1192 testVim('._swapCase_visualBlock', function(cm, vim, helpers) { 1193 helpers.doKeys('<C-v>', 'j', 'j', 'l', '~'); 1194 cm.setCursor(0, 3); 1195 helpers.doKeys('.'); 1196 eq('HelLO\nWorLd\nAbcdE', cm.getValue()); 1197 },{value: 'hEllo\nwOrlD\naBcDe' }); 1198 testVim('._delete_visualBlock', function(cm, vim, helpers) { 1199 helpers.doKeys('<C-v>', 'j', 'x'); 1200 eq('ive\ne\nsome\nsugar', cm.getValue()); 1201 helpers.doKeys('.'); 1202 eq('ve\n\nsome\nsugar', cm.getValue()); 1203 helpers.doKeys('j', 'j', '.'); 1204 eq('ve\n\nome\nugar', cm.getValue()); 1205 helpers.doKeys('u', '<C-r>', '.'); 1206 eq('ve\n\nme\ngar', cm.getValue()); 1207 },{value: 'give\nme\nsome\nsugar' }); 1208 testVim('>{motion}', function(cm, vim, helpers) { 1209 cm.setCursor(1, 3); 1210 var expectedLineCount = cm.lineCount(); 1211 var expectedValue = ' word1\n word2\nword3 '; 1212 helpers.doKeys('>', 'k'); 1213 eq(expectedValue, cm.getValue()); 1214 var register = helpers.getRegisterController().getRegister(); 1215 eq('', register.toString()); 1216 is(!register.linewise); 1217 helpers.assertCursorAt(0, 3); 1218 }, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); 1219 testVim('>>', function(cm, vim, helpers) { 1220 cm.setCursor(0, 3); 1221 var expectedLineCount = cm.lineCount(); 1222 var expectedValue = ' word1\n word2\nword3 '; 1223 helpers.doKeys('2', '>', '>'); 1224 eq(expectedValue, cm.getValue()); 1225 var register = helpers.getRegisterController().getRegister(); 1226 eq('', register.toString()); 1227 is(!register.linewise); 1228 helpers.assertCursorAt(0, 3); 1229 }, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); 1230 testVim('<{motion}', function(cm, vim, helpers) { 1231 cm.setCursor(1, 3); 1232 var expectedLineCount = cm.lineCount(); 1233 var expectedValue = ' word1\nword2\nword3 '; 1234 helpers.doKeys('<', 'k'); 1235 eq(expectedValue, cm.getValue()); 1236 var register = helpers.getRegisterController().getRegister(); 1237 eq('', register.toString()); 1238 is(!register.linewise); 1239 helpers.assertCursorAt(0, 1); 1240 }, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); 1241 testVim('<<', function(cm, vim, helpers) { 1242 cm.setCursor(0, 3); 1243 var expectedLineCount = cm.lineCount(); 1244 var expectedValue = ' word1\nword2\nword3 '; 1245 helpers.doKeys('2', '<', '<'); 1246 eq(expectedValue, cm.getValue()); 1247 var register = helpers.getRegisterController().getRegister(); 1248 eq('', register.toString()); 1249 is(!register.linewise); 1250 helpers.assertCursorAt(0, 1); 1251 }, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); 1252 testVim('=', function(cm, vim, helpers) { 1253 cm.setCursor(0, 3); 1254 helpers.doKeys('<C-v>', 'j', 'j'); 1255 var expectedValue = 'word1\nword2\nword3'; 1256 helpers.doKeys('='); 1257 eq(expectedValue, cm.getValue()); 1258 }, { value: ' word1\n word2\n word3', indentUnit: 2 }); 1259 1260 // Edit tests 1261 function testEdit(name, before, pos, edit, after) { 1262 return testVim(name, function(cm, vim, helpers) { 1263 var ch = before.search(pos) 1264 var line = before.substring(0, ch).split('\n').length - 1; 1265 if (line) { 1266 ch = before.substring(0, ch).split('\n').pop().length; 1267 } 1268 cm.setCursor(line, ch); 1269 helpers.doKeys.apply(this, edit.split('')); 1270 eq(after, cm.getValue()); 1271 }, {value: before}); 1272 } 1273 1274 // These Delete tests effectively cover word-wise Change, Visual & Yank. 1275 // Tabs are used as differentiated whitespace to catch edge cases. 1276 // Normal word: 1277 testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz'); 1278 testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz'); 1279 testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz'); 1280 testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz'); 1281 testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz'); 1282 testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz'); 1283 testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz'); 1284 testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz'); 1285 testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz'); 1286 testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz'); 1287 testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t'); 1288 testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo'); 1289 testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.'); 1290 testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.'); 1291 // Big word: 1292 testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz'); 1293 testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz'); 1294 testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz'); 1295 testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz'); 1296 testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz'); 1297 testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz'); 1298 testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz'); 1299 testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz'); 1300 testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz'); 1301 testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz'); 1302 testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t'); 1303 testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo'); 1304 testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t'); 1305 testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo'); 1306 // Deleting text objects 1307 // Open and close on same line 1308 testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz'); 1309 testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz'); 1310 testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz'); 1311 testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz'); 1312 testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz'); 1313 1314 testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz'); 1315 testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz'); 1316 testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz'); 1317 testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz'); 1318 1319 testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz'); 1320 testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz'); 1321 testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz'); 1322 testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz'); 1323 1324 testEdit('di`', 'foo `bAr` baz', /`/, 'di`', 'foo `` baz'); 1325 testEdit('di>', 'foo <bAr> baz', /</, 'di>', 'foo <> baz'); 1326 testEdit('da<', 'foo <bAr> baz', /</, 'da<', 'foo baz'); 1327 1328 // delete around and inner b. 1329 testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )'); 1330 1331 // delete around and inner B. 1332 testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }'); 1333 testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }'); 1334 1335 testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }'); 1336 testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz'); 1337 testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz'); 1338 testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz'); 1339 testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz'); 1340 testMotion('di(_outside_should_stay', ['d', 'i', '('], new Pos(0, 0), new Pos(0, 0)); 1341 1342 // Open and close on different lines, equally indented 1343 testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); 1344 testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b'); 1345 testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab'); 1346 testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab'); 1347 testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab'); 1348 1349 // open and close on diff lines, open indented less than close 1350 testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b'); 1351 testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b'); 1352 testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab'); 1353 testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab'); 1354 1355 // open and close on diff lines, open indented more than close 1356 testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b'); 1357 testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b'); 1358 testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb'); 1359 testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb'); 1360 1361 // open and close on diff lines, open indented more than close 1362 testEdit('di<_middle_spc', 'a\t<\n\tbar\n>b', /r/, 'di<', 'a\t<>b'); 1363 testEdit('di>_middle_spc', 'a\t<\n\tbar\n>b', /r/, 'di>', 'a\t<>b'); 1364 testEdit('da<_middle_spc', 'a\t<\n\tbar\n>b', /r/, 'da<', 'a\tb'); 1365 testEdit('da>_middle_spc', 'a\t<\n\tbar\n>b', /r/, 'da>', 'a\tb'); 1366 1367 function testSelection(name, before, pos, keys, sel) { 1368 return testVim(name, function(cm, vim, helpers) { 1369 var ch = before.search(pos) 1370 var line = before.substring(0, ch).split('\n').length - 1; 1371 if (line) { 1372 ch = before.substring(0, ch).split('\n').pop().length; 1373 } 1374 cm.setCursor(line, ch); 1375 helpers.doKeys.apply(this, keys.split('')); 1376 eq(sel, cm.getSelection()); 1377 }, {value: before}); 1378 } 1379 testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr'); 1380 testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t '); 1381 testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr'); 1382 testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t '); 1383 testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr'); 1384 testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr'); 1385 testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr'); 1386 testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t'); 1387 testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}'); 1388 1389 testVim('mouse_select', function(cm, vim, helpers) { 1390 cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'}); 1391 is(cm.state.vim.visualMode); 1392 is(!cm.state.vim.visualLine); 1393 is(!cm.state.vim.visualBlock); 1394 helpers.doKeys('<Esc>'); 1395 is(!cm.somethingSelected()); 1396 helpers.doKeys('g', 'v'); 1397 eq('cd', cm.getSelection()); 1398 }, {value: 'abcdef'}); 1399 1400 // Operator-motion tests 1401 testVim('D', function(cm, vim, helpers) { 1402 cm.setCursor(0, 3); 1403 helpers.doKeys('D'); 1404 eq(' wo\nword2\n word3', cm.getValue()); 1405 var register = helpers.getRegisterController().getRegister(); 1406 eq('rd1', register.toString()); 1407 is(!register.linewise); 1408 helpers.assertCursorAt(0, 2); 1409 }, { value: ' word1\nword2\n word3' }); 1410 testVim('C', function(cm, vim, helpers) { 1411 var curStart = makeCursor(0, 3); 1412 cm.setCursor(curStart); 1413 helpers.doKeys('C'); 1414 eq(' wo\nword2\n word3', cm.getValue()); 1415 var register = helpers.getRegisterController().getRegister(); 1416 eq('rd1', register.toString()); 1417 is(!register.linewise); 1418 eqCursorPos(curStart, cm.getCursor()); 1419 eq('vim-insert', cm.getOption('keyMap')); 1420 }, { value: ' word1\nword2\n word3' }); 1421 testVim('Y', function(cm, vim, helpers) { 1422 var curStart = makeCursor(0, 3); 1423 cm.setCursor(curStart); 1424 helpers.doKeys('Y'); 1425 eq(' word1\nword2\n word3', cm.getValue()); 1426 var register = helpers.getRegisterController().getRegister(); 1427 eq(' word1\n', register.toString()); 1428 is(register.linewise); 1429 helpers.assertCursorAt(0, 3); 1430 }, { value: ' word1\nword2\n word3' }); 1431 testVim('Yy_blockwise', function(cm, vim, helpers) { 1432 helpers.doKeys('<C-v>', 'j', '2', 'l', 'Y'); 1433 helpers.doKeys('G', 'p', 'g', 'g'); 1434 helpers.doKeys('<C-v>', 'j', '2', 'l', 'y'); 1435 helpers.assertCursorAt(0, 0); 1436 helpers.doKeys('$', 'p'); 1437 eq('123456123\n123456123\n123456\n123456', cm.getValue()); 1438 var register = helpers.getRegisterController().getRegister(); 1439 eq('123\n123', register.toString()); 1440 is(register.blockwise); 1441 helpers.assertCursorAt(0, 6); 1442 helpers.doKeys('$', 'j', 'p'); 1443 helpers.doKeys('$', 'j', 'P'); 1444 eq("123456123\n123456123123\n123456 121233\n123456 123", cm.getValue()); 1445 }, { value: '123456\n123456\n' }); 1446 testVim('~', function(cm, vim, helpers) { 1447 helpers.doKeys('3', '~'); 1448 eq('ABCdefg', cm.getValue()); 1449 helpers.assertCursorAt(0, 3); 1450 }, { value: 'abcdefg' }); 1451 1452 // Action tests 1453 testVim('ctrl-a', function(cm, vim, helpers) { 1454 cm.setCursor(0, 0); 1455 helpers.doKeys('<C-a>'); 1456 eq('-9', cm.getValue()); 1457 helpers.assertCursorAt(0, 1); 1458 helpers.doKeys('2','<C-a>'); 1459 eq('-7', cm.getValue()); 1460 }, {value: '-10'}); 1461 testVim('ctrl-x', function(cm, vim, helpers) { 1462 cm.setCursor(0, 0); 1463 helpers.doKeys('<C-x>'); 1464 eq('-1', cm.getValue()); 1465 helpers.assertCursorAt(0, 1); 1466 helpers.doKeys('2','<C-x>'); 1467 eq('-3', cm.getValue()); 1468 }, {value: '0'}); 1469 testVim('<C-x>/<C-a> search forward', function(cm, vim, helpers) { 1470 forEach(['<C-x>', '<C-a>'], function(key) { 1471 cm.setCursor(0, 0); 1472 helpers.doKeys(key); 1473 helpers.assertCursorAt(0, 5); 1474 helpers.doKeys('l'); 1475 helpers.doKeys(key); 1476 helpers.assertCursorAt(0, 10); 1477 cm.setCursor(0, 11); 1478 helpers.doKeys(key); 1479 helpers.assertCursorAt(0, 11); 1480 }); 1481 }, {value: '__jmp1 jmp2 jmp'}); 1482 testVim('insert_ctrl_w', function(cm, vim, helpers) { 1483 var curStart = makeCursor(0, 10); 1484 cm.setCursor(curStart); 1485 helpers.doKeys('a'); 1486 helpers.doKeys('<C-w>'); 1487 eq('word1/', cm.getValue()); 1488 var register = helpers.getRegisterController().getRegister(); 1489 eq('word2', register.toString()); 1490 is(!register.linewise); 1491 var curEnd = makeCursor(0, 6); 1492 eqCursorPos(curEnd, cm.getCursor()); 1493 eq('vim-insert', cm.getOption('keyMap')); 1494 }, { value: 'word1/word2' }); 1495 testVim('normal_ctrl_w', function(cm, vim, helpers) { 1496 var curStart = makeCursor(0, 3); 1497 cm.setCursor(curStart); 1498 helpers.doKeys('<C-w>'); 1499 eq('word', cm.getValue()); 1500 var curEnd = makeCursor(0, 3); 1501 helpers.assertCursorAt(0,3); 1502 eqCursorPos(curEnd, cm.getCursor()); 1503 eq('vim', cm.getOption('keyMap')); 1504 }, {value: 'word'}); 1505 testVim('a', function(cm, vim, helpers) { 1506 cm.setCursor(0, 1); 1507 helpers.doKeys('a'); 1508 helpers.assertCursorAt(0, 2); 1509 eq('vim-insert', cm.getOption('keyMap')); 1510 }); 1511 testVim('a_eol', function(cm, vim, helpers) { 1512 cm.setCursor(0, lines[0].length - 1); 1513 helpers.doKeys('a'); 1514 helpers.assertCursorAt(0, lines[0].length); 1515 eq('vim-insert', cm.getOption('keyMap')); 1516 }); 1517 testVim('A_endOfSelectedArea', function(cm, vim, helpers) { 1518 cm.setCursor(0, 0); 1519 helpers.doKeys('v', 'j', 'l'); 1520 helpers.doKeys('A'); 1521 helpers.assertCursorAt(1, 2); 1522 eq('vim-insert', cm.getOption('keyMap')); 1523 }, {value: 'foo\nbar'}); 1524 testVim('i', function(cm, vim, helpers) { 1525 cm.setCursor(0, 1); 1526 helpers.doKeys('i'); 1527 helpers.assertCursorAt(0, 1); 1528 eq('vim-insert', cm.getOption('keyMap')); 1529 }); 1530 testVim('i_repeat', function(cm, vim, helpers) { 1531 helpers.doKeys('3', 'i'); 1532 helpers.doKeys('test') 1533 helpers.doKeys('<Esc>'); 1534 eq('testtesttest', cm.getValue()); 1535 helpers.assertCursorAt(0, 11); 1536 }, { value: '' }); 1537 testVim('i_repeat_delete', function(cm, vim, helpers) { 1538 cm.setCursor(0, 4); 1539 helpers.doKeys('2', 'i'); 1540 helpers.doKeys('z') 1541 helpers.doInsertModeKeys('Backspace', 'Backspace'); 1542 helpers.doKeys('<Esc>'); 1543 eq('abe', cm.getValue()); 1544 helpers.assertCursorAt(0, 1); 1545 }, { value: 'abcde' }); 1546 testVim('insert', function(cm, vim, helpers) { 1547 helpers.doKeys('i'); 1548 eq('vim-insert', cm.getOption('keyMap')); 1549 eq(false, cm.state.overwrite); 1550 helpers.doKeys('<Ins>'); 1551 eq('vim-replace', cm.getOption('keyMap')); 1552 eq(true, cm.state.overwrite); 1553 helpers.doKeys('<Ins>'); 1554 eq('vim-insert', cm.getOption('keyMap')); 1555 eq(false, cm.state.overwrite); 1556 }); 1557 testVim('i_backspace', function(cm, vim, helpers) { 1558 cm.setCursor(0, 10); 1559 helpers.doKeys('i'); 1560 helpers.doInsertModeKeys('Backspace'); 1561 helpers.assertCursorAt(0, 9); 1562 eq('012345678', cm.getValue()); 1563 }, { value: '0123456789'}); 1564 testVim('i_overwrite_backspace', function(cm, vim, helpers) { 1565 cm.setCursor(0, 10); 1566 helpers.doKeys('i'); 1567 helpers.doKeys('<Ins>'); 1568 helpers.doInsertModeKeys('Backspace'); 1569 helpers.assertCursorAt(Pos(0, 9, "after")); 1570 eq('0123456789', cm.getValue()); 1571 }, { value: '0123456789'}); 1572 testVim('i_forward_delete', function(cm, vim, helpers) { 1573 cm.setCursor(0, 3); 1574 helpers.doKeys('i'); 1575 helpers.doInsertModeKeys('Delete'); 1576 helpers.assertCursorAt(0, 3); 1577 eq('A124\nBCD', cm.getValue()); 1578 helpers.doInsertModeKeys('Delete'); 1579 helpers.assertCursorAt(0, 3); 1580 eq('A12\nBCD', cm.getValue()); 1581 helpers.doInsertModeKeys('Delete'); 1582 helpers.assertCursorAt(0, 3); 1583 eq('A12BCD', cm.getValue()); 1584 }, { value: 'A1234\nBCD'}); 1585 testVim('forward_delete', function(cm, vim, helpers) { 1586 cm.setCursor(0, 3); 1587 helpers.doInsertModeKeys('Delete'); 1588 helpers.assertCursorAt(0, 3); 1589 eq('A124\nBCD', cm.getValue()); 1590 helpers.doInsertModeKeys('Delete'); 1591 helpers.assertCursorAt(0, 2); 1592 eq('A12\nBCD', cm.getValue()); 1593 helpers.doInsertModeKeys('Delete'); 1594 helpers.assertCursorAt(0, 1); 1595 eq('A1\nBCD', cm.getValue()); 1596 }, { value: 'A1234\nBCD'}); 1597 testVim('A', function(cm, vim, helpers) { 1598 helpers.doKeys('A'); 1599 helpers.assertCursorAt(0, lines[0].length); 1600 eq('vim-insert', cm.getOption('keyMap')); 1601 }); 1602 testVim('A_visual_block', function(cm, vim, helpers) { 1603 cm.setCursor(0, 1); 1604 helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'A'); 1605 helpers.doKeys('hello'); 1606 eq('testhello\nmehello\npleahellose', cm.getValue()); 1607 helpers.doKeys('<Esc>'); 1608 cm.setCursor(0, 0); 1609 helpers.doKeys('.'); 1610 // TODO this doesn't work yet 1611 // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue()); 1612 }, {value: 'test\nme\nplease'}); 1613 testVim('I', function(cm, vim, helpers) { 1614 cm.setCursor(0, 4); 1615 helpers.doKeys('I'); 1616 helpers.assertCursorAt(0, lines[0].textStart); 1617 eq('vim-insert', cm.getOption('keyMap')); 1618 }); 1619 testVim('I_repeat', function(cm, vim, helpers) { 1620 cm.setCursor(0, 1); 1621 helpers.doKeys('3', 'I'); 1622 helpers.doKeys('test') 1623 helpers.doKeys('<Esc>'); 1624 eq('testtesttestblah', cm.getValue()); 1625 helpers.assertCursorAt(0, 11); 1626 }, { value: 'blah' }); 1627 testVim('I_visual_block', function(cm, vim, helpers) { 1628 cm.setCursor(0, 0); 1629 helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'I'); 1630 helpers.doKeys('hello'); 1631 eq('hellotest\nhellome\nhelloplease', cm.getValue()); 1632 }, {value: 'test\nme\nplease'}); 1633 testVim('o', function(cm, vim, helpers) { 1634 cm.setCursor(0, 4); 1635 helpers.doKeys('o'); 1636 eq('word1\n\nword2', cm.getValue()); 1637 helpers.assertCursorAt(1, 0); 1638 eq('vim-insert', cm.getOption('keyMap')); 1639 }, { value: 'word1\nword2' }); 1640 testVim('o_repeat', function(cm, vim, helpers) { 1641 cm.setCursor(0, 0); 1642 helpers.doKeys('3', 'o'); 1643 helpers.doKeys('test') 1644 helpers.doKeys('<Esc>'); 1645 eq('\ntest\ntest\ntest', cm.getValue()); 1646 helpers.assertCursorAt(3, 3); 1647 }, { value: '' }); 1648 testVim('O', function(cm, vim, helpers) { 1649 cm.setCursor(0, 4); 1650 helpers.doKeys('O'); 1651 eq('\nword1\nword2', cm.getValue()); 1652 helpers.assertCursorAt(0, 0); 1653 eq('vim-insert', cm.getOption('keyMap')); 1654 }, { value: 'word1\nword2' }); 1655 testVim('J', function(cm, vim, helpers) { 1656 cm.setCursor(0, 4); 1657 helpers.doKeys('J'); 1658 var expectedValue = 'word1 word2\nword3\n word4'; 1659 eq(expectedValue, cm.getValue()); 1660 helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1); 1661 }, { value: 'word1 \n word2\nword3\n word4' }); 1662 testVim('J_repeat', function(cm, vim, helpers) { 1663 cm.setCursor(0, 4); 1664 helpers.doKeys('3', 'J'); 1665 var expectedValue = 'word1 word2 word3\n word4'; 1666 eq(expectedValue, cm.getValue()); 1667 helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1); 1668 }, { value: 'word1 \n word2\nword3\n word4' }); 1669 testVim('p', function(cm, vim, helpers) { 1670 cm.setCursor(0, 1); 1671 helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); 1672 helpers.doKeys('p'); 1673 eq('__abc\ndef_', cm.getValue()); 1674 helpers.assertCursorAt(1, 2); 1675 }, { value: '___' }); 1676 testVim('p_register', function(cm, vim, helpers) { 1677 cm.setCursor(0, 1); 1678 helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); 1679 helpers.doKeys('"', 'a', 'p'); 1680 eq('__abc\ndef_', cm.getValue()); 1681 helpers.assertCursorAt(1, 2); 1682 }, { value: '___' }); 1683 testVim('p_wrong_register', function(cm, vim, helpers) { 1684 cm.setCursor(0, 1); 1685 helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); 1686 helpers.doKeys('p'); 1687 eq('___', cm.getValue()); 1688 helpers.assertCursorAt(0, 1); 1689 }, { value: '___' }); 1690 testVim('p_line', function(cm, vim, helpers) { 1691 cm.setCursor(0, 1); 1692 helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); 1693 helpers.doKeys('2', 'p'); 1694 eq('___\n a\nd\n a\nd', cm.getValue()); 1695 helpers.assertCursorAt(1, 2); 1696 }, { value: '___' }); 1697 testVim('p_lastline', function(cm, vim, helpers) { 1698 cm.setCursor(0, 1); 1699 helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true); 1700 helpers.doKeys('2', 'p'); 1701 eq('___\n a\nd\n a\nd', cm.getValue()); 1702 helpers.assertCursorAt(1, 2); 1703 }, { value: '___' }); 1704 testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) { 1705 helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); 1706 helpers.doKeys(']', 'p'); 1707 eq(' ___\n abc\n def', cm.getValue()); 1708 }, { value: ' ___' }); 1709 testVim(']p_first_indent_is_larger', function(cm, vim, helpers) { 1710 helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); 1711 helpers.doKeys(']', 'p'); 1712 eq(' ___\n abc\ndef', cm.getValue()); 1713 }, { value: ' ___' }); 1714 testVim(']p_with_tab_indents', function(cm, vim, helpers) { 1715 helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true); 1716 helpers.doKeys(']', 'p'); 1717 eq('\t___\n\tabc\n\t\tdef', cm.getValue()); 1718 }, { value: '\t___', indentWithTabs: true}); 1719 testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) { 1720 helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); 1721 helpers.doKeys(']', 'p'); 1722 eq('\t___\n\tabc\n\t\tdef', cm.getValue()); 1723 }, { value: '\t___', indentWithTabs: true, tabSize: 2 }); 1724 testVim('[p', function(cm, vim, helpers) { 1725 helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); 1726 helpers.doKeys('[', 'p'); 1727 eq(' abc\n def\n ___', cm.getValue()); 1728 }, { value: ' ___' }); 1729 testVim('P', function(cm, vim, helpers) { 1730 cm.setCursor(0, 1); 1731 helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); 1732 helpers.doKeys('P'); 1733 eq('_abc\ndef__', cm.getValue()); 1734 helpers.assertCursorAt(1, 3); 1735 }, { value: '___' }); 1736 testVim('P_line', function(cm, vim, helpers) { 1737 cm.setCursor(0, 1); 1738 helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); 1739 helpers.doKeys('2', 'P'); 1740 eq(' a\nd\n a\nd\n___', cm.getValue()); 1741 helpers.assertCursorAt(0, 2); 1742 }, { value: '___' }); 1743 testVim('r', function(cm, vim, helpers) { 1744 cm.setCursor(0, 1); 1745 helpers.doKeys('3', 'r', 'u'); 1746 eq('wuuuet\nanother', cm.getValue(),'3r failed'); 1747 helpers.assertCursorAt(0, 3); 1748 cm.setCursor(0, 4); 1749 helpers.doKeys('v', 'j', 'h', 'r', '<Space>'); 1750 eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); 1751 cm.setValue("ox"); 1752 helpers.doKeys('r', '<C-c>'); 1753 eq('ox', cm.getValue()); 1754 helpers.doKeys('r', '<Del>'); 1755 eq('ox', cm.getValue()); 1756 helpers.doKeys('r', '<CR>'); 1757 eq('\nx', cm.getValue()); 1758 }, { value: 'wordet\nanother' }); 1759 testVim('r_visual_block', function(cm, vim, helpers) { 1760 cm.setCursor(2, 3); 1761 helpers.doKeys('<C-v>', 'k', 'k', 'h', 'h', 'r', 'l'); 1762 eq('1lll\n5lll\nalllefg', cm.getValue()); 1763 helpers.doKeys('<C-v>', 'l', 'j', 'r', '<Space>'); 1764 eq('1 l\n5 l\nalllefg', cm.getValue()); 1765 cm.setCursor(2, 0); 1766 helpers.doKeys('o'); 1767 helpers.doKeys('\t\t') 1768 helpers.doKeys('<Esc>'); 1769 helpers.doKeys('<C-v>', 'h', 'h', 'r', 'r'); 1770 eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue()); 1771 }, {value: '1234\n5678\nabcdefg'}); 1772 testVim('R', function(cm, vim, helpers) { 1773 cm.setCursor(0, 1); 1774 helpers.doKeys('R'); 1775 helpers.assertCursorAt(0, 1); 1776 eq('vim-replace', cm.getOption('keyMap')); 1777 is(cm.state.overwrite, 'Setting overwrite state failed'); 1778 }); 1779 testVim('mark', function(cm, vim, helpers) { 1780 cm.setCursor(2, 2); 1781 helpers.doKeys('m', 't'); 1782 cm.setCursor(0, 0); 1783 helpers.doKeys('`', 't'); 1784 helpers.assertCursorAt(2, 2); 1785 cm.setCursor(2, 0); 1786 cm.replaceRange(' h', cm.getCursor()); 1787 cm.setCursor(0, 0); 1788 helpers.doKeys('\'', 't'); 1789 helpers.assertCursorAt(2, 3); 1790 }); 1791 testVim('mark\'', function(cm, vim, helpers) { 1792 cm.setCursor(2, 2); 1793 cm.setCursor(0, 0); 1794 helpers.doKeys('`', '\''); 1795 helpers.assertCursorAt(2, 2); 1796 cm.setCursor(2, 0); 1797 cm.replaceRange(' h', cm.getCursor()); 1798 cm.setCursor(0, 0); 1799 helpers.doKeys('\'', '\''); 1800 helpers.assertCursorAt(2, 3); 1801 }); 1802 testVim('mark.', function(cm, vim, helpers) { 1803 cm.setCursor(0, 0); 1804 helpers.doKeys('O', 'testing', '<Esc>'); 1805 cm.setCursor(3, 3); 1806 helpers.doKeys('\'', '.'); 1807 helpers.assertCursorAt(0, 0); 1808 cm.setCursor(4, 4); 1809 helpers.doKeys('`', '.'); 1810 helpers.assertCursorAt(0, 6); 1811 }); 1812 testVim('jumpToMark_next', function(cm, vim, helpers) { 1813 cm.setCursor(2, 2); 1814 helpers.doKeys('m', 't'); 1815 cm.setCursor(0, 0); 1816 helpers.doKeys(']', '`'); 1817 helpers.assertCursorAt(2, 2); 1818 cm.setCursor(0, 0); 1819 helpers.doKeys(']', '\''); 1820 helpers.assertCursorAt(2, 0); 1821 }); 1822 testVim('jumpToMark_next_repeat', function(cm, vim, helpers) { 1823 cm.setCursor(2, 2); 1824 helpers.doKeys('m', 'a'); 1825 cm.setCursor(3, 2); 1826 helpers.doKeys('m', 'b'); 1827 cm.setCursor(4, 2); 1828 helpers.doKeys('m', 'c'); 1829 cm.setCursor(0, 0); 1830 helpers.doKeys('2', ']', '`'); 1831 helpers.assertCursorAt(3, 2); 1832 cm.setCursor(0, 0); 1833 helpers.doKeys('2', ']', '\''); 1834 helpers.assertCursorAt(3, 1); 1835 }); 1836 testVim('jumpToMark_next_sameline', function(cm, vim, helpers) { 1837 cm.setCursor(2, 0); 1838 helpers.doKeys('m', 'a'); 1839 cm.setCursor(2, 4); 1840 helpers.doKeys('m', 'b'); 1841 cm.setCursor(2, 2); 1842 helpers.doKeys(']', '`'); 1843 helpers.assertCursorAt(2, 4); 1844 }); 1845 testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) { 1846 cm.setCursor(2, 0); 1847 helpers.doKeys('m', 'a'); 1848 cm.setCursor(4, 0); 1849 helpers.doKeys(']', '`'); 1850 helpers.assertCursorAt(4, 0); 1851 }); 1852 testVim('jumpToMark_next_nomark', function(cm, vim, helpers) { 1853 cm.setCursor(2, 2); 1854 helpers.doKeys(']', '`'); 1855 helpers.assertCursorAt(2, 2); 1856 helpers.doKeys(']', '\''); 1857 helpers.assertCursorAt(2, 0); 1858 }); 1859 testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) { 1860 cm.setCursor(2, 2); 1861 helpers.doKeys('m', 'a'); 1862 cm.setCursor(3, 4); 1863 helpers.doKeys('m', 'b'); 1864 cm.setCursor(2, 1); 1865 helpers.doKeys(']', '\''); 1866 helpers.assertCursorAt(3, 1); 1867 }); 1868 testVim('jumpToMark_next_action', function(cm, vim, helpers) { 1869 cm.setCursor(2, 2); 1870 helpers.doKeys('m', 't'); 1871 cm.setCursor(0, 0); 1872 helpers.doKeys('d', ']', '`'); 1873 helpers.assertCursorAt(0, 0); 1874 var actual = cm.getLine(0); 1875 var expected = 'pop pop 0 1 2 3 4'; 1876 eq(actual, expected, "Deleting while jumping to the next mark failed."); 1877 }); 1878 testVim('jumpToMark_next_line_action', function(cm, vim, helpers) { 1879 cm.setCursor(2, 2); 1880 helpers.doKeys('m', 't'); 1881 cm.setCursor(0, 0); 1882 helpers.doKeys('d', ']', '\''); 1883 helpers.assertCursorAt(0, 1); 1884 var actual = cm.getLine(0); 1885 var expected = ' (a) [b] {c} ' 1886 eq(actual, expected, "Deleting while jumping to the next mark line failed."); 1887 }); 1888 testVim('jumpToMark_prev', function(cm, vim, helpers) { 1889 cm.setCursor(2, 2); 1890 helpers.doKeys('m', 't'); 1891 cm.setCursor(4, 0); 1892 helpers.doKeys('[', '`'); 1893 helpers.assertCursorAt(2, 2); 1894 cm.setCursor(4, 0); 1895 helpers.doKeys('[', '\''); 1896 helpers.assertCursorAt(2, 0); 1897 }); 1898 testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) { 1899 cm.setCursor(2, 2); 1900 helpers.doKeys('m', 'a'); 1901 cm.setCursor(3, 2); 1902 helpers.doKeys('m', 'b'); 1903 cm.setCursor(4, 2); 1904 helpers.doKeys('m', 'c'); 1905 cm.setCursor(5, 0); 1906 helpers.doKeys('2', '[', '`'); 1907 helpers.assertCursorAt(3, 2); 1908 cm.setCursor(5, 0); 1909 helpers.doKeys('2', '[', '\''); 1910 helpers.assertCursorAt(3, 1); 1911 }); 1912 testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) { 1913 cm.setCursor(2, 0); 1914 helpers.doKeys('m', 'a'); 1915 cm.setCursor(2, 4); 1916 helpers.doKeys('m', 'b'); 1917 cm.setCursor(2, 2); 1918 helpers.doKeys('[', '`'); 1919 helpers.assertCursorAt(2, 0); 1920 }); 1921 testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) { 1922 cm.setCursor(4, 4); 1923 helpers.doKeys('m', 'a'); 1924 cm.setCursor(2, 0); 1925 helpers.doKeys('[', '`'); 1926 helpers.assertCursorAt(2, 0); 1927 }); 1928 testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) { 1929 cm.setCursor(2, 2); 1930 helpers.doKeys('[', '`'); 1931 helpers.assertCursorAt(2, 2); 1932 helpers.doKeys('[', '\''); 1933 helpers.assertCursorAt(2, 0); 1934 }); 1935 testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) { 1936 cm.setCursor(2, 2); 1937 helpers.doKeys('m', 'a'); 1938 cm.setCursor(3, 4); 1939 helpers.doKeys('m', 'b'); 1940 cm.setCursor(3, 6); 1941 helpers.doKeys('[', '\''); 1942 helpers.assertCursorAt(2, 0); 1943 }); 1944 testVim('delmark_single', function(cm, vim, helpers) { 1945 cm.setCursor(1, 2); 1946 helpers.doKeys('m', 't'); 1947 helpers.doEx('delmarks t'); 1948 cm.setCursor(0, 0); 1949 helpers.doKeys('`', 't'); 1950 helpers.assertCursorAt(0, 0); 1951 }); 1952 testVim('delmark_range', function(cm, vim, helpers) { 1953 cm.setCursor(1, 2); 1954 helpers.doKeys('m', 'a'); 1955 cm.setCursor(2, 2); 1956 helpers.doKeys('m', 'b'); 1957 cm.setCursor(3, 2); 1958 helpers.doKeys('m', 'c'); 1959 cm.setCursor(4, 2); 1960 helpers.doKeys('m', 'd'); 1961 cm.setCursor(5, 2); 1962 helpers.doKeys('m', 'e'); 1963 helpers.doEx('delmarks b-d'); 1964 cm.setCursor(0, 0); 1965 helpers.doKeys('`', 'a'); 1966 helpers.assertCursorAt(1, 2); 1967 helpers.doKeys('`', 'b'); 1968 helpers.assertCursorAt(1, 2); 1969 helpers.doKeys('`', 'c'); 1970 helpers.assertCursorAt(1, 2); 1971 helpers.doKeys('`', 'd'); 1972 helpers.assertCursorAt(1, 2); 1973 helpers.doKeys('`', 'e'); 1974 helpers.assertCursorAt(5, 2); 1975 }); 1976 testVim('delmark_multi', function(cm, vim, helpers) { 1977 cm.setCursor(1, 2); 1978 helpers.doKeys('m', 'a'); 1979 cm.setCursor(2, 2); 1980 helpers.doKeys('m', 'b'); 1981 cm.setCursor(3, 2); 1982 helpers.doKeys('m', 'c'); 1983 cm.setCursor(4, 2); 1984 helpers.doKeys('m', 'd'); 1985 cm.setCursor(5, 2); 1986 helpers.doKeys('m', 'e'); 1987 helpers.doEx('delmarks bcd'); 1988 cm.setCursor(0, 0); 1989 helpers.doKeys('`', 'a'); 1990 helpers.assertCursorAt(1, 2); 1991 helpers.doKeys('`', 'b'); 1992 helpers.assertCursorAt(1, 2); 1993 helpers.doKeys('`', 'c'); 1994 helpers.assertCursorAt(1, 2); 1995 helpers.doKeys('`', 'd'); 1996 helpers.assertCursorAt(1, 2); 1997 helpers.doKeys('`', 'e'); 1998 helpers.assertCursorAt(5, 2); 1999 }); 2000 testVim('delmark_multi_space', function(cm, vim, helpers) { 2001 cm.setCursor(1, 2); 2002 helpers.doKeys('m', 'a'); 2003 cm.setCursor(2, 2); 2004 helpers.doKeys('m', 'b'); 2005 cm.setCursor(3, 2); 2006 helpers.doKeys('m', 'c'); 2007 cm.setCursor(4, 2); 2008 helpers.doKeys('m', 'd'); 2009 cm.setCursor(5, 2); 2010 helpers.doKeys('m', 'e'); 2011 helpers.doEx('delmarks b c d'); 2012 cm.setCursor(0, 0); 2013 helpers.doKeys('`', 'a'); 2014 helpers.assertCursorAt(1, 2); 2015 helpers.doKeys('`', 'b'); 2016 helpers.assertCursorAt(1, 2); 2017 helpers.doKeys('`', 'c'); 2018 helpers.assertCursorAt(1, 2); 2019 helpers.doKeys('`', 'd'); 2020 helpers.assertCursorAt(1, 2); 2021 helpers.doKeys('`', 'e'); 2022 helpers.assertCursorAt(5, 2); 2023 }); 2024 testVim('delmark_all', function(cm, vim, helpers) { 2025 cm.setCursor(1, 2); 2026 helpers.doKeys('m', 'a'); 2027 cm.setCursor(2, 2); 2028 helpers.doKeys('m', 'b'); 2029 cm.setCursor(3, 2); 2030 helpers.doKeys('m', 'c'); 2031 cm.setCursor(4, 2); 2032 helpers.doKeys('m', 'd'); 2033 cm.setCursor(5, 2); 2034 helpers.doKeys('m', 'e'); 2035 helpers.doEx('delmarks a b-de'); 2036 cm.setCursor(0, 0); 2037 helpers.doKeys('`', 'a'); 2038 helpers.assertCursorAt(0, 0); 2039 helpers.doKeys('`', 'b'); 2040 helpers.assertCursorAt(0, 0); 2041 helpers.doKeys('`', 'c'); 2042 helpers.assertCursorAt(0, 0); 2043 helpers.doKeys('`', 'd'); 2044 helpers.assertCursorAt(0, 0); 2045 helpers.doKeys('`', 'e'); 2046 helpers.assertCursorAt(0, 0); 2047 }); 2048 testVim('visual', function(cm, vim, helpers) { 2049 helpers.doKeys('l', 'v', 'l', 'l'); 2050 helpers.assertCursorAt(0, 4); 2051 eqCursorPos(makeCursor(0, 1), cm.getCursor('anchor')); 2052 helpers.doKeys('d'); 2053 eq('15', cm.getValue()); 2054 }, { value: '12345' }); 2055 testVim('visual_yank', function(cm, vim, helpers) { 2056 helpers.doKeys('v', '3', 'l', 'y'); 2057 helpers.assertCursorAt(0, 0); 2058 helpers.doKeys('p'); 2059 eq('aa te test for yank', cm.getValue()); 2060 }, { value: 'a test for yank' }) 2061 testVim('visual_w', function(cm, vim, helpers) { 2062 helpers.doKeys('v', 'w'); 2063 eq(cm.getSelection(), 'motion t'); 2064 }, { value: 'motion test'}); 2065 testVim('visual_initial_selection', function(cm, vim, helpers) { 2066 cm.setCursor(0, 1); 2067 helpers.doKeys('v'); 2068 cm.getSelection('n'); 2069 }, { value: 'init'}); 2070 testVim('visual_crossover_left', function(cm, vim, helpers) { 2071 cm.setCursor(0, 2); 2072 helpers.doKeys('v', 'l', 'h', 'h'); 2073 cm.getSelection('ro'); 2074 }, { value: 'cross'}); 2075 testVim('visual_crossover_left', function(cm, vim, helpers) { 2076 cm.setCursor(0, 2); 2077 helpers.doKeys('v', 'h', 'l', 'l'); 2078 cm.getSelection('os'); 2079 }, { value: 'cross'}); 2080 testVim('visual_crossover_up', function(cm, vim, helpers) { 2081 cm.setCursor(3, 2); 2082 helpers.doKeys('v', 'j', 'k', 'k'); 2083 eqCursorPos(Pos(2, 2), cm.getCursor('head')); 2084 eqCursorPos(Pos(3, 3), cm.getCursor('anchor')); 2085 helpers.doKeys('k'); 2086 eqCursorPos(Pos(1, 2), cm.getCursor('head')); 2087 eqCursorPos(Pos(3, 3), cm.getCursor('anchor')); 2088 }, { value: 'cross\ncross\ncross\ncross\ncross\n'}); 2089 testVim('visual_crossover_down', function(cm, vim, helpers) { 2090 cm.setCursor(1, 2); 2091 helpers.doKeys('v', 'k', 'j', 'j'); 2092 eqCursorPos(Pos(2, 3), cm.getCursor('head')); 2093 eqCursorPos(Pos(1, 2), cm.getCursor('anchor')); 2094 helpers.doKeys('j'); 2095 eqCursorPos(Pos(3, 3), cm.getCursor('head')); 2096 eqCursorPos(Pos(1, 2), cm.getCursor('anchor')); 2097 }, { value: 'cross\ncross\ncross\ncross\ncross\n'}); 2098 testVim('visual_exit', function(cm, vim, helpers) { 2099 helpers.doKeys('<C-v>', 'l', 'j', 'j', '<Esc>'); 2100 eqCursorPos(cm.getCursor('anchor'), cm.getCursor('head')); 2101 eq(vim.visualMode, false); 2102 }, { value: 'hello\nworld\nfoo' }); 2103 testVim('visual_line', function(cm, vim, helpers) { 2104 helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); 2105 eq(' 4\n 5', cm.getValue()); 2106 }, { value: ' 1\n 2\n 3\n 4\n 5' }); 2107 testVim('visual_block_move_to_eol', function(cm, vim, helpers) { 2108 // moveToEol should move all block cursors to end of line 2109 cm.setCursor(0, 0); 2110 helpers.doKeys('<C-v>', 'G', '$'); 2111 var selections = cm.getSelections().join(); 2112 eq('123,45,6', selections); 2113 // Checks that with cursor at Infinity, finding words backwards still works. 2114 helpers.doKeys('2', 'k', 'b'); 2115 selections = cm.getSelections().join(); 2116 eq('1', selections); 2117 }, {value: '123\n45\n6'}); 2118 testVim('visual_block_different_line_lengths', function(cm, vim, helpers) { 2119 // test the block selection with lines of different length 2120 // i.e. extending the selection 2121 // till the end of the longest line. 2122 helpers.doKeys('<C-v>', 'l', 'j', 'j', '6', 'l', 'd'); 2123 helpers.doKeys('d', 'd', 'd', 'd'); 2124 eq('', cm.getValue()); 2125 }, {value: '1234\n5678\nabcdefg'}); 2126 testVim('visual_block_truncate_on_short_line', function(cm, vim, helpers) { 2127 // check for left side selection in case 2128 // of moving up to a shorter line. 2129 cm.replaceRange('', cm.getCursor()); 2130 cm.setCursor(3, 4); 2131 helpers.doKeys('<C-v>', 'l', 'k', 'k', 'd'); 2132 eq('hello world\n{\ntis\nsa!', cm.getValue()); 2133 }, {value: 'hello world\n{\nthis is\nsparta!'}); 2134 testVim('visual_block_corners', function(cm, vim, helpers) { 2135 cm.setCursor(1, 2); 2136 helpers.doKeys('<C-v>', '2', 'l', 'k'); 2137 // circle around the anchor 2138 // and check the selections 2139 var selections = cm.getSelections(); 2140 eq('345891', selections.join('')); 2141 helpers.doKeys('4', 'h'); 2142 selections = cm.getSelections(); 2143 eq('123678', selections.join('')); 2144 helpers.doKeys('j', 'j'); 2145 selections = cm.getSelections(); 2146 eq('678abc', selections.join('')); 2147 helpers.doKeys('4', 'l'); 2148 selections = cm.getSelections(); 2149 eq('891cde', selections.join('')); 2150 }, {value: '12345\n67891\nabcde'}); 2151 testVim('visual_block_mode_switch', function(cm, vim, helpers) { 2152 // switch between visual modes 2153 cm.setCursor(1, 1); 2154 // blockwise to characterwise visual 2155 helpers.doKeys('<C-v>', 'j', 'l', 'v'); 2156 var selections = cm.getSelections(); 2157 eq('7891\nabc', selections.join('')); 2158 // characterwise to blockwise 2159 helpers.doKeys('<C-v>'); 2160 selections = cm.getSelections(); 2161 eq('78bc', selections.join('')); 2162 // blockwise to linewise visual 2163 helpers.doKeys('V'); 2164 selections = cm.getSelections(); 2165 eq('67891\nabcde', selections.join('')); 2166 }, {value: '12345\n67891\nabcde'}); 2167 testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { 2168 // visual block with long and short lines 2169 cm.setCursor(0, 3); 2170 helpers.doKeys('<C-v>', 'j', 'j', 'j'); 2171 var selections = cm.getSelections().join(); 2172 eq('4,,d,b', selections); 2173 helpers.doKeys('3', 'k'); 2174 selections = cm.getSelections().join(); 2175 eq('4', selections); 2176 helpers.doKeys('5', 'j', 'k'); 2177 selections = cm.getSelections().join(""); 2178 eq(10, selections.length); 2179 }, {value: '123456\n78\nabcdefg\nfoobar\n}\n'}); 2180 testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) { 2181 cm.setCursor(0, 0); 2182 helpers.doKeys('<C-v>', '3' , 'l', '<Esc>'); 2183 eqCursorPos(makeCursor(0, 3), cm.getCursor()); 2184 helpers.doKeys('h', '<C-v>', '2' , 'j' ,'3' , 'l'); 2185 eq(cm.getSelections().join(), "3456,,cdef"); 2186 helpers.doKeys('4' , 'h'); 2187 eq(cm.getSelections().join(), "23,8,bc"); 2188 helpers.doKeys('2' , 'l'); 2189 eq(cm.getSelections().join(), "34,,cd"); 2190 }, {value: '123456\n78\nabcdefg\nfoobar'}); 2191 2192 testVim('visual_marks', function(cm, vim, helpers) { 2193 helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v'); 2194 // Test visual mode marks 2195 cm.setCursor(2, 1); 2196 helpers.doKeys('\'', '<'); 2197 helpers.assertCursorAt(0, 1); 2198 helpers.doKeys('\'', '>'); 2199 helpers.assertCursorAt(2, 0); 2200 }); 2201 testVim('visual_join', function(cm, vim, helpers) { 2202 helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J'); 2203 eq(' 1 2 3\n 4\n 5', cm.getValue()); 2204 is(!vim.visualMode); 2205 }, { value: ' 1\n 2\n 3\n 4\n 5' }); 2206 testVim('visual_join_2', function(cm, vim, helpers) { 2207 helpers.doKeys('G', 'V', 'g', 'g', 'J'); 2208 eq('1 2 3 4 5 6 ', cm.getValue()); 2209 is(!vim.visualMode); 2210 }, { value: '1\n2\n3\n4\n5\n6\n'}); 2211 testVim('visual_blank', function(cm, vim, helpers) { 2212 helpers.doKeys('v', 'k'); 2213 eq(vim.visualMode, true); 2214 }, { value: '\n' }); 2215 testVim('reselect_visual', function(cm, vim, helpers) { 2216 helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v'); 2217 helpers.assertCursorAt(0, 5); 2218 eqCursorPos(makeCursor(0, 1), cm.getCursor('anchor')); 2219 helpers.doKeys('v'); 2220 cm.setCursor(1, 0); 2221 helpers.doKeys('v', 'l', 'l', 'p'); 2222 eq('123456\n2345\nbar', cm.getValue()); 2223 cm.setCursor(0, 0); 2224 helpers.doKeys('g', 'v'); 2225 // here the fake cursor is at (1, 3) 2226 helpers.assertCursorAt(1, 4); 2227 eqCursorPos(makeCursor(1, 0), cm.getCursor('anchor')); 2228 helpers.doKeys('v'); 2229 cm.setCursor(2, 0); 2230 helpers.doKeys('v', 'l', 'l', 'g', 'v'); 2231 helpers.assertCursorAt(1, 4); 2232 eqCursorPos(makeCursor(1, 0), cm.getCursor('anchor')); 2233 helpers.doKeys('g', 'v'); 2234 helpers.assertCursorAt(2, 3); 2235 eqCursorPos(makeCursor(2, 0), cm.getCursor('anchor')); 2236 eq('123456\n2345\nbar', cm.getValue()); 2237 }, { value: '123456\nfoo\nbar' }); 2238 testVim('reselect_visual_line', function(cm, vim, helpers) { 2239 helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd'); 2240 eq('foo\nand\nbar', cm.getValue()); 2241 cm.setCursor(1, 0); 2242 helpers.doKeys('V', 'y', 'j'); 2243 helpers.doKeys('V', 'p' , 'g', 'v', 'd'); 2244 eq('foo\nand', cm.getValue()); 2245 }, { value: 'hello\nthis\nis\nfoo\nand\nbar' }); 2246 testVim('reselect_visual_block', function(cm, vim, helpers) { 2247 cm.setCursor(1, 2); 2248 helpers.doKeys('<C-v>', 'k', 'h', '<C-v>'); 2249 cm.setCursor(2, 1); 2250 helpers.doKeys('v', 'l', 'g', 'v'); 2251 eqCursorPos(Pos(1, 2), vim.sel.anchor); 2252 eqCursorPos(Pos(0, 1), vim.sel.head); 2253 // Ensure selection is done with visual block mode rather than one 2254 // continuous range. 2255 eq(cm.getSelections().join(''), '23oo') 2256 helpers.doKeys('g', 'v'); 2257 eqCursorPos(Pos(2, 1), vim.sel.anchor); 2258 eqCursorPos(Pos(2, 2), vim.sel.head); 2259 helpers.doKeys('<Esc>'); 2260 // Ensure selection of deleted range 2261 cm.setCursor(1, 1); 2262 helpers.doKeys('v', '<C-v>', 'j', 'd', 'g', 'v'); 2263 eq(cm.getSelections().join(''), 'or'); 2264 }, { value: '123456\nfoo\nbar' }); 2265 testVim('s_normal', function(cm, vim, helpers) { 2266 cm.setCursor(0, 1); 2267 helpers.doKeys('s'); 2268 helpers.doKeys('<Esc>'); 2269 eq('ac', cm.getValue()); 2270 }, { value: 'abc'}); 2271 testVim('s_visual', function(cm, vim, helpers) { 2272 cm.setCursor(0, 1); 2273 helpers.doKeys('v', 's'); 2274 helpers.doKeys('<Esc>'); 2275 helpers.assertCursorAt(0, 0); 2276 eq('ac', cm.getValue()); 2277 }, { value: 'abc'}); 2278 testVim('o_visual', function(cm, vim, helpers) { 2279 cm.setCursor(0,0); 2280 helpers.doKeys('v','l','l','l','o'); 2281 helpers.assertCursorAt(0,0); 2282 helpers.doKeys('v','v','j','j','j','o'); 2283 helpers.assertCursorAt(0,0); 2284 helpers.doKeys('O'); 2285 helpers.doKeys('l','l') 2286 helpers.assertCursorAt(3, 3); 2287 helpers.doKeys('d'); 2288 eq('p',cm.getValue()); 2289 }, { value: 'abcd\nefgh\nijkl\nmnop'}); 2290 testVim('o_visual_block', function(cm, vim, helpers) { 2291 cm.setCursor(0, 1); 2292 helpers.doKeys('<C-v>','3','j','l','l', 'o'); 2293 eqCursorPos(Pos(3, 3), vim.sel.anchor); 2294 eqCursorPos(Pos(0, 1), vim.sel.head); 2295 helpers.doKeys('O'); 2296 eqCursorPos(Pos(3, 1), vim.sel.anchor); 2297 eqCursorPos(Pos(0, 3), vim.sel.head); 2298 helpers.doKeys('o'); 2299 eqCursorPos(Pos(0, 3), vim.sel.anchor); 2300 eqCursorPos(Pos(3, 1), vim.sel.head); 2301 }, { value: 'abcd\nefgh\nijkl\nmnop'}); 2302 testVim('changeCase_visual', function(cm, vim, helpers) { 2303 cm.setCursor(0, 0); 2304 helpers.doKeys('v', 'l', 'l'); 2305 helpers.doKeys('U'); 2306 helpers.assertCursorAt(0, 0); 2307 helpers.doKeys('v', 'l', 'l'); 2308 helpers.doKeys('u'); 2309 helpers.assertCursorAt(0, 0); 2310 helpers.doKeys('l', 'l', 'l', '.'); 2311 helpers.assertCursorAt(0, 3); 2312 cm.setCursor(0, 0); 2313 helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q'); 2314 helpers.assertCursorAt(0, 0); 2315 helpers.doKeys('j', '@', 'a'); 2316 helpers.assertCursorAt(1, 0); 2317 cm.setCursor(3, 0); 2318 helpers.doKeys('V', 'U', 'j', '.'); 2319 eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); 2320 }, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); 2321 testVim('changeCase_visual_block', function(cm, vim, helpers) { 2322 cm.setCursor(2, 1); 2323 helpers.doKeys('<C-v>', 'k', 'k', 'h', 'U'); 2324 eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue()); 2325 cm.setCursor(0, 2); 2326 helpers.doKeys('.'); 2327 eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue()); 2328 // check when last line is shorter. 2329 cm.setCursor(2, 2); 2330 helpers.doKeys('.'); 2331 eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue()); 2332 }, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); 2333 testVim('visual_paste', function(cm, vim, helpers) { 2334 cm.setCursor(0, 0); 2335 helpers.doKeys('v', 'l', 'l', 'y'); 2336 helpers.assertCursorAt(0, 0); 2337 helpers.doKeys('3', 'l', 'j', 'v', 'l', 'p'); 2338 helpers.assertCursorAt(1, 5); 2339 eq('this is a\nunithitest for visual paste', cm.getValue()); 2340 cm.setCursor(0, 0); 2341 // in case of pasting whole line 2342 helpers.doKeys('y', 'y'); 2343 cm.setCursor(1, 6); 2344 helpers.doKeys('v', 'l', 'l', 'l', 'p'); 2345 helpers.assertCursorAt(2, 0); 2346 eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue()); 2347 }, { value: 'this is a\nunit test for visual paste'}); 2348 2349 // This checks the contents of the register used to paste the text 2350 testVim('v_paste_from_register', function(cm, vim, helpers) { 2351 cm.setCursor(0, 0); 2352 helpers.doKeys('"', 'a', 'y', 'w'); 2353 cm.setCursor(1, 0); 2354 helpers.doKeys('v', 'p'); 2355 cm.openDialog = helpers.fakeOpenDialog('registers'); 2356 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2357 is(/a\s+register/.test(text)); 2358 }); 2359 }, { value: 'register contents\nare not erased'}); 2360 testVim('S_normal', function(cm, vim, helpers) { 2361 cm.setCursor(0, 1); 2362 helpers.doKeys('j', 'S'); 2363 helpers.doKeys('<Esc>'); 2364 helpers.assertCursorAt(1, 1); 2365 eq('aa{\n \ncc', cm.getValue()); 2366 helpers.doKeys('j', 'S'); 2367 eq('aa{\n \n ', cm.getValue()); 2368 helpers.assertCursorAt(2, 2); 2369 helpers.doKeys('<Esc>'); 2370 helpers.doKeys('d', 'd', 'd', 'd'); 2371 helpers.assertCursorAt(0, 0); 2372 helpers.doKeys('S'); 2373 is(vim.insertMode); 2374 eq('', cm.getValue()); 2375 }, { value: 'aa{\nbb\ncc'}); 2376 testVim('blockwise_paste', function(cm, vim, helpers) { 2377 cm.setCursor(0, 0); 2378 helpers.doKeys('<C-v>', '3', 'j', 'l', 'y'); 2379 cm.setCursor(0, 2); 2380 // paste one char after the current cursor position 2381 helpers.doKeys('p'); 2382 eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue()); 2383 cm.setCursor(0, 0); 2384 helpers.doKeys('v', '4', 'l', 'y'); 2385 cm.setCursor(0, 0); 2386 helpers.doKeys('<C-v>', '3', 'j', 'p'); 2387 eq('helheelhelo\norwold\noofo\narba', cm.getValue()); 2388 }, { value: 'hello\nworld\nfoo\nbar'}); 2389 testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) { 2390 // extend short lines in case of different line lengths. 2391 cm.setCursor(0, 0); 2392 helpers.doKeys('<C-v>', 'j', 'j', 'y'); 2393 cm.setCursor(0, 3); 2394 helpers.doKeys('p'); 2395 eq('hellho\nfoo f\nbar b', cm.getValue()); 2396 }, { value: 'hello\nfoo\nbar'}); 2397 testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) { 2398 cm.setCursor(0, 0); 2399 helpers.doKeys('<C-v>', '2', 'j', 'x'); 2400 cm.setCursor(0, 0); 2401 helpers.doKeys('P'); 2402 eq('cut\nand\npaste\nme', cm.getValue()); 2403 }, { value: 'cut\nand\npaste\nme'}); 2404 testVim('blockwise_paste_from_register', function(cm, vim, helpers) { 2405 cm.setCursor(0, 0); 2406 helpers.doKeys('<C-v>', '2', 'j', '"', 'a', 'y'); 2407 cm.setCursor(0, 3); 2408 helpers.doKeys('"', 'a', 'p'); 2409 eq('foobfar\nhellho\nworlwd', cm.getValue()); 2410 }, { value: 'foobar\nhello\nworld'}); 2411 testVim('blockwise_paste_last_line', function(cm, vim, helpers) { 2412 cm.setCursor(0, 0); 2413 helpers.doKeys('<C-v>', '2', 'j', 'l', 'y'); 2414 cm.setCursor(3, 0); 2415 helpers.doKeys('p'); 2416 eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue()); 2417 }, { value: 'cut\nand\npaste\nme'}); 2418 2419 testVim('S_visual', function(cm, vim, helpers) { 2420 cm.setCursor(0, 1); 2421 helpers.doKeys('v', 'j', 'S'); 2422 helpers.doKeys('<Esc>'); 2423 helpers.assertCursorAt(0, 0); 2424 eq('\ncc', cm.getValue()); 2425 }, { value: 'aa\nbb\ncc'}); 2426 2427 testVim('d_/', function(cm, vim, helpers) { 2428 cm.openDialog = helpers.fakeOpenDialog('match'); 2429 helpers.doKeys('2', 'd', '/'); 2430 helpers.assertCursorAt(0, 0); 2431 eq('match \n next', cm.getValue()); 2432 cm.openDialog = helpers.fakeOpenDialog('2'); 2433 helpers.doKeys('d', ':'); 2434 // TODO eq(' next', cm.getValue()); 2435 }, { value: 'text match match \n next' }); 2436 testVim('/ and n/N', function(cm, vim, helpers) { 2437 cm.openDialog = helpers.fakeOpenDialog('match'); 2438 helpers.doKeys('/'); 2439 helpers.assertCursorAt(0, 11); 2440 helpers.doKeys('n'); 2441 helpers.assertCursorAt(1, 6); 2442 helpers.doKeys('N'); 2443 helpers.assertCursorAt(0, 11); 2444 2445 cm.setCursor(0, 0); 2446 helpers.doKeys('2', '/'); 2447 helpers.assertCursorAt(1, 6); 2448 }, { value: 'match nope match \n nope Match' }); 2449 testVim('/_case', function(cm, vim, helpers) { 2450 cm.openDialog = helpers.fakeOpenDialog('Match'); 2451 helpers.doKeys('/'); 2452 helpers.assertCursorAt(1, 6); 2453 }, { value: 'match nope match \n nope Match' }); 2454 testVim('/_2_pcre', function(cm, vim, helpers) { 2455 CodeMirror.Vim.setOption('pcre', true); 2456 cm.openDialog = helpers.fakeOpenDialog('(word){2}'); 2457 helpers.doKeys('/'); 2458 helpers.assertCursorAt(1, 9); 2459 helpers.doKeys('n'); 2460 helpers.assertCursorAt(2, 1); 2461 }, { value: 'word\n another wordword\n wordwordword\n' }); 2462 testVim('/_2_nopcre', function(cm, vim, helpers) { 2463 CodeMirror.Vim.setOption('pcre', false); 2464 cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}'); 2465 helpers.doKeys('/'); 2466 helpers.assertCursorAt(1, 9); 2467 helpers.doKeys('n'); 2468 helpers.assertCursorAt(2, 1); 2469 }, { value: 'word\n another wordword\n wordwordword\n' }); 2470 testVim('/_nongreedy', function(cm, vim, helpers) { 2471 cm.openDialog = helpers.fakeOpenDialog('aa'); 2472 helpers.doKeys('/'); 2473 helpers.assertCursorAt(0, 4); 2474 helpers.doKeys('n'); 2475 helpers.assertCursorAt(1, 3); 2476 helpers.doKeys('n'); 2477 helpers.assertCursorAt(0, 0); 2478 }, { value: 'aaa aa \n a aa'}); 2479 testVim('?_nongreedy', function(cm, vim, helpers) { 2480 cm.openDialog = helpers.fakeOpenDialog('aa'); 2481 helpers.doKeys('?'); 2482 helpers.assertCursorAt(1, 3); 2483 helpers.doKeys('n'); 2484 helpers.assertCursorAt(0, 4); 2485 helpers.doKeys('n'); 2486 helpers.assertCursorAt(0, 0); 2487 }, { value: 'aaa aa \n a aa'}); 2488 testVim('/_greedy', function(cm, vim, helpers) { 2489 cm.openDialog = helpers.fakeOpenDialog('a+'); 2490 helpers.doKeys('/'); 2491 helpers.assertCursorAt(0, 4); 2492 helpers.doKeys('n'); 2493 helpers.assertCursorAt(1, 1); 2494 helpers.doKeys('n'); 2495 helpers.assertCursorAt(1, 3); 2496 helpers.doKeys('n'); 2497 helpers.assertCursorAt(0, 0); 2498 }, { value: 'aaa aa \n a aa'}); 2499 testVim('?_greedy', function(cm, vim, helpers) { 2500 cm.openDialog = helpers.fakeOpenDialog('a+'); 2501 helpers.doKeys('?'); 2502 helpers.assertCursorAt(1, 3); 2503 helpers.doKeys('n'); 2504 helpers.assertCursorAt(1, 1); 2505 helpers.doKeys('n'); 2506 helpers.assertCursorAt(0, 4); 2507 helpers.doKeys('n'); 2508 helpers.assertCursorAt(0, 0); 2509 }, { value: 'aaa aa \n a aa'}); 2510 testVim('/_greedy_0_or_more', function(cm, vim, helpers) { 2511 cm.openDialog = helpers.fakeOpenDialog('a*'); 2512 helpers.doKeys('/'); 2513 helpers.assertCursorAt(0, 3); 2514 helpers.doKeys('n'); 2515 helpers.assertCursorAt(0, 4); 2516 helpers.doKeys('n'); 2517 helpers.assertCursorAt(0, 5); 2518 helpers.doKeys('n'); 2519 helpers.assertCursorAt(1, 0); 2520 helpers.doKeys('n'); 2521 helpers.assertCursorAt(1, 1); 2522 helpers.doKeys('n'); 2523 helpers.assertCursorAt(0, 0); 2524 }, { value: 'aaa aa\n aa'}); 2525 testVim('?_greedy_0_or_more', function(cm, vim, helpers) { 2526 cm.openDialog = helpers.fakeOpenDialog('a*'); 2527 helpers.doKeys('?'); 2528 helpers.assertCursorAt(1, 1); 2529 helpers.doKeys('n'); 2530 helpers.assertCursorAt(0, 5); 2531 helpers.doKeys('n'); 2532 helpers.assertCursorAt(0, 3); 2533 helpers.doKeys('n'); 2534 helpers.assertCursorAt(0, 0); 2535 }, { value: 'aaa aa\n aa'}); 2536 testVim('? and n/N', function(cm, vim, helpers) { 2537 cm.openDialog = helpers.fakeOpenDialog('match'); 2538 helpers.doKeys('?'); 2539 helpers.assertCursorAt(1, 6); 2540 helpers.doKeys('n'); 2541 helpers.assertCursorAt(0, 11); 2542 helpers.doKeys('N'); 2543 helpers.assertCursorAt(1, 6); 2544 2545 cm.setCursor(0, 0); 2546 helpers.doKeys('2', '?'); 2547 helpers.assertCursorAt(0, 11); 2548 }, { value: 'match nope match \n nope Match' }); 2549 testVim('*', function(cm, vim, helpers) { 2550 cm.setCursor(0, 9); 2551 helpers.doKeys('*'); 2552 helpers.assertCursorAt(0, 22); 2553 2554 cm.setCursor(0, 9); 2555 helpers.doKeys('2', '*'); 2556 helpers.assertCursorAt(1, 8); 2557 }, { value: 'nomatch match nomatch match \nnomatch Match' }); 2558 testVim('*_no_word', function(cm, vim, helpers) { 2559 cm.setCursor(0, 0); 2560 helpers.doKeys('*'); 2561 helpers.assertCursorAt(0, 0); 2562 }, { value: ' \n match \n' }); 2563 testVim('*_symbol', function(cm, vim, helpers) { 2564 cm.setCursor(0, 0); 2565 helpers.doKeys('*'); 2566 helpers.assertCursorAt(1, 0); 2567 }, { value: ' /}\n/} match \n' }); 2568 testVim('#', function(cm, vim, helpers) { 2569 cm.setCursor(0, 9); 2570 helpers.doKeys('#'); 2571 helpers.assertCursorAt(1, 8); 2572 2573 cm.setCursor(0, 9); 2574 helpers.doKeys('2', '#'); 2575 helpers.assertCursorAt(0, 22); 2576 }, { value: 'nomatch match nomatch match \nnomatch Match' }); 2577 testVim('*_seek', function(cm, vim, helpers) { 2578 // Should skip over space and symbols. 2579 cm.setCursor(0, 3); 2580 helpers.doKeys('*'); 2581 helpers.assertCursorAt(0, 22); 2582 }, { value: ' := match nomatch match \nnomatch Match' }); 2583 testVim('#', function(cm, vim, helpers) { 2584 // Should skip over space and symbols. 2585 cm.setCursor(0, 3); 2586 helpers.doKeys('#'); 2587 helpers.assertCursorAt(1, 8); 2588 }, { value: ' := match nomatch match \nnomatch Match' }); 2589 testVim('g*', function(cm, vim, helpers) { 2590 cm.setCursor(0, 8); 2591 helpers.doKeys('g', '*'); 2592 helpers.assertCursorAt(0, 18); 2593 cm.setCursor(0, 8); 2594 helpers.doKeys('3', 'g', '*'); 2595 helpers.assertCursorAt(1, 8); 2596 }, { value: 'matches match alsoMatch\nmatchme matching' }); 2597 testVim('g#', function(cm, vim, helpers) { 2598 cm.setCursor(0, 8); 2599 helpers.doKeys('g', '#'); 2600 helpers.assertCursorAt(0, 0); 2601 cm.setCursor(0, 8); 2602 helpers.doKeys('3', 'g', '#'); 2603 helpers.assertCursorAt(1, 0); 2604 }, { value: 'matches match alsoMatch\nmatchme matching' }); 2605 testVim('macro_insert', function(cm, vim, helpers) { 2606 cm.setCursor(0, 0); 2607 helpers.doKeys('q', 'a', '0', 'i'); 2608 helpers.doKeys('foo') 2609 helpers.doKeys('<Esc>'); 2610 helpers.doKeys('q', '@', 'a'); 2611 eq('foofoo', cm.getValue()); 2612 }, { value: ''}); 2613 testVim('macro_insert_repeat', function(cm, vim, helpers) { 2614 cm.setCursor(0, 0); 2615 helpers.doKeys('q', 'a', '$', 'a'); 2616 helpers.doKeys('larry.') 2617 helpers.doKeys('<Esc>'); 2618 helpers.doKeys('a'); 2619 helpers.doKeys('curly.') 2620 helpers.doKeys('<Esc>'); 2621 helpers.doKeys('q'); 2622 helpers.doKeys('a'); 2623 helpers.doKeys('moe.') 2624 helpers.doKeys('<Esc>'); 2625 helpers.doKeys('@', 'a'); 2626 // At this point, the most recent edit should be the 2nd insert change 2627 // inside the macro, i.e. "curly.". 2628 helpers.doKeys('.'); 2629 eq('larry.curly.moe.larry.curly.curly.', cm.getValue()); 2630 }, { value: ''}); 2631 testVim('macro_space', function(cm, vim, helpers) { 2632 cm.setCursor(0, 0); 2633 helpers.doKeys('<Space>', '<Space>'); 2634 helpers.assertCursorAt(0, 2); 2635 helpers.doKeys('q', 'a', '<Space>', '<Space>', 'q'); 2636 helpers.assertCursorAt(0, 4); 2637 helpers.doKeys('@', 'a'); 2638 helpers.assertCursorAt(0, 6); 2639 helpers.doKeys('@', 'a'); 2640 helpers.assertCursorAt(0, 8); 2641 }, { value: 'one line of text.'}); 2642 testVim('macro_t_search', function(cm, vim, helpers) { 2643 cm.setCursor(0, 0); 2644 helpers.doKeys('q', 'a', 't', 'e', 'q'); 2645 helpers.assertCursorAt(0, 1); 2646 helpers.doKeys('l', '@', 'a'); 2647 helpers.assertCursorAt(0, 6); 2648 helpers.doKeys('l', ';'); 2649 helpers.assertCursorAt(0, 12); 2650 }, { value: 'one line of text.'}); 2651 testVim('macro_f_search', function(cm, vim, helpers) { 2652 cm.setCursor(0, 0); 2653 helpers.doKeys('q', 'b', 'f', 'e', 'q'); 2654 helpers.assertCursorAt(0, 2); 2655 helpers.doKeys('@', 'b'); 2656 helpers.assertCursorAt(0, 7); 2657 helpers.doKeys(';'); 2658 helpers.assertCursorAt(0, 13); 2659 }, { value: 'one line of text.'}); 2660 testVim('macro_slash_search', function(cm, vim, helpers) { 2661 cm.setCursor(0, 0); 2662 helpers.doKeys('q', 'c'); 2663 cm.openDialog = helpers.fakeOpenDialog('e'); 2664 helpers.doKeys('/', 'q'); 2665 helpers.assertCursorAt(0, 2); 2666 helpers.doKeys('@', 'c'); 2667 helpers.assertCursorAt(0, 7); 2668 helpers.doKeys('n'); 2669 helpers.assertCursorAt(0, 13); 2670 }, { value: 'one line of text.'}); 2671 testVim('macro_multislash_search', function(cm, vim, helpers) { 2672 cm.setCursor(0, 0); 2673 helpers.doKeys('q', 'd'); 2674 cm.openDialog = helpers.fakeOpenDialog('e'); 2675 helpers.doKeys('/'); 2676 cm.openDialog = helpers.fakeOpenDialog('t'); 2677 helpers.doKeys('/', 'q'); 2678 helpers.assertCursorAt(0, 12); 2679 helpers.doKeys('@', 'd'); 2680 helpers.assertCursorAt(0, 15); 2681 }, { value: 'one line of text to rule them all.'}); 2682 testVim('macro_last_ex_command_register', function (cm, vim, helpers) { 2683 cm.setCursor(0, 0); 2684 helpers.doEx('s/a/b'); 2685 helpers.doKeys('2', '@', ':'); 2686 eq('bbbaa', cm.getValue()); 2687 helpers.assertCursorAt(0, 2); 2688 }, { value: 'aaaaa'}); 2689 testVim('macro_last_run_macro', function (cm, vim, helpers) { 2690 cm.setCursor(0, 0); 2691 helpers.doKeys('q', 'a', 'C', 'a', '<Esc>', 'q'); 2692 helpers.doKeys('q', 'b', 'C', 'b', '<Esc>', 'q'); 2693 helpers.doKeys('@', 'a'); 2694 helpers.doKeys('d', 'd'); 2695 helpers.doKeys('@', '@'); 2696 eq('a', cm.getValue()); 2697 }, { value: ''}); 2698 testVim('macro_parens', function(cm, vim, helpers) { 2699 cm.setCursor(0, 0); 2700 helpers.doKeys('q', 'z', 'i'); 2701 helpers.doKeys('(') 2702 helpers.doKeys('<Esc>'); 2703 helpers.doKeys('e', 'a'); 2704 helpers.doKeys(')') 2705 helpers.doKeys('<Esc>'); 2706 helpers.doKeys('q'); 2707 helpers.doKeys('w', '@', 'z'); 2708 helpers.doKeys('w', '@', 'z'); 2709 eq('(see) (spot) (run)', cm.getValue()); 2710 }, { value: 'see spot run'}); 2711 testVim('macro_overwrite', function(cm, vim, helpers) { 2712 cm.setCursor(0, 0); 2713 helpers.doKeys('q', 'z', '0', 'i'); 2714 helpers.doKeys('I ') 2715 helpers.doKeys('<Esc>'); 2716 helpers.doKeys('q'); 2717 helpers.doKeys('e'); 2718 // Now replace the macro with something else. 2719 helpers.doKeys('q', 'z', 'a'); 2720 helpers.doKeys('.') 2721 helpers.doKeys('<Esc>'); 2722 helpers.doKeys('q'); 2723 helpers.doKeys('e', '@', 'z'); 2724 helpers.doKeys('e', '@', 'z'); 2725 eq('I see. spot. run.', cm.getValue()); 2726 }, { value: 'see spot run'}); 2727 testVim('macro_search_f', function(cm, vim, helpers) { 2728 cm.setCursor(0, 0); 2729 helpers.doKeys('q', 'a', 'f', ' '); 2730 helpers.assertCursorAt(0,3); 2731 helpers.doKeys('q', '0'); 2732 helpers.assertCursorAt(0,0); 2733 helpers.doKeys('@', 'a'); 2734 helpers.assertCursorAt(0,3); 2735 }, { value: 'The quick brown fox jumped over the lazy dog.'}); 2736 testVim('macro_search_2f', function(cm, vim, helpers) { 2737 cm.setCursor(0, 0); 2738 helpers.doKeys('q', 'a', '2', 'f', ' '); 2739 helpers.assertCursorAt(0,9); 2740 helpers.doKeys('q', '0'); 2741 helpers.assertCursorAt(0,0); 2742 helpers.doKeys('@', 'a'); 2743 helpers.assertCursorAt(0,9); 2744 }, { value: 'The quick brown fox jumped over the lazy dog.'}); 2745 testVim('macro_yank_tick', function(cm, vim, helpers) { 2746 cm.setCursor(0, 0); 2747 // Start recording a macro into the \' register. 2748 helpers.doKeys('q', '\''); 2749 helpers.doKeys('y', '<Right>', '<Right>', '<Right>', '<Right>', 'p'); 2750 helpers.assertCursorAt(0,4); 2751 eq('the tex parrot', cm.getValue()); 2752 }, { value: 'the ex parrot'}); 2753 testVim('yank_register', function(cm, vim, helpers) { 2754 cm.setCursor(0, 0); 2755 helpers.doKeys('"', 'a', 'y', 'y'); 2756 helpers.doKeys('j', '"', 'b', 'y', 'y'); 2757 cm.openDialog = helpers.fakeOpenDialog('registers'); 2758 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2759 is(/a\s+foo/.test(text)); 2760 is(/b\s+bar/.test(text)); 2761 }); 2762 helpers.doKeys(':'); 2763 }, { value: 'foo\nbar'}); 2764 testVim('yank_visual_block', function(cm, vim, helpers) { 2765 cm.setCursor(0, 1); 2766 helpers.doKeys('<C-v>', 'l', 'j', '"', 'a', 'y'); 2767 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2768 is(/a\s+oo\nar/.test(text)); 2769 }); 2770 helpers.doKeys(':'); 2771 }, { value: 'foo\nbar'}); 2772 testVim('yank_append_line_to_line_register', function(cm, vim, helpers) { 2773 cm.setCursor(0, 0); 2774 helpers.doKeys('"', 'a', 'y', 'y'); 2775 helpers.doKeys('j', '"', 'A', 'y', 'y'); 2776 cm.openDialog = helpers.fakeOpenDialog('registers'); 2777 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2778 is(/a\s+foo\nbar/.test(text)); 2779 is(/"\s+foo\nbar/.test(text)); 2780 }); 2781 helpers.doKeys(':'); 2782 }, { value: 'foo\nbar'}); 2783 testVim('yank_append_word_to_word_register', function(cm, vim, helpers) { 2784 cm.setCursor(0, 0); 2785 helpers.doKeys('"', 'a', 'y', 'w'); 2786 helpers.doKeys('j', '"', 'A', 'y', 'w'); 2787 cm.openDialog = helpers.fakeOpenDialog('registers'); 2788 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2789 is(/a\s+foobar/.test(text)); 2790 is(/"\s+foobar/.test(text)); 2791 }); 2792 helpers.doKeys(':'); 2793 }, { value: 'foo\nbar'}); 2794 testVim('yank_append_line_to_word_register', function(cm, vim, helpers) { 2795 cm.setCursor(0, 0); 2796 helpers.doKeys('"', 'a', 'y', 'w'); 2797 helpers.doKeys('j', '"', 'A', 'y', 'y'); 2798 cm.openDialog = helpers.fakeOpenDialog('registers'); 2799 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2800 is(/a\s+foo\nbar/.test(text)); 2801 is(/"\s+foo\nbar/.test(text)); 2802 }); 2803 helpers.doKeys(':'); 2804 }, { value: 'foo\nbar'}); 2805 testVim('yank_append_word_to_line_register', function(cm, vim, helpers) { 2806 cm.setCursor(0, 0); 2807 helpers.doKeys('"', 'a', 'y', 'y'); 2808 helpers.doKeys('j', '"', 'A', 'y', 'w'); 2809 cm.openDialog = helpers.fakeOpenDialog('registers'); 2810 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2811 is(/a\s+foo\nbar/.test(text)); 2812 is(/"\s+foo\nbar/.test(text)); 2813 }); 2814 helpers.doKeys(':'); 2815 }, { value: 'foo\nbar'}); 2816 testVim('macro_register', function(cm, vim, helpers) { 2817 cm.setCursor(0, 0); 2818 helpers.doKeys('q', 'a', 'i'); 2819 helpers.doKeys('gangnam') 2820 helpers.doKeys('<Esc>'); 2821 helpers.doKeys('q'); 2822 helpers.doKeys('q', 'b', 'o'); 2823 helpers.doKeys('style') 2824 helpers.doKeys('<Esc>'); 2825 helpers.doKeys('q'); 2826 cm.openDialog = helpers.fakeOpenDialog('registers'); 2827 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2828 is(/a\s+i/.test(text)); 2829 is(/b\s+o/.test(text)); 2830 }); 2831 helpers.doKeys(':'); 2832 }, { value: ''}); 2833 testVim('._register', function(cm,vim,helpers) { 2834 cm.setCursor(0,0); 2835 helpers.doKeys('i'); 2836 helpers.doKeys('foo') 2837 helpers.doKeys('<Esc>'); 2838 cm.openDialog = helpers.fakeOpenDialog('registers'); 2839 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2840 is(/\.\s+foo/.test(text)); 2841 }); 2842 helpers.doKeys(':'); 2843 }, {value: ''}); 2844 testVim(':_register', function(cm,vim,helpers) { 2845 helpers.doEx('bar'); 2846 cm.openDialog = helpers.fakeOpenDialog('registers'); 2847 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2848 is(/:\s+bar/.test(text)); 2849 }); 2850 helpers.doKeys(':'); 2851 }, {value: ''}); 2852 testVim('search_register_escape', function(cm, vim, helpers) { 2853 // Check that the register is restored if the user escapes rather than confirms. 2854 cm.openDialog = helpers.fakeOpenDialog('waldo'); 2855 helpers.doKeys('/'); 2856 var onKeyDown; 2857 var onKeyUp; 2858 var KEYCODES = { 2859 f: 70, 2860 o: 79, 2861 Esc: 27 2862 }; 2863 cm.openDialog = function(template, callback, options) { 2864 onKeyDown = options.onKeyDown; 2865 onKeyUp = options.onKeyUp; 2866 }; 2867 var close = function() {}; 2868 helpers.doKeys('/'); 2869 // Fake some keyboard events coming in. 2870 onKeyDown({keyCode: KEYCODES.f}, '', close); 2871 onKeyUp({keyCode: KEYCODES.f}, '', close); 2872 onKeyDown({keyCode: KEYCODES.o}, 'f', close); 2873 onKeyUp({keyCode: KEYCODES.o}, 'f', close); 2874 onKeyDown({keyCode: KEYCODES.o}, 'fo', close); 2875 onKeyUp({keyCode: KEYCODES.o}, 'fo', close); 2876 onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close); 2877 cm.openDialog = helpers.fakeOpenDialog('registers'); 2878 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2879 is(/waldo/.test(text)); 2880 is(!/foo/.test(text)); 2881 }); 2882 helpers.doKeys(':'); 2883 }, {value: ''}); 2884 testVim('search_register', function(cm, vim, helpers) { 2885 cm.openDialog = helpers.fakeOpenDialog('foo'); 2886 helpers.doKeys('/'); 2887 cm.openDialog = helpers.fakeOpenDialog('registers'); 2888 cm.openNotification = helpers.fakeOpenNotification(function(text) { 2889 is(/\/\s+foo/.test(text)); 2890 }); 2891 helpers.doKeys(':'); 2892 }, {value: ''}); 2893 testVim('search_history', function(cm, vim, helpers) { 2894 cm.openDialog = helpers.fakeOpenDialog('this'); 2895 helpers.doKeys('/'); 2896 cm.openDialog = helpers.fakeOpenDialog('checks'); 2897 helpers.doKeys('/'); 2898 cm.openDialog = helpers.fakeOpenDialog('search'); 2899 helpers.doKeys('/'); 2900 cm.openDialog = helpers.fakeOpenDialog('history'); 2901 helpers.doKeys('/'); 2902 cm.openDialog = helpers.fakeOpenDialog('checks'); 2903 helpers.doKeys('/'); 2904 var onKeyDown; 2905 var onKeyUp; 2906 var query = ''; 2907 var keyCodes = { 2908 Up: 38, 2909 Down: 40 2910 }; 2911 cm.openDialog = function(template, callback, options) { 2912 onKeyUp = options.onKeyUp; 2913 onKeyDown = options.onKeyDown; 2914 }; 2915 var close = function(newVal) { 2916 if (typeof newVal == 'string') query = newVal; 2917 } 2918 helpers.doKeys('/'); 2919 onKeyDown({keyCode: keyCodes.Up}, query, close); 2920 onKeyUp({keyCode: keyCodes.Up}, query, close); 2921 eq(query, 'checks'); 2922 onKeyDown({keyCode: keyCodes.Up}, query, close); 2923 onKeyUp({keyCode: keyCodes.Up}, query, close); 2924 eq(query, 'history'); 2925 onKeyDown({keyCode: keyCodes.Up}, query, close); 2926 onKeyUp({keyCode: keyCodes.Up}, query, close); 2927 eq(query, 'search'); 2928 onKeyDown({keyCode: keyCodes.Up}, query, close); 2929 onKeyUp({keyCode: keyCodes.Up}, query, close); 2930 eq(query, 'this'); 2931 onKeyDown({keyCode: keyCodes.Down}, query, close); 2932 onKeyUp({keyCode: keyCodes.Down}, query, close); 2933 eq(query, 'search'); 2934 }, {value: ''}); 2935 testVim('exCommand_history', function(cm, vim, helpers) { 2936 cm.openDialog = helpers.fakeOpenDialog('registers'); 2937 helpers.doKeys(':'); 2938 cm.openDialog = helpers.fakeOpenDialog('sort'); 2939 helpers.doKeys(':'); 2940 cm.openDialog = helpers.fakeOpenDialog('map'); 2941 helpers.doKeys(':'); 2942 cm.openDialog = helpers.fakeOpenDialog('invalid'); 2943 helpers.doKeys(':'); 2944 var onKeyDown; 2945 var onKeyUp; 2946 var input = ''; 2947 var keyCodes = { 2948 Up: 38, 2949 Down: 40, 2950 s: 115 2951 }; 2952 cm.openDialog = function(template, callback, options) { 2953 onKeyUp = options.onKeyUp; 2954 onKeyDown = options.onKeyDown; 2955 }; 2956 var close = function(newVal) { 2957 if (typeof newVal == 'string') input = newVal; 2958 } 2959 helpers.doKeys(':'); 2960 onKeyDown({keyCode: keyCodes.Up}, input, close); 2961 eq(input, 'invalid'); 2962 onKeyDown({keyCode: keyCodes.Up}, input, close); 2963 eq(input, 'map'); 2964 onKeyDown({keyCode: keyCodes.Up}, input, close); 2965 eq(input, 'sort'); 2966 onKeyDown({keyCode: keyCodes.Up}, input, close); 2967 eq(input, 'registers'); 2968 onKeyDown({keyCode: keyCodes.s}, '', close); 2969 input = 's'; 2970 onKeyDown({keyCode: keyCodes.Up}, input, close); 2971 eq(input, 'sort'); 2972 }, {value: ''}); 2973 testVim('search_clear', function(cm, vim, helpers) { 2974 var onKeyDown; 2975 var input = ''; 2976 var keyCodes = { 2977 Ctrl: 17, 2978 u: 85 2979 }; 2980 cm.openDialog = function(template, callback, options) { 2981 onKeyDown = options.onKeyDown; 2982 }; 2983 var close = function(newVal) { 2984 if (typeof newVal == 'string') input = newVal; 2985 } 2986 helpers.doKeys('/'); 2987 input = 'foo'; 2988 onKeyDown({keyCode: keyCodes.Ctrl}, input, close); 2989 onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close); 2990 eq(input, ''); 2991 }); 2992 testVim('exCommand_clear', function(cm, vim, helpers) { 2993 var onKeyDown; 2994 var input = ''; 2995 var keyCodes = { 2996 Ctrl: 17, 2997 u: 85 2998 }; 2999 cm.openDialog = function(template, callback, options) { 3000 onKeyDown = options.onKeyDown; 3001 }; 3002 var close = function(newVal) { 3003 if (typeof newVal == 'string') input = newVal; 3004 } 3005 helpers.doKeys(':'); 3006 input = 'foo'; 3007 onKeyDown({keyCode: keyCodes.Ctrl}, input, close); 3008 onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close); 3009 eq(input, ''); 3010 }); 3011 testVim('.', function(cm, vim, helpers) { 3012 cm.setCursor(0, 0); 3013 helpers.doKeys('2', 'd', 'w'); 3014 helpers.doKeys('.'); 3015 eq('5 6', cm.getValue()); 3016 }, { value: '1 2 3 4 5 6'}); 3017 testVim('._repeat', function(cm, vim, helpers) { 3018 cm.setCursor(0, 0); 3019 helpers.doKeys('2', 'd', 'w'); 3020 helpers.doKeys('3', '.'); 3021 eq('6', cm.getValue()); 3022 }, { value: '1 2 3 4 5 6'}); 3023 testVim('._insert', function(cm, vim, helpers) { 3024 helpers.doKeys('i'); 3025 helpers.doKeys('test') 3026 helpers.doKeys('<Esc>'); 3027 helpers.doKeys('.'); 3028 eq('testestt', cm.getValue()); 3029 helpers.assertCursorAt(0, 6); 3030 helpers.doKeys('O'); 3031 helpers.doKeys('xyz') 3032 helpers.doInsertModeKeys('Backspace'); 3033 helpers.doInsertModeKeys('Down'); 3034 helpers.doKeys('<Esc>'); 3035 helpers.doKeys('.'); 3036 eq('xy\nxy\ntestestt', cm.getValue()); 3037 helpers.assertCursorAt(1, 1); 3038 }, { value: ''}); 3039 testVim('._insert_repeat', function(cm, vim, helpers) { 3040 helpers.doKeys('i'); 3041 helpers.doKeys('test') 3042 cm.setCursor(0, 4); 3043 helpers.doKeys('<Esc>'); 3044 helpers.doKeys('2', '.'); 3045 eq('testesttestt', cm.getValue()); 3046 helpers.assertCursorAt(0, 10); 3047 }, { value: ''}); 3048 testVim('._repeat_insert', function(cm, vim, helpers) { 3049 helpers.doKeys('3', 'i'); 3050 helpers.doKeys('te') 3051 cm.setCursor(0, 2); 3052 helpers.doKeys('<Esc>'); 3053 helpers.doKeys('.'); 3054 eq('tetettetetee', cm.getValue()); 3055 helpers.assertCursorAt(0, 10); 3056 }, { value: ''}); 3057 testVim('._insert_o', function(cm, vim, helpers) { 3058 helpers.doKeys('o'); 3059 helpers.doKeys('z') 3060 cm.setCursor(1, 1); 3061 helpers.doKeys('<Esc>'); 3062 helpers.doKeys('.'); 3063 eq('\nz\nz', cm.getValue()); 3064 helpers.assertCursorAt(2, 0); 3065 }, { value: ''}); 3066 testVim('._insert_o_repeat', function(cm, vim, helpers) { 3067 helpers.doKeys('o'); 3068 helpers.doKeys('z') 3069 helpers.doKeys('<Esc>'); 3070 cm.setCursor(1, 0); 3071 helpers.doKeys('2', '.'); 3072 eq('\nz\nz\nz', cm.getValue()); 3073 helpers.assertCursorAt(3, 0); 3074 }, { value: ''}); 3075 testVim('._insert_o_indent', function(cm, vim, helpers) { 3076 helpers.doKeys('o'); 3077 helpers.doKeys('z') 3078 helpers.doKeys('<Esc>'); 3079 cm.setCursor(1, 2); 3080 helpers.doKeys('.'); 3081 eq('{\n z\n z', cm.getValue()); 3082 helpers.assertCursorAt(2, 2); 3083 }, { value: '{'}); 3084 testVim('._insert_cw', function(cm, vim, helpers) { 3085 helpers.doKeys('c', 'w'); 3086 helpers.doKeys('test') 3087 helpers.doKeys('<Esc>'); 3088 cm.setCursor(0, 3); 3089 helpers.doKeys('2', 'l'); 3090 helpers.doKeys('.'); 3091 eq('test test word3', cm.getValue()); 3092 helpers.assertCursorAt(0, 8); 3093 }, { value: 'word1 word2 word3' }); 3094 testVim('._insert_cw_repeat', function(cm, vim, helpers) { 3095 // For some reason, repeat cw in desktop VIM will does not repeat insert mode 3096 // changes. Will conform to that behavior. 3097 helpers.doKeys('c', 'w'); 3098 helpers.doKeys('test'); 3099 helpers.doKeys('<Esc>'); 3100 cm.setCursor(0, 4); 3101 helpers.doKeys('l'); 3102 helpers.doKeys('2', '.'); 3103 eq('test test', cm.getValue()); 3104 helpers.assertCursorAt(0, 8); 3105 }, { value: 'word1 word2 word3' }); 3106 testVim('._delete', function(cm, vim, helpers) { 3107 cm.setCursor(0, 5); 3108 helpers.doKeys('i'); 3109 helpers.doInsertModeKeys('Backspace'); 3110 helpers.doKeys('<Esc>'); 3111 helpers.doKeys('.'); 3112 eq('zace', cm.getValue()); 3113 helpers.assertCursorAt(0, 1); 3114 }, { value: 'zabcde'}); 3115 testVim('._delete_repeat', function(cm, vim, helpers) { 3116 cm.setCursor(0, 6); 3117 helpers.doKeys('i'); 3118 helpers.doInsertModeKeys('Backspace'); 3119 helpers.doKeys('<Esc>'); 3120 helpers.doKeys('2', '.'); 3121 eq('zzce', cm.getValue()); 3122 helpers.assertCursorAt(0, 1); 3123 }, { value: 'zzabcde'}); 3124 testVim('._visual_>', function(cm, vim, helpers) { 3125 cm.setCursor(0, 0); 3126 helpers.doKeys('V', 'j', '>'); 3127 cm.setCursor(2, 0) 3128 helpers.doKeys('.'); 3129 eq(' 1\n 2\n 3\n 4', cm.getValue()); 3130 helpers.assertCursorAt(2, 2); 3131 }, { value: '1\n2\n3\n4'}); 3132 testVim('._replace_repeat', function(cm, vim, helpers) { 3133 helpers.doKeys('R'); 3134 cm.replaceRange('123', cm.getCursor(), offsetCursor(cm.getCursor(), 0, 3)); 3135 cm.setCursor(0, 3); 3136 helpers.doKeys('<Esc>'); 3137 helpers.doKeys('2', '.'); 3138 eq('12123123\nabcdefg', cm.getValue()); 3139 helpers.assertCursorAt(0, 7); 3140 cm.setCursor(1, 0); 3141 helpers.doKeys('.'); 3142 eq('12123123\n123123g', cm.getValue()); 3143 helpers.doKeys('l', '"', '.', 'p'); 3144 eq('12123123\n123123g123', cm.getValue()); 3145 }, { value: 'abcdef\nabcdefg'}); 3146 testVim('f;', function(cm, vim, helpers) { 3147 cm.setCursor(0, 0); 3148 helpers.doKeys('f', 'x'); 3149 helpers.doKeys(';'); 3150 helpers.doKeys('2', ';'); 3151 eq(9, cm.getCursor().ch); 3152 }, { value: '01x3xx678x'}); 3153 testVim('F;', function(cm, vim, helpers) { 3154 cm.setCursor(0, 8); 3155 helpers.doKeys('F', 'x'); 3156 helpers.doKeys(';'); 3157 helpers.doKeys('2', ';'); 3158 eq(2, cm.getCursor().ch); 3159 }, { value: '01x3xx6x8x'}); 3160 testVim('t;', function(cm, vim, helpers) { 3161 cm.setCursor(0, 0); 3162 helpers.doKeys('t', 'x'); 3163 helpers.doKeys(';'); 3164 helpers.doKeys('2', ';'); 3165 eq(8, cm.getCursor().ch); 3166 }, { value: '01x3xx678x'}); 3167 testVim('T;', function(cm, vim, helpers) { 3168 cm.setCursor(0, 9); 3169 helpers.doKeys('T', 'x'); 3170 helpers.doKeys(';'); 3171 helpers.doKeys('2', ';'); 3172 eq(2, cm.getCursor().ch); 3173 }, { value: '0xx3xx678x'}); 3174 testVim('f,', function(cm, vim, helpers) { 3175 cm.setCursor(0, 6); 3176 helpers.doKeys('f', 'x'); 3177 helpers.doKeys(','); 3178 helpers.doKeys('2', ','); 3179 eq(2, cm.getCursor().ch); 3180 }, { value: '01x3xx678x'}); 3181 testVim('F,', function(cm, vim, helpers) { 3182 cm.setCursor(0, 3); 3183 helpers.doKeys('F', 'x'); 3184 helpers.doKeys(','); 3185 helpers.doKeys('2', ','); 3186 eq(9, cm.getCursor().ch); 3187 }, { value: '01x3xx678x'}); 3188 testVim('t,', function(cm, vim, helpers) { 3189 cm.setCursor(0, 6); 3190 helpers.doKeys('t', 'x'); 3191 helpers.doKeys(','); 3192 helpers.doKeys('2', ','); 3193 eq(3, cm.getCursor().ch); 3194 }, { value: '01x3xx678x'}); 3195 testVim('T,', function(cm, vim, helpers) { 3196 cm.setCursor(0, 4); 3197 helpers.doKeys('T', 'x'); 3198 helpers.doKeys(','); 3199 helpers.doKeys('2', ','); 3200 eq(8, cm.getCursor().ch); 3201 }, { value: '01x3xx67xx'}); 3202 testVim('fd,;', function(cm, vim, helpers) { 3203 cm.setCursor(0, 0); 3204 helpers.doKeys('f', '4'); 3205 cm.setCursor(0, 0); 3206 helpers.doKeys('d', ';'); 3207 eq('56789', cm.getValue()); 3208 helpers.doKeys('u'); 3209 cm.setCursor(0, 9); 3210 helpers.doKeys('d', ','); 3211 eq('01239', cm.getValue()); 3212 }, { value: '0123456789'}); 3213 testVim('Fd,;', function(cm, vim, helpers) { 3214 cm.setCursor(0, 9); 3215 helpers.doKeys('F', '4'); 3216 cm.setCursor(0, 9); 3217 helpers.doKeys('d', ';'); 3218 eq('01239', cm.getValue()); 3219 helpers.doKeys('u'); 3220 cm.setCursor(0, 0); 3221 helpers.doKeys('d', ','); 3222 eq('56789', cm.getValue()); 3223 }, { value: '0123456789'}); 3224 testVim('td,;', function(cm, vim, helpers) { 3225 cm.setCursor(0, 0); 3226 helpers.doKeys('t', '4'); 3227 cm.setCursor(0, 0); 3228 helpers.doKeys('d', ';'); 3229 eq('456789', cm.getValue()); 3230 helpers.doKeys('u'); 3231 cm.setCursor(0, 9); 3232 helpers.doKeys('d', ','); 3233 eq('012349', cm.getValue()); 3234 }, { value: '0123456789'}); 3235 testVim('Td,;', function(cm, vim, helpers) { 3236 cm.setCursor(0, 9); 3237 helpers.doKeys('T', '4'); 3238 cm.setCursor(0, 9); 3239 helpers.doKeys('d', ';'); 3240 eq('012349', cm.getValue()); 3241 helpers.doKeys('u'); 3242 cm.setCursor(0, 0); 3243 helpers.doKeys('d', ','); 3244 eq('456789', cm.getValue()); 3245 }, { value: '0123456789'}); 3246 testVim('fc,;', function(cm, vim, helpers) { 3247 cm.setCursor(0, 0); 3248 helpers.doKeys('f', '4'); 3249 cm.setCursor(0, 0); 3250 helpers.doKeys('c', ';', '<Esc>'); 3251 eq('56789', cm.getValue()); 3252 helpers.doKeys('u'); 3253 cm.setCursor(0, 9); 3254 helpers.doKeys('c', ','); 3255 eq('01239', cm.getValue()); 3256 }, { value: '0123456789'}); 3257 testVim('Fc,;', function(cm, vim, helpers) { 3258 cm.setCursor(0, 9); 3259 helpers.doKeys('F', '4'); 3260 cm.setCursor(0, 9); 3261 helpers.doKeys('c', ';', '<Esc>'); 3262 eq('01239', cm.getValue()); 3263 helpers.doKeys('u'); 3264 cm.setCursor(0, 0); 3265 helpers.doKeys('c', ','); 3266 eq('56789', cm.getValue()); 3267 }, { value: '0123456789'}); 3268 testVim('tc,;', function(cm, vim, helpers) { 3269 cm.setCursor(0, 0); 3270 helpers.doKeys('t', '4'); 3271 cm.setCursor(0, 0); 3272 helpers.doKeys('c', ';', '<Esc>'); 3273 eq('456789', cm.getValue()); 3274 helpers.doKeys('u'); 3275 cm.setCursor(0, 9); 3276 helpers.doKeys('c', ','); 3277 eq('012349', cm.getValue()); 3278 }, { value: '0123456789'}); 3279 testVim('Tc,;', function(cm, vim, helpers) { 3280 cm.setCursor(0, 9); 3281 helpers.doKeys('T', '4'); 3282 cm.setCursor(0, 9); 3283 helpers.doKeys('c', ';', '<Esc>'); 3284 eq('012349', cm.getValue()); 3285 helpers.doKeys('u'); 3286 cm.setCursor(0, 0); 3287 helpers.doKeys('c', ','); 3288 eq('456789', cm.getValue()); 3289 }, { value: '0123456789'}); 3290 testVim('fy,;', function(cm, vim, helpers) { 3291 cm.setCursor(0, 0); 3292 helpers.doKeys('f', '4'); 3293 cm.setCursor(0, 0); 3294 helpers.doKeys('y', ';', 'P'); 3295 eq('012340123456789', cm.getValue()); 3296 helpers.doKeys('u'); 3297 cm.setCursor(0, 9); 3298 helpers.doKeys('y', ',', 'P'); 3299 eq('012345678456789', cm.getValue()); 3300 }, { value: '0123456789'}); 3301 testVim('Fy,;', function(cm, vim, helpers) { 3302 cm.setCursor(0, 9); 3303 helpers.doKeys('F', '4'); 3304 cm.setCursor(0, 9); 3305 helpers.doKeys('y', ';', 'p'); 3306 eq('012345678945678', cm.getValue()); 3307 helpers.doKeys('u'); 3308 cm.setCursor(0, 0); 3309 helpers.doKeys('y', ',', 'P'); 3310 eq('012340123456789', cm.getValue()); 3311 }, { value: '0123456789'}); 3312 testVim('ty,;', function(cm, vim, helpers) { 3313 cm.setCursor(0, 0); 3314 helpers.doKeys('t', '4'); 3315 cm.setCursor(0, 0); 3316 helpers.doKeys('y', ';', 'P'); 3317 eq('01230123456789', cm.getValue()); 3318 helpers.doKeys('u'); 3319 cm.setCursor(0, 9); 3320 helpers.doKeys('y', ',', 'p'); 3321 eq('01234567895678', cm.getValue()); 3322 }, { value: '0123456789'}); 3323 testVim('Ty,;', function(cm, vim, helpers) { 3324 cm.setCursor(0, 9); 3325 helpers.doKeys('T', '4'); 3326 cm.setCursor(0, 9); 3327 helpers.doKeys('y', ';', 'p'); 3328 eq('01234567895678', cm.getValue()); 3329 helpers.doKeys('u'); 3330 cm.setCursor(0, 0); 3331 helpers.doKeys('y', ',', 'P'); 3332 eq('01230123456789', cm.getValue()); 3333 }, { value: '0123456789'}); 3334 testVim('HML', function(cm, vim, helpers) { 3335 var lines = 35; 3336 var textHeight = cm.defaultTextHeight(); 3337 cm.setSize(600, lines*textHeight); 3338 cm.setCursor(120, 0); 3339 helpers.doKeys('H'); 3340 helpers.assertCursorAt(86, 2); 3341 helpers.doKeys('L'); 3342 helpers.assertCursorAt(120, 4); 3343 helpers.doKeys('M'); 3344 helpers.assertCursorAt(103,4); 3345 }, { value: (function(){ 3346 var lines = new Array(100); 3347 var upper = ' xx\n'; 3348 var lower = ' xx\n'; 3349 upper = lines.join(upper); 3350 lower = lines.join(lower); 3351 return upper + lower; 3352 })()}); 3353 3354 var zVals = []; 3355 forEach(['zb','zz','zt','z-','z.','z<CR>'], function(e, idx){ 3356 var lineNum = 250; 3357 var lines = 35; 3358 testVim(e, function(cm, vim, helpers) { 3359 var k1 = e[0]; 3360 var k2 = e.substring(1); 3361 var textHeight = cm.defaultTextHeight(); 3362 cm.setSize(600, lines*textHeight); 3363 cm.setCursor(lineNum, 0); 3364 helpers.doKeys(k1, k2); 3365 zVals[idx] = cm.getScrollInfo().top; 3366 }, { value: (function(){ 3367 return new Array(500).join('\n'); 3368 })()}); 3369 }); 3370 testVim('zb_to_bottom', function(cm, vim, helpers){ 3371 var lineNum = 250; 3372 cm.setSize(600, 35*cm.defaultTextHeight()); 3373 cm.setCursor(lineNum, 0); 3374 helpers.doKeys('z', 'b'); 3375 var scrollInfo = cm.getScrollInfo(); 3376 eq(scrollInfo.top + scrollInfo.clientHeight, cm.charCoords(Pos(lineNum, 0), 'local').bottom); 3377 }, { value: (function(){ 3378 return new Array(500).join('\n'); 3379 })()}); 3380 testVim('zt_to_top', function(cm, vim, helpers){ 3381 var lineNum = 250; 3382 cm.setSize(600, 35*cm.defaultTextHeight()); 3383 cm.setCursor(lineNum, 0); 3384 helpers.doKeys('z', 't'); 3385 eq(cm.getScrollInfo().top, cm.charCoords(Pos(lineNum, 0), 'local').top); 3386 }, { value: (function(){ 3387 return new Array(500).join('\n'); 3388 })()}); 3389 testVim('zb<zz', function(cm, vim, helpers){ 3390 eq(zVals[0]<zVals[1], true); 3391 }); 3392 testVim('zz<zt', function(cm, vim, helpers){ 3393 eq(zVals[1]<zVals[2], true); 3394 }); 3395 testVim('zb==z-', function(cm, vim, helpers){ 3396 eq(zVals[0], zVals[3]); 3397 }); 3398 testVim('zz==z.', function(cm, vim, helpers){ 3399 eq(zVals[1], zVals[4]); 3400 }); 3401 testVim('zt==z<CR>', function(cm, vim, helpers){ 3402 eq(zVals[2], zVals[5]); 3403 }); 3404 3405 var moveTillCharacterSandbox = 3406 'The quick brown fox \n'; 3407 testVim('moveTillCharacter', function(cm, vim, helpers){ 3408 cm.setCursor(0, 0); 3409 // Search for the 'q'. 3410 cm.openDialog = helpers.fakeOpenDialog('q'); 3411 helpers.doKeys('/'); 3412 eq(4, cm.getCursor().ch); 3413 // Jump to just before the first o in the list. 3414 helpers.doKeys('t'); 3415 helpers.doKeys('o'); 3416 eq('The quick brown fox \n', cm.getValue()); 3417 // Delete that one character. 3418 helpers.doKeys('d'); 3419 helpers.doKeys('t'); 3420 helpers.doKeys('o'); 3421 eq('The quick bown fox \n', cm.getValue()); 3422 // Delete everything until the next 'o'. 3423 helpers.doKeys('.'); 3424 eq('The quick box \n', cm.getValue()); 3425 // An unmatched character should have no effect. 3426 helpers.doKeys('d'); 3427 helpers.doKeys('t'); 3428 helpers.doKeys('q'); 3429 eq('The quick box \n', cm.getValue()); 3430 // Matches should only be possible on single lines. 3431 helpers.doKeys('d'); 3432 helpers.doKeys('t'); 3433 helpers.doKeys('z'); 3434 eq('The quick box \n', cm.getValue()); 3435 // After all that, the search for 'q' should still be active, so the 'N' command 3436 // can run it again in reverse. Use that to delete everything back to the 'q'. 3437 helpers.doKeys('d'); 3438 helpers.doKeys('N'); 3439 eq('The ox \n', cm.getValue()); 3440 eq(4, cm.getCursor().ch); 3441 }, { value: moveTillCharacterSandbox}); 3442 testVim('searchForPipe', function(cm, vim, helpers){ 3443 CodeMirror.Vim.setOption('pcre', false); 3444 cm.setCursor(0, 0); 3445 // Search for the '|'. 3446 cm.openDialog = helpers.fakeOpenDialog('|'); 3447 helpers.doKeys('/'); 3448 eq(4, cm.getCursor().ch); 3449 }, { value: 'this|that'}); 3450 3451 3452 var scrollMotionSandbox = 3453 '\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'; 3454 testVim('scrollMotion', function(cm, vim, helpers){ 3455 var prevCursor, prevScrollInfo; 3456 cm.setCursor(0, 0); 3457 // ctrl-y at the top of the file should have no effect. 3458 helpers.doKeys('<C-y>'); 3459 eq(0, cm.getCursor().line); 3460 prevScrollInfo = cm.getScrollInfo(); 3461 helpers.doKeys('<C-e>'); 3462 eq(1, cm.getCursor().line); 3463 is(prevScrollInfo.top < cm.getScrollInfo().top); 3464 // Jump to the end of the sandbox. 3465 cm.setCursor(1000, 0); 3466 prevCursor = cm.getCursor(); 3467 // ctrl-e at the bottom of the file should have no effect. 3468 helpers.doKeys('<C-e>'); 3469 eq(prevCursor.line, cm.getCursor().line); 3470 prevScrollInfo = cm.getScrollInfo(); 3471 helpers.doKeys('<C-y>'); 3472 eq(prevCursor.line - 1, cm.getCursor().line, "Y"); 3473 is(prevScrollInfo.top > cm.getScrollInfo().top); 3474 }, { value: scrollMotionSandbox}); 3475 3476 var squareBracketMotionSandbox = ''+ 3477 '({\n'+//0 3478 ' ({\n'+//11 3479 ' /*comment {\n'+//2 3480 ' */(\n'+//3 3481 '#else \n'+//4 3482 ' /* )\n'+//5 3483 '#if }\n'+//6 3484 ' )}*/\n'+//7 3485 ')}\n'+//8 3486 '{}\n'+//9 3487 '#else {{\n'+//10 3488 '{}\n'+//11 3489 '}\n'+//12 3490 '{\n'+//13 3491 '#endif\n'+//14 3492 '}\n'+//15 3493 '}\n'+//16 3494 '#else';//17 3495 testVim('[[, ]]', function(cm, vim, helpers) { 3496 cm.setCursor(0, 0); 3497 helpers.doKeys(']', ']'); 3498 helpers.assertCursorAt(9,0); 3499 helpers.doKeys('2', ']', ']'); 3500 helpers.assertCursorAt(13,0); 3501 helpers.doKeys(']', ']'); 3502 helpers.assertCursorAt(17,0); 3503 helpers.doKeys('[', '['); 3504 helpers.assertCursorAt(13,0); 3505 helpers.doKeys('2', '[', '['); 3506 helpers.assertCursorAt(9,0); 3507 helpers.doKeys('[', '['); 3508 helpers.assertCursorAt(0,0); 3509 }, { value: squareBracketMotionSandbox}); 3510 testVim('[], ][', function(cm, vim, helpers) { 3511 cm.setCursor(0, 0); 3512 helpers.doKeys(']', '['); 3513 helpers.assertCursorAt(12,0); 3514 helpers.doKeys('2', ']', '['); 3515 helpers.assertCursorAt(16,0); 3516 helpers.doKeys(']', '['); 3517 helpers.assertCursorAt(17,0); 3518 helpers.doKeys('[', ']'); 3519 helpers.assertCursorAt(16,0); 3520 helpers.doKeys('2', '[', ']'); 3521 helpers.assertCursorAt(12,0); 3522 helpers.doKeys('[', ']'); 3523 helpers.assertCursorAt(0,0); 3524 }, { value: squareBracketMotionSandbox}); 3525 testVim('[{, ]}', function(cm, vim, helpers) { 3526 cm.setCursor(4, 10); 3527 helpers.doKeys('[', '{'); 3528 helpers.assertCursorAt(2,12); 3529 helpers.doKeys('2', '[', '{'); 3530 helpers.assertCursorAt(0,1); 3531 cm.setCursor(4, 10); 3532 helpers.doKeys(']', '}'); 3533 helpers.assertCursorAt(6,11); 3534 helpers.doKeys('2', ']', '}'); 3535 helpers.assertCursorAt(8,1); 3536 cm.setCursor(0,1); 3537 helpers.doKeys(']', '}'); 3538 helpers.assertCursorAt(8,1); 3539 helpers.doKeys('[', '{'); 3540 helpers.assertCursorAt(0,1); 3541 }, { value: squareBracketMotionSandbox}); 3542 testVim('[(, ])', function(cm, vim, helpers) { 3543 cm.setCursor(4, 10); 3544 helpers.doKeys('[', '('); 3545 helpers.assertCursorAt(3,14); 3546 helpers.doKeys('2', '[', '('); 3547 helpers.assertCursorAt(0,0); 3548 cm.setCursor(4, 10); 3549 helpers.doKeys(']', ')'); 3550 helpers.assertCursorAt(5,11); 3551 helpers.doKeys('2', ']', ')'); 3552 helpers.assertCursorAt(8,0); 3553 helpers.doKeys('[', '('); 3554 helpers.assertCursorAt(0,0); 3555 helpers.doKeys(']', ')'); 3556 helpers.assertCursorAt(8,0); 3557 }, { value: squareBracketMotionSandbox}); 3558 testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { 3559 forEach(['*', '/'], function(key){ 3560 cm.setCursor(7, 0); 3561 helpers.doKeys('2', '[', key); 3562 helpers.assertCursorAt(2,2); 3563 helpers.doKeys('2', ']', key); 3564 helpers.assertCursorAt(7,5); 3565 }); 3566 }, { value: squareBracketMotionSandbox}); 3567 testVim('[#, ]#', function(cm, vim, helpers) { 3568 cm.setCursor(10, 3); 3569 helpers.doKeys('2', '[', '#'); 3570 helpers.assertCursorAt(4,0); 3571 helpers.doKeys('5', ']', '#'); 3572 helpers.assertCursorAt(17,0); 3573 cm.setCursor(10, 3); 3574 helpers.doKeys(']', '#'); 3575 helpers.assertCursorAt(14,0); 3576 }, { value: squareBracketMotionSandbox}); 3577 testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) { 3578 cm.setCursor(11, 0); 3579 helpers.doKeys('[', 'm'); 3580 helpers.assertCursorAt(10,7); 3581 helpers.doKeys('4', '[', 'm'); 3582 helpers.assertCursorAt(1,3); 3583 helpers.doKeys('5', ']', 'm'); 3584 helpers.assertCursorAt(11,0); 3585 helpers.doKeys('[', 'M'); 3586 helpers.assertCursorAt(9,1); 3587 helpers.doKeys('3', ']', 'M'); 3588 helpers.assertCursorAt(15,0); 3589 helpers.doKeys('5', '[', 'M'); 3590 helpers.assertCursorAt(7,3); 3591 }, { value: squareBracketMotionSandbox}); 3592 3593 testVim('i_indent_right', function(cm, vim, helpers) { 3594 cm.setCursor(0, 3); 3595 var expectedValue = ' word1\nword2\nword3 '; 3596 helpers.doKeys('i', '<C-t>'); 3597 eq(expectedValue, cm.getValue()); 3598 helpers.assertCursorAt(0, 5); 3599 }, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); 3600 testVim('i_indent_left', function(cm, vim, helpers) { 3601 cm.setCursor(0, 3); 3602 var expectedValue = ' word1\nword2\nword3 '; 3603 helpers.doKeys('i', '<C-d>'); 3604 eq(expectedValue, cm.getValue()); 3605 helpers.assertCursorAt(0, 1); 3606 }, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); 3607 3608 // Ex mode tests 3609 testVim('ex_go_to_line', function(cm, vim, helpers) { 3610 cm.setCursor(0, 0); 3611 helpers.doEx('4'); 3612 helpers.assertCursorAt(3, 0); 3613 }, { value: 'a\nb\nc\nd\ne\n'}); 3614 testVim('ex_go_to_mark', function(cm, vim, helpers) { 3615 cm.setCursor(3, 0); 3616 helpers.doKeys('m', 'a'); 3617 cm.setCursor(0, 0); 3618 helpers.doEx('\'a'); 3619 helpers.assertCursorAt(3, 0); 3620 }, { value: 'a\nb\nc\nd\ne\n'}); 3621 testVim('ex_go_to_line_offset', function(cm, vim, helpers) { 3622 cm.setCursor(0, 0); 3623 helpers.doEx('+3'); 3624 helpers.assertCursorAt(3, 0); 3625 helpers.doEx('-1'); 3626 helpers.assertCursorAt(2, 0); 3627 helpers.doEx('.2'); 3628 helpers.assertCursorAt(4, 0); 3629 helpers.doEx('.-3'); 3630 helpers.assertCursorAt(1, 0); 3631 }, { value: 'a\nb\nc\nd\ne\n'}); 3632 testVim('ex_go_to_mark_offset', function(cm, vim, helpers) { 3633 cm.setCursor(2, 0); 3634 helpers.doKeys('m', 'a'); 3635 cm.setCursor(0, 0); 3636 helpers.doEx('\'a1'); 3637 helpers.assertCursorAt(3, 0); 3638 helpers.doEx('\'a-1'); 3639 helpers.assertCursorAt(1, 0); 3640 helpers.doEx('\'a+2'); 3641 helpers.assertCursorAt(4, 0); 3642 }, { value: 'a\nb\nc\nd\ne\n'}); 3643 testVim('ex_write', function(cm, vim, helpers) { 3644 var tmp = CodeMirror.commands.save; 3645 var written; 3646 var actualCm; 3647 CodeMirror.commands.save = function(cm) { 3648 written = true; 3649 actualCm = cm; 3650 }; 3651 // Test that w, wr, wri ... write all trigger :write. 3652 var command = 'write'; 3653 for (var i = 1; i < command.length; i++) { 3654 written = false; 3655 actualCm = null; 3656 helpers.doEx(command.substring(0, i)); 3657 eq(written, true); 3658 eq(actualCm, cm); 3659 } 3660 CodeMirror.commands.save = tmp; 3661 }); 3662 testVim('ex_sort', function(cm, vim, helpers) { 3663 helpers.doEx('sort'); 3664 eq('Z\na\nb\nc\nd', cm.getValue()); 3665 }, { value: 'b\nZ\nd\nc\na'}); 3666 testVim('ex_sort_reverse', function(cm, vim, helpers) { 3667 helpers.doEx('sort!'); 3668 eq('d\nc\nb\na', cm.getValue()); 3669 }, { value: 'b\nd\nc\na'}); 3670 testVim('ex_sort_range', function(cm, vim, helpers) { 3671 helpers.doEx('2,3sort'); 3672 eq('b\nc\nd\na', cm.getValue()); 3673 }, { value: 'b\nd\nc\na'}); 3674 testVim('ex_sort_oneline', function(cm, vim, helpers) { 3675 helpers.doEx('2sort'); 3676 // Expect no change. 3677 eq('b\nd\nc\na', cm.getValue()); 3678 }, { value: 'b\nd\nc\na'}); 3679 testVim('ex_sort_ignoreCase', function(cm, vim, helpers) { 3680 helpers.doEx('sort i'); 3681 eq('a\nb\nc\nd\nZ', cm.getValue()); 3682 }, { value: 'b\nZ\nd\nc\na'}); 3683 testVim('ex_sort_unique', function(cm, vim, helpers) { 3684 helpers.doEx('sort u'); 3685 eq('Z\na\nb\nc\nd', cm.getValue()); 3686 }, { value: 'b\nZ\na\na\nd\na\nc\na'}); 3687 testVim('ex_sort_decimal', function(cm, vim, helpers) { 3688 helpers.doEx('sort d'); 3689 eq('d3\n s5\n6\n.9', cm.getValue()); 3690 }, { value: '6\nd3\n s5\n.9'}); 3691 testVim('ex_sort_decimal_negative', function(cm, vim, helpers) { 3692 helpers.doEx('sort d'); 3693 eq('z-9\nd3\n s5\n6\n.9', cm.getValue()); 3694 }, { value: '6\nd3\n s5\n.9\nz-9'}); 3695 testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) { 3696 helpers.doEx('sort! d'); 3697 eq('.9\n6\n s5\nd3', cm.getValue()); 3698 }, { value: '6\nd3\n s5\n.9'}); 3699 testVim('ex_sort_hex', function(cm, vim, helpers) { 3700 helpers.doEx('sort x'); 3701 eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue()); 3702 }, { value: '6\nd3\n s5\n&0xB\n.9'}); 3703 testVim('ex_sort_octal', function(cm, vim, helpers) { 3704 helpers.doEx('sort o'); 3705 eq('.9\n.8\nd3\n s5\n6', cm.getValue()); 3706 }, { value: '6\nd3\n s5\n.9\n.8'}); 3707 testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { 3708 helpers.doEx('sort d'); 3709 eq('z\ny\nc1\nb2\na3', cm.getValue()); 3710 }, { value: 'a3\nz\nc1\ny\nb2'}); 3711 testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { 3712 helpers.doEx('sort! d'); 3713 eq('a3\nb2\nc1\nz\ny', cm.getValue()); 3714 }, { value: 'a3\nz\nc1\ny\nb2'}); 3715 testVim('ex_sort_pattern_alpha', function(cm, vim, helpers) { 3716 helpers.doEx('sort /[a-z]/'); 3717 eq('a3\nb2\nc1\ny\nz', cm.getValue()); 3718 }, { value: 'z\ny\nc1\nb2\na3'}); 3719 testVim('ex_sort_pattern_alpha_reverse', function(cm, vim, helpers) { 3720 helpers.doEx('sort! /[a-z]/'); 3721 eq('z\ny\nc1\nb2\na3', cm.getValue()); 3722 }, { value: 'z\ny\nc1\nb2\na3'}); 3723 testVim('ex_sort_pattern_alpha_ignoreCase', function(cm, vim, helpers) { 3724 helpers.doEx('sort i/[a-z]/'); 3725 eq('a3\nb2\nC1\nY\nz', cm.getValue()); 3726 }, { value: 'z\nY\nC1\nb2\na3'}); 3727 testVim('ex_sort_pattern_alpha_longer', function(cm, vim, helpers) { 3728 helpers.doEx('sort /[a-z]+/'); 3729 eq('a\naa\nab\nade\nadele\nadelle\nadriana\nalex\nalexandra\nb\nc\ny\nz', cm.getValue()); 3730 }, { value: 'z\nab\naa\nade\nadelle\nalexandra\nalex\nadriana\nadele\ny\nc\nb\na'}); 3731 testVim('ex_sort_pattern_alpha_only', function(cm, vim, helpers) { 3732 helpers.doEx('sort /^[a-z]$/'); 3733 eq('z1\ny2\na3\nb\nc', cm.getValue()); 3734 }, { value: 'z1\ny2\na3\nc\nb'}); 3735 testVim('ex_sort_pattern_alpha_only_reverse', function(cm, vim, helpers) { 3736 helpers.doEx('sort! /^[a-z]$/'); 3737 eq('c\nb\nz1\ny2\na3', cm.getValue()); 3738 }, { value: 'z1\ny2\na3\nc\nb'}); 3739 testVim('ex_sort_pattern_alpha_num', function(cm, vim, helpers) { 3740 helpers.doEx('sort /[a-z][0-9]/'); 3741 eq('c\nb\na3\ny2\nz1', cm.getValue()); 3742 }, { value: 'z1\ny2\na3\nc\nb'}); 3743 // test for :global command 3744 testVim('ex_global', function(cm, vim, helpers) { 3745 cm.setCursor(0, 0); 3746 helpers.doEx('g/one/s//two'); 3747 eq('two two\n two two\n two two', cm.getValue()); 3748 helpers.doEx('1,2g/two/s//one'); 3749 eq('one one\n one one\n two two', cm.getValue()); 3750 }, {value: 'one one\n one one\n one one'}); 3751 testVim('ex_global_confirm', function(cm, vim, helpers) { 3752 cm.setCursor(0, 0); 3753 var onKeyDown; 3754 var openDialogSave = cm.openDialog; 3755 var KEYCODES = { 3756 a: 65, 3757 n: 78, 3758 q: 81, 3759 y: 89 3760 }; 3761 // Intercept the ex command, 'global' 3762 cm.openDialog = function(template, callback, options) { 3763 // Intercept the prompt for the embedded ex command, 'substitute' 3764 cm.openDialog = function(template, callback, options) { 3765 onKeyDown = options.onKeyDown; 3766 }; 3767 callback('g/one/s//two/gc'); 3768 }; 3769 helpers.doKeys(':'); 3770 var close = function() {}; 3771 onKeyDown({keyCode: KEYCODES.n}, '', close); 3772 onKeyDown({keyCode: KEYCODES.y}, '', close); 3773 onKeyDown({keyCode: KEYCODES.a}, '', close); 3774 onKeyDown({keyCode: KEYCODES.q}, '', close); 3775 onKeyDown({keyCode: KEYCODES.y}, '', close); 3776 eq('one two\n two two\n one one\n two one\n one one', cm.getValue()); 3777 }, {value: 'one one\n one one\n one one\n one one\n one one'}); 3778 // Basic substitute tests. 3779 testVim('ex_substitute_same_line', function(cm, vim, helpers) { 3780 cm.setCursor(1, 0); 3781 helpers.doEx('s/one/two/g'); 3782 eq('one one\n two two', cm.getValue()); 3783 }, { value: 'one one\n one one'}); 3784 testVim('ex_substitute_alternate_separator', function(cm, vim, helpers) { 3785 cm.setCursor(1, 0); 3786 helpers.doEx('s#o/e#two#g'); 3787 eq('o/e o/e\n two two', cm.getValue()); 3788 }, { value: 'o/e o/e\n o/e o/e'}); 3789 testVim('ex_substitute_full_file', function(cm, vim, helpers) { 3790 cm.setCursor(1, 0); 3791 helpers.doEx('%s/one/two/g'); 3792 eq('two two\n two two', cm.getValue()); 3793 }, { value: 'one one\n one one'}); 3794 testVim('ex_substitute_input_range', function(cm, vim, helpers) { 3795 cm.setCursor(1, 0); 3796 helpers.doEx('1,3s/\\d/0/g'); 3797 eq('0\n0\n0\n4', cm.getValue()); 3798 }, { value: '1\n2\n3\n4' }); 3799 testVim('ex_substitute_range_current_to_input', function(cm, vim, helpers) { 3800 cm.setCursor(1, 0); 3801 helpers.doEx('.,3s/\\d/0/g'); 3802 eq('1\n0\n0\n4', cm.getValue()); 3803 }, { value: '1\n2\n3\n4' }); 3804 testVim('ex_substitute_range_input_to_current', function(cm, vim, helpers) { 3805 cm.setCursor(3, 0); 3806 helpers.doEx('2,.s/\\d/0/g'); 3807 eq('1\n0\n0\n0\n5', cm.getValue()); 3808 }, { value: '1\n2\n3\n4\n5' }); 3809 testVim('ex_substitute_range_offset', function(cm, vim, helpers) { 3810 cm.setCursor(2, 0); 3811 helpers.doEx('-1,+1s/\\d/0/g'); 3812 eq('1\n0\n0\n0\n5', cm.getValue()); 3813 }, { value: '1\n2\n3\n4\n5' }); 3814 testVim('ex_substitute_range_implicit_offset', function(cm, vim, helpers) { 3815 cm.setCursor(0, 0); 3816 helpers.doEx('.1,.3s/\\d/0/g'); 3817 eq('1\n0\n0\n0\n5', cm.getValue()); 3818 }, { value: '1\n2\n3\n4\n5' }); 3819 testVim('ex_substitute_to_eof', function(cm, vim, helpers) { 3820 cm.setCursor(2, 0); 3821 helpers.doEx('.,$s/\\d/0/g'); 3822 eq('1\n2\n0\n0\n0', cm.getValue()); 3823 }, { value: '1\n2\n3\n4\n5' }); 3824 testVim('ex_substitute_to_relative_eof', function(cm, vim, helpers) { 3825 cm.setCursor(4, 0); 3826 helpers.doEx('2,$-2s/\\d/0/g'); 3827 eq('1\n0\n0\n4\n5', cm.getValue()); 3828 }, { value: '1\n2\n3\n4\n5' }); 3829 testVim('ex_substitute_range_mark', function(cm, vim, helpers) { 3830 cm.setCursor(2, 0); 3831 helpers.doKeys('ma'); 3832 cm.setCursor(0, 0); 3833 helpers.doEx('.,\'as/\\d/0/g'); 3834 eq('0\n0\n0\n4\n5', cm.getValue()); 3835 }, { value: '1\n2\n3\n4\n5' }); 3836 testVim('ex_substitute_range_mark_offset', function(cm, vim, helpers) { 3837 cm.setCursor(2, 0); 3838 helpers.doKeys('ma'); 3839 cm.setCursor(0, 0); 3840 helpers.doEx('\'a-1,\'a+1s/\\d/0/g'); 3841 eq('1\n0\n0\n0\n5', cm.getValue()); 3842 }, { value: '1\n2\n3\n4\n5' }); 3843 testVim('ex_substitute_visual_range', function(cm, vim, helpers) { 3844 cm.setCursor(1, 0); 3845 // Set last visual mode selection marks '< and '> at lines 2 and 4 3846 helpers.doKeys('V', '2', 'j', 'v'); 3847 helpers.doEx('\'<,\'>s/\\d/0/g'); 3848 eq('1\n0\n0\n0\n5', cm.getValue()); 3849 }, { value: '1\n2\n3\n4\n5' }); 3850 testVim('ex_substitute_empty_query', function(cm, vim, helpers) { 3851 // If the query is empty, use last query. 3852 cm.setCursor(1, 0); 3853 cm.openDialog = helpers.fakeOpenDialog('1'); 3854 helpers.doKeys('/'); 3855 helpers.doEx('s//b/g'); 3856 eq('abb ab2 ab3', cm.getValue()); 3857 }, { value: 'a11 a12 a13' }); 3858 testVim('ex_substitute_javascript', function(cm, vim, helpers) { 3859 CodeMirror.Vim.setOption('pcre', false); 3860 cm.setCursor(1, 0); 3861 // Throw all the things that javascript likes to treat as special values 3862 // into the replace part. All should be literal (this is VIM). 3863 helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g') 3864 eq('a $$ $\' $` $& 0 b', cm.getValue()); 3865 }, { value: 'a 0 b' }); 3866 testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) { 3867 cm.setCursor(0, 0); 3868 helpers.doEx('s/a/b/g'); 3869 cm.setCursor(1, 0); 3870 helpers.doEx('s'); 3871 eq('b b\nb a', cm.getValue()); 3872 }, {value: 'a a\na a'}); 3873 3874 // More complex substitute tests that test both pcre and nopcre options. 3875 function testSubstitute(name, options) { 3876 testVim(name + '_pcre', function(cm, vim, helpers) { 3877 cm.setCursor(1, 0); 3878 CodeMirror.Vim.setOption('pcre', true); 3879 helpers.doEx(options.expr); 3880 eq(options.expectedValue, cm.getValue()); 3881 }, options); 3882 // If no noPcreExpr is defined, assume that it's the same as the expr. 3883 var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr; 3884 testVim(name + '_nopcre', function(cm, vim, helpers) { 3885 cm.setCursor(1, 0); 3886 CodeMirror.Vim.setOption('pcre', false); 3887 helpers.doEx(noPcreExpr); 3888 eq(options.expectedValue, cm.getValue()); 3889 }, options); 3890 } 3891 testSubstitute('ex_substitute_capture', { 3892 value: 'a11 a12 a13', 3893 expectedValue: 'a1111 a1212 a1313', 3894 // $n is a backreference 3895 expr: 's/(\\d+)/$1$1/g', 3896 // \n is a backreference. 3897 noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'}); 3898 testSubstitute('ex_substitute_capture2', { 3899 value: 'a 0 b', 3900 expectedValue: 'a $00 b', 3901 expr: 's/(\\d+)/$$$1$1/g', 3902 noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'}); 3903 testSubstitute('ex_substitute_nocapture', { 3904 value: 'a11 a12 a13', 3905 expectedValue: 'a$1$1 a$1$1 a$1$1', 3906 expr: 's/(\\d+)/$$1$$1/g', 3907 noPcreExpr: 's/\\(\\d+\\)/$1$1/g'}); 3908 testSubstitute('ex_substitute_nocapture2', { 3909 value: 'a 0 b', 3910 expectedValue: 'a $10 b', 3911 expr: 's/(\\d+)/$$1$1/g', 3912 noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'}); 3913 testSubstitute('ex_substitute_nocapture', { 3914 value: 'a b c', 3915 expectedValue: 'a $ c', 3916 expr: 's/b/$$/', 3917 noPcreExpr: 's/b/$/'}); 3918 testSubstitute('ex_substitute_slash_regex', { 3919 value: 'one/two \n three/four', 3920 expectedValue: 'one|two \n three|four', 3921 expr: '%s/\\//|'}); 3922 testSubstitute('ex_substitute_pipe_regex', { 3923 value: 'one|two \n three|four', 3924 expectedValue: 'one,two \n three,four', 3925 expr: '%s/\\|/,/', 3926 noPcreExpr: '%s/|/,/'}); 3927 testSubstitute('ex_substitute_or_regex', { 3928 value: 'one|two \n three|four', 3929 expectedValue: 'ana|twa \n thraa|faar', 3930 expr: '%s/o|e|u/a/g', 3931 noPcreExpr: '%s/o\\|e\\|u/a/g'}); 3932 testSubstitute('ex_substitute_or_word_regex', { 3933 value: 'one|two \n three|four', 3934 expectedValue: 'five|five \n three|four', 3935 expr: '%s/(one|two)/five/g', 3936 noPcreExpr: '%s/\\(one\\|two\\)/five/g'}); 3937 testSubstitute('ex_substitute_forward_slash_regex', { 3938 value: 'forward slash \/ was here', 3939 expectedValue: 'forward slash was here', 3940 expr: '%s#\\/##g', 3941 noPcreExpr: '%s#/##g'}); 3942 testVim("ex_substitute_ampersand_pcre", function(cm, vim, helpers) { 3943 cm.setCursor(0, 0); 3944 CodeMirror.Vim.setOption('pcre', true); 3945 helpers.doEx('%s/foo/namespace.&/'); 3946 eq("namespace.foo", cm.getValue()); 3947 }, { value: 'foo' }); 3948 testVim("ex_substitute_ampersand_multiple_pcre", function(cm, vim, helpers) { 3949 cm.setCursor(0, 0); 3950 CodeMirror.Vim.setOption('pcre', true); 3951 helpers.doEx('%s/f.o/namespace.&/'); 3952 eq("namespace.foo\nnamespace.fzo", cm.getValue()); 3953 }, { value: 'foo\nfzo' }); 3954 testVim("ex_escaped_ampersand_should_not_substitute_pcre", function(cm, vim, helpers) { 3955 cm.setCursor(0, 0); 3956 CodeMirror.Vim.setOption('pcre', true); 3957 helpers.doEx('%s/foo/namespace.\\&/'); 3958 eq("namespace.&", cm.getValue()); 3959 }, { value: 'foo' }); 3960 testSubstitute('ex_substitute_backslashslash_regex', { 3961 value: 'one\\two \n three\\four', 3962 expectedValue: 'one,two \n three,four', 3963 expr: '%s/\\\\/,'}); 3964 testSubstitute('ex_substitute_slash_replacement', { 3965 value: 'one,two \n three,four', 3966 expectedValue: 'one/two \n three/four', 3967 expr: '%s/,/\\/'}); 3968 testSubstitute('ex_substitute_backslash_replacement', { 3969 value: 'one,two \n three,four', 3970 expectedValue: 'one\\two \n three\\four', 3971 expr: '%s/,/\\\\/g'}); 3972 testSubstitute('ex_substitute_multibackslash_replacement', { 3973 value: 'one,two \n three,four', 3974 expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. 3975 expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. 3976 testSubstitute('ex_substitute_dollar_match', { 3977 value: 'one,two \n three,four', 3978 expectedValue: 'one,two ,\n three,four', 3979 expr: '%s/$/,/g'}); 3980 testSubstitute('ex_substitute_newline_match', { 3981 value: 'one,two \n three,four', 3982 expectedValue: 'one,two , three,four', 3983 expr: '%s/\\n/,/g'}); 3984 testSubstitute('ex_substitute_newline_replacement', { 3985 value: 'one,two \n three,four', 3986 expectedValue: 'one\ntwo \n three\nfour', 3987 expr: '%s/,/\\n/g'}); 3988 testSubstitute('ex_substitute_braces_word', { 3989 value: 'ababab abb ab{2}', 3990 expectedValue: 'ab abb ab{2}', 3991 expr: '%s/(ab){2}//g', 3992 noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'}); 3993 testSubstitute('ex_substitute_braces_range', { 3994 value: 'a aa aaa aaaa', 3995 expectedValue: 'a a', 3996 expr: '%s/a{2,3}//g', 3997 noPcreExpr: '%s/a\\{2,3\\}//g'}); 3998 testSubstitute('ex_substitute_braces_literal', { 3999 value: 'ababab abb ab{2}', 4000 expectedValue: 'ababab abb ', 4001 expr: '%s/ab\\{2\\}//g', 4002 noPcreExpr: '%s/ab{2}//g'}); 4003 testSubstitute('ex_substitute_braces_char', { 4004 value: 'ababab abb ab{2}', 4005 expectedValue: 'ababab ab{2}', 4006 expr: '%s/ab{2}//g', 4007 noPcreExpr: '%s/ab\\{2\\}//g'}); 4008 testSubstitute('ex_substitute_braces_no_escape', { 4009 value: 'ababab abb ab{2}', 4010 expectedValue: 'ababab ab{2}', 4011 expr: '%s/ab{2}//g', 4012 noPcreExpr: '%s/ab\\{2}//g'}); 4013 testSubstitute('ex_substitute_count', { 4014 value: '1\n2\n3\n4', 4015 expectedValue: '1\n0\n0\n4', 4016 expr: 's/\\d/0/i 2'}); 4017 testSubstitute('ex_substitute_count_with_range', { 4018 value: '1\n2\n3\n4', 4019 expectedValue: '1\n2\n0\n0', 4020 expr: '1,3s/\\d/0/ 3'}); 4021 testSubstitute('ex_substitute_not_global', { 4022 value: 'aaa\nbaa\ncaa', 4023 expectedValue: 'xaa\nbxa\ncxa', 4024 expr: '%s/a/x/'}); 4025 function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) { 4026 testVim(name, function(cm, vim, helpers) { 4027 var savedOpenDialog = cm.openDialog; 4028 var savedKeyName = CodeMirror.keyName; 4029 var onKeyDown; 4030 var recordedCallback; 4031 var closed = true; // Start out closed, set false on second openDialog. 4032 function close() { 4033 closed = true; 4034 } 4035 // First openDialog should save callback. 4036 cm.openDialog = function(template, callback, options) { 4037 recordedCallback = callback; 4038 } 4039 // Do first openDialog. 4040 helpers.doKeys(':'); 4041 // Second openDialog should save keyDown handler. 4042 cm.openDialog = function(template, callback, options) { 4043 onKeyDown = options.onKeyDown; 4044 closed = false; 4045 }; 4046 // Return the command to Vim and trigger second openDialog. 4047 recordedCallback(command); 4048 // The event should really use keyCode, but here just mock it out and use 4049 // key and replace keyName to just return key. 4050 CodeMirror.keyName = function (e) { return e.key; } 4051 keys = keys.toUpperCase(); 4052 for (var i = 0; i < keys.length; i++) { 4053 is(!closed); 4054 onKeyDown({ key: keys.charAt(i) }, '', close); 4055 } 4056 try { 4057 eq(expectedValue, cm.getValue()); 4058 helpers.assertCursorAt(finalPos); 4059 is(closed); 4060 } catch(e) { 4061 throw e 4062 } finally { 4063 // Restore overridden functions. 4064 CodeMirror.keyName = savedKeyName; 4065 cm.openDialog = savedOpenDialog; 4066 } 4067 }, { value: initialValue }); 4068 } 4069 testSubstituteConfirm('ex_substitute_confirm_emptydoc', 4070 '%s/x/b/c', '', '', '', makeCursor(0, 0)); 4071 testSubstituteConfirm('ex_substitute_confirm_nomatch', 4072 '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0)); 4073 testSubstituteConfirm('ex_substitute_confirm_accept', 4074 '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1)); 4075 testSubstituteConfirm('ex_substitute_confirm_random_keys', 4076 '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1)); 4077 testSubstituteConfirm('ex_substitute_confirm_some', 4078 '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1)); 4079 testSubstituteConfirm('ex_substitute_confirm_all', 4080 '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1)); 4081 testSubstituteConfirm('ex_substitute_confirm_accept_then_all', 4082 '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1)); 4083 testSubstituteConfirm('ex_substitute_confirm_quit', 4084 '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3)); 4085 testSubstituteConfirm('ex_substitute_confirm_last', 4086 '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); 4087 testSubstituteConfirm('ex_substitute_confirm_oneline', 4088 '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); 4089 testSubstituteConfirm('ex_substitute_confirm_range_accept', 4090 '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0)); 4091 testSubstituteConfirm('ex_substitute_confirm_range_some', 4092 '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0)); 4093 testSubstituteConfirm('ex_substitute_confirm_range_all', 4094 '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0)); 4095 testSubstituteConfirm('ex_substitute_confirm_range_last', 4096 '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0)); 4097 //:noh should clear highlighting of search-results but allow to resume search through n 4098 testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { 4099 cm.openDialog = helpers.fakeOpenDialog('match'); 4100 helpers.doKeys('?'); 4101 helpers.doEx('noh'); 4102 eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared'); 4103 helpers.doKeys('n'); 4104 helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); 4105 }, { value: 'match nope match \n nope Match' }); 4106 testVim('ex_yank', function (cm, vim, helpers) { 4107 var curStart = makeCursor(3, 0); 4108 cm.setCursor(curStart); 4109 helpers.doEx('y'); 4110 var register = helpers.getRegisterController().getRegister(); 4111 var line = cm.getLine(3); 4112 eq(line + '\n', register.toString()); 4113 }); 4114 testVim('set_boolean', function(cm, vim, helpers) { 4115 CodeMirror.Vim.defineOption('testoption', true, 'boolean'); 4116 // Test default value is set. 4117 is(CodeMirror.Vim.getOption('testoption')); 4118 // Test fail to set to non-boolean 4119 var result = CodeMirror.Vim.setOption('testoption', '5'); 4120 is(result instanceof Error); 4121 // Test setOption 4122 CodeMirror.Vim.setOption('testoption', false); 4123 is(!CodeMirror.Vim.getOption('testoption')); 4124 }); 4125 testVim('ex_set_boolean', function(cm, vim, helpers) { 4126 CodeMirror.Vim.defineOption('testoption', true, 'boolean'); 4127 // Test default value is set. 4128 is(CodeMirror.Vim.getOption('testoption')); 4129 is(!cm.state.currentNotificationClose); 4130 // Test fail to set to non-boolean 4131 helpers.doEx('set testoption=22'); 4132 is(cm.state.currentNotificationClose); 4133 // Test setOption 4134 helpers.doEx('set notestoption'); 4135 is(!CodeMirror.Vim.getOption('testoption')); 4136 }); 4137 testVim('set_string', function(cm, vim, helpers) { 4138 CodeMirror.Vim.defineOption('testoption', 'a', 'string'); 4139 // Test default value is set. 4140 eq('a', CodeMirror.Vim.getOption('testoption')); 4141 // Test no fail to set non-string. 4142 var result = CodeMirror.Vim.setOption('testoption', true); 4143 is(!result); 4144 // Test fail to set 'notestoption' 4145 result = CodeMirror.Vim.setOption('notestoption', 'b'); 4146 is(result instanceof Error); 4147 // Test setOption 4148 CodeMirror.Vim.setOption('testoption', 'c'); 4149 eq('c', CodeMirror.Vim.getOption('testoption')); 4150 }); 4151 testVim('ex_set_string', function(cm, vim, helpers) { 4152 CodeMirror.Vim.defineOption('testopt', 'a', 'string'); 4153 // Test default value is set. 4154 eq('a', CodeMirror.Vim.getOption('testopt')); 4155 // Test fail to set 'notestopt' 4156 is(!cm.state.currentNotificationClose); 4157 helpers.doEx('set notestopt=b'); 4158 is(cm.state.currentNotificationClose); 4159 // Test setOption 4160 helpers.doEx('set testopt=c') 4161 eq('c', CodeMirror.Vim.getOption('testopt')); 4162 helpers.doEx('set testopt=c') 4163 eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global 4164 eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local 4165 eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global 4166 eq('c', CodeMirror.Vim.getOption('testopt')); // global 4167 // Test setOption global 4168 helpers.doEx('setg testopt=d') 4169 eq('c', CodeMirror.Vim.getOption('testopt', cm)); 4170 eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); 4171 eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); 4172 eq('d', CodeMirror.Vim.getOption('testopt')); 4173 // Test setOption local 4174 helpers.doEx('setl testopt=e') 4175 eq('e', CodeMirror.Vim.getOption('testopt', cm)); 4176 eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); 4177 eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); 4178 eq('d', CodeMirror.Vim.getOption('testopt')); 4179 }); 4180 testVim('ex_set_callback', function(cm, vim, helpers) { 4181 var global; 4182 4183 function cb(val, cm, cfg) { 4184 if (val === undefined) { 4185 // Getter 4186 if (cm) { 4187 return cm._local; 4188 } else { 4189 return global; 4190 } 4191 } else { 4192 // Setter 4193 if (cm) { 4194 cm._local = val; 4195 } else { 4196 global = val; 4197 } 4198 } 4199 } 4200 4201 CodeMirror.Vim.defineOption('testopt', 'a', 'string', cb); 4202 // Test default value is set. 4203 eq('a', CodeMirror.Vim.getOption('testopt')); 4204 // Test fail to set 'notestopt' 4205 is(!cm.state.currentNotificationClose); 4206 helpers.doEx('set notestopt=b'); 4207 is(cm.state.currentNotificationClose); 4208 // Test setOption (Identical to the string tests, but via callback instead) 4209 helpers.doEx('set testopt=c') 4210 eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global 4211 eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local 4212 eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global 4213 eq('c', CodeMirror.Vim.getOption('testopt')); // global 4214 // Test setOption global 4215 helpers.doEx('setg testopt=d') 4216 eq('c', CodeMirror.Vim.getOption('testopt', cm)); 4217 eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); 4218 eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); 4219 eq('d', CodeMirror.Vim.getOption('testopt')); 4220 // Test setOption local 4221 helpers.doEx('setl testopt=e') 4222 eq('e', CodeMirror.Vim.getOption('testopt', cm)); 4223 eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); 4224 eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); 4225 eq('d', CodeMirror.Vim.getOption('testopt')); 4226 }) 4227 testVim('ex_set_filetype', function(cm, vim, helpers) { 4228 CodeMirror.defineMode('test_mode', function() { 4229 return {token: function(stream) { 4230 stream.match(/^\s+|^\S+/); 4231 }}; 4232 }); 4233 CodeMirror.defineMode('test_mode_2', function() { 4234 return {token: function(stream) { 4235 stream.match(/^\s+|^\S+/); 4236 }}; 4237 }); 4238 // Test mode is set. 4239 helpers.doEx('set filetype=test_mode'); 4240 eq('test_mode', cm.getMode().name); 4241 // Test 'ft' alias also sets mode. 4242 helpers.doEx('set ft=test_mode_2'); 4243 eq('test_mode_2', cm.getMode().name); 4244 }); 4245 testVim('ex_set_filetype_null', function(cm, vim, helpers) { 4246 CodeMirror.defineMode('test_mode', function() { 4247 return {token: function(stream) { 4248 stream.match(/^\s+|^\S+/); 4249 }}; 4250 }); 4251 cm.setOption('mode', 'test_mode'); 4252 // Test mode is set to null. 4253 helpers.doEx('set filetype='); 4254 eq('null', cm.getMode().name); 4255 }); 4256 4257 testVim('mapclear', function(cm, vim, helpers) { 4258 CodeMirror.Vim.map('w', 'l'); 4259 cm.setCursor(0, 0); 4260 helpers.assertCursorAt(0, 0); 4261 helpers.doKeys('w'); 4262 helpers.assertCursorAt(0, 1); 4263 CodeMirror.Vim.mapclear('visual'); 4264 helpers.doKeys('v', 'w', 'v'); 4265 helpers.assertCursorAt(0, 4); 4266 helpers.doKeys('w'); 4267 helpers.assertCursorAt(0, 5); 4268 CodeMirror.Vim.mapclear(); 4269 }, { value: 'abc abc' }); 4270 testVim('mapclear_context', function(cm, vim, helpers) { 4271 CodeMirror.Vim.map('w', 'l', 'normal'); 4272 cm.setCursor(0, 0); 4273 helpers.assertCursorAt(0, 0); 4274 helpers.doKeys('w'); 4275 helpers.assertCursorAt(0, 1); 4276 CodeMirror.Vim.mapclear('normal'); 4277 helpers.doKeys('w'); 4278 helpers.assertCursorAt(0, 4); 4279 CodeMirror.Vim.mapclear(); 4280 }, { value: 'abc abc' }); 4281 4282 testVim('ex_map_key2key', function(cm, vim, helpers) { 4283 helpers.doEx('map a x'); 4284 helpers.doKeys('a'); 4285 helpers.assertCursorAt(0, 0); 4286 eq('bc', cm.getValue()); 4287 CodeMirror.Vim.mapclear(); 4288 }, { value: 'abc' }); 4289 testVim('ex_unmap_key2key', function(cm, vim, helpers) { 4290 helpers.doEx('map a x'); 4291 helpers.doEx('unmap a'); 4292 helpers.doKeys('a'); 4293 eq('vim-insert', cm.getOption('keyMap')); 4294 CodeMirror.Vim.mapclear(); 4295 }, { value: 'abc' }); 4296 testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { 4297 expectFail(function() { 4298 helpers.doEx('unmap a'); 4299 }); 4300 helpers.doKeys('a'); 4301 eq('vim-insert', cm.getOption('keyMap')); 4302 CodeMirror.Vim.mapclear(); 4303 }, { value: 'abc' }); 4304 testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) { 4305 helpers.doEx('map ; :'); 4306 var dialogOpened = false; 4307 cm.openDialog = function() { 4308 dialogOpened = true; 4309 } 4310 helpers.doKeys(';'); 4311 eq(dialogOpened, true); 4312 CodeMirror.Vim.mapclear(); 4313 }); 4314 testVim('ex_map_ex2key:', function(cm, vim, helpers) { 4315 helpers.doEx('map :del x'); 4316 helpers.doEx('del'); 4317 helpers.assertCursorAt(0, 0); 4318 eq('bc', cm.getValue()); 4319 CodeMirror.Vim.mapclear(); 4320 }, { value: 'abc' }); 4321 testVim('ex_map_ex2ex', function(cm, vim, helpers) { 4322 helpers.doEx('map :del :w'); 4323 var tmp = CodeMirror.commands.save; 4324 var written = false; 4325 var actualCm; 4326 CodeMirror.commands.save = function(cm) { 4327 written = true; 4328 actualCm = cm; 4329 }; 4330 helpers.doEx('del'); 4331 CodeMirror.commands.save = tmp; 4332 eq(written, true); 4333 eq(actualCm, cm); 4334 CodeMirror.Vim.mapclear(); 4335 }); 4336 testVim('ex_map_key2ex', function(cm, vim, helpers) { 4337 helpers.doEx('map a :w'); 4338 var tmp = CodeMirror.commands.save; 4339 var written = false; 4340 var actualCm; 4341 CodeMirror.commands.save = function(cm) { 4342 written = true; 4343 actualCm = cm; 4344 }; 4345 helpers.doKeys('a'); 4346 CodeMirror.commands.save = tmp; 4347 eq(written, true); 4348 eq(actualCm, cm); 4349 CodeMirror.Vim.mapclear(); 4350 }); 4351 testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { 4352 CodeMirror.Vim.map('b', ':w', 'visual'); 4353 var tmp = CodeMirror.commands.save; 4354 var written = false; 4355 var actualCm; 4356 CodeMirror.commands.save = function(cm) { 4357 written = true; 4358 actualCm = cm; 4359 }; 4360 // Mapping should not work in normal mode. 4361 helpers.doKeys('b'); 4362 eq(written, false); 4363 // Mapping should work in visual mode. 4364 helpers.doKeys('v', 'b'); 4365 eq(written, true); 4366 eq(actualCm, cm); 4367 4368 CodeMirror.commands.save = tmp; 4369 CodeMirror.Vim.mapclear(); 4370 }); 4371 testVim('ex_imap', function(cm, vim, helpers) { 4372 CodeMirror.Vim.map('jk', '<Esc>', 'insert'); 4373 helpers.doKeys('i'); 4374 is(vim.insertMode); 4375 helpers.doKeys('j', 'k'); 4376 is(!vim.insertMode); 4377 cm.setCursor(0, 1); 4378 CodeMirror.Vim.map('jj', '<Esc>', 'insert'); 4379 helpers.doKeys('<C-v>', '2', 'j', 'l', 'c'); 4380 helpers.doKeys('f', 'o'); 4381 eq('1fo4\n5fo8\nafodefg', cm.getValue()); 4382 helpers.doKeys('j', 'j'); 4383 cm.setCursor(0, 0); 4384 helpers.doKeys('.'); 4385 eq('foo4\nfoo8\nfoodefg', cm.getValue()); 4386 CodeMirror.Vim.mapclear(); 4387 }, { value: '1234\n5678\nabcdefg' }); 4388 testVim('ex_unmap_api', function(cm, vim, helpers) { 4389 CodeMirror.Vim.map('<Alt-X>', 'gg', 'normal'); 4390 is(CodeMirror.Vim.handleKey(cm, "<Alt-X>", "normal"), "Alt-X key is mapped"); 4391 CodeMirror.Vim.unmap("<Alt-X>", "normal"); 4392 is(!CodeMirror.Vim.handleKey(cm, "<Alt-X>", "normal"), "Alt-X key is unmapped"); 4393 CodeMirror.Vim.mapclear(); 4394 }); 4395 // Testing registration of functions as ex-commands and mapping to <Key>-keys 4396 testVim('ex_api_test', function(cm, vim, helpers) { 4397 var res=false; 4398 var val='from'; 4399 CodeMirror.Vim.defineEx('extest','ext',function(cm,params){ 4400 if(params.args)val=params.args[0]; 4401 else res=true; 4402 }); 4403 helpers.doEx(':ext to'); 4404 eq(val,'to','Defining ex-command failed'); 4405 CodeMirror.Vim.map('<C-CR><Space>',':ext'); 4406 helpers.doKeys('<C-CR>','<Space>'); 4407 is(res,'Mapping to key failed'); 4408 CodeMirror.Vim.mapclear(); 4409 }); 4410 // For now, this test needs to be last because it messes up : for future tests. 4411 testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { 4412 helpers.doEx('map : x'); 4413 helpers.doKeys(':'); 4414 helpers.assertCursorAt(0, 0); 4415 eq('bc', cm.getValue()); 4416 CodeMirror.Vim.mapclear(); 4417 }, { value: 'abc' }); 4418 4419 testVim('noremap', function(cm, vim, helpers) { 4420 CodeMirror.Vim.noremap(';', 'l'); 4421 cm.setCursor(0, 0); 4422 eq('wOrd1', cm.getValue()); 4423 // Mapping should work in normal mode. 4424 helpers.doKeys(';', 'r', '1'); 4425 eq('w1rd1', cm.getValue()); 4426 // Mapping will not work in insert mode because of no current fallback 4427 // keyToKey mapping support. 4428 helpers.doKeys('i', ';', '<Esc>'); 4429 eq('w;1rd1', cm.getValue()); 4430 // unmap all mappings 4431 CodeMirror.Vim.mapclear(); 4432 }, { value: 'wOrd1' }); 4433 testVim('noremap_swap', function(cm, vim, helpers) { 4434 CodeMirror.Vim.noremap('i', 'a', 'normal'); 4435 CodeMirror.Vim.noremap('a', 'i', 'normal'); 4436 cm.setCursor(0, 0); 4437 // 'a' should act like 'i'. 4438 helpers.doKeys('a'); 4439 eqCursorPos(Pos(0, 0), cm.getCursor()); 4440 // ...and 'i' should act like 'a'. 4441 helpers.doKeys('<Esc>', 'i'); 4442 eqCursorPos(Pos(0, 1), cm.getCursor()); 4443 // unmap all mappings 4444 CodeMirror.Vim.mapclear(); 4445 }, { value: 'foo' }); 4446 testVim('noremap_map_interaction', function(cm, vim, helpers) { 4447 // noremap should clobber map 4448 CodeMirror.Vim.map(';', 'l'); 4449 CodeMirror.Vim.noremap(';', 'l'); 4450 CodeMirror.Vim.map('l', 'j'); 4451 cm.setCursor(0, 0); 4452 helpers.doKeys(';'); 4453 eqCursorPos(Pos(0, 1), cm.getCursor()); 4454 helpers.doKeys('l'); 4455 eqCursorPos(Pos(1, 1), cm.getCursor()); 4456 // map should be able to point to a noremap 4457 CodeMirror.Vim.map('m', ';'); 4458 helpers.doKeys('m'); 4459 eqCursorPos(Pos(1, 2), cm.getCursor()); 4460 // unmap all mappings 4461 CodeMirror.Vim.mapclear(); 4462 }, { value: 'wOrd1\nwOrd2' }); 4463 testVim('noremap_map_interaction2', function(cm, vim, helpers) { 4464 // map should point to the most recent noremap 4465 CodeMirror.Vim.noremap(';', 'l'); 4466 CodeMirror.Vim.map('m', ';'); 4467 CodeMirror.Vim.noremap(';', 'h'); 4468 cm.setCursor(0, 0); 4469 helpers.doKeys('l'); 4470 eqCursorPos(Pos(0, 1), cm.getCursor()); 4471 helpers.doKeys('m'); 4472 eqCursorPos(Pos(0, 0), cm.getCursor()); 4473 // unmap all mappings 4474 CodeMirror.Vim.mapclear(); 4475 }, { value: 'wOrd1\nwOrd2' }); 4476 4477 // Test event handlers 4478 testVim('beforeSelectionChange', function(cm, vim, helpers) { 4479 cm.setCursor(0, 100); 4480 eqCursorPos(cm.getCursor('head'), cm.getCursor('anchor')); 4481 }, { value: 'abc' }); 4482 4483 testVim('increment_binary', function(cm, vim, helpers) { 4484 cm.setCursor(0, 4); 4485 helpers.doKeys('<C-a>'); 4486 eq('0b001', cm.getValue()); 4487 helpers.doKeys('<C-a>'); 4488 eq('0b010', cm.getValue()); 4489 helpers.doKeys('<C-x>'); 4490 eq('0b001', cm.getValue()); 4491 helpers.doKeys('<C-x>'); 4492 eq('0b000', cm.getValue()); 4493 cm.setCursor(0, 0); 4494 helpers.doKeys('<C-a>'); 4495 eq('0b001', cm.getValue()); 4496 helpers.doKeys('<C-a>'); 4497 eq('0b010', cm.getValue()); 4498 helpers.doKeys('<C-x>'); 4499 eq('0b001', cm.getValue()); 4500 helpers.doKeys('<C-x>'); 4501 eq('0b000', cm.getValue()); 4502 }, { value: '0b000' }); 4503 4504 testVim('increment_octal', function(cm, vim, helpers) { 4505 cm.setCursor(0, 2); 4506 helpers.doKeys('<C-a>'); 4507 eq('001', cm.getValue()); 4508 helpers.doKeys('<C-a>'); 4509 eq('002', cm.getValue()); 4510 helpers.doKeys('<C-a>'); 4511 eq('003', cm.getValue()); 4512 helpers.doKeys('<C-a>'); 4513 eq('004', cm.getValue()); 4514 helpers.doKeys('<C-a>'); 4515 eq('005', cm.getValue()); 4516 helpers.doKeys('<C-a>'); 4517 eq('006', cm.getValue()); 4518 helpers.doKeys('<C-a>'); 4519 eq('007', cm.getValue()); 4520 helpers.doKeys('<C-a>'); 4521 eq('010', cm.getValue()); 4522 helpers.doKeys('<C-x>'); 4523 eq('007', cm.getValue()); 4524 helpers.doKeys('<C-x>'); 4525 eq('006', cm.getValue()); 4526 helpers.doKeys('<C-x>'); 4527 eq('005', cm.getValue()); 4528 helpers.doKeys('<C-x>'); 4529 eq('004', cm.getValue()); 4530 helpers.doKeys('<C-x>'); 4531 eq('003', cm.getValue()); 4532 helpers.doKeys('<C-x>'); 4533 eq('002', cm.getValue()); 4534 helpers.doKeys('<C-x>'); 4535 eq('001', cm.getValue()); 4536 helpers.doKeys('<C-x>'); 4537 eq('000', cm.getValue()); 4538 cm.setCursor(0, 0); 4539 helpers.doKeys('<C-a>'); 4540 eq('001', cm.getValue()); 4541 helpers.doKeys('<C-a>'); 4542 eq('002', cm.getValue()); 4543 helpers.doKeys('<C-x>'); 4544 eq('001', cm.getValue()); 4545 helpers.doKeys('<C-x>'); 4546 eq('000', cm.getValue()); 4547 }, { value: '000' }); 4548 4549 testVim('increment_decimal', function(cm, vim, helpers) { 4550 cm.setCursor(0, 2); 4551 helpers.doKeys('<C-a>'); 4552 eq('101', cm.getValue()); 4553 helpers.doKeys('<C-a>'); 4554 eq('102', cm.getValue()); 4555 helpers.doKeys('<C-a>'); 4556 eq('103', cm.getValue()); 4557 helpers.doKeys('<C-a>'); 4558 eq('104', cm.getValue()); 4559 helpers.doKeys('<C-a>'); 4560 eq('105', cm.getValue()); 4561 helpers.doKeys('<C-a>'); 4562 eq('106', cm.getValue()); 4563 helpers.doKeys('<C-a>'); 4564 eq('107', cm.getValue()); 4565 helpers.doKeys('<C-a>'); 4566 eq('108', cm.getValue()); 4567 helpers.doKeys('<C-a>'); 4568 eq('109', cm.getValue()); 4569 helpers.doKeys('<C-a>'); 4570 eq('110', cm.getValue()); 4571 helpers.doKeys('<C-x>'); 4572 eq('109', cm.getValue()); 4573 helpers.doKeys('<C-x>'); 4574 eq('108', cm.getValue()); 4575 helpers.doKeys('<C-x>'); 4576 eq('107', cm.getValue()); 4577 helpers.doKeys('<C-x>'); 4578 eq('106', cm.getValue()); 4579 helpers.doKeys('<C-x>'); 4580 eq('105', cm.getValue()); 4581 helpers.doKeys('<C-x>'); 4582 eq('104', cm.getValue()); 4583 helpers.doKeys('<C-x>'); 4584 eq('103', cm.getValue()); 4585 helpers.doKeys('<C-x>'); 4586 eq('102', cm.getValue()); 4587 helpers.doKeys('<C-x>'); 4588 eq('101', cm.getValue()); 4589 helpers.doKeys('<C-x>'); 4590 eq('100', cm.getValue()); 4591 cm.setCursor(0, 0); 4592 helpers.doKeys('<C-a>'); 4593 eq('101', cm.getValue()); 4594 helpers.doKeys('<C-a>'); 4595 eq('102', cm.getValue()); 4596 helpers.doKeys('<C-x>'); 4597 eq('101', cm.getValue()); 4598 helpers.doKeys('<C-x>'); 4599 eq('100', cm.getValue()); 4600 }, { value: '100' }); 4601 4602 testVim('increment_decimal_single_zero', function(cm, vim, helpers) { 4603 helpers.doKeys('<C-a>'); 4604 eq('1', cm.getValue()); 4605 helpers.doKeys('<C-a>'); 4606 eq('2', cm.getValue()); 4607 helpers.doKeys('<C-a>'); 4608 eq('3', cm.getValue()); 4609 helpers.doKeys('<C-a>'); 4610 eq('4', cm.getValue()); 4611 helpers.doKeys('<C-a>'); 4612 eq('5', cm.getValue()); 4613 helpers.doKeys('<C-a>'); 4614 eq('6', cm.getValue()); 4615 helpers.doKeys('<C-a>'); 4616 eq('7', cm.getValue()); 4617 helpers.doKeys('<C-a>'); 4618 eq('8', cm.getValue()); 4619 helpers.doKeys('<C-a>'); 4620 eq('9', cm.getValue()); 4621 helpers.doKeys('<C-a>'); 4622 eq('10', cm.getValue()); 4623 helpers.doKeys('<C-x>'); 4624 eq('9', cm.getValue()); 4625 helpers.doKeys('<C-x>'); 4626 eq('8', cm.getValue()); 4627 helpers.doKeys('<C-x>'); 4628 eq('7', cm.getValue()); 4629 helpers.doKeys('<C-x>'); 4630 eq('6', cm.getValue()); 4631 helpers.doKeys('<C-x>'); 4632 eq('5', cm.getValue()); 4633 helpers.doKeys('<C-x>'); 4634 eq('4', cm.getValue()); 4635 helpers.doKeys('<C-x>'); 4636 eq('3', cm.getValue()); 4637 helpers.doKeys('<C-x>'); 4638 eq('2', cm.getValue()); 4639 helpers.doKeys('<C-x>'); 4640 eq('1', cm.getValue()); 4641 helpers.doKeys('<C-x>'); 4642 eq('0', cm.getValue()); 4643 cm.setCursor(0, 0); 4644 helpers.doKeys('<C-a>'); 4645 eq('1', cm.getValue()); 4646 helpers.doKeys('<C-a>'); 4647 eq('2', cm.getValue()); 4648 helpers.doKeys('<C-x>'); 4649 eq('1', cm.getValue()); 4650 helpers.doKeys('<C-x>'); 4651 eq('0', cm.getValue()); 4652 }, { value: '0' }); 4653 4654 testVim('increment_hexadecimal', function(cm, vim, helpers) { 4655 cm.setCursor(0, 2); 4656 helpers.doKeys('<C-a>'); 4657 eq('0x1', cm.getValue()); 4658 helpers.doKeys('<C-a>'); 4659 eq('0x2', cm.getValue()); 4660 helpers.doKeys('<C-a>'); 4661 eq('0x3', cm.getValue()); 4662 helpers.doKeys('<C-a>'); 4663 eq('0x4', cm.getValue()); 4664 helpers.doKeys('<C-a>'); 4665 eq('0x5', cm.getValue()); 4666 helpers.doKeys('<C-a>'); 4667 eq('0x6', cm.getValue()); 4668 helpers.doKeys('<C-a>'); 4669 eq('0x7', cm.getValue()); 4670 helpers.doKeys('<C-a>'); 4671 eq('0x8', cm.getValue()); 4672 helpers.doKeys('<C-a>'); 4673 eq('0x9', cm.getValue()); 4674 helpers.doKeys('<C-a>'); 4675 eq('0xa', cm.getValue()); 4676 helpers.doKeys('<C-a>'); 4677 eq('0xb', cm.getValue()); 4678 helpers.doKeys('<C-a>'); 4679 eq('0xc', cm.getValue()); 4680 helpers.doKeys('<C-a>'); 4681 eq('0xd', cm.getValue()); 4682 helpers.doKeys('<C-a>'); 4683 eq('0xe', cm.getValue()); 4684 helpers.doKeys('<C-a>'); 4685 eq('0xf', cm.getValue()); 4686 helpers.doKeys('<C-a>'); 4687 eq('0x10', cm.getValue()); 4688 helpers.doKeys('<C-x>'); 4689 eq('0x0f', cm.getValue()); 4690 helpers.doKeys('<C-x>'); 4691 eq('0x0e', cm.getValue()); 4692 helpers.doKeys('<C-x>'); 4693 eq('0x0d', cm.getValue()); 4694 helpers.doKeys('<C-x>'); 4695 eq('0x0c', cm.getValue()); 4696 helpers.doKeys('<C-x>'); 4697 eq('0x0b', cm.getValue()); 4698 helpers.doKeys('<C-x>'); 4699 eq('0x0a', cm.getValue()); 4700 helpers.doKeys('<C-x>'); 4701 eq('0x09', cm.getValue()); 4702 helpers.doKeys('<C-x>'); 4703 eq('0x08', cm.getValue()); 4704 helpers.doKeys('<C-x>'); 4705 eq('0x07', cm.getValue()); 4706 helpers.doKeys('<C-x>'); 4707 eq('0x06', cm.getValue()); 4708 helpers.doKeys('<C-x>'); 4709 eq('0x05', cm.getValue()); 4710 helpers.doKeys('<C-x>'); 4711 eq('0x04', cm.getValue()); 4712 helpers.doKeys('<C-x>'); 4713 eq('0x03', cm.getValue()); 4714 helpers.doKeys('<C-x>'); 4715 eq('0x02', cm.getValue()); 4716 helpers.doKeys('<C-x>'); 4717 eq('0x01', cm.getValue()); 4718 helpers.doKeys('<C-x>'); 4719 eq('0x00', cm.getValue()); 4720 cm.setCursor(0, 0); 4721 helpers.doKeys('<C-a>'); 4722 eq('0x01', cm.getValue()); 4723 helpers.doKeys('<C-a>'); 4724 eq('0x02', cm.getValue()); 4725 helpers.doKeys('<C-x>'); 4726 eq('0x01', cm.getValue()); 4727 helpers.doKeys('<C-x>'); 4728 eq('0x00', cm.getValue()); 4729 }, { value: '0x0' });