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