File modules/editor/codemirror/test/vim_test.min.js

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