1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/devtools/sourceeditor/test/cm_vim_test.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2859 @@ 1.4 +var code = '' + 1.5 +' wOrd1 (#%\n' + 1.6 +' word3] \n' + 1.7 +'aopop pop 0 1 2 3 4\n' + 1.8 +' (a) [b] {c} \n' + 1.9 +'int getchar(void) {\n' + 1.10 +' static char buf[BUFSIZ];\n' + 1.11 +' static char *bufp = buf;\n' + 1.12 +' if (n == 0) { /* buffer is empty */\n' + 1.13 +' n = read(0, buf, sizeof buf);\n' + 1.14 +' bufp = buf;\n' + 1.15 +' }\n' + 1.16 +'\n' + 1.17 +' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' + 1.18 +' \n' + 1.19 +'}\n'; 1.20 + 1.21 +var lines = (function() { 1.22 + lineText = code.split('\n'); 1.23 + var ret = []; 1.24 + for (var i = 0; i < lineText.length; i++) { 1.25 + ret[i] = { 1.26 + line: i, 1.27 + length: lineText[i].length, 1.28 + lineText: lineText[i], 1.29 + textStart: /^\s*/.exec(lineText[i])[0].length 1.30 + }; 1.31 + } 1.32 + return ret; 1.33 +})(); 1.34 +var endOfDocument = makeCursor(lines.length - 1, 1.35 + lines[lines.length - 1].length); 1.36 +var wordLine = lines[0]; 1.37 +var bigWordLine = lines[1]; 1.38 +var charLine = lines[2]; 1.39 +var bracesLine = lines[3]; 1.40 +var seekBraceLine = lines[4]; 1.41 + 1.42 +var word1 = { 1.43 + start: { line: wordLine.line, ch: 1 }, 1.44 + end: { line: wordLine.line, ch: 5 } 1.45 +}; 1.46 +var word2 = { 1.47 + start: { line: wordLine.line, ch: word1.end.ch + 2 }, 1.48 + end: { line: wordLine.line, ch: word1.end.ch + 4 } 1.49 +}; 1.50 +var word3 = { 1.51 + start: { line: bigWordLine.line, ch: 1 }, 1.52 + end: { line: bigWordLine.line, ch: 5 } 1.53 +}; 1.54 +var bigWord1 = word1; 1.55 +var bigWord2 = word2; 1.56 +var bigWord3 = { 1.57 + start: { line: bigWordLine.line, ch: 1 }, 1.58 + end: { line: bigWordLine.line, ch: 7 } 1.59 +}; 1.60 +var bigWord4 = { 1.61 + start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 }, 1.62 + end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 } 1.63 +}; 1.64 + 1.65 +var oChars = [ { line: charLine.line, ch: 1 }, 1.66 + { line: charLine.line, ch: 3 }, 1.67 + { line: charLine.line, ch: 7 } ]; 1.68 +var pChars = [ { line: charLine.line, ch: 2 }, 1.69 + { line: charLine.line, ch: 4 }, 1.70 + { line: charLine.line, ch: 6 }, 1.71 + { line: charLine.line, ch: 8 } ]; 1.72 +var numChars = [ { line: charLine.line, ch: 10 }, 1.73 + { line: charLine.line, ch: 12 }, 1.74 + { line: charLine.line, ch: 14 }, 1.75 + { line: charLine.line, ch: 16 }, 1.76 + { line: charLine.line, ch: 18 }]; 1.77 +var parens1 = { 1.78 + start: { line: bracesLine.line, ch: 1 }, 1.79 + end: { line: bracesLine.line, ch: 3 } 1.80 +}; 1.81 +var squares1 = { 1.82 + start: { line: bracesLine.line, ch: 5 }, 1.83 + end: { line: bracesLine.line, ch: 7 } 1.84 +}; 1.85 +var curlys1 = { 1.86 + start: { line: bracesLine.line, ch: 9 }, 1.87 + end: { line: bracesLine.line, ch: 11 } 1.88 +}; 1.89 +var seekOutside = { 1.90 + start: { line: seekBraceLine.line, ch: 1 }, 1.91 + end: { line: seekBraceLine.line, ch: 16 } 1.92 +}; 1.93 +var seekInside = { 1.94 + start: { line: seekBraceLine.line, ch: 14 }, 1.95 + end: { line: seekBraceLine.line, ch: 11 } 1.96 +}; 1.97 + 1.98 +function copyCursor(cur) { 1.99 + return { ch: cur.ch, line: cur.line }; 1.100 +} 1.101 + 1.102 +function forEach(arr, func) { 1.103 + for (var i = 0; i < arr.length; i++) { 1.104 + func(arr[i]); 1.105 + } 1.106 +} 1.107 + 1.108 +function testVim(name, run, opts, expectedFail) { 1.109 + var vimOpts = { 1.110 + lineNumbers: true, 1.111 + vimMode: true, 1.112 + showCursorWhenSelecting: true, 1.113 + value: code 1.114 + }; 1.115 + for (var prop in opts) { 1.116 + if (opts.hasOwnProperty(prop)) { 1.117 + vimOpts[prop] = opts[prop]; 1.118 + } 1.119 + } 1.120 + return test('vim_' + name, function() { 1.121 + var place = document.getElementById("testground"); 1.122 + var cm = CodeMirror(place, vimOpts); 1.123 + var vim = CodeMirror.Vim.maybeInitVimState_(cm); 1.124 + 1.125 + function doKeysFn(cm) { 1.126 + return function(args) { 1.127 + if (args instanceof Array) { 1.128 + arguments = args; 1.129 + } 1.130 + for (var i = 0; i < arguments.length; i++) { 1.131 + CodeMirror.Vim.handleKey(cm, arguments[i]); 1.132 + } 1.133 + } 1.134 + } 1.135 + function doInsertModeKeysFn(cm) { 1.136 + return function(args) { 1.137 + if (args instanceof Array) { arguments = args; } 1.138 + function executeHandler(handler) { 1.139 + if (typeof handler == 'string') { 1.140 + CodeMirror.commands[handler](cm); 1.141 + } else { 1.142 + handler(cm); 1.143 + } 1.144 + return true; 1.145 + } 1.146 + for (var i = 0; i < arguments.length; i++) { 1.147 + var key = arguments[i]; 1.148 + // Find key in keymap and handle. 1.149 + var handled = CodeMirror.lookupKey(key, ['vim-insert'], executeHandler); 1.150 + // Record for insert mode. 1.151 + if (handled === true && cm.state.vim.insertMode && arguments[i] != 'Esc') { 1.152 + var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; 1.153 + if (lastChange) { 1.154 + lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key)); 1.155 + } 1.156 + } 1.157 + } 1.158 + } 1.159 + } 1.160 + function doExFn(cm) { 1.161 + return function(command) { 1.162 + cm.openDialog = helpers.fakeOpenDialog(command); 1.163 + helpers.doKeys(':'); 1.164 + } 1.165 + } 1.166 + function assertCursorAtFn(cm) { 1.167 + return function(line, ch) { 1.168 + var pos; 1.169 + if (ch == null && typeof line.line == 'number') { 1.170 + pos = line; 1.171 + } else { 1.172 + pos = makeCursor(line, ch); 1.173 + } 1.174 + eqPos(pos, cm.getCursor()); 1.175 + } 1.176 + } 1.177 + function fakeOpenDialog(result) { 1.178 + return function(text, callback) { 1.179 + return callback(result); 1.180 + } 1.181 + } 1.182 + function fakeOpenNotification(matcher) { 1.183 + return function(text) { 1.184 + matcher(text); 1.185 + } 1.186 + } 1.187 + var helpers = { 1.188 + doKeys: doKeysFn(cm), 1.189 + // Warning: Only emulates keymap events, not character insertions. Use 1.190 + // replaceRange to simulate character insertions. 1.191 + // Keys are in CodeMirror format, NOT vim format. 1.192 + doInsertModeKeys: doInsertModeKeysFn(cm), 1.193 + doEx: doExFn(cm), 1.194 + assertCursorAt: assertCursorAtFn(cm), 1.195 + fakeOpenDialog: fakeOpenDialog, 1.196 + fakeOpenNotification: fakeOpenNotification, 1.197 + getRegisterController: function() { 1.198 + return CodeMirror.Vim.getRegisterController(); 1.199 + } 1.200 + } 1.201 + CodeMirror.Vim.resetVimGlobalState_(); 1.202 + var successful = false; 1.203 + var savedOpenNotification = cm.openNotification; 1.204 + try { 1.205 + run(cm, vim, helpers); 1.206 + successful = true; 1.207 + } finally { 1.208 + cm.openNotification = savedOpenNotification; 1.209 + if (!successful || verbose) { 1.210 + place.style.visibility = "visible"; 1.211 + } else { 1.212 + place.removeChild(cm.getWrapperElement()); 1.213 + } 1.214 + } 1.215 + }, expectedFail); 1.216 +}; 1.217 +testVim('qq@q', function(cm, vim, helpers) { 1.218 + cm.setCursor(0, 0); 1.219 + helpers.doKeys('q', 'q', 'l', 'l', 'q'); 1.220 + helpers.assertCursorAt(0,2); 1.221 + helpers.doKeys('@', 'q'); 1.222 + helpers.assertCursorAt(0,4); 1.223 +}, { value: ' '}); 1.224 +testVim('@@', function(cm, vim, helpers) { 1.225 + cm.setCursor(0, 0); 1.226 + helpers.doKeys('q', 'q', 'l', 'l', 'q'); 1.227 + helpers.assertCursorAt(0,2); 1.228 + helpers.doKeys('@', 'q'); 1.229 + helpers.assertCursorAt(0,4); 1.230 + helpers.doKeys('@', '@'); 1.231 + helpers.assertCursorAt(0,6); 1.232 +}, { value: ' '}); 1.233 +var jumplistScene = ''+ 1.234 + 'word\n'+ 1.235 + '(word)\n'+ 1.236 + '{word\n'+ 1.237 + 'word.\n'+ 1.238 + '\n'+ 1.239 + 'word search\n'+ 1.240 + '}word\n'+ 1.241 + 'word\n'+ 1.242 + 'word\n'; 1.243 +function testJumplist(name, keys, endPos, startPos, dialog) { 1.244 + endPos = makeCursor(endPos[0], endPos[1]); 1.245 + startPos = makeCursor(startPos[0], startPos[1]); 1.246 + testVim(name, function(cm, vim, helpers) { 1.247 + CodeMirror.Vim.resetVimGlobalState_(); 1.248 + if(dialog)cm.openDialog = helpers.fakeOpenDialog('word'); 1.249 + cm.setCursor(startPos); 1.250 + helpers.doKeys.apply(null, keys); 1.251 + helpers.assertCursorAt(endPos); 1.252 + }, {value: jumplistScene}); 1.253 +}; 1.254 +testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]); 1.255 +testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]); 1.256 +testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]); 1.257 +testJumplist('jumplist_[[', ['[', '[', '<C-o>'], [5,2], [5,2]); 1.258 +testJumplist('jumplist_]]', [']', ']', '<C-o>'], [2,2], [2,2]); 1.259 +testJumplist('jumplist_G', ['G', '<C-o>'], [5,2], [5,2]); 1.260 +testJumplist('jumplist_gg', ['g', 'g', '<C-o>'], [5,2], [5,2]); 1.261 +testJumplist('jumplist_%', ['%', '<C-o>'], [1,5], [1,5]); 1.262 +testJumplist('jumplist_{', ['{', '<C-o>'], [1,5], [1,5]); 1.263 +testJumplist('jumplist_}', ['}', '<C-o>'], [1,5], [1,5]); 1.264 +testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', '<C-i>'], [1,5], [1,5]); 1.265 +testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', '<C-i>'], [1,5], [1,5]); 1.266 +testJumplist('jumplist_*_cachedCursor', ['*', '<C-o>'], [1,3], [1,3]); 1.267 +testJumplist('jumplist_#_cachedCursor', ['#', '<C-o>'], [1,3], [1,3]); 1.268 +testJumplist('jumplist_n', ['#', 'n', '<C-o>'], [1,1], [2,3]); 1.269 +testJumplist('jumplist_N', ['#', 'N', '<C-o>'], [1,1], [2,3]); 1.270 +testJumplist('jumplist_repeat_<c-o>', ['*', '*', '*', '3', '<C-o>'], [2,3], [2,3]); 1.271 +testJumplist('jumplist_repeat_<c-i>', ['*', '*', '*', '3', '<C-o>', '2', '<C-i>'], [5,0], [2,3]); 1.272 +testJumplist('jumplist_repeated_motion', ['3', '*', '<C-o>'], [2,3], [2,3]); 1.273 +testJumplist('jumplist_/', ['/', '<C-o>'], [2,3], [2,3], 'dialog'); 1.274 +testJumplist('jumplist_?', ['?', '<C-o>'], [2,3], [2,3], 'dialog'); 1.275 +testJumplist('jumplist_skip_delted_mark<c-o>', 1.276 + ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-o>', '<C-o>'], 1.277 + [0,2], [0,2]); 1.278 +testJumplist('jumplist_skip_delted_mark<c-i>', 1.279 + ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-i>', '<C-i>'], 1.280 + [1,0], [0,2]); 1.281 + 1.282 +/** 1.283 + * @param name Name of the test 1.284 + * @param keys An array of keys or a string with a single key to simulate. 1.285 + * @param endPos The expected end position of the cursor. 1.286 + * @param startPos The position the cursor should start at, defaults to 0, 0. 1.287 + */ 1.288 +function testMotion(name, keys, endPos, startPos) { 1.289 + testVim(name, function(cm, vim, helpers) { 1.290 + if (!startPos) { 1.291 + startPos = { line: 0, ch: 0 }; 1.292 + } 1.293 + cm.setCursor(startPos); 1.294 + helpers.doKeys(keys); 1.295 + helpers.assertCursorAt(endPos); 1.296 + }); 1.297 +}; 1.298 + 1.299 +function makeCursor(line, ch) { 1.300 + return { line: line, ch: ch }; 1.301 +}; 1.302 + 1.303 +function offsetCursor(cur, offsetLine, offsetCh) { 1.304 + return { line: cur.line + offsetLine, ch: cur.ch + offsetCh }; 1.305 +}; 1.306 + 1.307 +// Motion tests 1.308 +testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4)); 1.309 +testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4)); 1.310 +testMotion('h', 'h', makeCursor(0, 0), word1.start); 1.311 +testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end); 1.312 +testMotion('l', 'l', makeCursor(0, 1)); 1.313 +testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2)); 1.314 +testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end); 1.315 +testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end); 1.316 +testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument); 1.317 +testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end); 1.318 +testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4)); 1.319 +testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4)); 1.320 +testMotion('w', 'w', word1.start); 1.321 +testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2)); 1.322 +testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51)); 1.323 +testMotion('w_repeat', ['2', 'w'], word2.start); 1.324 +testMotion('w_wrap', ['w'], word3.start, word2.start); 1.325 +testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument); 1.326 +testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0)); 1.327 +testMotion('W', 'W', bigWord1.start); 1.328 +testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start); 1.329 +testMotion('e', 'e', word1.end); 1.330 +testMotion('e_repeat', ['2', 'e'], word2.end); 1.331 +testMotion('e_wrap', 'e', word3.end, word2.end); 1.332 +testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument); 1.333 +testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0)); 1.334 +testMotion('b', 'b', word3.start, word3.end); 1.335 +testMotion('b_repeat', ['2', 'b'], word2.start, word3.end); 1.336 +testMotion('b_wrap', 'b', word2.start, word3.start); 1.337 +testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0)); 1.338 +testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument); 1.339 +testMotion('ge', ['g', 'e'], word2.end, word3.end); 1.340 +testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start); 1.341 +testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start); 1.342 +testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0), 1.343 + makeCursor(0, 0)); 1.344 +testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument); 1.345 +testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart), 1.346 + makeCursor(3, 1)); 1.347 +testMotion('gg_repeat', ['3', 'g', 'g'], 1.348 + makeCursor(lines[2].line, lines[2].textStart)); 1.349 +testMotion('G', 'G', 1.350 + makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart), 1.351 + makeCursor(3, 1)); 1.352 +testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line, 1.353 + lines[2].textStart)); 1.354 +// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B. 1.355 +testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8)); 1.356 +testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8)); 1.357 +testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8)); 1.358 +testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4)); 1.359 +testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8)); 1.360 +testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1)); 1.361 +testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1), 1.362 + makeCursor(0, 3)); 1.363 +testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0)); 1.364 +testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]); 1.365 +testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0)); 1.366 +testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1), 1.367 + makeCursor(charLine.line, 0)); 1.368 +testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1), 1.369 + pChars[0]); 1.370 +testMotion('F', ['F', 'p'], pChars[0], pChars[1]); 1.371 +testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]); 1.372 +testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]); 1.373 +testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]); 1.374 +testMotion('%_parens', ['%'], parens1.end, parens1.start); 1.375 +testMotion('%_squares', ['%'], squares1.end, squares1.start); 1.376 +testMotion('%_braces', ['%'], curlys1.end, curlys1.start); 1.377 +testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start); 1.378 +testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start); 1.379 +testVim('%_seek_skip', function(cm, vim, helpers) { 1.380 + cm.setCursor(0,0); 1.381 + helpers.doKeys(['%']); 1.382 + helpers.assertCursorAt(0,9); 1.383 +}, {value:'01234"("()'}); 1.384 +testVim('%_skip_string', function(cm, vim, helpers) { 1.385 + cm.setCursor(0,0); 1.386 + helpers.doKeys(['%']); 1.387 + helpers.assertCursorAt(0,4); 1.388 + cm.setCursor(0,2); 1.389 + helpers.doKeys(['%']); 1.390 + helpers.assertCursorAt(0,0); 1.391 +}, {value:'(")")'}); 1.392 +(')') 1.393 +testVim('%_skip_comment', function(cm, vim, helpers) { 1.394 + cm.setCursor(0,0); 1.395 + helpers.doKeys(['%']); 1.396 + helpers.assertCursorAt(0,6); 1.397 + cm.setCursor(0,3); 1.398 + helpers.doKeys(['%']); 1.399 + helpers.assertCursorAt(0,0); 1.400 +}, {value:'(/*)*/)'}); 1.401 +// Make sure that moving down after going to the end of a line always leaves you 1.402 +// at the end of a line, but preserves the offset in other cases 1.403 +testVim('Changing lines after Eol operation', function(cm, vim, helpers) { 1.404 + cm.setCursor(0,0); 1.405 + helpers.doKeys(['$']); 1.406 + helpers.doKeys(['j']); 1.407 + // After moving to Eol and then down, we should be at Eol of line 2 1.408 + helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 }); 1.409 + helpers.doKeys(['j']); 1.410 + // After moving down, we should be at Eol of line 3 1.411 + helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 }); 1.412 + helpers.doKeys(['h']); 1.413 + helpers.doKeys(['j']); 1.414 + // After moving back one space and then down, since line 4 is shorter than line 2, we should 1.415 + // be at Eol of line 2 - 1 1.416 + helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 }); 1.417 + helpers.doKeys(['j']); 1.418 + helpers.doKeys(['j']); 1.419 + // After moving down again, since line 3 has enough characters, we should be back to the 1.420 + // same place we were at on line 1 1.421 + helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 }); 1.422 +}); 1.423 +//making sure gj and gk recover from clipping 1.424 +testVim('gj_gk_clipping', function(cm,vim,helpers){ 1.425 + cm.setCursor(0, 1); 1.426 + helpers.doKeys('g','j','g','j'); 1.427 + helpers.assertCursorAt(2, 1); 1.428 + helpers.doKeys('g','k','g','k'); 1.429 + helpers.assertCursorAt(0, 1); 1.430 +},{value: 'line 1\n\nline 2'}); 1.431 +//testing a mix of j/k and gj/gk 1.432 +testVim('j_k_and_gj_gk', function(cm,vim,helpers){ 1.433 + cm.setSize(120); 1.434 + cm.setCursor(0, 0); 1.435 + //go to the last character on the first line 1.436 + helpers.doKeys('$'); 1.437 + //move up/down on the column within the wrapped line 1.438 + //side-effect: cursor is not locked to eol anymore 1.439 + helpers.doKeys('g','k'); 1.440 + var cur=cm.getCursor(); 1.441 + eq(cur.line,0); 1.442 + is((cur.ch<176),'gk didn\'t move cursor back (1)'); 1.443 + helpers.doKeys('g','j'); 1.444 + helpers.assertCursorAt(0, 176); 1.445 + //should move to character 177 on line 2 (j/k preserve character index within line) 1.446 + helpers.doKeys('j'); 1.447 + //due to different line wrapping, the cursor can be on a different screen-x now 1.448 + //gj and gk preserve screen-x on movement, much like moveV 1.449 + helpers.doKeys('3','g','k'); 1.450 + cur=cm.getCursor(); 1.451 + eq(cur.line,1); 1.452 + is((cur.ch<176),'gk didn\'t move cursor back (2)'); 1.453 + helpers.doKeys('g','j','2','g','j'); 1.454 + //should return to the same character-index 1.455 + helpers.doKeys('k'); 1.456 + helpers.assertCursorAt(0, 176); 1.457 +},{ 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.'}); 1.458 +testVim('gj_gk', function(cm, vim, helpers) { 1.459 + if (phantom) return; 1.460 + cm.setSize(120); 1.461 + // Test top of document edge case. 1.462 + cm.setCursor(0, 4); 1.463 + helpers.doKeys('g', 'j'); 1.464 + helpers.doKeys('10', 'g', 'k'); 1.465 + helpers.assertCursorAt(0, 4); 1.466 + 1.467 + // Test moving down preserves column position. 1.468 + helpers.doKeys('g', 'j'); 1.469 + var pos1 = cm.getCursor(); 1.470 + var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4}; 1.471 + helpers.doKeys('g', 'j'); 1.472 + helpers.assertCursorAt(expectedPos2); 1.473 + 1.474 + // Move to the last character 1.475 + cm.setCursor(0, 0); 1.476 + // Move left to reset HSPos 1.477 + helpers.doKeys('h'); 1.478 + // Test bottom of document edge case. 1.479 + helpers.doKeys('100', 'g', 'j'); 1.480 + var endingPos = cm.getCursor(); 1.481 + is(endingPos != 0, 'gj should not be on wrapped line 0'); 1.482 + var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); 1.483 + var endingCharCoords = cm.charCoords(endingPos); 1.484 + is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); 1.485 +},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' }); 1.486 +testVim('}', function(cm, vim, helpers) { 1.487 + cm.setCursor(0, 0); 1.488 + helpers.doKeys('}'); 1.489 + helpers.assertCursorAt(1, 0); 1.490 + cm.setCursor(0, 0); 1.491 + helpers.doKeys('2', '}'); 1.492 + helpers.assertCursorAt(4, 0); 1.493 + cm.setCursor(0, 0); 1.494 + helpers.doKeys('6', '}'); 1.495 + helpers.assertCursorAt(5, 0); 1.496 +}, { value: 'a\n\nb\nc\n\nd' }); 1.497 +testVim('{', function(cm, vim, helpers) { 1.498 + cm.setCursor(5, 0); 1.499 + helpers.doKeys('{'); 1.500 + helpers.assertCursorAt(4, 0); 1.501 + cm.setCursor(5, 0); 1.502 + helpers.doKeys('2', '{'); 1.503 + helpers.assertCursorAt(1, 0); 1.504 + cm.setCursor(5, 0); 1.505 + helpers.doKeys('6', '{'); 1.506 + helpers.assertCursorAt(0, 0); 1.507 +}, { value: 'a\n\nb\nc\n\nd' }); 1.508 + 1.509 +// Operator tests 1.510 +testVim('dl', function(cm, vim, helpers) { 1.511 + var curStart = makeCursor(0, 0); 1.512 + cm.setCursor(curStart); 1.513 + helpers.doKeys('d', 'l'); 1.514 + eq('word1 ', cm.getValue()); 1.515 + var register = helpers.getRegisterController().getRegister(); 1.516 + eq(' ', register.toString()); 1.517 + is(!register.linewise); 1.518 + eqPos(curStart, cm.getCursor()); 1.519 +}, { value: ' word1 ' }); 1.520 +testVim('dl_eol', function(cm, vim, helpers) { 1.521 + cm.setCursor(0, 6); 1.522 + helpers.doKeys('d', 'l'); 1.523 + eq(' word1', cm.getValue()); 1.524 + var register = helpers.getRegisterController().getRegister(); 1.525 + eq(' ', register.toString()); 1.526 + is(!register.linewise); 1.527 + helpers.assertCursorAt(0, 5); 1.528 +}, { value: ' word1 ' }); 1.529 +testVim('dl_repeat', function(cm, vim, helpers) { 1.530 + var curStart = makeCursor(0, 0); 1.531 + cm.setCursor(curStart); 1.532 + helpers.doKeys('2', 'd', 'l'); 1.533 + eq('ord1 ', cm.getValue()); 1.534 + var register = helpers.getRegisterController().getRegister(); 1.535 + eq(' w', register.toString()); 1.536 + is(!register.linewise); 1.537 + eqPos(curStart, cm.getCursor()); 1.538 +}, { value: ' word1 ' }); 1.539 +testVim('dh', function(cm, vim, helpers) { 1.540 + var curStart = makeCursor(0, 3); 1.541 + cm.setCursor(curStart); 1.542 + helpers.doKeys('d', 'h'); 1.543 + eq(' wrd1 ', cm.getValue()); 1.544 + var register = helpers.getRegisterController().getRegister(); 1.545 + eq('o', register.toString()); 1.546 + is(!register.linewise); 1.547 + eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); 1.548 +}, { value: ' word1 ' }); 1.549 +testVim('dj', function(cm, vim, helpers) { 1.550 + var curStart = makeCursor(0, 3); 1.551 + cm.setCursor(curStart); 1.552 + helpers.doKeys('d', 'j'); 1.553 + eq(' word3', cm.getValue()); 1.554 + var register = helpers.getRegisterController().getRegister(); 1.555 + eq(' word1\nword2\n', register.toString()); 1.556 + is(register.linewise); 1.557 + helpers.assertCursorAt(0, 1); 1.558 +}, { value: ' word1\nword2\n word3' }); 1.559 +testVim('dj_end_of_document', function(cm, vim, helpers) { 1.560 + var curStart = makeCursor(0, 3); 1.561 + cm.setCursor(curStart); 1.562 + helpers.doKeys('d', 'j'); 1.563 + eq(' word1 ', cm.getValue()); 1.564 + var register = helpers.getRegisterController().getRegister(); 1.565 + eq('', register.toString()); 1.566 + is(!register.linewise); 1.567 + helpers.assertCursorAt(0, 3); 1.568 +}, { value: ' word1 ' }); 1.569 +testVim('dk', function(cm, vim, helpers) { 1.570 + var curStart = makeCursor(1, 3); 1.571 + cm.setCursor(curStart); 1.572 + helpers.doKeys('d', 'k'); 1.573 + eq(' word3', cm.getValue()); 1.574 + var register = helpers.getRegisterController().getRegister(); 1.575 + eq(' word1\nword2\n', register.toString()); 1.576 + is(register.linewise); 1.577 + helpers.assertCursorAt(0, 1); 1.578 +}, { value: ' word1\nword2\n word3' }); 1.579 +testVim('dk_start_of_document', function(cm, vim, helpers) { 1.580 + var curStart = makeCursor(0, 3); 1.581 + cm.setCursor(curStart); 1.582 + helpers.doKeys('d', 'k'); 1.583 + eq(' word1 ', cm.getValue()); 1.584 + var register = helpers.getRegisterController().getRegister(); 1.585 + eq('', register.toString()); 1.586 + is(!register.linewise); 1.587 + helpers.assertCursorAt(0, 3); 1.588 +}, { value: ' word1 ' }); 1.589 +testVim('dw_space', function(cm, vim, helpers) { 1.590 + var curStart = makeCursor(0, 0); 1.591 + cm.setCursor(curStart); 1.592 + helpers.doKeys('d', 'w'); 1.593 + eq('word1 ', cm.getValue()); 1.594 + var register = helpers.getRegisterController().getRegister(); 1.595 + eq(' ', register.toString()); 1.596 + is(!register.linewise); 1.597 + eqPos(curStart, cm.getCursor()); 1.598 +}, { value: ' word1 ' }); 1.599 +testVim('dw_word', function(cm, vim, helpers) { 1.600 + var curStart = makeCursor(0, 1); 1.601 + cm.setCursor(curStart); 1.602 + helpers.doKeys('d', 'w'); 1.603 + eq(' word2', cm.getValue()); 1.604 + var register = helpers.getRegisterController().getRegister(); 1.605 + eq('word1 ', register.toString()); 1.606 + is(!register.linewise); 1.607 + eqPos(curStart, cm.getCursor()); 1.608 +}, { value: ' word1 word2' }); 1.609 +testVim('dw_only_word', function(cm, vim, helpers) { 1.610 + // Test that if there is only 1 word left, dw deletes till the end of the 1.611 + // line. 1.612 + cm.setCursor(0, 1); 1.613 + helpers.doKeys('d', 'w'); 1.614 + eq(' ', cm.getValue()); 1.615 + var register = helpers.getRegisterController().getRegister(); 1.616 + eq('word1 ', register.toString()); 1.617 + is(!register.linewise); 1.618 + helpers.assertCursorAt(0, 0); 1.619 +}, { value: ' word1 ' }); 1.620 +testVim('dw_eol', function(cm, vim, helpers) { 1.621 + // Assert that dw does not delete the newline if last word to delete is at end 1.622 + // of line. 1.623 + cm.setCursor(0, 1); 1.624 + helpers.doKeys('d', 'w'); 1.625 + eq(' \nword2', cm.getValue()); 1.626 + var register = helpers.getRegisterController().getRegister(); 1.627 + eq('word1', register.toString()); 1.628 + is(!register.linewise); 1.629 + helpers.assertCursorAt(0, 0); 1.630 +}, { value: ' word1\nword2' }); 1.631 +testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) { 1.632 + // Assert that dw does not delete the newline if last word to delete is at end 1.633 + // of line and it is followed by multiple newlines. 1.634 + cm.setCursor(0, 1); 1.635 + helpers.doKeys('d', 'w'); 1.636 + eq(' \n\nword2', cm.getValue()); 1.637 + var register = helpers.getRegisterController().getRegister(); 1.638 + eq('word1', register.toString()); 1.639 + is(!register.linewise); 1.640 + helpers.assertCursorAt(0, 0); 1.641 +}, { value: ' word1\n\nword2' }); 1.642 +testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) { 1.643 + cm.setCursor(0, 0); 1.644 + helpers.doKeys('d', 'w'); 1.645 + eq(' \nword', cm.getValue()); 1.646 +}, { value: '\n \nword' }); 1.647 +testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) { 1.648 + cm.setCursor(0, 0); 1.649 + helpers.doKeys('d', 'w'); 1.650 + eq('word', cm.getValue()); 1.651 +}, { value: '\nword' }); 1.652 +testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) { 1.653 + cm.setCursor(0, 0); 1.654 + helpers.doKeys('d', 'w'); 1.655 + eq('\n', cm.getValue()); 1.656 +}, { value: '\n\n' }); 1.657 +testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) { 1.658 + cm.setCursor(0, 0); 1.659 + helpers.doKeys('d', 'w'); 1.660 + eq('\n \n', cm.getValue()); 1.661 +}, { value: ' \n \n' }); 1.662 +testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) { 1.663 + cm.setCursor(0, 0); 1.664 + helpers.doKeys('d', 'w'); 1.665 + eq('\n\n', cm.getValue()); 1.666 +}, { value: ' \n\n' }); 1.667 +testVim('dw_word_whitespace_word', function(cm, vim, helpers) { 1.668 + cm.setCursor(0, 0); 1.669 + helpers.doKeys('d', 'w'); 1.670 + eq('\n \nword2', cm.getValue()); 1.671 +}, { value: 'word1\n \nword2'}) 1.672 +testVim('dw_end_of_document', function(cm, vim, helpers) { 1.673 + cm.setCursor(1, 2); 1.674 + helpers.doKeys('d', 'w'); 1.675 + eq('\nab', cm.getValue()); 1.676 +}, { value: '\nabc' }); 1.677 +testVim('dw_repeat', function(cm, vim, helpers) { 1.678 + // Assert that dw does delete newline if it should go to the next line, and 1.679 + // that repeat works properly. 1.680 + cm.setCursor(0, 1); 1.681 + helpers.doKeys('d', '2', 'w'); 1.682 + eq(' ', cm.getValue()); 1.683 + var register = helpers.getRegisterController().getRegister(); 1.684 + eq('word1\nword2', register.toString()); 1.685 + is(!register.linewise); 1.686 + helpers.assertCursorAt(0, 0); 1.687 +}, { value: ' word1\nword2' }); 1.688 +testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) { 1.689 + cm.setCursor(0, 0); 1.690 + helpers.doKeys('d', 'e'); 1.691 + eq('\n\n', cm.getValue()); 1.692 +}, { value: 'word\n\n' }); 1.693 +testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) { 1.694 + cm.setCursor(0, 3); 1.695 + helpers.doKeys('d', 'e'); 1.696 + eq('wor', cm.getValue()); 1.697 +}, { value: 'word\n\n\n' }); 1.698 +testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) { 1.699 + cm.setCursor(0, 0); 1.700 + helpers.doKeys('d', 'e'); 1.701 + eq('', cm.getValue()); 1.702 +}, { value: ' \n\n\n' }); 1.703 +testVim('de_end_of_document', function(cm, vim, helpers) { 1.704 + cm.setCursor(1, 2); 1.705 + helpers.doKeys('d', 'e'); 1.706 + eq('\nab', cm.getValue()); 1.707 +}, { value: '\nabc' }); 1.708 +testVim('db_empty_lines', function(cm, vim, helpers) { 1.709 + cm.setCursor(2, 0); 1.710 + helpers.doKeys('d', 'b'); 1.711 + eq('\n\n', cm.getValue()); 1.712 +}, { value: '\n\n\n' }); 1.713 +testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) { 1.714 + cm.setCursor(2, 0); 1.715 + helpers.doKeys('d', 'b'); 1.716 + eq('\nword', cm.getValue()); 1.717 +}, { value: '\n\nword' }); 1.718 +testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) { 1.719 + cm.setCursor(2, 3); 1.720 + helpers.doKeys('d', 'b'); 1.721 + eq('\n\nd', cm.getValue()); 1.722 +}, { value: '\n\nword' }); 1.723 +testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) { 1.724 + cm.setCursor(2, 0); 1.725 + helpers.doKeys('d', 'b'); 1.726 + eq('', cm.getValue()); 1.727 +}, { value: '\n \n' }); 1.728 +testVim('db_start_of_document', function(cm, vim, helpers) { 1.729 + cm.setCursor(0, 0); 1.730 + helpers.doKeys('d', 'b'); 1.731 + eq('abc\n', cm.getValue()); 1.732 +}, { value: 'abc\n' }); 1.733 +testVim('dge_empty_lines', function(cm, vim, helpers) { 1.734 + cm.setCursor(1, 0); 1.735 + helpers.doKeys('d', 'g', 'e'); 1.736 + // Note: In real VIM the result should be '', but it's not quite consistent, 1.737 + // since 2 newlines are deleted. But in the similar case of word\n\n, only 1.738 + // 1 newline is deleted. We'll diverge from VIM's behavior since it's much 1.739 + // easier this way. 1.740 + eq('\n', cm.getValue()); 1.741 +}, { value: '\n\n' }); 1.742 +testVim('dge_word_and_empty_lines', function(cm, vim, helpers) { 1.743 + cm.setCursor(1, 0); 1.744 + helpers.doKeys('d', 'g', 'e'); 1.745 + eq('wor\n', cm.getValue()); 1.746 +}, { value: 'word\n\n'}); 1.747 +testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) { 1.748 + cm.setCursor(2, 0); 1.749 + helpers.doKeys('d', 'g', 'e'); 1.750 + eq('', cm.getValue()); 1.751 +}, { value: '\n \n' }); 1.752 +testVim('dge_start_of_document', function(cm, vim, helpers) { 1.753 + cm.setCursor(0, 0); 1.754 + helpers.doKeys('d', 'g', 'e'); 1.755 + eq('bc\n', cm.getValue()); 1.756 +}, { value: 'abc\n' }); 1.757 +testVim('d_inclusive', function(cm, vim, helpers) { 1.758 + // Assert that when inclusive is set, the character the cursor is on gets 1.759 + // deleted too. 1.760 + var curStart = makeCursor(0, 1); 1.761 + cm.setCursor(curStart); 1.762 + helpers.doKeys('d', 'e'); 1.763 + eq(' ', cm.getValue()); 1.764 + var register = helpers.getRegisterController().getRegister(); 1.765 + eq('word1', register.toString()); 1.766 + is(!register.linewise); 1.767 + eqPos(curStart, cm.getCursor()); 1.768 +}, { value: ' word1 ' }); 1.769 +testVim('d_reverse', function(cm, vim, helpers) { 1.770 + // Test that deleting in reverse works. 1.771 + cm.setCursor(1, 0); 1.772 + helpers.doKeys('d', 'b'); 1.773 + eq(' word2 ', cm.getValue()); 1.774 + var register = helpers.getRegisterController().getRegister(); 1.775 + eq('word1\n', register.toString()); 1.776 + is(!register.linewise); 1.777 + helpers.assertCursorAt(0, 1); 1.778 +}, { value: ' word1\nword2 ' }); 1.779 +testVim('dd', function(cm, vim, helpers) { 1.780 + cm.setCursor(0, 3); 1.781 + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, 1.782 + { line: 1, ch: 0 }); 1.783 + var expectedLineCount = cm.lineCount() - 1; 1.784 + helpers.doKeys('d', 'd'); 1.785 + eq(expectedLineCount, cm.lineCount()); 1.786 + var register = helpers.getRegisterController().getRegister(); 1.787 + eq(expectedBuffer, register.toString()); 1.788 + is(register.linewise); 1.789 + helpers.assertCursorAt(0, lines[1].textStart); 1.790 +}); 1.791 +testVim('dd_prefix_repeat', function(cm, vim, helpers) { 1.792 + cm.setCursor(0, 3); 1.793 + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, 1.794 + { line: 2, ch: 0 }); 1.795 + var expectedLineCount = cm.lineCount() - 2; 1.796 + helpers.doKeys('2', 'd', 'd'); 1.797 + eq(expectedLineCount, cm.lineCount()); 1.798 + var register = helpers.getRegisterController().getRegister(); 1.799 + eq(expectedBuffer, register.toString()); 1.800 + is(register.linewise); 1.801 + helpers.assertCursorAt(0, lines[2].textStart); 1.802 +}); 1.803 +testVim('dd_motion_repeat', function(cm, vim, helpers) { 1.804 + cm.setCursor(0, 3); 1.805 + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, 1.806 + { line: 2, ch: 0 }); 1.807 + var expectedLineCount = cm.lineCount() - 2; 1.808 + helpers.doKeys('d', '2', 'd'); 1.809 + eq(expectedLineCount, cm.lineCount()); 1.810 + var register = helpers.getRegisterController().getRegister(); 1.811 + eq(expectedBuffer, register.toString()); 1.812 + is(register.linewise); 1.813 + helpers.assertCursorAt(0, lines[2].textStart); 1.814 +}); 1.815 +testVim('dd_multiply_repeat', function(cm, vim, helpers) { 1.816 + cm.setCursor(0, 3); 1.817 + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, 1.818 + { line: 6, ch: 0 }); 1.819 + var expectedLineCount = cm.lineCount() - 6; 1.820 + helpers.doKeys('2', 'd', '3', 'd'); 1.821 + eq(expectedLineCount, cm.lineCount()); 1.822 + var register = helpers.getRegisterController().getRegister(); 1.823 + eq(expectedBuffer, register.toString()); 1.824 + is(register.linewise); 1.825 + helpers.assertCursorAt(0, lines[6].textStart); 1.826 +}); 1.827 +testVim('dd_lastline', function(cm, vim, helpers) { 1.828 + cm.setCursor(cm.lineCount(), 0); 1.829 + var expectedLineCount = cm.lineCount() - 1; 1.830 + helpers.doKeys('d', 'd'); 1.831 + eq(expectedLineCount, cm.lineCount()); 1.832 + helpers.assertCursorAt(cm.lineCount() - 1, 0); 1.833 +}); 1.834 +// Yank commands should behave the exact same as d commands, expect that nothing 1.835 +// gets deleted. 1.836 +testVim('yw_repeat', function(cm, vim, helpers) { 1.837 + // Assert that yw does yank newline if it should go to the next line, and 1.838 + // that repeat works properly. 1.839 + var curStart = makeCursor(0, 1); 1.840 + cm.setCursor(curStart); 1.841 + helpers.doKeys('y', '2', 'w'); 1.842 + eq(' word1\nword2', cm.getValue()); 1.843 + var register = helpers.getRegisterController().getRegister(); 1.844 + eq('word1\nword2', register.toString()); 1.845 + is(!register.linewise); 1.846 + eqPos(curStart, cm.getCursor()); 1.847 +}, { value: ' word1\nword2' }); 1.848 +testVim('yy_multiply_repeat', function(cm, vim, helpers) { 1.849 + var curStart = makeCursor(0, 3); 1.850 + cm.setCursor(curStart); 1.851 + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, 1.852 + { line: 6, ch: 0 }); 1.853 + var expectedLineCount = cm.lineCount(); 1.854 + helpers.doKeys('2', 'y', '3', 'y'); 1.855 + eq(expectedLineCount, cm.lineCount()); 1.856 + var register = helpers.getRegisterController().getRegister(); 1.857 + eq(expectedBuffer, register.toString()); 1.858 + is(register.linewise); 1.859 + eqPos(curStart, cm.getCursor()); 1.860 +}); 1.861 +// Change commands behave like d commands except that it also enters insert 1.862 +// mode. In addition, when the change is linewise, an additional newline is 1.863 +// inserted so that insert mode starts on that line. 1.864 +testVim('cw', function(cm, vim, helpers) { 1.865 + cm.setCursor(0, 0); 1.866 + helpers.doKeys('c', '2', 'w'); 1.867 + eq(' word3', cm.getValue()); 1.868 + helpers.assertCursorAt(0, 0); 1.869 +}, { value: 'word1 word2 word3'}); 1.870 +testVim('cw_repeat', function(cm, vim, helpers) { 1.871 + // Assert that cw does delete newline if it should go to the next line, and 1.872 + // that repeat works properly. 1.873 + var curStart = makeCursor(0, 1); 1.874 + cm.setCursor(curStart); 1.875 + helpers.doKeys('c', '2', 'w'); 1.876 + eq(' ', cm.getValue()); 1.877 + var register = helpers.getRegisterController().getRegister(); 1.878 + eq('word1\nword2', register.toString()); 1.879 + is(!register.linewise); 1.880 + eqPos(curStart, cm.getCursor()); 1.881 + eq('vim-insert', cm.getOption('keyMap')); 1.882 +}, { value: ' word1\nword2' }); 1.883 +testVim('cc_multiply_repeat', function(cm, vim, helpers) { 1.884 + cm.setCursor(0, 3); 1.885 + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, 1.886 + { line: 6, ch: 0 }); 1.887 + var expectedLineCount = cm.lineCount() - 5; 1.888 + helpers.doKeys('2', 'c', '3', 'c'); 1.889 + eq(expectedLineCount, cm.lineCount()); 1.890 + var register = helpers.getRegisterController().getRegister(); 1.891 + eq(expectedBuffer, register.toString()); 1.892 + is(register.linewise); 1.893 + eq('vim-insert', cm.getOption('keyMap')); 1.894 +}); 1.895 +testVim('cc_append', function(cm, vim, helpers) { 1.896 + var expectedLineCount = cm.lineCount(); 1.897 + cm.setCursor(cm.lastLine(), 0); 1.898 + helpers.doKeys('c', 'c'); 1.899 + eq(expectedLineCount, cm.lineCount()); 1.900 +}); 1.901 +// Swapcase commands edit in place and do not modify registers. 1.902 +testVim('g~w_repeat', function(cm, vim, helpers) { 1.903 + // Assert that dw does delete newline if it should go to the next line, and 1.904 + // that repeat works properly. 1.905 + var curStart = makeCursor(0, 1); 1.906 + cm.setCursor(curStart); 1.907 + helpers.doKeys('g', '~', '2', 'w'); 1.908 + eq(' WORD1\nWORD2', cm.getValue()); 1.909 + var register = helpers.getRegisterController().getRegister(); 1.910 + eq('', register.toString()); 1.911 + is(!register.linewise); 1.912 + eqPos(curStart, cm.getCursor()); 1.913 +}, { value: ' word1\nword2' }); 1.914 +testVim('g~g~', function(cm, vim, helpers) { 1.915 + var curStart = makeCursor(0, 3); 1.916 + cm.setCursor(curStart); 1.917 + var expectedLineCount = cm.lineCount(); 1.918 + var expectedValue = cm.getValue().toUpperCase(); 1.919 + helpers.doKeys('2', 'g', '~', '3', 'g', '~'); 1.920 + eq(expectedValue, cm.getValue()); 1.921 + var register = helpers.getRegisterController().getRegister(); 1.922 + eq('', register.toString()); 1.923 + is(!register.linewise); 1.924 + eqPos(curStart, cm.getCursor()); 1.925 +}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); 1.926 +testVim('>{motion}', function(cm, vim, helpers) { 1.927 + cm.setCursor(1, 3); 1.928 + var expectedLineCount = cm.lineCount(); 1.929 + var expectedValue = ' word1\n word2\nword3 '; 1.930 + helpers.doKeys('>', 'k'); 1.931 + eq(expectedValue, cm.getValue()); 1.932 + var register = helpers.getRegisterController().getRegister(); 1.933 + eq('', register.toString()); 1.934 + is(!register.linewise); 1.935 + helpers.assertCursorAt(0, 3); 1.936 +}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); 1.937 +testVim('>>', function(cm, vim, helpers) { 1.938 + cm.setCursor(0, 3); 1.939 + var expectedLineCount = cm.lineCount(); 1.940 + var expectedValue = ' word1\n word2\nword3 '; 1.941 + helpers.doKeys('2', '>', '>'); 1.942 + eq(expectedValue, cm.getValue()); 1.943 + var register = helpers.getRegisterController().getRegister(); 1.944 + eq('', register.toString()); 1.945 + is(!register.linewise); 1.946 + helpers.assertCursorAt(0, 3); 1.947 +}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); 1.948 +testVim('<{motion}', function(cm, vim, helpers) { 1.949 + cm.setCursor(1, 3); 1.950 + var expectedLineCount = cm.lineCount(); 1.951 + var expectedValue = ' word1\nword2\nword3 '; 1.952 + helpers.doKeys('<', 'k'); 1.953 + eq(expectedValue, cm.getValue()); 1.954 + var register = helpers.getRegisterController().getRegister(); 1.955 + eq('', register.toString()); 1.956 + is(!register.linewise); 1.957 + helpers.assertCursorAt(0, 1); 1.958 +}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); 1.959 +testVim('<<', function(cm, vim, helpers) { 1.960 + cm.setCursor(0, 3); 1.961 + var expectedLineCount = cm.lineCount(); 1.962 + var expectedValue = ' word1\nword2\nword3 '; 1.963 + helpers.doKeys('2', '<', '<'); 1.964 + eq(expectedValue, cm.getValue()); 1.965 + var register = helpers.getRegisterController().getRegister(); 1.966 + eq('', register.toString()); 1.967 + is(!register.linewise); 1.968 + helpers.assertCursorAt(0, 1); 1.969 +}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); 1.970 + 1.971 +// Edit tests 1.972 +function testEdit(name, before, pos, edit, after) { 1.973 + return testVim(name, function(cm, vim, helpers) { 1.974 + var ch = before.search(pos) 1.975 + var line = before.substring(0, ch).split('\n').length - 1; 1.976 + if (line) { 1.977 + ch = before.substring(0, ch).split('\n').pop().length; 1.978 + } 1.979 + cm.setCursor(line, ch); 1.980 + helpers.doKeys.apply(this, edit.split('')); 1.981 + eq(after, cm.getValue()); 1.982 + }, {value: before}); 1.983 +} 1.984 + 1.985 +// These Delete tests effectively cover word-wise Change, Visual & Yank. 1.986 +// Tabs are used as differentiated whitespace to catch edge cases. 1.987 +// Normal word: 1.988 +testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz'); 1.989 +testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz'); 1.990 +testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz'); 1.991 +testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz'); 1.992 +testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz'); 1.993 +testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz'); 1.994 +testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz'); 1.995 +testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz'); 1.996 +testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz'); 1.997 +testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz'); 1.998 +testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t'); 1.999 +testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo'); 1.1000 +testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.'); 1.1001 +testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.'); 1.1002 +// Big word: 1.1003 +testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz'); 1.1004 +testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz'); 1.1005 +testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz'); 1.1006 +testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz'); 1.1007 +testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz'); 1.1008 +testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz'); 1.1009 +testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz'); 1.1010 +testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz'); 1.1011 +testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz'); 1.1012 +testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz'); 1.1013 +testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t'); 1.1014 +testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo'); 1.1015 +testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t'); 1.1016 +testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo'); 1.1017 +// Deleting text objects 1.1018 +// Open and close on same line 1.1019 +testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz'); 1.1020 +testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz'); 1.1021 +testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz'); 1.1022 +testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz'); 1.1023 + 1.1024 +testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz'); 1.1025 +testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz'); 1.1026 +testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz'); 1.1027 +testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz'); 1.1028 + 1.1029 +testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz'); 1.1030 +testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz'); 1.1031 +testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz'); 1.1032 +testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz'); 1.1033 + 1.1034 +// Open and close on different lines, equally indented 1.1035 +testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); 1.1036 +testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b'); 1.1037 +testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab'); 1.1038 +testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab'); 1.1039 + 1.1040 +// open and close on diff lines, open indented less than close 1.1041 +testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b'); 1.1042 +testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b'); 1.1043 +testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab'); 1.1044 +testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab'); 1.1045 + 1.1046 +// open and close on diff lines, open indented more than close 1.1047 +testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b'); 1.1048 +testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b'); 1.1049 +testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb'); 1.1050 +testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb'); 1.1051 + 1.1052 +// Operator-motion tests 1.1053 +testVim('D', function(cm, vim, helpers) { 1.1054 + cm.setCursor(0, 3); 1.1055 + helpers.doKeys('D'); 1.1056 + eq(' wo\nword2\n word3', cm.getValue()); 1.1057 + var register = helpers.getRegisterController().getRegister(); 1.1058 + eq('rd1', register.toString()); 1.1059 + is(!register.linewise); 1.1060 + helpers.assertCursorAt(0, 2); 1.1061 +}, { value: ' word1\nword2\n word3' }); 1.1062 +testVim('C', function(cm, vim, helpers) { 1.1063 + var curStart = makeCursor(0, 3); 1.1064 + cm.setCursor(curStart); 1.1065 + helpers.doKeys('C'); 1.1066 + eq(' wo\nword2\n word3', cm.getValue()); 1.1067 + var register = helpers.getRegisterController().getRegister(); 1.1068 + eq('rd1', register.toString()); 1.1069 + is(!register.linewise); 1.1070 + eqPos(curStart, cm.getCursor()); 1.1071 + eq('vim-insert', cm.getOption('keyMap')); 1.1072 +}, { value: ' word1\nword2\n word3' }); 1.1073 +testVim('Y', function(cm, vim, helpers) { 1.1074 + var curStart = makeCursor(0, 3); 1.1075 + cm.setCursor(curStart); 1.1076 + helpers.doKeys('Y'); 1.1077 + eq(' word1\nword2\n word3', cm.getValue()); 1.1078 + var register = helpers.getRegisterController().getRegister(); 1.1079 + eq('rd1', register.toString()); 1.1080 + is(!register.linewise); 1.1081 + helpers.assertCursorAt(0, 3); 1.1082 +}, { value: ' word1\nword2\n word3' }); 1.1083 +testVim('~', function(cm, vim, helpers) { 1.1084 + helpers.doKeys('3', '~'); 1.1085 + eq('ABCdefg', cm.getValue()); 1.1086 + helpers.assertCursorAt(0, 3); 1.1087 +}, { value: 'abcdefg' }); 1.1088 + 1.1089 +// Action tests 1.1090 +testVim('ctrl-a', function(cm, vim, helpers) { 1.1091 + cm.setCursor(0, 0); 1.1092 + helpers.doKeys('<C-a>'); 1.1093 + eq('-9', cm.getValue()); 1.1094 + helpers.assertCursorAt(0, 1); 1.1095 + helpers.doKeys('2','<C-a>'); 1.1096 + eq('-7', cm.getValue()); 1.1097 +}, {value: '-10'}); 1.1098 +testVim('ctrl-x', function(cm, vim, helpers) { 1.1099 + cm.setCursor(0, 0); 1.1100 + helpers.doKeys('<C-x>'); 1.1101 + eq('-1', cm.getValue()); 1.1102 + helpers.assertCursorAt(0, 1); 1.1103 + helpers.doKeys('2','<C-x>'); 1.1104 + eq('-3', cm.getValue()); 1.1105 +}, {value: '0'}); 1.1106 +testVim('<C-x>/<C-a> search forward', function(cm, vim, helpers) { 1.1107 + forEach(['<C-x>', '<C-a>'], function(key) { 1.1108 + cm.setCursor(0, 0); 1.1109 + helpers.doKeys(key); 1.1110 + helpers.assertCursorAt(0, 5); 1.1111 + helpers.doKeys('l'); 1.1112 + helpers.doKeys(key); 1.1113 + helpers.assertCursorAt(0, 10); 1.1114 + cm.setCursor(0, 11); 1.1115 + helpers.doKeys(key); 1.1116 + helpers.assertCursorAt(0, 11); 1.1117 + }); 1.1118 +}, {value: '__jmp1 jmp2 jmp'}); 1.1119 +testVim('a', function(cm, vim, helpers) { 1.1120 + cm.setCursor(0, 1); 1.1121 + helpers.doKeys('a'); 1.1122 + helpers.assertCursorAt(0, 2); 1.1123 + eq('vim-insert', cm.getOption('keyMap')); 1.1124 +}); 1.1125 +testVim('a_eol', function(cm, vim, helpers) { 1.1126 + cm.setCursor(0, lines[0].length - 1); 1.1127 + helpers.doKeys('a'); 1.1128 + helpers.assertCursorAt(0, lines[0].length); 1.1129 + eq('vim-insert', cm.getOption('keyMap')); 1.1130 +}); 1.1131 +testVim('i', function(cm, vim, helpers) { 1.1132 + cm.setCursor(0, 1); 1.1133 + helpers.doKeys('i'); 1.1134 + helpers.assertCursorAt(0, 1); 1.1135 + eq('vim-insert', cm.getOption('keyMap')); 1.1136 +}); 1.1137 +testVim('i_repeat', function(cm, vim, helpers) { 1.1138 + helpers.doKeys('3', 'i'); 1.1139 + cm.replaceRange('test', cm.getCursor()); 1.1140 + helpers.doInsertModeKeys('Esc'); 1.1141 + eq('testtesttest', cm.getValue()); 1.1142 + helpers.assertCursorAt(0, 11); 1.1143 +}, { value: '' }); 1.1144 +testVim('i_repeat_delete', function(cm, vim, helpers) { 1.1145 + cm.setCursor(0, 4); 1.1146 + helpers.doKeys('2', 'i'); 1.1147 + cm.replaceRange('z', cm.getCursor()); 1.1148 + helpers.doInsertModeKeys('Backspace', 'Backspace', 'Esc'); 1.1149 + eq('abe', cm.getValue()); 1.1150 + helpers.assertCursorAt(0, 1); 1.1151 +}, { value: 'abcde' }); 1.1152 +testVim('A', function(cm, vim, helpers) { 1.1153 + helpers.doKeys('A'); 1.1154 + helpers.assertCursorAt(0, lines[0].length); 1.1155 + eq('vim-insert', cm.getOption('keyMap')); 1.1156 +}); 1.1157 +testVim('I', function(cm, vim, helpers) { 1.1158 + cm.setCursor(0, 4); 1.1159 + helpers.doKeys('I'); 1.1160 + helpers.assertCursorAt(0, lines[0].textStart); 1.1161 + eq('vim-insert', cm.getOption('keyMap')); 1.1162 +}); 1.1163 +testVim('I_repeat', function(cm, vim, helpers) { 1.1164 + cm.setCursor(0, 1); 1.1165 + helpers.doKeys('3', 'I'); 1.1166 + cm.replaceRange('test', cm.getCursor()); 1.1167 + helpers.doInsertModeKeys('Esc'); 1.1168 + eq('testtesttestblah', cm.getValue()); 1.1169 + helpers.assertCursorAt(0, 11); 1.1170 +}, { value: 'blah' }); 1.1171 +testVim('o', function(cm, vim, helpers) { 1.1172 + cm.setCursor(0, 4); 1.1173 + helpers.doKeys('o'); 1.1174 + eq('word1\n\nword2', cm.getValue()); 1.1175 + helpers.assertCursorAt(1, 0); 1.1176 + eq('vim-insert', cm.getOption('keyMap')); 1.1177 +}, { value: 'word1\nword2' }); 1.1178 +testVim('o_repeat', function(cm, vim, helpers) { 1.1179 + cm.setCursor(0, 0); 1.1180 + helpers.doKeys('3', 'o'); 1.1181 + cm.replaceRange('test', cm.getCursor()); 1.1182 + helpers.doInsertModeKeys('Esc'); 1.1183 + eq('\ntest\ntest\ntest', cm.getValue()); 1.1184 + helpers.assertCursorAt(3, 3); 1.1185 +}, { value: '' }); 1.1186 +testVim('O', function(cm, vim, helpers) { 1.1187 + cm.setCursor(0, 4); 1.1188 + helpers.doKeys('O'); 1.1189 + eq('\nword1\nword2', cm.getValue()); 1.1190 + helpers.assertCursorAt(0, 0); 1.1191 + eq('vim-insert', cm.getOption('keyMap')); 1.1192 +}, { value: 'word1\nword2' }); 1.1193 +testVim('J', function(cm, vim, helpers) { 1.1194 + cm.setCursor(0, 4); 1.1195 + helpers.doKeys('J'); 1.1196 + var expectedValue = 'word1 word2\nword3\n word4'; 1.1197 + eq(expectedValue, cm.getValue()); 1.1198 + helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1); 1.1199 +}, { value: 'word1 \n word2\nword3\n word4' }); 1.1200 +testVim('J_repeat', function(cm, vim, helpers) { 1.1201 + cm.setCursor(0, 4); 1.1202 + helpers.doKeys('3', 'J'); 1.1203 + var expectedValue = 'word1 word2 word3\n word4'; 1.1204 + eq(expectedValue, cm.getValue()); 1.1205 + helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1); 1.1206 +}, { value: 'word1 \n word2\nword3\n word4' }); 1.1207 +testVim('p', function(cm, vim, helpers) { 1.1208 + cm.setCursor(0, 1); 1.1209 + helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); 1.1210 + helpers.doKeys('p'); 1.1211 + eq('__abc\ndef_', cm.getValue()); 1.1212 + helpers.assertCursorAt(1, 2); 1.1213 +}, { value: '___' }); 1.1214 +testVim('p_register', function(cm, vim, helpers) { 1.1215 + cm.setCursor(0, 1); 1.1216 + helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); 1.1217 + helpers.doKeys('"', 'a', 'p'); 1.1218 + eq('__abc\ndef_', cm.getValue()); 1.1219 + helpers.assertCursorAt(1, 2); 1.1220 +}, { value: '___' }); 1.1221 +testVim('p_wrong_register', function(cm, vim, helpers) { 1.1222 + cm.setCursor(0, 1); 1.1223 + helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); 1.1224 + helpers.doKeys('p'); 1.1225 + eq('___', cm.getValue()); 1.1226 + helpers.assertCursorAt(0, 1); 1.1227 +}, { value: '___' }); 1.1228 +testVim('p_line', function(cm, vim, helpers) { 1.1229 + cm.setCursor(0, 1); 1.1230 + helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); 1.1231 + helpers.doKeys('2', 'p'); 1.1232 + eq('___\n a\nd\n a\nd', cm.getValue()); 1.1233 + helpers.assertCursorAt(1, 2); 1.1234 +}, { value: '___' }); 1.1235 +testVim('p_lastline', function(cm, vim, helpers) { 1.1236 + cm.setCursor(0, 1); 1.1237 + helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true); 1.1238 + helpers.doKeys('2', 'p'); 1.1239 + eq('___\n a\nd\n a\nd', cm.getValue()); 1.1240 + helpers.assertCursorAt(1, 2); 1.1241 +}, { value: '___' }); 1.1242 +testVim('P', function(cm, vim, helpers) { 1.1243 + cm.setCursor(0, 1); 1.1244 + helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); 1.1245 + helpers.doKeys('P'); 1.1246 + eq('_abc\ndef__', cm.getValue()); 1.1247 + helpers.assertCursorAt(1, 3); 1.1248 +}, { value: '___' }); 1.1249 +testVim('P_line', function(cm, vim, helpers) { 1.1250 + cm.setCursor(0, 1); 1.1251 + helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); 1.1252 + helpers.doKeys('2', 'P'); 1.1253 + eq(' a\nd\n a\nd\n___', cm.getValue()); 1.1254 + helpers.assertCursorAt(0, 2); 1.1255 +}, { value: '___' }); 1.1256 +testVim('r', function(cm, vim, helpers) { 1.1257 + cm.setCursor(0, 1); 1.1258 + helpers.doKeys('3', 'r', 'u'); 1.1259 + eq('wuuuet\nanother', cm.getValue(),'3r failed'); 1.1260 + helpers.assertCursorAt(0, 3); 1.1261 + cm.setCursor(0, 4); 1.1262 + helpers.doKeys('v', 'j', 'h', 'r', '<Space>'); 1.1263 + eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); 1.1264 +}, { value: 'wordet\nanother' }); 1.1265 +testVim('R', function(cm, vim, helpers) { 1.1266 + cm.setCursor(0, 1); 1.1267 + helpers.doKeys('R'); 1.1268 + helpers.assertCursorAt(0, 1); 1.1269 + eq('vim-replace', cm.getOption('keyMap')); 1.1270 + is(cm.state.overwrite, 'Setting overwrite state failed'); 1.1271 +}); 1.1272 +testVim('mark', function(cm, vim, helpers) { 1.1273 + cm.setCursor(2, 2); 1.1274 + helpers.doKeys('m', 't'); 1.1275 + cm.setCursor(0, 0); 1.1276 + helpers.doKeys('\'', 't'); 1.1277 + helpers.assertCursorAt(2, 2); 1.1278 + cm.setCursor(0, 0); 1.1279 + helpers.doKeys('`', 't'); 1.1280 + helpers.assertCursorAt(2, 2); 1.1281 +}); 1.1282 +testVim('jumpToMark_next', function(cm, vim, helpers) { 1.1283 + cm.setCursor(2, 2); 1.1284 + helpers.doKeys('m', 't'); 1.1285 + cm.setCursor(0, 0); 1.1286 + helpers.doKeys(']', '`'); 1.1287 + helpers.assertCursorAt(2, 2); 1.1288 + cm.setCursor(0, 0); 1.1289 + helpers.doKeys(']', '\''); 1.1290 + helpers.assertCursorAt(2, 0); 1.1291 +}); 1.1292 +testVim('jumpToMark_next_repeat', function(cm, vim, helpers) { 1.1293 + cm.setCursor(2, 2); 1.1294 + helpers.doKeys('m', 'a'); 1.1295 + cm.setCursor(3, 2); 1.1296 + helpers.doKeys('m', 'b'); 1.1297 + cm.setCursor(4, 2); 1.1298 + helpers.doKeys('m', 'c'); 1.1299 + cm.setCursor(0, 0); 1.1300 + helpers.doKeys('2', ']', '`'); 1.1301 + helpers.assertCursorAt(3, 2); 1.1302 + cm.setCursor(0, 0); 1.1303 + helpers.doKeys('2', ']', '\''); 1.1304 + helpers.assertCursorAt(3, 1); 1.1305 +}); 1.1306 +testVim('jumpToMark_next_sameline', function(cm, vim, helpers) { 1.1307 + cm.setCursor(2, 0); 1.1308 + helpers.doKeys('m', 'a'); 1.1309 + cm.setCursor(2, 4); 1.1310 + helpers.doKeys('m', 'b'); 1.1311 + cm.setCursor(2, 2); 1.1312 + helpers.doKeys(']', '`'); 1.1313 + helpers.assertCursorAt(2, 4); 1.1314 +}); 1.1315 +testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) { 1.1316 + cm.setCursor(2, 0); 1.1317 + helpers.doKeys('m', 'a'); 1.1318 + cm.setCursor(4, 0); 1.1319 + helpers.doKeys(']', '`'); 1.1320 + helpers.assertCursorAt(4, 0); 1.1321 +}); 1.1322 +testVim('jumpToMark_next_nomark', function(cm, vim, helpers) { 1.1323 + cm.setCursor(2, 2); 1.1324 + helpers.doKeys(']', '`'); 1.1325 + helpers.assertCursorAt(2, 2); 1.1326 + helpers.doKeys(']', '\''); 1.1327 + helpers.assertCursorAt(2, 0); 1.1328 +}); 1.1329 +testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) { 1.1330 + cm.setCursor(2, 2); 1.1331 + helpers.doKeys('m', 'a'); 1.1332 + cm.setCursor(3, 4); 1.1333 + helpers.doKeys('m', 'b'); 1.1334 + cm.setCursor(2, 1); 1.1335 + helpers.doKeys(']', '\''); 1.1336 + helpers.assertCursorAt(3, 1); 1.1337 +}); 1.1338 +testVim('jumpToMark_next_action', function(cm, vim, helpers) { 1.1339 + cm.setCursor(2, 2); 1.1340 + helpers.doKeys('m', 't'); 1.1341 + cm.setCursor(0, 0); 1.1342 + helpers.doKeys('d', ']', '`'); 1.1343 + helpers.assertCursorAt(0, 0); 1.1344 + var actual = cm.getLine(0); 1.1345 + var expected = 'pop pop 0 1 2 3 4'; 1.1346 + eq(actual, expected, "Deleting while jumping to the next mark failed."); 1.1347 +}); 1.1348 +testVim('jumpToMark_next_line_action', function(cm, vim, helpers) { 1.1349 + cm.setCursor(2, 2); 1.1350 + helpers.doKeys('m', 't'); 1.1351 + cm.setCursor(0, 0); 1.1352 + helpers.doKeys('d', ']', '\''); 1.1353 + helpers.assertCursorAt(0, 1); 1.1354 + var actual = cm.getLine(0); 1.1355 + var expected = ' (a) [b] {c} ' 1.1356 + eq(actual, expected, "Deleting while jumping to the next mark line failed."); 1.1357 +}); 1.1358 +testVim('jumpToMark_prev', function(cm, vim, helpers) { 1.1359 + cm.setCursor(2, 2); 1.1360 + helpers.doKeys('m', 't'); 1.1361 + cm.setCursor(4, 0); 1.1362 + helpers.doKeys('[', '`'); 1.1363 + helpers.assertCursorAt(2, 2); 1.1364 + cm.setCursor(4, 0); 1.1365 + helpers.doKeys('[', '\''); 1.1366 + helpers.assertCursorAt(2, 0); 1.1367 +}); 1.1368 +testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) { 1.1369 + cm.setCursor(2, 2); 1.1370 + helpers.doKeys('m', 'a'); 1.1371 + cm.setCursor(3, 2); 1.1372 + helpers.doKeys('m', 'b'); 1.1373 + cm.setCursor(4, 2); 1.1374 + helpers.doKeys('m', 'c'); 1.1375 + cm.setCursor(5, 0); 1.1376 + helpers.doKeys('2', '[', '`'); 1.1377 + helpers.assertCursorAt(3, 2); 1.1378 + cm.setCursor(5, 0); 1.1379 + helpers.doKeys('2', '[', '\''); 1.1380 + helpers.assertCursorAt(3, 1); 1.1381 +}); 1.1382 +testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) { 1.1383 + cm.setCursor(2, 0); 1.1384 + helpers.doKeys('m', 'a'); 1.1385 + cm.setCursor(2, 4); 1.1386 + helpers.doKeys('m', 'b'); 1.1387 + cm.setCursor(2, 2); 1.1388 + helpers.doKeys('[', '`'); 1.1389 + helpers.assertCursorAt(2, 0); 1.1390 +}); 1.1391 +testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) { 1.1392 + cm.setCursor(4, 4); 1.1393 + helpers.doKeys('m', 'a'); 1.1394 + cm.setCursor(2, 0); 1.1395 + helpers.doKeys('[', '`'); 1.1396 + helpers.assertCursorAt(2, 0); 1.1397 +}); 1.1398 +testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) { 1.1399 + cm.setCursor(2, 2); 1.1400 + helpers.doKeys('[', '`'); 1.1401 + helpers.assertCursorAt(2, 2); 1.1402 + helpers.doKeys('[', '\''); 1.1403 + helpers.assertCursorAt(2, 0); 1.1404 +}); 1.1405 +testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) { 1.1406 + cm.setCursor(2, 2); 1.1407 + helpers.doKeys('m', 'a'); 1.1408 + cm.setCursor(3, 4); 1.1409 + helpers.doKeys('m', 'b'); 1.1410 + cm.setCursor(3, 6); 1.1411 + helpers.doKeys('[', '\''); 1.1412 + helpers.assertCursorAt(2, 0); 1.1413 +}); 1.1414 +testVim('delmark_single', function(cm, vim, helpers) { 1.1415 + cm.setCursor(1, 2); 1.1416 + helpers.doKeys('m', 't'); 1.1417 + helpers.doEx('delmarks t'); 1.1418 + cm.setCursor(0, 0); 1.1419 + helpers.doKeys('`', 't'); 1.1420 + helpers.assertCursorAt(0, 0); 1.1421 +}); 1.1422 +testVim('delmark_range', function(cm, vim, helpers) { 1.1423 + cm.setCursor(1, 2); 1.1424 + helpers.doKeys('m', 'a'); 1.1425 + cm.setCursor(2, 2); 1.1426 + helpers.doKeys('m', 'b'); 1.1427 + cm.setCursor(3, 2); 1.1428 + helpers.doKeys('m', 'c'); 1.1429 + cm.setCursor(4, 2); 1.1430 + helpers.doKeys('m', 'd'); 1.1431 + cm.setCursor(5, 2); 1.1432 + helpers.doKeys('m', 'e'); 1.1433 + helpers.doEx('delmarks b-d'); 1.1434 + cm.setCursor(0, 0); 1.1435 + helpers.doKeys('`', 'a'); 1.1436 + helpers.assertCursorAt(1, 2); 1.1437 + helpers.doKeys('`', 'b'); 1.1438 + helpers.assertCursorAt(1, 2); 1.1439 + helpers.doKeys('`', 'c'); 1.1440 + helpers.assertCursorAt(1, 2); 1.1441 + helpers.doKeys('`', 'd'); 1.1442 + helpers.assertCursorAt(1, 2); 1.1443 + helpers.doKeys('`', 'e'); 1.1444 + helpers.assertCursorAt(5, 2); 1.1445 +}); 1.1446 +testVim('delmark_multi', function(cm, vim, helpers) { 1.1447 + cm.setCursor(1, 2); 1.1448 + helpers.doKeys('m', 'a'); 1.1449 + cm.setCursor(2, 2); 1.1450 + helpers.doKeys('m', 'b'); 1.1451 + cm.setCursor(3, 2); 1.1452 + helpers.doKeys('m', 'c'); 1.1453 + cm.setCursor(4, 2); 1.1454 + helpers.doKeys('m', 'd'); 1.1455 + cm.setCursor(5, 2); 1.1456 + helpers.doKeys('m', 'e'); 1.1457 + helpers.doEx('delmarks bcd'); 1.1458 + cm.setCursor(0, 0); 1.1459 + helpers.doKeys('`', 'a'); 1.1460 + helpers.assertCursorAt(1, 2); 1.1461 + helpers.doKeys('`', 'b'); 1.1462 + helpers.assertCursorAt(1, 2); 1.1463 + helpers.doKeys('`', 'c'); 1.1464 + helpers.assertCursorAt(1, 2); 1.1465 + helpers.doKeys('`', 'd'); 1.1466 + helpers.assertCursorAt(1, 2); 1.1467 + helpers.doKeys('`', 'e'); 1.1468 + helpers.assertCursorAt(5, 2); 1.1469 +}); 1.1470 +testVim('delmark_multi_space', function(cm, vim, helpers) { 1.1471 + cm.setCursor(1, 2); 1.1472 + helpers.doKeys('m', 'a'); 1.1473 + cm.setCursor(2, 2); 1.1474 + helpers.doKeys('m', 'b'); 1.1475 + cm.setCursor(3, 2); 1.1476 + helpers.doKeys('m', 'c'); 1.1477 + cm.setCursor(4, 2); 1.1478 + helpers.doKeys('m', 'd'); 1.1479 + cm.setCursor(5, 2); 1.1480 + helpers.doKeys('m', 'e'); 1.1481 + helpers.doEx('delmarks b c d'); 1.1482 + cm.setCursor(0, 0); 1.1483 + helpers.doKeys('`', 'a'); 1.1484 + helpers.assertCursorAt(1, 2); 1.1485 + helpers.doKeys('`', 'b'); 1.1486 + helpers.assertCursorAt(1, 2); 1.1487 + helpers.doKeys('`', 'c'); 1.1488 + helpers.assertCursorAt(1, 2); 1.1489 + helpers.doKeys('`', 'd'); 1.1490 + helpers.assertCursorAt(1, 2); 1.1491 + helpers.doKeys('`', 'e'); 1.1492 + helpers.assertCursorAt(5, 2); 1.1493 +}); 1.1494 +testVim('delmark_all', function(cm, vim, helpers) { 1.1495 + cm.setCursor(1, 2); 1.1496 + helpers.doKeys('m', 'a'); 1.1497 + cm.setCursor(2, 2); 1.1498 + helpers.doKeys('m', 'b'); 1.1499 + cm.setCursor(3, 2); 1.1500 + helpers.doKeys('m', 'c'); 1.1501 + cm.setCursor(4, 2); 1.1502 + helpers.doKeys('m', 'd'); 1.1503 + cm.setCursor(5, 2); 1.1504 + helpers.doKeys('m', 'e'); 1.1505 + helpers.doEx('delmarks a b-de'); 1.1506 + cm.setCursor(0, 0); 1.1507 + helpers.doKeys('`', 'a'); 1.1508 + helpers.assertCursorAt(0, 0); 1.1509 + helpers.doKeys('`', 'b'); 1.1510 + helpers.assertCursorAt(0, 0); 1.1511 + helpers.doKeys('`', 'c'); 1.1512 + helpers.assertCursorAt(0, 0); 1.1513 + helpers.doKeys('`', 'd'); 1.1514 + helpers.assertCursorAt(0, 0); 1.1515 + helpers.doKeys('`', 'e'); 1.1516 + helpers.assertCursorAt(0, 0); 1.1517 +}); 1.1518 +testVim('visual', function(cm, vim, helpers) { 1.1519 + helpers.doKeys('l', 'v', 'l', 'l'); 1.1520 + helpers.assertCursorAt(0, 3); 1.1521 + eqPos(makeCursor(0, 1), cm.getCursor('anchor')); 1.1522 + helpers.doKeys('d'); 1.1523 + eq('15', cm.getValue()); 1.1524 +}, { value: '12345' }); 1.1525 +testVim('visual_line', function(cm, vim, helpers) { 1.1526 + helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); 1.1527 + eq(' 4\n 5', cm.getValue()); 1.1528 +}, { value: ' 1\n 2\n 3\n 4\n 5' }); 1.1529 +testVim('visual_marks', function(cm, vim, helpers) { 1.1530 + helpers.doKeys('l', 'v', 'l', 'l', 'v'); 1.1531 + // Test visual mode marks 1.1532 + cm.setCursor(0, 0); 1.1533 + helpers.doKeys('\'', '<'); 1.1534 + helpers.assertCursorAt(0, 1); 1.1535 + helpers.doKeys('\'', '>'); 1.1536 + helpers.assertCursorAt(0, 3); 1.1537 +}); 1.1538 +testVim('visual_join', function(cm, vim, helpers) { 1.1539 + helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J'); 1.1540 + eq(' 1 2 3\n 4\n 5', cm.getValue()); 1.1541 +}, { value: ' 1\n 2\n 3\n 4\n 5' }); 1.1542 +testVim('visual_blank', function(cm, vim, helpers) { 1.1543 + helpers.doKeys('v', 'k'); 1.1544 + eq(vim.visualMode, true); 1.1545 +}, { value: '\n' }); 1.1546 +testVim('reselect_visual', function(cm, vim, helpers) { 1.1547 + helpers.doKeys('l', 'v', 'l', 'l', 'y', 'g', 'v'); 1.1548 + helpers.assertCursorAt(0, 3); 1.1549 + eqPos(makeCursor(0, 1), cm.getCursor('anchor')); 1.1550 + helpers.doKeys('d'); 1.1551 + eq('15', cm.getValue()); 1.1552 +}, { value: '12345' }); 1.1553 +testVim('reselect_visual_line', function(cm, vim, helpers) { 1.1554 + helpers.doKeys('l', 'V', 'l', 'j', 'j', 'V', 'g', 'v', 'd'); 1.1555 + eq(' 4\n 5', cm.getValue()); 1.1556 +}, { value: ' 1\n 2\n 3\n 4\n 5' }); 1.1557 +testVim('s_normal', function(cm, vim, helpers) { 1.1558 + cm.setCursor(0, 1); 1.1559 + helpers.doKeys('s'); 1.1560 + helpers.doInsertModeKeys('Esc'); 1.1561 + helpers.assertCursorAt(0, 0); 1.1562 + eq('ac', cm.getValue()); 1.1563 +}, { value: 'abc'}); 1.1564 +testVim('s_visual', function(cm, vim, helpers) { 1.1565 + cm.setCursor(0, 1); 1.1566 + helpers.doKeys('v', 's'); 1.1567 + helpers.doInsertModeKeys('Esc'); 1.1568 + helpers.assertCursorAt(0, 0); 1.1569 + eq('ac', cm.getValue()); 1.1570 +}, { value: 'abc'}); 1.1571 +testVim('o_visual', function(cm,vim,helpers) { 1.1572 + cm.setCursor(0,0); 1.1573 + helpers.doKeys('v','l','l','l','o'); 1.1574 + helpers.assertCursorAt(0,0); 1.1575 + helpers.doKeys('v','v','j','j','j','o'); 1.1576 + helpers.assertCursorAt(0,0); 1.1577 + helpers.doKeys('o'); 1.1578 + helpers.doKeys('l','l') 1.1579 + helpers.assertCursorAt(3,2); 1.1580 + helpers.doKeys('d'); 1.1581 + eq('p',cm.getValue()); 1.1582 +}, { value: 'abcd\nefgh\nijkl\nmnop'}); 1.1583 + 1.1584 +testVim('S_normal', function(cm, vim, helpers) { 1.1585 + cm.setCursor(0, 1); 1.1586 + helpers.doKeys('j', 'S'); 1.1587 + helpers.doInsertModeKeys('Esc'); 1.1588 + helpers.assertCursorAt(1, 0); 1.1589 + eq('aa\n\ncc', cm.getValue()); 1.1590 +}, { value: 'aa\nbb\ncc'}); 1.1591 +testVim('S_visual', function(cm, vim, helpers) { 1.1592 + cm.setCursor(0, 1); 1.1593 + helpers.doKeys('v', 'j', 'S'); 1.1594 + helpers.doInsertModeKeys('Esc'); 1.1595 + helpers.assertCursorAt(0, 0); 1.1596 + eq('\ncc', cm.getValue()); 1.1597 +}, { value: 'aa\nbb\ncc'}); 1.1598 + 1.1599 +testVim('/ and n/N', function(cm, vim, helpers) { 1.1600 + cm.openDialog = helpers.fakeOpenDialog('match'); 1.1601 + helpers.doKeys('/'); 1.1602 + helpers.assertCursorAt(0, 11); 1.1603 + helpers.doKeys('n'); 1.1604 + helpers.assertCursorAt(1, 6); 1.1605 + helpers.doKeys('N'); 1.1606 + helpers.assertCursorAt(0, 11); 1.1607 + 1.1608 + cm.setCursor(0, 0); 1.1609 + helpers.doKeys('2', '/'); 1.1610 + helpers.assertCursorAt(1, 6); 1.1611 +}, { value: 'match nope match \n nope Match' }); 1.1612 +testVim('/_case', function(cm, vim, helpers) { 1.1613 + cm.openDialog = helpers.fakeOpenDialog('Match'); 1.1614 + helpers.doKeys('/'); 1.1615 + helpers.assertCursorAt(1, 6); 1.1616 +}, { value: 'match nope match \n nope Match' }); 1.1617 +testVim('/_2_pcre', function(cm, vim, helpers) { 1.1618 + CodeMirror.Vim.setOption('pcre', true); 1.1619 + cm.openDialog = helpers.fakeOpenDialog('(word){2}'); 1.1620 + helpers.doKeys('/'); 1.1621 + helpers.assertCursorAt(1, 9); 1.1622 + helpers.doKeys('n'); 1.1623 + helpers.assertCursorAt(2, 1); 1.1624 +}, { value: 'word\n another wordword\n wordwordword\n' }); 1.1625 +testVim('/_2_nopcre', function(cm, vim, helpers) { 1.1626 + CodeMirror.Vim.setOption('pcre', false); 1.1627 + cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}'); 1.1628 + helpers.doKeys('/'); 1.1629 + helpers.assertCursorAt(1, 9); 1.1630 + helpers.doKeys('n'); 1.1631 + helpers.assertCursorAt(2, 1); 1.1632 +}, { value: 'word\n another wordword\n wordwordword\n' }); 1.1633 +testVim('/_nongreedy', function(cm, vim, helpers) { 1.1634 + cm.openDialog = helpers.fakeOpenDialog('aa'); 1.1635 + helpers.doKeys('/'); 1.1636 + helpers.assertCursorAt(0, 4); 1.1637 + helpers.doKeys('n'); 1.1638 + helpers.assertCursorAt(1, 3); 1.1639 + helpers.doKeys('n'); 1.1640 + helpers.assertCursorAt(0, 0); 1.1641 +}, { value: 'aaa aa \n a aa'}); 1.1642 +testVim('?_nongreedy', function(cm, vim, helpers) { 1.1643 + cm.openDialog = helpers.fakeOpenDialog('aa'); 1.1644 + helpers.doKeys('?'); 1.1645 + helpers.assertCursorAt(1, 3); 1.1646 + helpers.doKeys('n'); 1.1647 + helpers.assertCursorAt(0, 4); 1.1648 + helpers.doKeys('n'); 1.1649 + helpers.assertCursorAt(0, 0); 1.1650 +}, { value: 'aaa aa \n a aa'}); 1.1651 +testVim('/_greedy', function(cm, vim, helpers) { 1.1652 + cm.openDialog = helpers.fakeOpenDialog('a+'); 1.1653 + helpers.doKeys('/'); 1.1654 + helpers.assertCursorAt(0, 4); 1.1655 + helpers.doKeys('n'); 1.1656 + helpers.assertCursorAt(1, 1); 1.1657 + helpers.doKeys('n'); 1.1658 + helpers.assertCursorAt(1, 3); 1.1659 + helpers.doKeys('n'); 1.1660 + helpers.assertCursorAt(0, 0); 1.1661 +}, { value: 'aaa aa \n a aa'}); 1.1662 +testVim('?_greedy', function(cm, vim, helpers) { 1.1663 + cm.openDialog = helpers.fakeOpenDialog('a+'); 1.1664 + helpers.doKeys('?'); 1.1665 + helpers.assertCursorAt(1, 3); 1.1666 + helpers.doKeys('n'); 1.1667 + helpers.assertCursorAt(1, 1); 1.1668 + helpers.doKeys('n'); 1.1669 + helpers.assertCursorAt(0, 4); 1.1670 + helpers.doKeys('n'); 1.1671 + helpers.assertCursorAt(0, 0); 1.1672 +}, { value: 'aaa aa \n a aa'}); 1.1673 +testVim('/_greedy_0_or_more', function(cm, vim, helpers) { 1.1674 + cm.openDialog = helpers.fakeOpenDialog('a*'); 1.1675 + helpers.doKeys('/'); 1.1676 + helpers.assertCursorAt(0, 3); 1.1677 + helpers.doKeys('n'); 1.1678 + helpers.assertCursorAt(0, 4); 1.1679 + helpers.doKeys('n'); 1.1680 + helpers.assertCursorAt(0, 5); 1.1681 + helpers.doKeys('n'); 1.1682 + helpers.assertCursorAt(1, 0); 1.1683 + helpers.doKeys('n'); 1.1684 + helpers.assertCursorAt(1, 1); 1.1685 + helpers.doKeys('n'); 1.1686 + helpers.assertCursorAt(0, 0); 1.1687 +}, { value: 'aaa aa\n aa'}); 1.1688 +testVim('?_greedy_0_or_more', function(cm, vim, helpers) { 1.1689 + cm.openDialog = helpers.fakeOpenDialog('a*'); 1.1690 + helpers.doKeys('?'); 1.1691 + helpers.assertCursorAt(1, 1); 1.1692 + helpers.doKeys('n'); 1.1693 + helpers.assertCursorAt(1, 0); 1.1694 + helpers.doKeys('n'); 1.1695 + helpers.assertCursorAt(0, 5); 1.1696 + helpers.doKeys('n'); 1.1697 + helpers.assertCursorAt(0, 4); 1.1698 + helpers.doKeys('n'); 1.1699 + helpers.assertCursorAt(0, 3); 1.1700 + helpers.doKeys('n'); 1.1701 + helpers.assertCursorAt(0, 0); 1.1702 +}, { value: 'aaa aa\n aa'}); 1.1703 +testVim('? and n/N', function(cm, vim, helpers) { 1.1704 + cm.openDialog = helpers.fakeOpenDialog('match'); 1.1705 + helpers.doKeys('?'); 1.1706 + helpers.assertCursorAt(1, 6); 1.1707 + helpers.doKeys('n'); 1.1708 + helpers.assertCursorAt(0, 11); 1.1709 + helpers.doKeys('N'); 1.1710 + helpers.assertCursorAt(1, 6); 1.1711 + 1.1712 + cm.setCursor(0, 0); 1.1713 + helpers.doKeys('2', '?'); 1.1714 + helpers.assertCursorAt(0, 11); 1.1715 +}, { value: 'match nope match \n nope Match' }); 1.1716 +testVim('*', function(cm, vim, helpers) { 1.1717 + cm.setCursor(0, 9); 1.1718 + helpers.doKeys('*'); 1.1719 + helpers.assertCursorAt(0, 22); 1.1720 + 1.1721 + cm.setCursor(0, 9); 1.1722 + helpers.doKeys('2', '*'); 1.1723 + helpers.assertCursorAt(1, 8); 1.1724 +}, { value: 'nomatch match nomatch match \nnomatch Match' }); 1.1725 +testVim('*_no_word', function(cm, vim, helpers) { 1.1726 + cm.setCursor(0, 0); 1.1727 + helpers.doKeys('*'); 1.1728 + helpers.assertCursorAt(0, 0); 1.1729 +}, { value: ' \n match \n' }); 1.1730 +testVim('*_symbol', function(cm, vim, helpers) { 1.1731 + cm.setCursor(0, 0); 1.1732 + helpers.doKeys('*'); 1.1733 + helpers.assertCursorAt(1, 0); 1.1734 +}, { value: ' /}\n/} match \n' }); 1.1735 +testVim('#', function(cm, vim, helpers) { 1.1736 + cm.setCursor(0, 9); 1.1737 + helpers.doKeys('#'); 1.1738 + helpers.assertCursorAt(1, 8); 1.1739 + 1.1740 + cm.setCursor(0, 9); 1.1741 + helpers.doKeys('2', '#'); 1.1742 + helpers.assertCursorAt(0, 22); 1.1743 +}, { value: 'nomatch match nomatch match \nnomatch Match' }); 1.1744 +testVim('*_seek', function(cm, vim, helpers) { 1.1745 + // Should skip over space and symbols. 1.1746 + cm.setCursor(0, 3); 1.1747 + helpers.doKeys('*'); 1.1748 + helpers.assertCursorAt(0, 22); 1.1749 +}, { value: ' := match nomatch match \nnomatch Match' }); 1.1750 +testVim('#', function(cm, vim, helpers) { 1.1751 + // Should skip over space and symbols. 1.1752 + cm.setCursor(0, 3); 1.1753 + helpers.doKeys('#'); 1.1754 + helpers.assertCursorAt(1, 8); 1.1755 +}, { value: ' := match nomatch match \nnomatch Match' }); 1.1756 +testVim('macro_insert', function(cm, vim, helpers) { 1.1757 + cm.setCursor(0, 0); 1.1758 + helpers.doKeys('q', 'a', '0', 'i'); 1.1759 + cm.replaceRange('foo', cm.getCursor()); 1.1760 + helpers.doInsertModeKeys('Esc'); 1.1761 + helpers.doKeys('q', '@', 'a'); 1.1762 + eq('foofoo', cm.getValue()); 1.1763 +}, { value: ''}); 1.1764 +testVim('macro_space', function(cm, vim, helpers) { 1.1765 + cm.setCursor(0, 0); 1.1766 + helpers.doKeys('<Space>', '<Space>'); 1.1767 + helpers.assertCursorAt(0, 2); 1.1768 + helpers.doKeys('q', 'a', '<Space>', '<Space>', 'q'); 1.1769 + helpers.assertCursorAt(0, 4); 1.1770 + helpers.doKeys('@', 'a'); 1.1771 + helpers.assertCursorAt(0, 6); 1.1772 + helpers.doKeys('@', 'a'); 1.1773 + helpers.assertCursorAt(0, 8); 1.1774 +}, { value: 'one line of text.'}); 1.1775 +testVim('macro_parens', function(cm, vim, helpers) { 1.1776 + cm.setCursor(0, 0); 1.1777 + helpers.doKeys('q', 'z', 'i'); 1.1778 + cm.replaceRange('(', cm.getCursor()); 1.1779 + helpers.doInsertModeKeys('Esc'); 1.1780 + helpers.doKeys('e', 'a'); 1.1781 + cm.replaceRange(')', cm.getCursor()); 1.1782 + helpers.doInsertModeKeys('Esc'); 1.1783 + helpers.doKeys('q'); 1.1784 + helpers.doKeys('w', '@', 'z'); 1.1785 + helpers.doKeys('w', '@', 'z'); 1.1786 + eq('(see) (spot) (run)', cm.getValue()); 1.1787 +}, { value: 'see spot run'}); 1.1788 +testVim('macro_overwrite', function(cm, vim, helpers) { 1.1789 + cm.setCursor(0, 0); 1.1790 + helpers.doKeys('q', 'z', '0', 'i'); 1.1791 + cm.replaceRange('I ', cm.getCursor()); 1.1792 + helpers.doInsertModeKeys('Esc'); 1.1793 + helpers.doKeys('q'); 1.1794 + helpers.doKeys('e'); 1.1795 + // Now replace the macro with something else. 1.1796 + helpers.doKeys('q', 'z', 'a'); 1.1797 + cm.replaceRange('.', cm.getCursor()); 1.1798 + helpers.doInsertModeKeys('Esc'); 1.1799 + helpers.doKeys('q'); 1.1800 + helpers.doKeys('e', '@', 'z'); 1.1801 + helpers.doKeys('e', '@', 'z'); 1.1802 + eq('I see. spot. run.', cm.getValue()); 1.1803 +}, { value: 'see spot run'}); 1.1804 +testVim('macro_search_f', function(cm, vim, helpers) { 1.1805 + cm.setCursor(0, 0); 1.1806 + helpers.doKeys('q', 'a', 'f', ' '); 1.1807 + helpers.assertCursorAt(0,3); 1.1808 + helpers.doKeys('q', '0'); 1.1809 + helpers.assertCursorAt(0,0); 1.1810 + helpers.doKeys('@', 'a'); 1.1811 + helpers.assertCursorAt(0,3); 1.1812 +}, { value: 'The quick brown fox jumped over the lazy dog.'}); 1.1813 +testVim('macro_search_2f', function(cm, vim, helpers) { 1.1814 + cm.setCursor(0, 0); 1.1815 + helpers.doKeys('q', 'a', '2', 'f', ' '); 1.1816 + helpers.assertCursorAt(0,9); 1.1817 + helpers.doKeys('q', '0'); 1.1818 + helpers.assertCursorAt(0,0); 1.1819 + helpers.doKeys('@', 'a'); 1.1820 + helpers.assertCursorAt(0,9); 1.1821 +}, { value: 'The quick brown fox jumped over the lazy dog.'}); 1.1822 +testVim('yank_register', function(cm, vim, helpers) { 1.1823 + cm.setCursor(0, 0); 1.1824 + helpers.doKeys('"', 'a', 'y', 'y'); 1.1825 + helpers.doKeys('j', '"', 'b', 'y', 'y'); 1.1826 + cm.openDialog = helpers.fakeOpenDialog('registers'); 1.1827 + cm.openNotification = helpers.fakeOpenNotification(function(text) { 1.1828 + is(/a\s+foo/.test(text)); 1.1829 + is(/b\s+bar/.test(text)); 1.1830 + }); 1.1831 + helpers.doKeys(':'); 1.1832 +}, { value: 'foo\nbar'}); 1.1833 +testVim('macro_register', function(cm, vim, helpers) { 1.1834 + cm.setCursor(0, 0); 1.1835 + helpers.doKeys('q', 'a', 'i'); 1.1836 + cm.replaceRange('gangnam', cm.getCursor()); 1.1837 + helpers.doInsertModeKeys('Esc'); 1.1838 + helpers.doKeys('q'); 1.1839 + helpers.doKeys('q', 'b', 'o'); 1.1840 + cm.replaceRange('style', cm.getCursor()); 1.1841 + helpers.doInsertModeKeys('Esc'); 1.1842 + helpers.doKeys('q'); 1.1843 + cm.openDialog = helpers.fakeOpenDialog('registers'); 1.1844 + cm.openNotification = helpers.fakeOpenNotification(function(text) { 1.1845 + is(/a\s+i/.test(text)); 1.1846 + is(/b\s+o/.test(text)); 1.1847 + }); 1.1848 + helpers.doKeys(':'); 1.1849 +}, { value: ''}); 1.1850 +testVim('.', function(cm, vim, helpers) { 1.1851 + cm.setCursor(0, 0); 1.1852 + helpers.doKeys('2', 'd', 'w'); 1.1853 + helpers.doKeys('.'); 1.1854 + eq('5 6', cm.getValue()); 1.1855 +}, { value: '1 2 3 4 5 6'}); 1.1856 +testVim('._repeat', function(cm, vim, helpers) { 1.1857 + cm.setCursor(0, 0); 1.1858 + helpers.doKeys('2', 'd', 'w'); 1.1859 + helpers.doKeys('3', '.'); 1.1860 + eq('6', cm.getValue()); 1.1861 +}, { value: '1 2 3 4 5 6'}); 1.1862 +testVim('._insert', function(cm, vim, helpers) { 1.1863 + helpers.doKeys('i'); 1.1864 + cm.replaceRange('test', cm.getCursor()); 1.1865 + helpers.doInsertModeKeys('Esc'); 1.1866 + helpers.doKeys('.'); 1.1867 + eq('testestt', cm.getValue()); 1.1868 + helpers.assertCursorAt(0, 6); 1.1869 +}, { value: ''}); 1.1870 +testVim('._insert_repeat', function(cm, vim, helpers) { 1.1871 + helpers.doKeys('i'); 1.1872 + cm.replaceRange('test', cm.getCursor()); 1.1873 + cm.setCursor(0, 4); 1.1874 + helpers.doInsertModeKeys('Esc'); 1.1875 + helpers.doKeys('2', '.'); 1.1876 + eq('testesttestt', cm.getValue()); 1.1877 + helpers.assertCursorAt(0, 10); 1.1878 +}, { value: ''}); 1.1879 +testVim('._repeat_insert', function(cm, vim, helpers) { 1.1880 + helpers.doKeys('3', 'i'); 1.1881 + cm.replaceRange('te', cm.getCursor()); 1.1882 + cm.setCursor(0, 2); 1.1883 + helpers.doInsertModeKeys('Esc'); 1.1884 + helpers.doKeys('.'); 1.1885 + eq('tetettetetee', cm.getValue()); 1.1886 + helpers.assertCursorAt(0, 10); 1.1887 +}, { value: ''}); 1.1888 +testVim('._insert_o', function(cm, vim, helpers) { 1.1889 + helpers.doKeys('o'); 1.1890 + cm.replaceRange('z', cm.getCursor()); 1.1891 + cm.setCursor(1, 1); 1.1892 + helpers.doInsertModeKeys('Esc'); 1.1893 + helpers.doKeys('.'); 1.1894 + eq('\nz\nz', cm.getValue()); 1.1895 + helpers.assertCursorAt(2, 0); 1.1896 +}, { value: ''}); 1.1897 +testVim('._insert_o_repeat', function(cm, vim, helpers) { 1.1898 + helpers.doKeys('o'); 1.1899 + cm.replaceRange('z', cm.getCursor()); 1.1900 + helpers.doInsertModeKeys('Esc'); 1.1901 + cm.setCursor(1, 0); 1.1902 + helpers.doKeys('2', '.'); 1.1903 + eq('\nz\nz\nz', cm.getValue()); 1.1904 + helpers.assertCursorAt(3, 0); 1.1905 +}, { value: ''}); 1.1906 +testVim('._insert_o_indent', function(cm, vim, helpers) { 1.1907 + helpers.doKeys('o'); 1.1908 + cm.replaceRange('z', cm.getCursor()); 1.1909 + helpers.doInsertModeKeys('Esc'); 1.1910 + cm.setCursor(1, 2); 1.1911 + helpers.doKeys('.'); 1.1912 + eq('{\n z\n z', cm.getValue()); 1.1913 + helpers.assertCursorAt(2, 2); 1.1914 +}, { value: '{'}); 1.1915 +testVim('._insert_cw', function(cm, vim, helpers) { 1.1916 + helpers.doKeys('c', 'w'); 1.1917 + cm.replaceRange('test', cm.getCursor()); 1.1918 + helpers.doInsertModeKeys('Esc'); 1.1919 + cm.setCursor(0, 3); 1.1920 + helpers.doKeys('2', 'l'); 1.1921 + helpers.doKeys('.'); 1.1922 + eq('test test word3', cm.getValue()); 1.1923 + helpers.assertCursorAt(0, 8); 1.1924 +}, { value: 'word1 word2 word3' }); 1.1925 +testVim('._insert_cw_repeat', function(cm, vim, helpers) { 1.1926 + // For some reason, repeat cw in desktop VIM will does not repeat insert mode 1.1927 + // changes. Will conform to that behavior. 1.1928 + helpers.doKeys('c', 'w'); 1.1929 + cm.replaceRange('test', cm.getCursor()); 1.1930 + helpers.doInsertModeKeys('Esc'); 1.1931 + cm.setCursor(0, 4); 1.1932 + helpers.doKeys('l'); 1.1933 + helpers.doKeys('2', '.'); 1.1934 + eq('test test', cm.getValue()); 1.1935 + helpers.assertCursorAt(0, 8); 1.1936 +}, { value: 'word1 word2 word3' }); 1.1937 +testVim('._delete', function(cm, vim, helpers) { 1.1938 + cm.setCursor(0, 5); 1.1939 + helpers.doKeys('i'); 1.1940 + helpers.doInsertModeKeys('Backspace', 'Esc'); 1.1941 + helpers.doKeys('.'); 1.1942 + eq('zace', cm.getValue()); 1.1943 + helpers.assertCursorAt(0, 1); 1.1944 +}, { value: 'zabcde'}); 1.1945 +testVim('._delete_repeat', function(cm, vim, helpers) { 1.1946 + cm.setCursor(0, 6); 1.1947 + helpers.doKeys('i'); 1.1948 + helpers.doInsertModeKeys('Backspace', 'Esc'); 1.1949 + helpers.doKeys('2', '.'); 1.1950 + eq('zzce', cm.getValue()); 1.1951 + helpers.assertCursorAt(0, 1); 1.1952 +}, { value: 'zzabcde'}); 1.1953 +testVim('f;', function(cm, vim, helpers) { 1.1954 + cm.setCursor(0, 0); 1.1955 + helpers.doKeys('f', 'x'); 1.1956 + helpers.doKeys(';'); 1.1957 + helpers.doKeys('2', ';'); 1.1958 + eq(9, cm.getCursor().ch); 1.1959 +}, { value: '01x3xx678x'}); 1.1960 +testVim('F;', function(cm, vim, helpers) { 1.1961 + cm.setCursor(0, 8); 1.1962 + helpers.doKeys('F', 'x'); 1.1963 + helpers.doKeys(';'); 1.1964 + helpers.doKeys('2', ';'); 1.1965 + eq(2, cm.getCursor().ch); 1.1966 +}, { value: '01x3xx6x8x'}); 1.1967 +testVim('t;', function(cm, vim, helpers) { 1.1968 + cm.setCursor(0, 0); 1.1969 + helpers.doKeys('t', 'x'); 1.1970 + helpers.doKeys(';'); 1.1971 + helpers.doKeys('2', ';'); 1.1972 + eq(8, cm.getCursor().ch); 1.1973 +}, { value: '01x3xx678x'}); 1.1974 +testVim('T;', function(cm, vim, helpers) { 1.1975 + cm.setCursor(0, 9); 1.1976 + helpers.doKeys('T', 'x'); 1.1977 + helpers.doKeys(';'); 1.1978 + helpers.doKeys('2', ';'); 1.1979 + eq(2, cm.getCursor().ch); 1.1980 +}, { value: '0xx3xx678x'}); 1.1981 +testVim('f,', function(cm, vim, helpers) { 1.1982 + cm.setCursor(0, 6); 1.1983 + helpers.doKeys('f', 'x'); 1.1984 + helpers.doKeys(','); 1.1985 + helpers.doKeys('2', ','); 1.1986 + eq(2, cm.getCursor().ch); 1.1987 +}, { value: '01x3xx678x'}); 1.1988 +testVim('F,', function(cm, vim, helpers) { 1.1989 + cm.setCursor(0, 3); 1.1990 + helpers.doKeys('F', 'x'); 1.1991 + helpers.doKeys(','); 1.1992 + helpers.doKeys('2', ','); 1.1993 + eq(9, cm.getCursor().ch); 1.1994 +}, { value: '01x3xx678x'}); 1.1995 +testVim('t,', function(cm, vim, helpers) { 1.1996 + cm.setCursor(0, 6); 1.1997 + helpers.doKeys('t', 'x'); 1.1998 + helpers.doKeys(','); 1.1999 + helpers.doKeys('2', ','); 1.2000 + eq(3, cm.getCursor().ch); 1.2001 +}, { value: '01x3xx678x'}); 1.2002 +testVim('T,', function(cm, vim, helpers) { 1.2003 + cm.setCursor(0, 4); 1.2004 + helpers.doKeys('T', 'x'); 1.2005 + helpers.doKeys(','); 1.2006 + helpers.doKeys('2', ','); 1.2007 + eq(8, cm.getCursor().ch); 1.2008 +}, { value: '01x3xx67xx'}); 1.2009 +testVim('fd,;', function(cm, vim, helpers) { 1.2010 + cm.setCursor(0, 0); 1.2011 + helpers.doKeys('f', '4'); 1.2012 + cm.setCursor(0, 0); 1.2013 + helpers.doKeys('d', ';'); 1.2014 + eq('56789', cm.getValue()); 1.2015 + helpers.doKeys('u'); 1.2016 + cm.setCursor(0, 9); 1.2017 + helpers.doKeys('d', ','); 1.2018 + eq('01239', cm.getValue()); 1.2019 +}, { value: '0123456789'}); 1.2020 +testVim('Fd,;', function(cm, vim, helpers) { 1.2021 + cm.setCursor(0, 9); 1.2022 + helpers.doKeys('F', '4'); 1.2023 + cm.setCursor(0, 9); 1.2024 + helpers.doKeys('d', ';'); 1.2025 + eq('01239', cm.getValue()); 1.2026 + helpers.doKeys('u'); 1.2027 + cm.setCursor(0, 0); 1.2028 + helpers.doKeys('d', ','); 1.2029 + eq('56789', cm.getValue()); 1.2030 +}, { value: '0123456789'}); 1.2031 +testVim('td,;', function(cm, vim, helpers) { 1.2032 + cm.setCursor(0, 0); 1.2033 + helpers.doKeys('t', '4'); 1.2034 + cm.setCursor(0, 0); 1.2035 + helpers.doKeys('d', ';'); 1.2036 + eq('456789', cm.getValue()); 1.2037 + helpers.doKeys('u'); 1.2038 + cm.setCursor(0, 9); 1.2039 + helpers.doKeys('d', ','); 1.2040 + eq('012349', cm.getValue()); 1.2041 +}, { value: '0123456789'}); 1.2042 +testVim('Td,;', function(cm, vim, helpers) { 1.2043 + cm.setCursor(0, 9); 1.2044 + helpers.doKeys('T', '4'); 1.2045 + cm.setCursor(0, 9); 1.2046 + helpers.doKeys('d', ';'); 1.2047 + eq('012349', cm.getValue()); 1.2048 + helpers.doKeys('u'); 1.2049 + cm.setCursor(0, 0); 1.2050 + helpers.doKeys('d', ','); 1.2051 + eq('456789', cm.getValue()); 1.2052 +}, { value: '0123456789'}); 1.2053 +testVim('fc,;', function(cm, vim, helpers) { 1.2054 + cm.setCursor(0, 0); 1.2055 + helpers.doKeys('f', '4'); 1.2056 + cm.setCursor(0, 0); 1.2057 + helpers.doKeys('c', ';', 'Esc'); 1.2058 + eq('56789', cm.getValue()); 1.2059 + helpers.doKeys('u'); 1.2060 + cm.setCursor(0, 9); 1.2061 + helpers.doKeys('c', ','); 1.2062 + eq('01239', cm.getValue()); 1.2063 +}, { value: '0123456789'}); 1.2064 +testVim('Fc,;', function(cm, vim, helpers) { 1.2065 + cm.setCursor(0, 9); 1.2066 + helpers.doKeys('F', '4'); 1.2067 + cm.setCursor(0, 9); 1.2068 + helpers.doKeys('c', ';', 'Esc'); 1.2069 + eq('01239', cm.getValue()); 1.2070 + helpers.doKeys('u'); 1.2071 + cm.setCursor(0, 0); 1.2072 + helpers.doKeys('c', ','); 1.2073 + eq('56789', cm.getValue()); 1.2074 +}, { value: '0123456789'}); 1.2075 +testVim('tc,;', function(cm, vim, helpers) { 1.2076 + cm.setCursor(0, 0); 1.2077 + helpers.doKeys('t', '4'); 1.2078 + cm.setCursor(0, 0); 1.2079 + helpers.doKeys('c', ';', 'Esc'); 1.2080 + eq('456789', cm.getValue()); 1.2081 + helpers.doKeys('u'); 1.2082 + cm.setCursor(0, 9); 1.2083 + helpers.doKeys('c', ','); 1.2084 + eq('012349', cm.getValue()); 1.2085 +}, { value: '0123456789'}); 1.2086 +testVim('Tc,;', function(cm, vim, helpers) { 1.2087 + cm.setCursor(0, 9); 1.2088 + helpers.doKeys('T', '4'); 1.2089 + cm.setCursor(0, 9); 1.2090 + helpers.doKeys('c', ';', 'Esc'); 1.2091 + eq('012349', cm.getValue()); 1.2092 + helpers.doKeys('u'); 1.2093 + cm.setCursor(0, 0); 1.2094 + helpers.doKeys('c', ','); 1.2095 + eq('456789', cm.getValue()); 1.2096 +}, { value: '0123456789'}); 1.2097 +testVim('fy,;', function(cm, vim, helpers) { 1.2098 + cm.setCursor(0, 0); 1.2099 + helpers.doKeys('f', '4'); 1.2100 + cm.setCursor(0, 0); 1.2101 + helpers.doKeys('y', ';', 'P'); 1.2102 + eq('012340123456789', cm.getValue()); 1.2103 + helpers.doKeys('u'); 1.2104 + cm.setCursor(0, 9); 1.2105 + helpers.doKeys('y', ',', 'P'); 1.2106 + eq('012345678456789', cm.getValue()); 1.2107 +}, { value: '0123456789'}); 1.2108 +testVim('Fy,;', function(cm, vim, helpers) { 1.2109 + cm.setCursor(0, 9); 1.2110 + helpers.doKeys('F', '4'); 1.2111 + cm.setCursor(0, 9); 1.2112 + helpers.doKeys('y', ';', 'p'); 1.2113 + eq('012345678945678', cm.getValue()); 1.2114 + helpers.doKeys('u'); 1.2115 + cm.setCursor(0, 0); 1.2116 + helpers.doKeys('y', ',', 'P'); 1.2117 + eq('012340123456789', cm.getValue()); 1.2118 +}, { value: '0123456789'}); 1.2119 +testVim('ty,;', function(cm, vim, helpers) { 1.2120 + cm.setCursor(0, 0); 1.2121 + helpers.doKeys('t', '4'); 1.2122 + cm.setCursor(0, 0); 1.2123 + helpers.doKeys('y', ';', 'P'); 1.2124 + eq('01230123456789', cm.getValue()); 1.2125 + helpers.doKeys('u'); 1.2126 + cm.setCursor(0, 9); 1.2127 + helpers.doKeys('y', ',', 'p'); 1.2128 + eq('01234567895678', cm.getValue()); 1.2129 +}, { value: '0123456789'}); 1.2130 +testVim('Ty,;', function(cm, vim, helpers) { 1.2131 + cm.setCursor(0, 9); 1.2132 + helpers.doKeys('T', '4'); 1.2133 + cm.setCursor(0, 9); 1.2134 + helpers.doKeys('y', ';', 'p'); 1.2135 + eq('01234567895678', cm.getValue()); 1.2136 + helpers.doKeys('u'); 1.2137 + cm.setCursor(0, 0); 1.2138 + helpers.doKeys('y', ',', 'P'); 1.2139 + eq('01230123456789', cm.getValue()); 1.2140 +}, { value: '0123456789'}); 1.2141 +testVim('HML', function(cm, vim, helpers) { 1.2142 + var lines = 35; 1.2143 + var textHeight = cm.defaultTextHeight(); 1.2144 + cm.setSize(600, lines*textHeight); 1.2145 + cm.setCursor(120, 0); 1.2146 + helpers.doKeys('H'); 1.2147 + helpers.assertCursorAt(86, 2); 1.2148 + helpers.doKeys('L'); 1.2149 + helpers.assertCursorAt(120, 4); 1.2150 + helpers.doKeys('M'); 1.2151 + helpers.assertCursorAt(103,4); 1.2152 +}, { value: (function(){ 1.2153 + var lines = new Array(100); 1.2154 + var upper = ' xx\n'; 1.2155 + var lower = ' xx\n'; 1.2156 + upper = lines.join(upper); 1.2157 + lower = lines.join(lower); 1.2158 + return upper + lower; 1.2159 +})()}); 1.2160 + 1.2161 +var zVals = ['zb','zz','zt','z-','z.','z<CR>'].map(function(e, idx){ 1.2162 + var lineNum = 250; 1.2163 + var lines = 35; 1.2164 + testVim(e, function(cm, vim, helpers) { 1.2165 + var k1 = e[0]; 1.2166 + var k2 = e.substring(1); 1.2167 + var textHeight = cm.defaultTextHeight(); 1.2168 + cm.setSize(600, lines*textHeight); 1.2169 + cm.setCursor(lineNum, 0); 1.2170 + helpers.doKeys(k1, k2); 1.2171 + zVals[idx] = cm.getScrollInfo().top; 1.2172 + }, { value: (function(){ 1.2173 + return new Array(500).join('\n'); 1.2174 + })()}); 1.2175 +}); 1.2176 +testVim('zb<zz', function(cm, vim, helpers){ 1.2177 + eq(zVals[0]<zVals[1], true); 1.2178 +}); 1.2179 +testVim('zz<zt', function(cm, vim, helpers){ 1.2180 + eq(zVals[1]<zVals[2], true); 1.2181 +}); 1.2182 +testVim('zb==z-', function(cm, vim, helpers){ 1.2183 + eq(zVals[0], zVals[3]); 1.2184 +}); 1.2185 +testVim('zz==z.', function(cm, vim, helpers){ 1.2186 + eq(zVals[1], zVals[4]); 1.2187 +}); 1.2188 +testVim('zt==z<CR>', function(cm, vim, helpers){ 1.2189 + eq(zVals[2], zVals[5]); 1.2190 +}); 1.2191 + 1.2192 +var moveTillCharacterSandbox = 1.2193 + 'The quick brown fox \n' 1.2194 + 'jumped over the lazy dog.' 1.2195 +testVim('moveTillCharacter', function(cm, vim, helpers){ 1.2196 + cm.setCursor(0, 0); 1.2197 + // Search for the 'q'. 1.2198 + cm.openDialog = helpers.fakeOpenDialog('q'); 1.2199 + helpers.doKeys('/'); 1.2200 + eq(4, cm.getCursor().ch); 1.2201 + // Jump to just before the first o in the list. 1.2202 + helpers.doKeys('t'); 1.2203 + helpers.doKeys('o'); 1.2204 + eq('The quick brown fox \n', cm.getValue()); 1.2205 + // Delete that one character. 1.2206 + helpers.doKeys('d'); 1.2207 + helpers.doKeys('t'); 1.2208 + helpers.doKeys('o'); 1.2209 + eq('The quick bown fox \n', cm.getValue()); 1.2210 + // Delete everything until the next 'o'. 1.2211 + helpers.doKeys('.'); 1.2212 + eq('The quick box \n', cm.getValue()); 1.2213 + // An unmatched character should have no effect. 1.2214 + helpers.doKeys('d'); 1.2215 + helpers.doKeys('t'); 1.2216 + helpers.doKeys('q'); 1.2217 + eq('The quick box \n', cm.getValue()); 1.2218 + // Matches should only be possible on single lines. 1.2219 + helpers.doKeys('d'); 1.2220 + helpers.doKeys('t'); 1.2221 + helpers.doKeys('z'); 1.2222 + eq('The quick box \n', cm.getValue()); 1.2223 + // After all that, the search for 'q' should still be active, so the 'N' command 1.2224 + // can run it again in reverse. Use that to delete everything back to the 'q'. 1.2225 + helpers.doKeys('d'); 1.2226 + helpers.doKeys('N'); 1.2227 + eq('The ox \n', cm.getValue()); 1.2228 + eq(4, cm.getCursor().ch); 1.2229 +}, { value: moveTillCharacterSandbox}); 1.2230 +testVim('searchForPipe', function(cm, vim, helpers){ 1.2231 + CodeMirror.Vim.setOption('pcre', false); 1.2232 + cm.setCursor(0, 0); 1.2233 + // Search for the '|'. 1.2234 + cm.openDialog = helpers.fakeOpenDialog('|'); 1.2235 + helpers.doKeys('/'); 1.2236 + eq(4, cm.getCursor().ch); 1.2237 +}, { value: 'this|that'}); 1.2238 + 1.2239 + 1.2240 +var scrollMotionSandbox = 1.2241 + '\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' 1.2242 + '\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' 1.2243 + '\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' 1.2244 + '\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'; 1.2245 +testVim('scrollMotion', function(cm, vim, helpers){ 1.2246 + var prevCursor, prevScrollInfo; 1.2247 + cm.setCursor(0, 0); 1.2248 + // ctrl-y at the top of the file should have no effect. 1.2249 + helpers.doKeys('<C-y>'); 1.2250 + eq(0, cm.getCursor().line); 1.2251 + prevScrollInfo = cm.getScrollInfo(); 1.2252 + helpers.doKeys('<C-e>'); 1.2253 + eq(1, cm.getCursor().line); 1.2254 + is(prevScrollInfo.top < cm.getScrollInfo().top); 1.2255 + // Jump to the end of the sandbox. 1.2256 + cm.setCursor(1000, 0); 1.2257 + prevCursor = cm.getCursor(); 1.2258 + // ctrl-e at the bottom of the file should have no effect. 1.2259 + helpers.doKeys('<C-e>'); 1.2260 + eq(prevCursor.line, cm.getCursor().line); 1.2261 + prevScrollInfo = cm.getScrollInfo(); 1.2262 + helpers.doKeys('<C-y>'); 1.2263 + eq(prevCursor.line - 1, cm.getCursor().line); 1.2264 + is(prevScrollInfo.top > cm.getScrollInfo().top); 1.2265 +}, { value: scrollMotionSandbox}); 1.2266 + 1.2267 +var squareBracketMotionSandbox = ''+ 1.2268 + '({\n'+//0 1.2269 + ' ({\n'+//11 1.2270 + ' /*comment {\n'+//2 1.2271 + ' */(\n'+//3 1.2272 + '#else \n'+//4 1.2273 + ' /* )\n'+//5 1.2274 + '#if }\n'+//6 1.2275 + ' )}*/\n'+//7 1.2276 + ')}\n'+//8 1.2277 + '{}\n'+//9 1.2278 + '#else {{\n'+//10 1.2279 + '{}\n'+//11 1.2280 + '}\n'+//12 1.2281 + '{\n'+//13 1.2282 + '#endif\n'+//14 1.2283 + '}\n'+//15 1.2284 + '}\n'+//16 1.2285 + '#else';//17 1.2286 +testVim('[[, ]]', function(cm, vim, helpers) { 1.2287 + cm.setCursor(0, 0); 1.2288 + helpers.doKeys(']', ']'); 1.2289 + helpers.assertCursorAt(9,0); 1.2290 + helpers.doKeys('2', ']', ']'); 1.2291 + helpers.assertCursorAt(13,0); 1.2292 + helpers.doKeys(']', ']'); 1.2293 + helpers.assertCursorAt(17,0); 1.2294 + helpers.doKeys('[', '['); 1.2295 + helpers.assertCursorAt(13,0); 1.2296 + helpers.doKeys('2', '[', '['); 1.2297 + helpers.assertCursorAt(9,0); 1.2298 + helpers.doKeys('[', '['); 1.2299 + helpers.assertCursorAt(0,0); 1.2300 +}, { value: squareBracketMotionSandbox}); 1.2301 +testVim('[], ][', function(cm, vim, helpers) { 1.2302 + cm.setCursor(0, 0); 1.2303 + helpers.doKeys(']', '['); 1.2304 + helpers.assertCursorAt(12,0); 1.2305 + helpers.doKeys('2', ']', '['); 1.2306 + helpers.assertCursorAt(16,0); 1.2307 + helpers.doKeys(']', '['); 1.2308 + helpers.assertCursorAt(17,0); 1.2309 + helpers.doKeys('[', ']'); 1.2310 + helpers.assertCursorAt(16,0); 1.2311 + helpers.doKeys('2', '[', ']'); 1.2312 + helpers.assertCursorAt(12,0); 1.2313 + helpers.doKeys('[', ']'); 1.2314 + helpers.assertCursorAt(0,0); 1.2315 +}, { value: squareBracketMotionSandbox}); 1.2316 +testVim('[{, ]}', function(cm, vim, helpers) { 1.2317 + cm.setCursor(4, 10); 1.2318 + helpers.doKeys('[', '{'); 1.2319 + helpers.assertCursorAt(2,12); 1.2320 + helpers.doKeys('2', '[', '{'); 1.2321 + helpers.assertCursorAt(0,1); 1.2322 + cm.setCursor(4, 10); 1.2323 + helpers.doKeys(']', '}'); 1.2324 + helpers.assertCursorAt(6,11); 1.2325 + helpers.doKeys('2', ']', '}'); 1.2326 + helpers.assertCursorAt(8,1); 1.2327 + cm.setCursor(0,1); 1.2328 + helpers.doKeys(']', '}'); 1.2329 + helpers.assertCursorAt(8,1); 1.2330 + helpers.doKeys('[', '{'); 1.2331 + helpers.assertCursorAt(0,1); 1.2332 +}, { value: squareBracketMotionSandbox}); 1.2333 +testVim('[(, ])', function(cm, vim, helpers) { 1.2334 + cm.setCursor(4, 10); 1.2335 + helpers.doKeys('[', '('); 1.2336 + helpers.assertCursorAt(3,14); 1.2337 + helpers.doKeys('2', '[', '('); 1.2338 + helpers.assertCursorAt(0,0); 1.2339 + cm.setCursor(4, 10); 1.2340 + helpers.doKeys(']', ')'); 1.2341 + helpers.assertCursorAt(5,11); 1.2342 + helpers.doKeys('2', ']', ')'); 1.2343 + helpers.assertCursorAt(8,0); 1.2344 + helpers.doKeys('[', '('); 1.2345 + helpers.assertCursorAt(0,0); 1.2346 + helpers.doKeys(']', ')'); 1.2347 + helpers.assertCursorAt(8,0); 1.2348 +}, { value: squareBracketMotionSandbox}); 1.2349 +testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { 1.2350 + forEach(['*', '/'], function(key){ 1.2351 + cm.setCursor(7, 0); 1.2352 + helpers.doKeys('2', '[', key); 1.2353 + helpers.assertCursorAt(2,2); 1.2354 + helpers.doKeys('2', ']', key); 1.2355 + helpers.assertCursorAt(7,5); 1.2356 + }); 1.2357 +}, { value: squareBracketMotionSandbox}); 1.2358 +testVim('[#, ]#', function(cm, vim, helpers) { 1.2359 + cm.setCursor(10, 3); 1.2360 + helpers.doKeys('2', '[', '#'); 1.2361 + helpers.assertCursorAt(4,0); 1.2362 + helpers.doKeys('5', ']', '#'); 1.2363 + helpers.assertCursorAt(17,0); 1.2364 + cm.setCursor(10, 3); 1.2365 + helpers.doKeys(']', '#'); 1.2366 + helpers.assertCursorAt(14,0); 1.2367 +}, { value: squareBracketMotionSandbox}); 1.2368 +testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) { 1.2369 + cm.setCursor(11, 0); 1.2370 + helpers.doKeys('[', 'm'); 1.2371 + helpers.assertCursorAt(10,7); 1.2372 + helpers.doKeys('4', '[', 'm'); 1.2373 + helpers.assertCursorAt(1,3); 1.2374 + helpers.doKeys('5', ']', 'm'); 1.2375 + helpers.assertCursorAt(11,0); 1.2376 + helpers.doKeys('[', 'M'); 1.2377 + helpers.assertCursorAt(9,1); 1.2378 + helpers.doKeys('3', ']', 'M'); 1.2379 + helpers.assertCursorAt(15,0); 1.2380 + helpers.doKeys('5', '[', 'M'); 1.2381 + helpers.assertCursorAt(7,3); 1.2382 +}, { value: squareBracketMotionSandbox}); 1.2383 + 1.2384 +// Ex mode tests 1.2385 +testVim('ex_go_to_line', function(cm, vim, helpers) { 1.2386 + cm.setCursor(0, 0); 1.2387 + helpers.doEx('4'); 1.2388 + helpers.assertCursorAt(3, 0); 1.2389 +}, { value: 'a\nb\nc\nd\ne\n'}); 1.2390 +testVim('ex_write', function(cm, vim, helpers) { 1.2391 + var tmp = CodeMirror.commands.save; 1.2392 + var written; 1.2393 + var actualCm; 1.2394 + CodeMirror.commands.save = function(cm) { 1.2395 + written = true; 1.2396 + actualCm = cm; 1.2397 + }; 1.2398 + // Test that w, wr, wri ... write all trigger :write. 1.2399 + var command = 'write'; 1.2400 + for (var i = 1; i < command.length; i++) { 1.2401 + written = false; 1.2402 + actualCm = null; 1.2403 + helpers.doEx(command.substring(0, i)); 1.2404 + eq(written, true); 1.2405 + eq(actualCm, cm); 1.2406 + } 1.2407 + CodeMirror.commands.save = tmp; 1.2408 +}); 1.2409 +testVim('ex_sort', function(cm, vim, helpers) { 1.2410 + helpers.doEx('sort'); 1.2411 + eq('Z\na\nb\nc\nd', cm.getValue()); 1.2412 +}, { value: 'b\nZ\nd\nc\na'}); 1.2413 +testVim('ex_sort_reverse', function(cm, vim, helpers) { 1.2414 + helpers.doEx('sort!'); 1.2415 + eq('d\nc\nb\na', cm.getValue()); 1.2416 +}, { value: 'b\nd\nc\na'}); 1.2417 +testVim('ex_sort_range', function(cm, vim, helpers) { 1.2418 + helpers.doEx('2,3sort'); 1.2419 + eq('b\nc\nd\na', cm.getValue()); 1.2420 +}, { value: 'b\nd\nc\na'}); 1.2421 +testVim('ex_sort_oneline', function(cm, vim, helpers) { 1.2422 + helpers.doEx('2sort'); 1.2423 + // Expect no change. 1.2424 + eq('b\nd\nc\na', cm.getValue()); 1.2425 +}, { value: 'b\nd\nc\na'}); 1.2426 +testVim('ex_sort_ignoreCase', function(cm, vim, helpers) { 1.2427 + helpers.doEx('sort i'); 1.2428 + eq('a\nb\nc\nd\nZ', cm.getValue()); 1.2429 +}, { value: 'b\nZ\nd\nc\na'}); 1.2430 +testVim('ex_sort_unique', function(cm, vim, helpers) { 1.2431 + helpers.doEx('sort u'); 1.2432 + eq('Z\na\nb\nc\nd', cm.getValue()); 1.2433 +}, { value: 'b\nZ\na\na\nd\na\nc\na'}); 1.2434 +testVim('ex_sort_decimal', function(cm, vim, helpers) { 1.2435 + helpers.doEx('sort d'); 1.2436 + eq('d3\n s5\n6\n.9', cm.getValue()); 1.2437 +}, { value: '6\nd3\n s5\n.9'}); 1.2438 +testVim('ex_sort_decimal_negative', function(cm, vim, helpers) { 1.2439 + helpers.doEx('sort d'); 1.2440 + eq('z-9\nd3\n s5\n6\n.9', cm.getValue()); 1.2441 +}, { value: '6\nd3\n s5\n.9\nz-9'}); 1.2442 +testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) { 1.2443 + helpers.doEx('sort! d'); 1.2444 + eq('.9\n6\n s5\nd3', cm.getValue()); 1.2445 +}, { value: '6\nd3\n s5\n.9'}); 1.2446 +testVim('ex_sort_hex', function(cm, vim, helpers) { 1.2447 + helpers.doEx('sort x'); 1.2448 + eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue()); 1.2449 +}, { value: '6\nd3\n s5\n&0xB\n.9'}); 1.2450 +testVim('ex_sort_octal', function(cm, vim, helpers) { 1.2451 + helpers.doEx('sort o'); 1.2452 + eq('.8\n.9\nd3\n s5\n6', cm.getValue()); 1.2453 +}, { value: '6\nd3\n s5\n.9\n.8'}); 1.2454 +testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { 1.2455 + helpers.doEx('sort d'); 1.2456 + eq('y\nz\nc1\nb2\na3', cm.getValue()); 1.2457 +}, { value: 'a3\nz\nc1\ny\nb2'}); 1.2458 +testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { 1.2459 + helpers.doEx('sort! d'); 1.2460 + eq('a3\nb2\nc1\nz\ny', cm.getValue()); 1.2461 +}, { value: 'a3\nz\nc1\ny\nb2'}); 1.2462 + 1.2463 +// Basic substitute tests. 1.2464 +testVim('ex_substitute_same_line', function(cm, vim, helpers) { 1.2465 + cm.setCursor(1, 0); 1.2466 + helpers.doEx('s/one/two'); 1.2467 + eq('one one\n two two', cm.getValue()); 1.2468 +}, { value: 'one one\n one one'}); 1.2469 +testVim('ex_substitute_global', function(cm, vim, helpers) { 1.2470 + cm.setCursor(1, 0); 1.2471 + helpers.doEx('%s/one/two'); 1.2472 + eq('two two\n two two', cm.getValue()); 1.2473 +}, { value: 'one one\n one one'}); 1.2474 +testVim('ex_substitute_input_range', function(cm, vim, helpers) { 1.2475 + cm.setCursor(1, 0); 1.2476 + helpers.doEx('1,3s/\\d/0'); 1.2477 + eq('0\n0\n0\n4', cm.getValue()); 1.2478 +}, { value: '1\n2\n3\n4' }); 1.2479 +testVim('ex_substitute_visual_range', function(cm, vim, helpers) { 1.2480 + cm.setCursor(1, 0); 1.2481 + // Set last visual mode selection marks '< and '> at lines 2 and 4 1.2482 + helpers.doKeys('V', '2', 'j', 'v'); 1.2483 + helpers.doEx('\'<,\'>s/\\d/0'); 1.2484 + eq('1\n0\n0\n0\n5', cm.getValue()); 1.2485 +}, { value: '1\n2\n3\n4\n5' }); 1.2486 +testVim('ex_substitute_empty_query', function(cm, vim, helpers) { 1.2487 + // If the query is empty, use last query. 1.2488 + cm.setCursor(1, 0); 1.2489 + cm.openDialog = helpers.fakeOpenDialog('1'); 1.2490 + helpers.doKeys('/'); 1.2491 + helpers.doEx('s//b'); 1.2492 + eq('abb ab2 ab3', cm.getValue()); 1.2493 +}, { value: 'a11 a12 a13' }); 1.2494 +testVim('ex_substitute_javascript', function(cm, vim, helpers) { 1.2495 + CodeMirror.Vim.setOption('pcre', false); 1.2496 + cm.setCursor(1, 0); 1.2497 + // Throw all the things that javascript likes to treat as special values 1.2498 + // into the replace part. All should be literal (this is VIM). 1.2499 + helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/') 1.2500 + eq('a $$ $\' $` $& 0 b', cm.getValue()); 1.2501 +}, { value: 'a 0 b' }); 1.2502 + 1.2503 +// More complex substitute tests that test both pcre and nopcre options. 1.2504 +function testSubstitute(name, options) { 1.2505 + testVim(name + '_pcre', function(cm, vim, helpers) { 1.2506 + cm.setCursor(1, 0); 1.2507 + CodeMirror.Vim.setOption('pcre', true); 1.2508 + helpers.doEx(options.expr); 1.2509 + eq(options.expectedValue, cm.getValue()); 1.2510 + }, options); 1.2511 + // If no noPcreExpr is defined, assume that it's the same as the expr. 1.2512 + var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr; 1.2513 + testVim(name + '_nopcre', function(cm, vim, helpers) { 1.2514 + cm.setCursor(1, 0); 1.2515 + CodeMirror.Vim.setOption('pcre', false); 1.2516 + helpers.doEx(noPcreExpr); 1.2517 + eq(options.expectedValue, cm.getValue()); 1.2518 + }, options); 1.2519 +} 1.2520 +testSubstitute('ex_substitute_capture', { 1.2521 + value: 'a11 a12 a13', 1.2522 + expectedValue: 'a1111 a1212 a1313', 1.2523 + // $n is a backreference 1.2524 + expr: 's/(\\d+)/$1$1/', 1.2525 + // \n is a backreference. 1.2526 + noPcreExpr: 's/\\(\\d+\\)/\\1\\1/'}); 1.2527 +testSubstitute('ex_substitute_capture2', { 1.2528 + value: 'a 0 b', 1.2529 + expectedValue: 'a $00 b', 1.2530 + expr: 's/(\\d+)/$$$1$1/', 1.2531 + noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/'}); 1.2532 +testSubstitute('ex_substitute_nocapture', { 1.2533 + value: 'a11 a12 a13', 1.2534 + expectedValue: 'a$1$1 a$1$1 a$1$1', 1.2535 + expr: 's/(\\d+)/$$1$$1', 1.2536 + noPcreExpr: 's/\\(\\d+\\)/$1$1/'}); 1.2537 +testSubstitute('ex_substitute_nocapture2', { 1.2538 + value: 'a 0 b', 1.2539 + expectedValue: 'a $10 b', 1.2540 + expr: 's/(\\d+)/$$1$1', 1.2541 + noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/'}); 1.2542 +testSubstitute('ex_substitute_nocapture', { 1.2543 + value: 'a b c', 1.2544 + expectedValue: 'a $ c', 1.2545 + expr: 's/b/$$/', 1.2546 + noPcreExpr: 's/b/$/'}); 1.2547 +testSubstitute('ex_substitute_slash_regex', { 1.2548 + value: 'one/two \n three/four', 1.2549 + expectedValue: 'one|two \n three|four', 1.2550 + expr: '%s/\\//|'}); 1.2551 +testSubstitute('ex_substitute_pipe_regex', { 1.2552 + value: 'one|two \n three|four', 1.2553 + expectedValue: 'one,two \n three,four', 1.2554 + expr: '%s/\\|/,/', 1.2555 + noPcreExpr: '%s/|/,/'}); 1.2556 +testSubstitute('ex_substitute_or_regex', { 1.2557 + value: 'one|two \n three|four', 1.2558 + expectedValue: 'ana|twa \n thraa|faar', 1.2559 + expr: '%s/o|e|u/a', 1.2560 + noPcreExpr: '%s/o\\|e\\|u/a'}); 1.2561 +testSubstitute('ex_substitute_or_word_regex', { 1.2562 + value: 'one|two \n three|four', 1.2563 + expectedValue: 'five|five \n three|four', 1.2564 + expr: '%s/(one|two)/five/', 1.2565 + noPcreExpr: '%s/\\(one\\|two\\)/five'}); 1.2566 +testSubstitute('ex_substitute_backslashslash_regex', { 1.2567 + value: 'one\\two \n three\\four', 1.2568 + expectedValue: 'one,two \n three,four', 1.2569 + expr: '%s/\\\\/,'}); 1.2570 +testSubstitute('ex_substitute_slash_replacement', { 1.2571 + value: 'one,two \n three,four', 1.2572 + expectedValue: 'one/two \n three/four', 1.2573 + expr: '%s/,/\\/'}); 1.2574 +testSubstitute('ex_substitute_backslash_replacement', { 1.2575 + value: 'one,two \n three,four', 1.2576 + expectedValue: 'one\\two \n three\\four', 1.2577 + expr: '%s/,/\\\\/g'}); 1.2578 +testSubstitute('ex_substitute_multibackslash_replacement', { 1.2579 + value: 'one,two \n three,four', 1.2580 + expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. 1.2581 + expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. 1.2582 +testSubstitute('ex_substitute_braces_word', { 1.2583 + value: 'ababab abb ab{2}', 1.2584 + expectedValue: 'ab abb ab{2}', 1.2585 + expr: '%s/(ab){2}//g', 1.2586 + noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'}); 1.2587 +testSubstitute('ex_substitute_braces_range', { 1.2588 + value: 'a aa aaa aaaa', 1.2589 + expectedValue: 'a a', 1.2590 + expr: '%s/a{2,3}//g', 1.2591 + noPcreExpr: '%s/a\\{2,3\\}//g'}); 1.2592 +testSubstitute('ex_substitute_braces_literal', { 1.2593 + value: 'ababab abb ab{2}', 1.2594 + expectedValue: 'ababab abb ', 1.2595 + expr: '%s/ab\\{2\\}//g', 1.2596 + noPcreExpr: '%s/ab{2}//g'}); 1.2597 +testSubstitute('ex_substitute_braces_char', { 1.2598 + value: 'ababab abb ab{2}', 1.2599 + expectedValue: 'ababab ab{2}', 1.2600 + expr: '%s/ab{2}//g', 1.2601 + noPcreExpr: '%s/ab\\{2\\}//g'}); 1.2602 +testSubstitute('ex_substitute_braces_no_escape', { 1.2603 + value: 'ababab abb ab{2}', 1.2604 + expectedValue: 'ababab ab{2}', 1.2605 + expr: '%s/ab{2}//g', 1.2606 + noPcreExpr: '%s/ab\\{2}//g'}); 1.2607 +testSubstitute('ex_substitute_count', { 1.2608 + value: '1\n2\n3\n4', 1.2609 + expectedValue: '1\n0\n0\n4', 1.2610 + expr: 's/\\d/0/i 2'}); 1.2611 +testSubstitute('ex_substitute_count_with_range', { 1.2612 + value: '1\n2\n3\n4', 1.2613 + expectedValue: '1\n2\n0\n0', 1.2614 + expr: '1,3s/\\d/0/ 3'}); 1.2615 +function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) { 1.2616 + testVim(name, function(cm, vim, helpers) { 1.2617 + var savedOpenDialog = cm.openDialog; 1.2618 + var savedKeyName = CodeMirror.keyName; 1.2619 + var onKeyDown; 1.2620 + var recordedCallback; 1.2621 + var closed = true; // Start out closed, set false on second openDialog. 1.2622 + function close() { 1.2623 + closed = true; 1.2624 + } 1.2625 + // First openDialog should save callback. 1.2626 + cm.openDialog = function(template, callback, options) { 1.2627 + recordedCallback = callback; 1.2628 + } 1.2629 + // Do first openDialog. 1.2630 + helpers.doKeys(':'); 1.2631 + // Second openDialog should save keyDown handler. 1.2632 + cm.openDialog = function(template, callback, options) { 1.2633 + onKeyDown = options.onKeyDown; 1.2634 + closed = false; 1.2635 + }; 1.2636 + // Return the command to Vim and trigger second openDialog. 1.2637 + recordedCallback(command); 1.2638 + // The event should really use keyCode, but here just mock it out and use 1.2639 + // key and replace keyName to just return key. 1.2640 + CodeMirror.keyName = function (e) { return e.key; } 1.2641 + keys = keys.toUpperCase(); 1.2642 + for (var i = 0; i < keys.length; i++) { 1.2643 + is(!closed); 1.2644 + onKeyDown({ key: keys.charAt(i) }, '', close); 1.2645 + } 1.2646 + try { 1.2647 + eq(expectedValue, cm.getValue()); 1.2648 + helpers.assertCursorAt(finalPos); 1.2649 + is(closed); 1.2650 + } catch(e) { 1.2651 + throw e 1.2652 + } finally { 1.2653 + // Restore overriden functions. 1.2654 + CodeMirror.keyName = savedKeyName; 1.2655 + cm.openDialog = savedOpenDialog; 1.2656 + } 1.2657 + }, { value: initialValue }); 1.2658 +}; 1.2659 +testSubstituteConfirm('ex_substitute_confirm_emptydoc', 1.2660 + '%s/x/b/c', '', '', '', makeCursor(0, 0)); 1.2661 +testSubstituteConfirm('ex_substitute_confirm_nomatch', 1.2662 + '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0)); 1.2663 +testSubstituteConfirm('ex_substitute_confirm_accept', 1.2664 + '%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1)); 1.2665 +testSubstituteConfirm('ex_substitute_confirm_random_keys', 1.2666 + '%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1)); 1.2667 +testSubstituteConfirm('ex_substitute_confirm_some', 1.2668 + '%s/a/b/c', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1)); 1.2669 +testSubstituteConfirm('ex_substitute_confirm_all', 1.2670 + '%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1)); 1.2671 +testSubstituteConfirm('ex_substitute_confirm_accept_then_all', 1.2672 + '%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1)); 1.2673 +testSubstituteConfirm('ex_substitute_confirm_quit', 1.2674 + '%s/a/b/c', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3)); 1.2675 +testSubstituteConfirm('ex_substitute_confirm_last', 1.2676 + '%s/a/b/c', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); 1.2677 +testSubstituteConfirm('ex_substitute_confirm_oneline', 1.2678 + '1s/a/b/c', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); 1.2679 +testSubstituteConfirm('ex_substitute_confirm_range_accept', 1.2680 + '1,2s/a/b/c', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0)); 1.2681 +testSubstituteConfirm('ex_substitute_confirm_range_some', 1.2682 + '1,3s/a/b/c', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0)); 1.2683 +testSubstituteConfirm('ex_substitute_confirm_range_all', 1.2684 + '1,3s/a/b/c', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0)); 1.2685 +testSubstituteConfirm('ex_substitute_confirm_range_last', 1.2686 + '1,3s/a/b/c', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0)); 1.2687 +//:noh should clear highlighting of search-results but allow to resume search through n 1.2688 +testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { 1.2689 + cm.openDialog = helpers.fakeOpenDialog('match'); 1.2690 + helpers.doKeys('?'); 1.2691 + helpers.doEx('noh'); 1.2692 + eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared'); 1.2693 + helpers.doKeys('n'); 1.2694 + helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); 1.2695 +}, { value: 'match nope match \n nope Match' }); 1.2696 +testVim('set_boolean', function(cm, vim, helpers) { 1.2697 + CodeMirror.Vim.defineOption('testoption', true, 'boolean'); 1.2698 + // Test default value is set. 1.2699 + is(CodeMirror.Vim.getOption('testoption')); 1.2700 + try { 1.2701 + // Test fail to set to non-boolean 1.2702 + CodeMirror.Vim.setOption('testoption', '5'); 1.2703 + fail(); 1.2704 + } catch (expected) {}; 1.2705 + // Test setOption 1.2706 + CodeMirror.Vim.setOption('testoption', false); 1.2707 + is(!CodeMirror.Vim.getOption('testoption')); 1.2708 +}); 1.2709 +testVim('ex_set_boolean', function(cm, vim, helpers) { 1.2710 + CodeMirror.Vim.defineOption('testoption', true, 'boolean'); 1.2711 + // Test default value is set. 1.2712 + is(CodeMirror.Vim.getOption('testoption')); 1.2713 + try { 1.2714 + // Test fail to set to non-boolean 1.2715 + helpers.doEx('set testoption=22'); 1.2716 + fail(); 1.2717 + } catch (expected) {}; 1.2718 + // Test setOption 1.2719 + helpers.doEx('set notestoption'); 1.2720 + is(!CodeMirror.Vim.getOption('testoption')); 1.2721 +}); 1.2722 +testVim('set_string', function(cm, vim, helpers) { 1.2723 + CodeMirror.Vim.defineOption('testoption', 'a', 'string'); 1.2724 + // Test default value is set. 1.2725 + eq('a', CodeMirror.Vim.getOption('testoption')); 1.2726 + try { 1.2727 + // Test fail to set non-string. 1.2728 + CodeMirror.Vim.setOption('testoption', true); 1.2729 + fail(); 1.2730 + } catch (expected) {}; 1.2731 + try { 1.2732 + // Test fail to set 'notestoption' 1.2733 + CodeMirror.Vim.setOption('notestoption', 'b'); 1.2734 + fail(); 1.2735 + } catch (expected) {}; 1.2736 + // Test setOption 1.2737 + CodeMirror.Vim.setOption('testoption', 'c'); 1.2738 + eq('c', CodeMirror.Vim.getOption('testoption')); 1.2739 +}); 1.2740 +testVim('ex_set_string', function(cm, vim, helpers) { 1.2741 + CodeMirror.Vim.defineOption('testoption', 'a', 'string'); 1.2742 + // Test default value is set. 1.2743 + eq('a', CodeMirror.Vim.getOption('testoption')); 1.2744 + try { 1.2745 + // Test fail to set 'notestoption' 1.2746 + helpers.doEx('set notestoption=b'); 1.2747 + fail(); 1.2748 + } catch (expected) {}; 1.2749 + // Test setOption 1.2750 + helpers.doEx('set testoption=c') 1.2751 + eq('c', CodeMirror.Vim.getOption('testoption')); 1.2752 +}); 1.2753 +// TODO: Reset key maps after each test. 1.2754 +testVim('ex_map_key2key', function(cm, vim, helpers) { 1.2755 + helpers.doEx('map a x'); 1.2756 + helpers.doKeys('a'); 1.2757 + helpers.assertCursorAt(0, 0); 1.2758 + eq('bc', cm.getValue()); 1.2759 +}, { value: 'abc' }); 1.2760 +testVim('ex_unmap_key2key', function(cm, vim, helpers) { 1.2761 + helpers.doEx('unmap a'); 1.2762 + helpers.doKeys('a'); 1.2763 + eq('vim-insert', cm.getOption('keyMap')); 1.2764 +}, { value: 'abc' }); 1.2765 +testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { 1.2766 + try { 1.2767 + helpers.doEx('unmap a'); 1.2768 + fail(); 1.2769 + } catch (expected) {} 1.2770 + helpers.doKeys('a'); 1.2771 + eq('vim-insert', cm.getOption('keyMap')); 1.2772 +}, { value: 'abc' }); 1.2773 +testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) { 1.2774 + helpers.doEx('map ; :'); 1.2775 + var dialogOpened = false; 1.2776 + cm.openDialog = function() { 1.2777 + dialogOpened = true; 1.2778 + } 1.2779 + helpers.doKeys(';'); 1.2780 + eq(dialogOpened, true); 1.2781 +}); 1.2782 +testVim('ex_map_ex2key:', function(cm, vim, helpers) { 1.2783 + helpers.doEx('map :del x'); 1.2784 + helpers.doEx('del'); 1.2785 + helpers.assertCursorAt(0, 0); 1.2786 + eq('bc', cm.getValue()); 1.2787 +}, { value: 'abc' }); 1.2788 +testVim('ex_map_ex2ex', function(cm, vim, helpers) { 1.2789 + helpers.doEx('map :del :w'); 1.2790 + var tmp = CodeMirror.commands.save; 1.2791 + var written = false; 1.2792 + var actualCm; 1.2793 + CodeMirror.commands.save = function(cm) { 1.2794 + written = true; 1.2795 + actualCm = cm; 1.2796 + }; 1.2797 + helpers.doEx('del'); 1.2798 + CodeMirror.commands.save = tmp; 1.2799 + eq(written, true); 1.2800 + eq(actualCm, cm); 1.2801 +}); 1.2802 +testVim('ex_map_key2ex', function(cm, vim, helpers) { 1.2803 + helpers.doEx('map a :w'); 1.2804 + var tmp = CodeMirror.commands.save; 1.2805 + var written = false; 1.2806 + var actualCm; 1.2807 + CodeMirror.commands.save = function(cm) { 1.2808 + written = true; 1.2809 + actualCm = cm; 1.2810 + }; 1.2811 + helpers.doKeys('a'); 1.2812 + CodeMirror.commands.save = tmp; 1.2813 + eq(written, true); 1.2814 + eq(actualCm, cm); 1.2815 +}); 1.2816 +testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { 1.2817 + CodeMirror.Vim.map('b', ':w', 'visual'); 1.2818 + var tmp = CodeMirror.commands.save; 1.2819 + var written = false; 1.2820 + var actualCm; 1.2821 + CodeMirror.commands.save = function(cm) { 1.2822 + written = true; 1.2823 + actualCm = cm; 1.2824 + }; 1.2825 + // Mapping should not work in normal mode. 1.2826 + helpers.doKeys('b'); 1.2827 + eq(written, false); 1.2828 + // Mapping should work in visual mode. 1.2829 + helpers.doKeys('v', 'b'); 1.2830 + eq(written, true); 1.2831 + eq(actualCm, cm); 1.2832 + 1.2833 + CodeMirror.commands.save = tmp; 1.2834 +}); 1.2835 + 1.2836 +// Testing registration of functions as ex-commands and mapping to <Key>-keys 1.2837 +testVim('ex_api_test', function(cm, vim, helpers) { 1.2838 + var res=false; 1.2839 + var val='from'; 1.2840 + CodeMirror.Vim.defineEx('extest','ext',function(cm,params){ 1.2841 + if(params.args)val=params.args[0]; 1.2842 + else res=true; 1.2843 + }); 1.2844 + helpers.doEx(':ext to'); 1.2845 + eq(val,'to','Defining ex-command failed'); 1.2846 + CodeMirror.Vim.map('<C-CR><Space>',':ext'); 1.2847 + helpers.doKeys('<C-CR>','<Space>'); 1.2848 + is(res,'Mapping to key failed'); 1.2849 +}); 1.2850 +// For now, this test needs to be last because it messes up : for future tests. 1.2851 +testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { 1.2852 + helpers.doEx('map : x'); 1.2853 + helpers.doKeys(':'); 1.2854 + helpers.assertCursorAt(0, 0); 1.2855 + eq('bc', cm.getValue()); 1.2856 +}, { value: 'abc' }); 1.2857 + 1.2858 +// Test event handlers 1.2859 +testVim('beforeSelectionChange', function(cm, vim, helpers) { 1.2860 + cm.setCursor(0, 100); 1.2861 + eqPos(cm.getCursor('head'), cm.getCursor('anchor')); 1.2862 +}, { value: 'abc' });