Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
malwaredllc
GitHub Repository: malwaredllc/byob
Path: blob/master/web-gui/buildyourownbotnet/assets/js/codemirror/test/vim_test.js
1293 views
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
var helpers = {
180
doKeys: doKeysFn(cm),
181
// Warning: Only emulates keymap events, not character insertions. Use
182
// replaceRange to simulate character insertions.
183
// Keys are in CodeMirror format, NOT vim format.
184
doInsertModeKeys: doInsertModeKeysFn(cm),
185
doEx: doExFn(cm),
186
assertCursorAt: assertCursorAtFn(cm),
187
fakeOpenDialog: fakeOpenDialog,
188
getRegisterController: function() {
189
return CodeMirror.Vim.getRegisterController();
190
}
191
}
192
CodeMirror.Vim.resetVimGlobalState_();
193
var successful = false;
194
try {
195
run(cm, vim, helpers);
196
successful = true;
197
} finally {
198
if (!successful || verbose) {
199
place.style.visibility = "visible";
200
} else {
201
place.removeChild(cm.getWrapperElement());
202
}
203
}
204
}, expectedFail);
205
};
206
testVim('qq@q', function(cm, vim, helpers) {
207
cm.setCursor(0, 0);
208
helpers.doKeys('q', 'q', 'l', 'l', 'q');
209
helpers.assertCursorAt(0,2);
210
helpers.doKeys('@', 'q');
211
helpers.assertCursorAt(0,4);
212
}, { value: ' '});
213
testVim('@@', function(cm, vim, helpers) {
214
cm.setCursor(0, 0);
215
helpers.doKeys('q', 'q', 'l', 'l', 'q');
216
helpers.assertCursorAt(0,2);
217
helpers.doKeys('@', 'q');
218
helpers.assertCursorAt(0,4);
219
helpers.doKeys('@', '@');
220
helpers.assertCursorAt(0,6);
221
}, { value: ' '});
222
var jumplistScene = ''+
223
'word\n'+
224
'(word)\n'+
225
'{word\n'+
226
'word.\n'+
227
'\n'+
228
'word search\n'+
229
'}word\n'+
230
'word\n'+
231
'word\n';
232
function testJumplist(name, keys, endPos, startPos, dialog) {
233
endPos = makeCursor(endPos[0], endPos[1]);
234
startPos = makeCursor(startPos[0], startPos[1]);
235
testVim(name, function(cm, vim, helpers) {
236
CodeMirror.Vim.resetVimGlobalState_();
237
if(dialog)cm.openDialog = helpers.fakeOpenDialog('word');
238
cm.setCursor(startPos);
239
helpers.doKeys.apply(null, keys);
240
helpers.assertCursorAt(endPos);
241
}, {value: jumplistScene});
242
};
243
testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]);
244
testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]);
245
testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]);
246
testJumplist('jumplist_[[', ['[', '[', '<C-o>'], [5,2], [5,2]);
247
testJumplist('jumplist_]]', [']', ']', '<C-o>'], [2,2], [2,2]);
248
testJumplist('jumplist_G', ['G', '<C-o>'], [5,2], [5,2]);
249
testJumplist('jumplist_gg', ['g', 'g', '<C-o>'], [5,2], [5,2]);
250
testJumplist('jumplist_%', ['%', '<C-o>'], [1,5], [1,5]);
251
testJumplist('jumplist_{', ['{', '<C-o>'], [1,5], [1,5]);
252
testJumplist('jumplist_}', ['}', '<C-o>'], [1,5], [1,5]);
253
testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', '<C-i>'], [1,5], [1,5]);
254
testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', '<C-i>'], [1,5], [1,5]);
255
testJumplist('jumplist_*_cachedCursor', ['*', '<C-o>'], [1,3], [1,3]);
256
testJumplist('jumplist_#_cachedCursor', ['#', '<C-o>'], [1,3], [1,3]);
257
testJumplist('jumplist_n', ['#', 'n', '<C-o>'], [1,1], [2,3]);
258
testJumplist('jumplist_N', ['#', 'N', '<C-o>'], [1,1], [2,3]);
259
testJumplist('jumplist_repeat_<c-o>', ['*', '*', '*', '3', '<C-o>'], [2,3], [2,3]);
260
testJumplist('jumplist_repeat_<c-i>', ['*', '*', '*', '3', '<C-o>', '2', '<C-i>'], [5,0], [2,3]);
261
testJumplist('jumplist_repeated_motion', ['3', '*', '<C-o>'], [2,3], [2,3]);
262
testJumplist('jumplist_/', ['/', '<C-o>'], [2,3], [2,3], 'dialog');
263
testJumplist('jumplist_?', ['?', '<C-o>'], [2,3], [2,3], 'dialog');
264
testJumplist('jumplist_skip_delted_mark<c-o>',
265
['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-o>', '<C-o>'],
266
[0,2], [0,2]);
267
testJumplist('jumplist_skip_delted_mark<c-i>',
268
['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-i>', '<C-i>'],
269
[1,0], [0,2]);
270
/**
271
* @param name Name of the test
272
* @param keys An array of keys or a string with a single key to simulate.
273
* @param endPos The expected end position of the cursor.
274
* @param startPos The position the cursor should start at, defaults to 0, 0.
275
*/
276
function testMotion(name, keys, endPos, startPos) {
277
testVim(name, function(cm, vim, helpers) {
278
if (!startPos) {
279
startPos = { line: 0, ch: 0 };
280
}
281
cm.setCursor(startPos);
282
helpers.doKeys(keys);
283
helpers.assertCursorAt(endPos);
284
});
285
};
286
287
function makeCursor(line, ch) {
288
return { line: line, ch: ch };
289
};
290
291
function offsetCursor(cur, offsetLine, offsetCh) {
292
return { line: cur.line + offsetLine, ch: cur.ch + offsetCh };
293
};
294
295
// Motion tests
296
testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4));
297
testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4));
298
testMotion('h', 'h', makeCursor(0, 0), word1.start);
299
testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end);
300
testMotion('l', 'l', makeCursor(0, 1));
301
testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2));
302
testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end);
303
testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end);
304
testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument);
305
testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end);
306
testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4));
307
testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4));
308
testMotion('w', 'w', word1.start);
309
testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2));
310
testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51));
311
testMotion('w_repeat', ['2', 'w'], word2.start);
312
testMotion('w_wrap', ['w'], word3.start, word2.start);
313
testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument);
314
testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0));
315
testMotion('W', 'W', bigWord1.start);
316
testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start);
317
testMotion('e', 'e', word1.end);
318
testMotion('e_repeat', ['2', 'e'], word2.end);
319
testMotion('e_wrap', 'e', word3.end, word2.end);
320
testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument);
321
testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0));
322
testMotion('b', 'b', word3.start, word3.end);
323
testMotion('b_repeat', ['2', 'b'], word2.start, word3.end);
324
testMotion('b_wrap', 'b', word2.start, word3.start);
325
testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0));
326
testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument);
327
testMotion('ge', ['g', 'e'], word2.end, word3.end);
328
testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start);
329
testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start);
330
testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0),
331
makeCursor(0, 0));
332
testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument);
333
testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart),
334
makeCursor(3, 1));
335
testMotion('gg_repeat', ['3', 'g', 'g'],
336
makeCursor(lines[2].line, lines[2].textStart));
337
testMotion('G', 'G',
338
makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart),
339
makeCursor(3, 1));
340
testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line,
341
lines[2].textStart));
342
// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B.
343
testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8));
344
testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8));
345
testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8));
346
testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4));
347
testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8));
348
testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1));
349
testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1),
350
makeCursor(0, 3));
351
testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0));
352
testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]);
353
testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0));
354
testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1),
355
makeCursor(charLine.line, 0));
356
testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1),
357
pChars[0]);
358
testMotion('F', ['F', 'p'], pChars[0], pChars[1]);
359
testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]);
360
testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]);
361
testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]);
362
testMotion('%_parens', ['%'], parens1.end, parens1.start);
363
testMotion('%_squares', ['%'], squares1.end, squares1.start);
364
testMotion('%_braces', ['%'], curlys1.end, curlys1.start);
365
testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start);
366
testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start);
367
testVim('%_seek_skip', function(cm, vim, helpers) {
368
cm.setCursor(0,0);
369
helpers.doKeys(['%']);
370
helpers.assertCursorAt(0,9);
371
}, {value:'01234"("()'});
372
testVim('%_skip_string', function(cm, vim, helpers) {
373
cm.setCursor(0,0);
374
helpers.doKeys(['%']);
375
helpers.assertCursorAt(0,4);
376
cm.setCursor(0,2);
377
helpers.doKeys(['%']);
378
helpers.assertCursorAt(0,0);
379
}, {value:'(")")'});
380
(')')
381
testVim('%_skip_comment', function(cm, vim, helpers) {
382
cm.setCursor(0,0);
383
helpers.doKeys(['%']);
384
helpers.assertCursorAt(0,6);
385
cm.setCursor(0,3);
386
helpers.doKeys(['%']);
387
helpers.assertCursorAt(0,0);
388
}, {value:'(/*)*/)'});
389
// Make sure that moving down after going to the end of a line always leaves you
390
// at the end of a line, but preserves the offset in other cases
391
testVim('Changing lines after Eol operation', function(cm, vim, helpers) {
392
cm.setCursor(0,0);
393
helpers.doKeys(['$']);
394
helpers.doKeys(['j']);
395
// After moving to Eol and then down, we should be at Eol of line 2
396
helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 });
397
helpers.doKeys(['j']);
398
// After moving down, we should be at Eol of line 3
399
helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 });
400
helpers.doKeys(['h']);
401
helpers.doKeys(['j']);
402
// After moving back one space and then down, since line 4 is shorter than line 2, we should
403
// be at Eol of line 2 - 1
404
helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 });
405
helpers.doKeys(['j']);
406
helpers.doKeys(['j']);
407
// After moving down again, since line 3 has enough characters, we should be back to the
408
// same place we were at on line 1
409
helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 });
410
});
411
//making sure gj and gk recover from clipping
412
testVim('gj_gk_clipping', function(cm,vim,helpers){
413
cm.setCursor(0, 1);
414
helpers.doKeys('g','j','g','j');
415
helpers.assertCursorAt(2, 1);
416
helpers.doKeys('g','k','g','k');
417
helpers.assertCursorAt(0, 1);
418
},{value: 'line 1\n\nline 2'});
419
//testing a mix of j/k and gj/gk
420
testVim('j_k_and_gj_gk', function(cm,vim,helpers){
421
cm.setSize(120);
422
cm.setCursor(0, 0);
423
//go to the last character on the first line
424
helpers.doKeys('$');
425
//move up/down on the column within the wrapped line
426
//side-effect: cursor is not locked to eol anymore
427
helpers.doKeys('g','k');
428
var cur=cm.getCursor();
429
eq(cur.line,0);
430
is((cur.ch<176),'gk didn\'t move cursor back (1)');
431
helpers.doKeys('g','j');
432
helpers.assertCursorAt(0, 176);
433
//should move to character 177 on line 2 (j/k preserve character index within line)
434
helpers.doKeys('j');
435
//due to different line wrapping, the cursor can be on a different screen-x now
436
//gj and gk preserve screen-x on movement, much like moveV
437
helpers.doKeys('3','g','k');
438
cur=cm.getCursor();
439
eq(cur.line,1);
440
is((cur.ch<176),'gk didn\'t move cursor back (2)');
441
helpers.doKeys('g','j','2','g','j');
442
//should return to the same character-index
443
helpers.doKeys('k');
444
helpers.assertCursorAt(0, 176);
445
},{ 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.'});
446
testVim('gj_gk', function(cm, vim, helpers) {
447
if (phantom) return;
448
cm.setSize(120);
449
// Test top of document edge case.
450
cm.setCursor(0, 4);
451
helpers.doKeys('g', 'j');
452
helpers.doKeys('10', 'g', 'k');
453
helpers.assertCursorAt(0, 4);
454
455
// Test moving down preserves column position.
456
helpers.doKeys('g', 'j');
457
var pos1 = cm.getCursor();
458
var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4};
459
helpers.doKeys('g', 'j');
460
helpers.assertCursorAt(expectedPos2);
461
462
// Move to the last character
463
cm.setCursor(0, 0);
464
// Move left to reset HSPos
465
helpers.doKeys('h');
466
// Test bottom of document edge case.
467
helpers.doKeys('100', 'g', 'j');
468
var endingPos = cm.getCursor();
469
is(endingPos != 0, 'gj should not be on wrapped line 0');
470
var topLeftCharCoords = cm.charCoords(makeCursor(0, 0));
471
var endingCharCoords = cm.charCoords(endingPos);
472
is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0');
473
},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' });
474
testVim('}', function(cm, vim, helpers) {
475
cm.setCursor(0, 0);
476
helpers.doKeys('}');
477
helpers.assertCursorAt(1, 0);
478
cm.setCursor(0, 0);
479
helpers.doKeys('2', '}');
480
helpers.assertCursorAt(4, 0);
481
cm.setCursor(0, 0);
482
helpers.doKeys('6', '}');
483
helpers.assertCursorAt(5, 0);
484
}, { value: 'a\n\nb\nc\n\nd' });
485
testVim('{', function(cm, vim, helpers) {
486
cm.setCursor(5, 0);
487
helpers.doKeys('{');
488
helpers.assertCursorAt(4, 0);
489
cm.setCursor(5, 0);
490
helpers.doKeys('2', '{');
491
helpers.assertCursorAt(1, 0);
492
cm.setCursor(5, 0);
493
helpers.doKeys('6', '{');
494
helpers.assertCursorAt(0, 0);
495
}, { value: 'a\n\nb\nc\n\nd' });
496
497
// Operator tests
498
testVim('dl', function(cm, vim, helpers) {
499
var curStart = makeCursor(0, 0);
500
cm.setCursor(curStart);
501
helpers.doKeys('d', 'l');
502
eq('word1 ', cm.getValue());
503
var register = helpers.getRegisterController().getRegister();
504
eq(' ', register.text);
505
is(!register.linewise);
506
eqPos(curStart, cm.getCursor());
507
}, { value: ' word1 ' });
508
testVim('dl_eol', function(cm, vim, helpers) {
509
cm.setCursor(0, 6);
510
helpers.doKeys('d', 'l');
511
eq(' word1', cm.getValue());
512
var register = helpers.getRegisterController().getRegister();
513
eq(' ', register.text);
514
is(!register.linewise);
515
helpers.assertCursorAt(0, 5);
516
}, { value: ' word1 ' });
517
testVim('dl_repeat', function(cm, vim, helpers) {
518
var curStart = makeCursor(0, 0);
519
cm.setCursor(curStart);
520
helpers.doKeys('2', 'd', 'l');
521
eq('ord1 ', cm.getValue());
522
var register = helpers.getRegisterController().getRegister();
523
eq(' w', register.text);
524
is(!register.linewise);
525
eqPos(curStart, cm.getCursor());
526
}, { value: ' word1 ' });
527
testVim('dh', function(cm, vim, helpers) {
528
var curStart = makeCursor(0, 3);
529
cm.setCursor(curStart);
530
helpers.doKeys('d', 'h');
531
eq(' wrd1 ', cm.getValue());
532
var register = helpers.getRegisterController().getRegister();
533
eq('o', register.text);
534
is(!register.linewise);
535
eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor());
536
}, { value: ' word1 ' });
537
testVim('dj', function(cm, vim, helpers) {
538
var curStart = makeCursor(0, 3);
539
cm.setCursor(curStart);
540
helpers.doKeys('d', 'j');
541
eq(' word3', cm.getValue());
542
var register = helpers.getRegisterController().getRegister();
543
eq(' word1\nword2\n', register.text);
544
is(register.linewise);
545
helpers.assertCursorAt(0, 1);
546
}, { value: ' word1\nword2\n word3' });
547
testVim('dj_end_of_document', function(cm, vim, helpers) {
548
var curStart = makeCursor(0, 3);
549
cm.setCursor(curStart);
550
helpers.doKeys('d', 'j');
551
eq(' word1 ', cm.getValue());
552
var register = helpers.getRegisterController().getRegister();
553
eq('', register.text);
554
is(!register.linewise);
555
helpers.assertCursorAt(0, 3);
556
}, { value: ' word1 ' });
557
testVim('dk', function(cm, vim, helpers) {
558
var curStart = makeCursor(1, 3);
559
cm.setCursor(curStart);
560
helpers.doKeys('d', 'k');
561
eq(' word3', cm.getValue());
562
var register = helpers.getRegisterController().getRegister();
563
eq(' word1\nword2\n', register.text);
564
is(register.linewise);
565
helpers.assertCursorAt(0, 1);
566
}, { value: ' word1\nword2\n word3' });
567
testVim('dk_start_of_document', function(cm, vim, helpers) {
568
var curStart = makeCursor(0, 3);
569
cm.setCursor(curStart);
570
helpers.doKeys('d', 'k');
571
eq(' word1 ', cm.getValue());
572
var register = helpers.getRegisterController().getRegister();
573
eq('', register.text);
574
is(!register.linewise);
575
helpers.assertCursorAt(0, 3);
576
}, { value: ' word1 ' });
577
testVim('dw_space', function(cm, vim, helpers) {
578
var curStart = makeCursor(0, 0);
579
cm.setCursor(curStart);
580
helpers.doKeys('d', 'w');
581
eq('word1 ', cm.getValue());
582
var register = helpers.getRegisterController().getRegister();
583
eq(' ', register.text);
584
is(!register.linewise);
585
eqPos(curStart, cm.getCursor());
586
}, { value: ' word1 ' });
587
testVim('dw_word', function(cm, vim, helpers) {
588
var curStart = makeCursor(0, 1);
589
cm.setCursor(curStart);
590
helpers.doKeys('d', 'w');
591
eq(' word2', cm.getValue());
592
var register = helpers.getRegisterController().getRegister();
593
eq('word1 ', register.text);
594
is(!register.linewise);
595
eqPos(curStart, cm.getCursor());
596
}, { value: ' word1 word2' });
597
testVim('dw_only_word', function(cm, vim, helpers) {
598
// Test that if there is only 1 word left, dw deletes till the end of the
599
// line.
600
cm.setCursor(0, 1);
601
helpers.doKeys('d', 'w');
602
eq(' ', cm.getValue());
603
var register = helpers.getRegisterController().getRegister();
604
eq('word1 ', register.text);
605
is(!register.linewise);
606
helpers.assertCursorAt(0, 0);
607
}, { value: ' word1 ' });
608
testVim('dw_eol', function(cm, vim, helpers) {
609
// Assert that dw does not delete the newline if last word to delete is at end
610
// of line.
611
cm.setCursor(0, 1);
612
helpers.doKeys('d', 'w');
613
eq(' \nword2', cm.getValue());
614
var register = helpers.getRegisterController().getRegister();
615
eq('word1', register.text);
616
is(!register.linewise);
617
helpers.assertCursorAt(0, 0);
618
}, { value: ' word1\nword2' });
619
testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {
620
// Assert that dw does not delete the newline if last word to delete is at end
621
// of line and it is followed by multiple newlines.
622
cm.setCursor(0, 1);
623
helpers.doKeys('d', 'w');
624
eq(' \n\nword2', cm.getValue());
625
var register = helpers.getRegisterController().getRegister();
626
eq('word1', register.text);
627
is(!register.linewise);
628
helpers.assertCursorAt(0, 0);
629
}, { value: ' word1\n\nword2' });
630
testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) {
631
cm.setCursor(0, 0);
632
helpers.doKeys('d', 'w');
633
eq(' \nword', cm.getValue());
634
}, { value: '\n \nword' });
635
testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) {
636
cm.setCursor(0, 0);
637
helpers.doKeys('d', 'w');
638
eq('word', cm.getValue());
639
}, { value: '\nword' });
640
testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) {
641
cm.setCursor(0, 0);
642
helpers.doKeys('d', 'w');
643
eq('\n', cm.getValue());
644
}, { value: '\n\n' });
645
testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) {
646
cm.setCursor(0, 0);
647
helpers.doKeys('d', 'w');
648
eq('\n \n', cm.getValue());
649
}, { value: ' \n \n' });
650
testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) {
651
cm.setCursor(0, 0);
652
helpers.doKeys('d', 'w');
653
eq('\n\n', cm.getValue());
654
}, { value: ' \n\n' });
655
testVim('dw_word_whitespace_word', function(cm, vim, helpers) {
656
cm.setCursor(0, 0);
657
helpers.doKeys('d', 'w');
658
eq('\n \nword2', cm.getValue());
659
}, { value: 'word1\n \nword2'})
660
testVim('dw_end_of_document', function(cm, vim, helpers) {
661
cm.setCursor(1, 2);
662
helpers.doKeys('d', 'w');
663
eq('\nab', cm.getValue());
664
}, { value: '\nabc' });
665
testVim('dw_repeat', function(cm, vim, helpers) {
666
// Assert that dw does delete newline if it should go to the next line, and
667
// that repeat works properly.
668
cm.setCursor(0, 1);
669
helpers.doKeys('d', '2', 'w');
670
eq(' ', cm.getValue());
671
var register = helpers.getRegisterController().getRegister();
672
eq('word1\nword2', register.text);
673
is(!register.linewise);
674
helpers.assertCursorAt(0, 0);
675
}, { value: ' word1\nword2' });
676
testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) {
677
cm.setCursor(0, 0);
678
helpers.doKeys('d', 'e');
679
eq('\n\n', cm.getValue());
680
}, { value: 'word\n\n' });
681
testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) {
682
cm.setCursor(0, 3);
683
helpers.doKeys('d', 'e');
684
eq('wor', cm.getValue());
685
}, { value: 'word\n\n\n' });
686
testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) {
687
cm.setCursor(0, 0);
688
helpers.doKeys('d', 'e');
689
eq('', cm.getValue());
690
}, { value: ' \n\n\n' });
691
testVim('de_end_of_document', function(cm, vim, helpers) {
692
cm.setCursor(1, 2);
693
helpers.doKeys('d', 'e');
694
eq('\nab', cm.getValue());
695
}, { value: '\nabc' });
696
testVim('db_empty_lines', function(cm, vim, helpers) {
697
cm.setCursor(2, 0);
698
helpers.doKeys('d', 'b');
699
eq('\n\n', cm.getValue());
700
}, { value: '\n\n\n' });
701
testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) {
702
cm.setCursor(2, 0);
703
helpers.doKeys('d', 'b');
704
eq('\nword', cm.getValue());
705
}, { value: '\n\nword' });
706
testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) {
707
cm.setCursor(2, 3);
708
helpers.doKeys('d', 'b');
709
eq('\n\nd', cm.getValue());
710
}, { value: '\n\nword' });
711
testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) {
712
cm.setCursor(2, 0);
713
helpers.doKeys('d', 'b');
714
eq('', cm.getValue());
715
}, { value: '\n \n' });
716
testVim('db_start_of_document', function(cm, vim, helpers) {
717
cm.setCursor(0, 0);
718
helpers.doKeys('d', 'b');
719
eq('abc\n', cm.getValue());
720
}, { value: 'abc\n' });
721
testVim('dge_empty_lines', function(cm, vim, helpers) {
722
cm.setCursor(1, 0);
723
helpers.doKeys('d', 'g', 'e');
724
// Note: In real VIM the result should be '', but it's not quite consistent,
725
// since 2 newlines are deleted. But in the similar case of word\n\n, only
726
// 1 newline is deleted. We'll diverge from VIM's behavior since it's much
727
// easier this way.
728
eq('\n', cm.getValue());
729
}, { value: '\n\n' });
730
testVim('dge_word_and_empty_lines', function(cm, vim, helpers) {
731
cm.setCursor(1, 0);
732
helpers.doKeys('d', 'g', 'e');
733
eq('wor\n', cm.getValue());
734
}, { value: 'word\n\n'});
735
testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) {
736
cm.setCursor(2, 0);
737
helpers.doKeys('d', 'g', 'e');
738
eq('', cm.getValue());
739
}, { value: '\n \n' });
740
testVim('dge_start_of_document', function(cm, vim, helpers) {
741
cm.setCursor(0, 0);
742
helpers.doKeys('d', 'g', 'e');
743
eq('bc\n', cm.getValue());
744
}, { value: 'abc\n' });
745
testVim('d_inclusive', function(cm, vim, helpers) {
746
// Assert that when inclusive is set, the character the cursor is on gets
747
// deleted too.
748
var curStart = makeCursor(0, 1);
749
cm.setCursor(curStart);
750
helpers.doKeys('d', 'e');
751
eq(' ', cm.getValue());
752
var register = helpers.getRegisterController().getRegister();
753
eq('word1', register.text);
754
is(!register.linewise);
755
eqPos(curStart, cm.getCursor());
756
}, { value: ' word1 ' });
757
testVim('d_reverse', function(cm, vim, helpers) {
758
// Test that deleting in reverse works.
759
cm.setCursor(1, 0);
760
helpers.doKeys('d', 'b');
761
eq(' word2 ', cm.getValue());
762
var register = helpers.getRegisterController().getRegister();
763
eq('word1\n', register.text);
764
is(!register.linewise);
765
helpers.assertCursorAt(0, 1);
766
}, { value: ' word1\nword2 ' });
767
testVim('dd', function(cm, vim, helpers) {
768
cm.setCursor(0, 3);
769
var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
770
{ line: 1, ch: 0 });
771
var expectedLineCount = cm.lineCount() - 1;
772
helpers.doKeys('d', 'd');
773
eq(expectedLineCount, cm.lineCount());
774
var register = helpers.getRegisterController().getRegister();
775
eq(expectedBuffer, register.text);
776
is(register.linewise);
777
helpers.assertCursorAt(0, lines[1].textStart);
778
});
779
testVim('dd_prefix_repeat', function(cm, vim, helpers) {
780
cm.setCursor(0, 3);
781
var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
782
{ line: 2, ch: 0 });
783
var expectedLineCount = cm.lineCount() - 2;
784
helpers.doKeys('2', 'd', 'd');
785
eq(expectedLineCount, cm.lineCount());
786
var register = helpers.getRegisterController().getRegister();
787
eq(expectedBuffer, register.text);
788
is(register.linewise);
789
helpers.assertCursorAt(0, lines[2].textStart);
790
});
791
testVim('dd_motion_repeat', function(cm, vim, helpers) {
792
cm.setCursor(0, 3);
793
var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
794
{ line: 2, ch: 0 });
795
var expectedLineCount = cm.lineCount() - 2;
796
helpers.doKeys('d', '2', 'd');
797
eq(expectedLineCount, cm.lineCount());
798
var register = helpers.getRegisterController().getRegister();
799
eq(expectedBuffer, register.text);
800
is(register.linewise);
801
helpers.assertCursorAt(0, lines[2].textStart);
802
});
803
testVim('dd_multiply_repeat', function(cm, vim, helpers) {
804
cm.setCursor(0, 3);
805
var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
806
{ line: 6, ch: 0 });
807
var expectedLineCount = cm.lineCount() - 6;
808
helpers.doKeys('2', 'd', '3', 'd');
809
eq(expectedLineCount, cm.lineCount());
810
var register = helpers.getRegisterController().getRegister();
811
eq(expectedBuffer, register.text);
812
is(register.linewise);
813
helpers.assertCursorAt(0, lines[6].textStart);
814
});
815
testVim('dd_lastline', function(cm, vim, helpers) {
816
cm.setCursor(cm.lineCount(), 0);
817
var expectedLineCount = cm.lineCount() - 1;
818
helpers.doKeys('d', 'd');
819
eq(expectedLineCount, cm.lineCount());
820
helpers.assertCursorAt(cm.lineCount() - 1, 0);
821
});
822
// Yank commands should behave the exact same as d commands, expect that nothing
823
// gets deleted.
824
testVim('yw_repeat', function(cm, vim, helpers) {
825
// Assert that yw does yank newline if it should go to the next line, and
826
// that repeat works properly.
827
var curStart = makeCursor(0, 1);
828
cm.setCursor(curStart);
829
helpers.doKeys('y', '2', 'w');
830
eq(' word1\nword2', cm.getValue());
831
var register = helpers.getRegisterController().getRegister();
832
eq('word1\nword2', register.text);
833
is(!register.linewise);
834
eqPos(curStart, cm.getCursor());
835
}, { value: ' word1\nword2' });
836
testVim('yy_multiply_repeat', function(cm, vim, helpers) {
837
var curStart = makeCursor(0, 3);
838
cm.setCursor(curStart);
839
var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
840
{ line: 6, ch: 0 });
841
var expectedLineCount = cm.lineCount();
842
helpers.doKeys('2', 'y', '3', 'y');
843
eq(expectedLineCount, cm.lineCount());
844
var register = helpers.getRegisterController().getRegister();
845
eq(expectedBuffer, register.text);
846
is(register.linewise);
847
eqPos(curStart, cm.getCursor());
848
});
849
// Change commands behave like d commands except that it also enters insert
850
// mode. In addition, when the change is linewise, an additional newline is
851
// inserted so that insert mode starts on that line.
852
testVim('cw', function(cm, vim, helpers) {
853
cm.setCursor(0, 0);
854
helpers.doKeys('c', '2', 'w');
855
eq(' word3', cm.getValue());
856
helpers.assertCursorAt(0, 0);
857
}, { value: 'word1 word2 word3'});
858
testVim('cw_repeat', function(cm, vim, helpers) {
859
// Assert that cw does delete newline if it should go to the next line, and
860
// that repeat works properly.
861
var curStart = makeCursor(0, 1);
862
cm.setCursor(curStart);
863
helpers.doKeys('c', '2', 'w');
864
eq(' ', cm.getValue());
865
var register = helpers.getRegisterController().getRegister();
866
eq('word1\nword2', register.text);
867
is(!register.linewise);
868
eqPos(curStart, cm.getCursor());
869
eq('vim-insert', cm.getOption('keyMap'));
870
}, { value: ' word1\nword2' });
871
testVim('cc_multiply_repeat', function(cm, vim, helpers) {
872
cm.setCursor(0, 3);
873
var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
874
{ line: 6, ch: 0 });
875
var expectedLineCount = cm.lineCount() - 5;
876
helpers.doKeys('2', 'c', '3', 'c');
877
eq(expectedLineCount, cm.lineCount());
878
var register = helpers.getRegisterController().getRegister();
879
eq(expectedBuffer, register.text);
880
is(register.linewise);
881
eq('vim-insert', cm.getOption('keyMap'));
882
});
883
testVim('cc_append', function(cm, vim, helpers) {
884
var expectedLineCount = cm.lineCount();
885
cm.setCursor(cm.lastLine(), 0);
886
helpers.doKeys('c', 'c');
887
eq(expectedLineCount, cm.lineCount());
888
});
889
// Swapcase commands edit in place and do not modify registers.
890
testVim('g~w_repeat', function(cm, vim, helpers) {
891
// Assert that dw does delete newline if it should go to the next line, and
892
// that repeat works properly.
893
var curStart = makeCursor(0, 1);
894
cm.setCursor(curStart);
895
helpers.doKeys('g', '~', '2', 'w');
896
eq(' WORD1\nWORD2', cm.getValue());
897
var register = helpers.getRegisterController().getRegister();
898
eq('', register.text);
899
is(!register.linewise);
900
eqPos(curStart, cm.getCursor());
901
}, { value: ' word1\nword2' });
902
testVim('g~g~', function(cm, vim, helpers) {
903
var curStart = makeCursor(0, 3);
904
cm.setCursor(curStart);
905
var expectedLineCount = cm.lineCount();
906
var expectedValue = cm.getValue().toUpperCase();
907
helpers.doKeys('2', 'g', '~', '3', 'g', '~');
908
eq(expectedValue, cm.getValue());
909
var register = helpers.getRegisterController().getRegister();
910
eq('', register.text);
911
is(!register.linewise);
912
eqPos(curStart, cm.getCursor());
913
}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' });
914
testVim('>{motion}', function(cm, vim, helpers) {
915
cm.setCursor(1, 3);
916
var expectedLineCount = cm.lineCount();
917
var expectedValue = ' word1\n word2\nword3 ';
918
helpers.doKeys('>', 'k');
919
eq(expectedValue, cm.getValue());
920
var register = helpers.getRegisterController().getRegister();
921
eq('', register.text);
922
is(!register.linewise);
923
helpers.assertCursorAt(0, 3);
924
}, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
925
testVim('>>', function(cm, vim, helpers) {
926
cm.setCursor(0, 3);
927
var expectedLineCount = cm.lineCount();
928
var expectedValue = ' word1\n word2\nword3 ';
929
helpers.doKeys('2', '>', '>');
930
eq(expectedValue, cm.getValue());
931
var register = helpers.getRegisterController().getRegister();
932
eq('', register.text);
933
is(!register.linewise);
934
helpers.assertCursorAt(0, 3);
935
}, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
936
testVim('<{motion}', function(cm, vim, helpers) {
937
cm.setCursor(1, 3);
938
var expectedLineCount = cm.lineCount();
939
var expectedValue = ' word1\nword2\nword3 ';
940
helpers.doKeys('<', 'k');
941
eq(expectedValue, cm.getValue());
942
var register = helpers.getRegisterController().getRegister();
943
eq('', register.text);
944
is(!register.linewise);
945
helpers.assertCursorAt(0, 1);
946
}, { value: ' word1\n word2\nword3 ', indentUnit: 2 });
947
testVim('<<', function(cm, vim, helpers) {
948
cm.setCursor(0, 3);
949
var expectedLineCount = cm.lineCount();
950
var expectedValue = ' word1\nword2\nword3 ';
951
helpers.doKeys('2', '<', '<');
952
eq(expectedValue, cm.getValue());
953
var register = helpers.getRegisterController().getRegister();
954
eq('', register.text);
955
is(!register.linewise);
956
helpers.assertCursorAt(0, 1);
957
}, { value: ' word1\n word2\nword3 ', indentUnit: 2 });
958
959
// Edit tests
960
function testEdit(name, before, pos, edit, after) {
961
return testVim(name, function(cm, vim, helpers) {
962
cm.setCursor(0, before.search(pos));
963
helpers.doKeys.apply(this, edit.split(''));
964
eq(after, cm.getValue());
965
}, {value: before});
966
}
967
968
// These Delete tests effectively cover word-wise Change, Visual & Yank.
969
// Tabs are used as differentiated whitespace to catch edge cases.
970
// Normal word:
971
testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz');
972
testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz');
973
testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz');
974
testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz');
975
testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz');
976
testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz');
977
testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz');
978
testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz');
979
testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz');
980
testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz');
981
testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t');
982
testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo');
983
testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.');
984
testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.');
985
// Big word:
986
testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz');
987
testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz');
988
testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz');
989
testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz');
990
testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz');
991
testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz');
992
testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz');
993
testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz');
994
testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz');
995
testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz');
996
testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t');
997
testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo');
998
testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t');
999
testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo');
1000
1001
// Operator-motion tests
1002
testVim('D', function(cm, vim, helpers) {
1003
cm.setCursor(0, 3);
1004
helpers.doKeys('D');
1005
eq(' wo\nword2\n word3', cm.getValue());
1006
var register = helpers.getRegisterController().getRegister();
1007
eq('rd1', register.text);
1008
is(!register.linewise);
1009
helpers.assertCursorAt(0, 2);
1010
}, { value: ' word1\nword2\n word3' });
1011
testVim('C', function(cm, vim, helpers) {
1012
var curStart = makeCursor(0, 3);
1013
cm.setCursor(curStart);
1014
helpers.doKeys('C');
1015
eq(' wo\nword2\n word3', cm.getValue());
1016
var register = helpers.getRegisterController().getRegister();
1017
eq('rd1', register.text);
1018
is(!register.linewise);
1019
eqPos(curStart, cm.getCursor());
1020
eq('vim-insert', cm.getOption('keyMap'));
1021
}, { value: ' word1\nword2\n word3' });
1022
testVim('Y', function(cm, vim, helpers) {
1023
var curStart = makeCursor(0, 3);
1024
cm.setCursor(curStart);
1025
helpers.doKeys('Y');
1026
eq(' word1\nword2\n word3', cm.getValue());
1027
var register = helpers.getRegisterController().getRegister();
1028
eq('rd1', register.text);
1029
is(!register.linewise);
1030
helpers.assertCursorAt(0, 3);
1031
}, { value: ' word1\nword2\n word3' });
1032
testVim('~', function(cm, vim, helpers) {
1033
helpers.doKeys('3', '~');
1034
eq('ABCdefg', cm.getValue());
1035
helpers.assertCursorAt(0, 3);
1036
}, { value: 'abcdefg' });
1037
1038
// Action tests
1039
testVim('ctrl-a', function(cm, vim, helpers) {
1040
cm.setCursor(0, 0);
1041
helpers.doKeys('<C-a>');
1042
eq('-9', cm.getValue());
1043
helpers.assertCursorAt(0, 1);
1044
helpers.doKeys('2','<C-a>');
1045
eq('-7', cm.getValue());
1046
}, {value: '-10'});
1047
testVim('ctrl-x', function(cm, vim, helpers) {
1048
cm.setCursor(0, 0);
1049
helpers.doKeys('<C-x>');
1050
eq('-1', cm.getValue());
1051
helpers.assertCursorAt(0, 1);
1052
helpers.doKeys('2','<C-x>');
1053
eq('-3', cm.getValue());
1054
}, {value: '0'});
1055
testVim('<C-x>/<C-a> search forward', function(cm, vim, helpers) {
1056
forEach(['<C-x>', '<C-a>'], function(key) {
1057
cm.setCursor(0, 0);
1058
helpers.doKeys(key);
1059
helpers.assertCursorAt(0, 5);
1060
helpers.doKeys('l');
1061
helpers.doKeys(key);
1062
helpers.assertCursorAt(0, 10);
1063
cm.setCursor(0, 11);
1064
helpers.doKeys(key);
1065
helpers.assertCursorAt(0, 11);
1066
});
1067
}, {value: '__jmp1 jmp2 jmp'});
1068
testVim('a', function(cm, vim, helpers) {
1069
cm.setCursor(0, 1);
1070
helpers.doKeys('a');
1071
helpers.assertCursorAt(0, 2);
1072
eq('vim-insert', cm.getOption('keyMap'));
1073
});
1074
testVim('a_eol', function(cm, vim, helpers) {
1075
cm.setCursor(0, lines[0].length - 1);
1076
helpers.doKeys('a');
1077
helpers.assertCursorAt(0, lines[0].length);
1078
eq('vim-insert', cm.getOption('keyMap'));
1079
});
1080
testVim('i', function(cm, vim, helpers) {
1081
cm.setCursor(0, 1);
1082
helpers.doKeys('i');
1083
helpers.assertCursorAt(0, 1);
1084
eq('vim-insert', cm.getOption('keyMap'));
1085
});
1086
testVim('i_repeat', function(cm, vim, helpers) {
1087
helpers.doKeys('3', 'i');
1088
cm.replaceRange('test', cm.getCursor());
1089
helpers.doInsertModeKeys('Esc');
1090
eq('testtesttest', cm.getValue());
1091
helpers.assertCursorAt(0, 11);
1092
}, { value: '' });
1093
testVim('i_repeat_delete', function(cm, vim, helpers) {
1094
cm.setCursor(0, 4);
1095
helpers.doKeys('2', 'i');
1096
cm.replaceRange('z', cm.getCursor());
1097
helpers.doInsertModeKeys('Backspace', 'Backspace', 'Esc');
1098
eq('abe', cm.getValue());
1099
helpers.assertCursorAt(0, 1);
1100
}, { value: 'abcde' });
1101
testVim('A', function(cm, vim, helpers) {
1102
helpers.doKeys('A');
1103
helpers.assertCursorAt(0, lines[0].length);
1104
eq('vim-insert', cm.getOption('keyMap'));
1105
});
1106
testVim('I', function(cm, vim, helpers) {
1107
cm.setCursor(0, 4);
1108
helpers.doKeys('I');
1109
helpers.assertCursorAt(0, lines[0].textStart);
1110
eq('vim-insert', cm.getOption('keyMap'));
1111
});
1112
testVim('I_repeat', function(cm, vim, helpers) {
1113
cm.setCursor(0, 1);
1114
helpers.doKeys('3', 'I');
1115
cm.replaceRange('test', cm.getCursor());
1116
helpers.doInsertModeKeys('Esc');
1117
eq('testtesttestblah', cm.getValue());
1118
helpers.assertCursorAt(0, 11);
1119
}, { value: 'blah' });
1120
testVim('o', function(cm, vim, helpers) {
1121
cm.setCursor(0, 4);
1122
helpers.doKeys('o');
1123
eq('word1\n\nword2', cm.getValue());
1124
helpers.assertCursorAt(1, 0);
1125
eq('vim-insert', cm.getOption('keyMap'));
1126
}, { value: 'word1\nword2' });
1127
testVim('o_repeat', function(cm, vim, helpers) {
1128
cm.setCursor(0, 0);
1129
helpers.doKeys('3', 'o');
1130
cm.replaceRange('test', cm.getCursor());
1131
helpers.doInsertModeKeys('Esc');
1132
eq('\ntest\ntest\ntest', cm.getValue());
1133
helpers.assertCursorAt(3, 3);
1134
}, { value: '' });
1135
testVim('O', function(cm, vim, helpers) {
1136
cm.setCursor(0, 4);
1137
helpers.doKeys('O');
1138
eq('\nword1\nword2', cm.getValue());
1139
helpers.assertCursorAt(0, 0);
1140
eq('vim-insert', cm.getOption('keyMap'));
1141
}, { value: 'word1\nword2' });
1142
testVim('J', function(cm, vim, helpers) {
1143
cm.setCursor(0, 4);
1144
helpers.doKeys('J');
1145
var expectedValue = 'word1 word2\nword3\n word4';
1146
eq(expectedValue, cm.getValue());
1147
helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1);
1148
}, { value: 'word1 \n word2\nword3\n word4' });
1149
testVim('J_repeat', function(cm, vim, helpers) {
1150
cm.setCursor(0, 4);
1151
helpers.doKeys('3', 'J');
1152
var expectedValue = 'word1 word2 word3\n word4';
1153
eq(expectedValue, cm.getValue());
1154
helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1);
1155
}, { value: 'word1 \n word2\nword3\n word4' });
1156
testVim('p', function(cm, vim, helpers) {
1157
cm.setCursor(0, 1);
1158
helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
1159
helpers.doKeys('p');
1160
eq('__abc\ndef_', cm.getValue());
1161
helpers.assertCursorAt(1, 2);
1162
}, { value: '___' });
1163
testVim('p_register', function(cm, vim, helpers) {
1164
cm.setCursor(0, 1);
1165
helpers.getRegisterController().getRegister('a').set('abc\ndef', false);
1166
helpers.doKeys('"', 'a', 'p');
1167
eq('__abc\ndef_', cm.getValue());
1168
helpers.assertCursorAt(1, 2);
1169
}, { value: '___' });
1170
testVim('p_wrong_register', function(cm, vim, helpers) {
1171
cm.setCursor(0, 1);
1172
helpers.getRegisterController().getRegister('a').set('abc\ndef', false);
1173
helpers.doKeys('p');
1174
eq('___', cm.getValue());
1175
helpers.assertCursorAt(0, 1);
1176
}, { value: '___' });
1177
testVim('p_line', function(cm, vim, helpers) {
1178
cm.setCursor(0, 1);
1179
helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);
1180
helpers.doKeys('2', 'p');
1181
eq('___\n a\nd\n a\nd', cm.getValue());
1182
helpers.assertCursorAt(1, 2);
1183
}, { value: '___' });
1184
testVim('p_lastline', function(cm, vim, helpers) {
1185
cm.setCursor(0, 1);
1186
helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true);
1187
helpers.doKeys('2', 'p');
1188
eq('___\n a\nd\n a\nd', cm.getValue());
1189
helpers.assertCursorAt(1, 2);
1190
}, { value: '___' });
1191
testVim('P', function(cm, vim, helpers) {
1192
cm.setCursor(0, 1);
1193
helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
1194
helpers.doKeys('P');
1195
eq('_abc\ndef__', cm.getValue());
1196
helpers.assertCursorAt(1, 3);
1197
}, { value: '___' });
1198
testVim('P_line', function(cm, vim, helpers) {
1199
cm.setCursor(0, 1);
1200
helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);
1201
helpers.doKeys('2', 'P');
1202
eq(' a\nd\n a\nd\n___', cm.getValue());
1203
helpers.assertCursorAt(0, 2);
1204
}, { value: '___' });
1205
testVim('r', function(cm, vim, helpers) {
1206
cm.setCursor(0, 1);
1207
helpers.doKeys('3', 'r', 'u');
1208
eq('wuuuet\nanother', cm.getValue(),'3r failed');
1209
helpers.assertCursorAt(0, 3);
1210
cm.setCursor(0, 4);
1211
helpers.doKeys('v', 'j', 'h', 'r', '<Space>');
1212
eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed');
1213
}, { value: 'wordet\nanother' });
1214
testVim('R', function(cm, vim, helpers) {
1215
cm.setCursor(0, 1);
1216
helpers.doKeys('R');
1217
helpers.assertCursorAt(0, 1);
1218
eq('vim-replace', cm.getOption('keyMap'));
1219
is(cm.state.overwrite, 'Setting overwrite state failed');
1220
});
1221
testVim('mark', function(cm, vim, helpers) {
1222
cm.setCursor(2, 2);
1223
helpers.doKeys('m', 't');
1224
cm.setCursor(0, 0);
1225
helpers.doKeys('\'', 't');
1226
helpers.assertCursorAt(2, 2);
1227
cm.setCursor(0, 0);
1228
helpers.doKeys('`', 't');
1229
helpers.assertCursorAt(2, 2);
1230
});
1231
testVim('jumpToMark_next', function(cm, vim, helpers) {
1232
cm.setCursor(2, 2);
1233
helpers.doKeys('m', 't');
1234
cm.setCursor(0, 0);
1235
helpers.doKeys(']', '`');
1236
helpers.assertCursorAt(2, 2);
1237
cm.setCursor(0, 0);
1238
helpers.doKeys(']', '\'');
1239
helpers.assertCursorAt(2, 0);
1240
});
1241
testVim('jumpToMark_next_repeat', function(cm, vim, helpers) {
1242
cm.setCursor(2, 2);
1243
helpers.doKeys('m', 'a');
1244
cm.setCursor(3, 2);
1245
helpers.doKeys('m', 'b');
1246
cm.setCursor(4, 2);
1247
helpers.doKeys('m', 'c');
1248
cm.setCursor(0, 0);
1249
helpers.doKeys('2', ']', '`');
1250
helpers.assertCursorAt(3, 2);
1251
cm.setCursor(0, 0);
1252
helpers.doKeys('2', ']', '\'');
1253
helpers.assertCursorAt(3, 1);
1254
});
1255
testVim('jumpToMark_next_sameline', function(cm, vim, helpers) {
1256
cm.setCursor(2, 0);
1257
helpers.doKeys('m', 'a');
1258
cm.setCursor(2, 4);
1259
helpers.doKeys('m', 'b');
1260
cm.setCursor(2, 2);
1261
helpers.doKeys(']', '`');
1262
helpers.assertCursorAt(2, 4);
1263
});
1264
testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) {
1265
cm.setCursor(2, 0);
1266
helpers.doKeys('m', 'a');
1267
cm.setCursor(4, 0);
1268
helpers.doKeys(']', '`');
1269
helpers.assertCursorAt(4, 0);
1270
});
1271
testVim('jumpToMark_next_nomark', function(cm, vim, helpers) {
1272
cm.setCursor(2, 2);
1273
helpers.doKeys(']', '`');
1274
helpers.assertCursorAt(2, 2);
1275
helpers.doKeys(']', '\'');
1276
helpers.assertCursorAt(2, 0);
1277
});
1278
testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) {
1279
cm.setCursor(2, 2);
1280
helpers.doKeys('m', 'a');
1281
cm.setCursor(3, 4);
1282
helpers.doKeys('m', 'b');
1283
cm.setCursor(2, 1);
1284
helpers.doKeys(']', '\'');
1285
helpers.assertCursorAt(3, 1);
1286
});
1287
testVim('jumpToMark_next_action', function(cm, vim, helpers) {
1288
cm.setCursor(2, 2);
1289
helpers.doKeys('m', 't');
1290
cm.setCursor(0, 0);
1291
helpers.doKeys('d', ']', '`');
1292
helpers.assertCursorAt(0, 0);
1293
var actual = cm.getLine(0);
1294
var expected = 'pop pop 0 1 2 3 4';
1295
eq(actual, expected, "Deleting while jumping to the next mark failed.");
1296
});
1297
testVim('jumpToMark_next_line_action', function(cm, vim, helpers) {
1298
cm.setCursor(2, 2);
1299
helpers.doKeys('m', 't');
1300
cm.setCursor(0, 0);
1301
helpers.doKeys('d', ']', '\'');
1302
helpers.assertCursorAt(0, 1);
1303
var actual = cm.getLine(0);
1304
var expected = ' (a) [b] {c} '
1305
eq(actual, expected, "Deleting while jumping to the next mark line failed.");
1306
});
1307
testVim('jumpToMark_prev', function(cm, vim, helpers) {
1308
cm.setCursor(2, 2);
1309
helpers.doKeys('m', 't');
1310
cm.setCursor(4, 0);
1311
helpers.doKeys('[', '`');
1312
helpers.assertCursorAt(2, 2);
1313
cm.setCursor(4, 0);
1314
helpers.doKeys('[', '\'');
1315
helpers.assertCursorAt(2, 0);
1316
});
1317
testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) {
1318
cm.setCursor(2, 2);
1319
helpers.doKeys('m', 'a');
1320
cm.setCursor(3, 2);
1321
helpers.doKeys('m', 'b');
1322
cm.setCursor(4, 2);
1323
helpers.doKeys('m', 'c');
1324
cm.setCursor(5, 0);
1325
helpers.doKeys('2', '[', '`');
1326
helpers.assertCursorAt(3, 2);
1327
cm.setCursor(5, 0);
1328
helpers.doKeys('2', '[', '\'');
1329
helpers.assertCursorAt(3, 1);
1330
});
1331
testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) {
1332
cm.setCursor(2, 0);
1333
helpers.doKeys('m', 'a');
1334
cm.setCursor(2, 4);
1335
helpers.doKeys('m', 'b');
1336
cm.setCursor(2, 2);
1337
helpers.doKeys('[', '`');
1338
helpers.assertCursorAt(2, 0);
1339
});
1340
testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) {
1341
cm.setCursor(4, 4);
1342
helpers.doKeys('m', 'a');
1343
cm.setCursor(2, 0);
1344
helpers.doKeys('[', '`');
1345
helpers.assertCursorAt(2, 0);
1346
});
1347
testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) {
1348
cm.setCursor(2, 2);
1349
helpers.doKeys('[', '`');
1350
helpers.assertCursorAt(2, 2);
1351
helpers.doKeys('[', '\'');
1352
helpers.assertCursorAt(2, 0);
1353
});
1354
testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) {
1355
cm.setCursor(2, 2);
1356
helpers.doKeys('m', 'a');
1357
cm.setCursor(3, 4);
1358
helpers.doKeys('m', 'b');
1359
cm.setCursor(3, 6);
1360
helpers.doKeys('[', '\'');
1361
helpers.assertCursorAt(2, 0);
1362
});
1363
testVim('delmark_single', function(cm, vim, helpers) {
1364
cm.setCursor(1, 2);
1365
helpers.doKeys('m', 't');
1366
helpers.doEx('delmarks t');
1367
cm.setCursor(0, 0);
1368
helpers.doKeys('`', 't');
1369
helpers.assertCursorAt(0, 0);
1370
});
1371
testVim('delmark_range', function(cm, vim, helpers) {
1372
cm.setCursor(1, 2);
1373
helpers.doKeys('m', 'a');
1374
cm.setCursor(2, 2);
1375
helpers.doKeys('m', 'b');
1376
cm.setCursor(3, 2);
1377
helpers.doKeys('m', 'c');
1378
cm.setCursor(4, 2);
1379
helpers.doKeys('m', 'd');
1380
cm.setCursor(5, 2);
1381
helpers.doKeys('m', 'e');
1382
helpers.doEx('delmarks b-d');
1383
cm.setCursor(0, 0);
1384
helpers.doKeys('`', 'a');
1385
helpers.assertCursorAt(1, 2);
1386
helpers.doKeys('`', 'b');
1387
helpers.assertCursorAt(1, 2);
1388
helpers.doKeys('`', 'c');
1389
helpers.assertCursorAt(1, 2);
1390
helpers.doKeys('`', 'd');
1391
helpers.assertCursorAt(1, 2);
1392
helpers.doKeys('`', 'e');
1393
helpers.assertCursorAt(5, 2);
1394
});
1395
testVim('delmark_multi', function(cm, vim, helpers) {
1396
cm.setCursor(1, 2);
1397
helpers.doKeys('m', 'a');
1398
cm.setCursor(2, 2);
1399
helpers.doKeys('m', 'b');
1400
cm.setCursor(3, 2);
1401
helpers.doKeys('m', 'c');
1402
cm.setCursor(4, 2);
1403
helpers.doKeys('m', 'd');
1404
cm.setCursor(5, 2);
1405
helpers.doKeys('m', 'e');
1406
helpers.doEx('delmarks bcd');
1407
cm.setCursor(0, 0);
1408
helpers.doKeys('`', 'a');
1409
helpers.assertCursorAt(1, 2);
1410
helpers.doKeys('`', 'b');
1411
helpers.assertCursorAt(1, 2);
1412
helpers.doKeys('`', 'c');
1413
helpers.assertCursorAt(1, 2);
1414
helpers.doKeys('`', 'd');
1415
helpers.assertCursorAt(1, 2);
1416
helpers.doKeys('`', 'e');
1417
helpers.assertCursorAt(5, 2);
1418
});
1419
testVim('delmark_multi_space', 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 c 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_all', 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 a b-de');
1455
cm.setCursor(0, 0);
1456
helpers.doKeys('`', 'a');
1457
helpers.assertCursorAt(0, 0);
1458
helpers.doKeys('`', 'b');
1459
helpers.assertCursorAt(0, 0);
1460
helpers.doKeys('`', 'c');
1461
helpers.assertCursorAt(0, 0);
1462
helpers.doKeys('`', 'd');
1463
helpers.assertCursorAt(0, 0);
1464
helpers.doKeys('`', 'e');
1465
helpers.assertCursorAt(0, 0);
1466
});
1467
testVim('visual', function(cm, vim, helpers) {
1468
helpers.doKeys('l', 'v', 'l', 'l');
1469
helpers.assertCursorAt(0, 3);
1470
eqPos(makeCursor(0, 1), cm.getCursor('anchor'));
1471
helpers.doKeys('d');
1472
eq('15', cm.getValue());
1473
}, { value: '12345' });
1474
testVim('visual_line', function(cm, vim, helpers) {
1475
helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd');
1476
eq(' 4\n 5', cm.getValue());
1477
}, { value: ' 1\n 2\n 3\n 4\n 5' });
1478
testVim('visual_marks', function(cm, vim, helpers) {
1479
helpers.doKeys('l', 'v', 'l', 'l', 'v');
1480
// Test visual mode marks
1481
cm.setCursor(0, 0);
1482
helpers.doKeys('\'', '<');
1483
helpers.assertCursorAt(0, 1);
1484
helpers.doKeys('\'', '>');
1485
helpers.assertCursorAt(0, 3);
1486
});
1487
testVim('visual_join', function(cm, vim, helpers) {
1488
helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J');
1489
eq(' 1 2 3\n 4\n 5', cm.getValue());
1490
}, { value: ' 1\n 2\n 3\n 4\n 5' });
1491
testVim('visual_blank', function(cm, vim, helpers) {
1492
helpers.doKeys('v', 'k');
1493
eq(vim.visualMode, true);
1494
}, { value: '\n' });
1495
testVim('s_normal', function(cm, vim, helpers) {
1496
cm.setCursor(0, 1);
1497
helpers.doKeys('s');
1498
helpers.doInsertModeKeys('Esc');
1499
helpers.assertCursorAt(0, 0);
1500
eq('ac', cm.getValue());
1501
}, { value: 'abc'});
1502
testVim('s_visual', function(cm, vim, helpers) {
1503
cm.setCursor(0, 1);
1504
helpers.doKeys('v', 's');
1505
helpers.doInsertModeKeys('Esc');
1506
helpers.assertCursorAt(0, 0);
1507
eq('ac', cm.getValue());
1508
}, { value: 'abc'});
1509
testVim('S_normal', function(cm, vim, helpers) {
1510
cm.setCursor(0, 1);
1511
helpers.doKeys('j', 'S');
1512
helpers.doInsertModeKeys('Esc');
1513
helpers.assertCursorAt(1, 0);
1514
eq('aa\n\ncc', cm.getValue());
1515
}, { value: 'aa\nbb\ncc'});
1516
testVim('S_visual', function(cm, vim, helpers) {
1517
cm.setCursor(0, 1);
1518
helpers.doKeys('v', 'j', 'S');
1519
helpers.doInsertModeKeys('Esc');
1520
helpers.assertCursorAt(0, 0);
1521
eq('\ncc', cm.getValue());
1522
}, { value: 'aa\nbb\ncc'});
1523
testVim('/ and n/N', function(cm, vim, helpers) {
1524
cm.openDialog = helpers.fakeOpenDialog('match');
1525
helpers.doKeys('/');
1526
helpers.assertCursorAt(0, 11);
1527
helpers.doKeys('n');
1528
helpers.assertCursorAt(1, 6);
1529
helpers.doKeys('N');
1530
helpers.assertCursorAt(0, 11);
1531
1532
cm.setCursor(0, 0);
1533
helpers.doKeys('2', '/');
1534
helpers.assertCursorAt(1, 6);
1535
}, { value: 'match nope match \n nope Match' });
1536
testVim('/_case', function(cm, vim, helpers) {
1537
cm.openDialog = helpers.fakeOpenDialog('Match');
1538
helpers.doKeys('/');
1539
helpers.assertCursorAt(1, 6);
1540
}, { value: 'match nope match \n nope Match' });
1541
testVim('/_nongreedy', function(cm, vim, helpers) {
1542
cm.openDialog = helpers.fakeOpenDialog('aa');
1543
helpers.doKeys('/');
1544
helpers.assertCursorAt(0, 4);
1545
helpers.doKeys('n');
1546
helpers.assertCursorAt(1, 3);
1547
helpers.doKeys('n');
1548
helpers.assertCursorAt(0, 0);
1549
}, { value: 'aaa aa \n a aa'});
1550
testVim('?_nongreedy', function(cm, vim, helpers) {
1551
cm.openDialog = helpers.fakeOpenDialog('aa');
1552
helpers.doKeys('?');
1553
helpers.assertCursorAt(1, 3);
1554
helpers.doKeys('n');
1555
helpers.assertCursorAt(0, 4);
1556
helpers.doKeys('n');
1557
helpers.assertCursorAt(0, 0);
1558
}, { value: 'aaa aa \n a aa'});
1559
testVim('/_greedy', function(cm, vim, helpers) {
1560
cm.openDialog = helpers.fakeOpenDialog('a+');
1561
helpers.doKeys('/');
1562
helpers.assertCursorAt(0, 4);
1563
helpers.doKeys('n');
1564
helpers.assertCursorAt(1, 1);
1565
helpers.doKeys('n');
1566
helpers.assertCursorAt(1, 3);
1567
helpers.doKeys('n');
1568
helpers.assertCursorAt(0, 0);
1569
}, { value: 'aaa aa \n a aa'});
1570
testVim('?_greedy', function(cm, vim, helpers) {
1571
cm.openDialog = helpers.fakeOpenDialog('a+');
1572
helpers.doKeys('?');
1573
helpers.assertCursorAt(1, 3);
1574
helpers.doKeys('n');
1575
helpers.assertCursorAt(1, 1);
1576
helpers.doKeys('n');
1577
helpers.assertCursorAt(0, 4);
1578
helpers.doKeys('n');
1579
helpers.assertCursorAt(0, 0);
1580
}, { value: 'aaa aa \n a aa'});
1581
testVim('/_greedy_0_or_more', function(cm, vim, helpers) {
1582
cm.openDialog = helpers.fakeOpenDialog('a*');
1583
helpers.doKeys('/');
1584
helpers.assertCursorAt(0, 3);
1585
helpers.doKeys('n');
1586
helpers.assertCursorAt(0, 4);
1587
helpers.doKeys('n');
1588
helpers.assertCursorAt(0, 5);
1589
helpers.doKeys('n');
1590
helpers.assertCursorAt(1, 0);
1591
helpers.doKeys('n');
1592
helpers.assertCursorAt(1, 1);
1593
helpers.doKeys('n');
1594
helpers.assertCursorAt(0, 0);
1595
}, { value: 'aaa aa\n aa'});
1596
testVim('?_greedy_0_or_more', function(cm, vim, helpers) {
1597
cm.openDialog = helpers.fakeOpenDialog('a*');
1598
helpers.doKeys('?');
1599
helpers.assertCursorAt(1, 1);
1600
helpers.doKeys('n');
1601
helpers.assertCursorAt(1, 0);
1602
helpers.doKeys('n');
1603
helpers.assertCursorAt(0, 5);
1604
helpers.doKeys('n');
1605
helpers.assertCursorAt(0, 4);
1606
helpers.doKeys('n');
1607
helpers.assertCursorAt(0, 3);
1608
helpers.doKeys('n');
1609
helpers.assertCursorAt(0, 0);
1610
}, { value: 'aaa aa\n aa'});
1611
testVim('? and n/N', function(cm, vim, helpers) {
1612
cm.openDialog = helpers.fakeOpenDialog('match');
1613
helpers.doKeys('?');
1614
helpers.assertCursorAt(1, 6);
1615
helpers.doKeys('n');
1616
helpers.assertCursorAt(0, 11);
1617
helpers.doKeys('N');
1618
helpers.assertCursorAt(1, 6);
1619
1620
cm.setCursor(0, 0);
1621
helpers.doKeys('2', '?');
1622
helpers.assertCursorAt(0, 11);
1623
}, { value: 'match nope match \n nope Match' });
1624
testVim('*', function(cm, vim, helpers) {
1625
cm.setCursor(0, 9);
1626
helpers.doKeys('*');
1627
helpers.assertCursorAt(0, 22);
1628
1629
cm.setCursor(0, 9);
1630
helpers.doKeys('2', '*');
1631
helpers.assertCursorAt(1, 8);
1632
}, { value: 'nomatch match nomatch match \nnomatch Match' });
1633
testVim('*_no_word', function(cm, vim, helpers) {
1634
cm.setCursor(0, 0);
1635
helpers.doKeys('*');
1636
helpers.assertCursorAt(0, 0);
1637
}, { value: ' \n match \n' });
1638
testVim('*_symbol', function(cm, vim, helpers) {
1639
cm.setCursor(0, 0);
1640
helpers.doKeys('*');
1641
helpers.assertCursorAt(1, 0);
1642
}, { value: ' /}\n/} match \n' });
1643
testVim('#', function(cm, vim, helpers) {
1644
cm.setCursor(0, 9);
1645
helpers.doKeys('#');
1646
helpers.assertCursorAt(1, 8);
1647
1648
cm.setCursor(0, 9);
1649
helpers.doKeys('2', '#');
1650
helpers.assertCursorAt(0, 22);
1651
}, { value: 'nomatch match nomatch match \nnomatch Match' });
1652
testVim('*_seek', function(cm, vim, helpers) {
1653
// Should skip over space and symbols.
1654
cm.setCursor(0, 3);
1655
helpers.doKeys('*');
1656
helpers.assertCursorAt(0, 22);
1657
}, { value: ' := match nomatch match \nnomatch Match' });
1658
testVim('#', function(cm, vim, helpers) {
1659
// Should skip over space and symbols.
1660
cm.setCursor(0, 3);
1661
helpers.doKeys('#');
1662
helpers.assertCursorAt(1, 8);
1663
}, { value: ' := match nomatch match \nnomatch Match' });
1664
testVim('.', function(cm, vim, helpers) {
1665
cm.setCursor(0, 0);
1666
helpers.doKeys('2', 'd', 'w');
1667
helpers.doKeys('.');
1668
eq('5 6', cm.getValue());
1669
}, { value: '1 2 3 4 5 6'});
1670
testVim('._repeat', function(cm, vim, helpers) {
1671
cm.setCursor(0, 0);
1672
helpers.doKeys('2', 'd', 'w');
1673
helpers.doKeys('3', '.');
1674
eq('6', cm.getValue());
1675
}, { value: '1 2 3 4 5 6'});
1676
testVim('._insert', function(cm, vim, helpers) {
1677
helpers.doKeys('i');
1678
cm.replaceRange('test', cm.getCursor());
1679
helpers.doInsertModeKeys('Esc');
1680
helpers.doKeys('.');
1681
eq('testestt', cm.getValue());
1682
helpers.assertCursorAt(0, 6);
1683
}, { value: ''});
1684
testVim('._insert_repeat', function(cm, vim, helpers) {
1685
helpers.doKeys('i');
1686
cm.replaceRange('test', cm.getCursor());
1687
cm.setCursor(0, 4);
1688
helpers.doInsertModeKeys('Esc');
1689
helpers.doKeys('2', '.');
1690
eq('testesttestt', cm.getValue());
1691
helpers.assertCursorAt(0, 10);
1692
}, { value: ''});
1693
testVim('._repeat_insert', function(cm, vim, helpers) {
1694
helpers.doKeys('3', 'i');
1695
cm.replaceRange('te', cm.getCursor());
1696
cm.setCursor(0, 2);
1697
helpers.doInsertModeKeys('Esc');
1698
helpers.doKeys('.');
1699
eq('tetettetetee', cm.getValue());
1700
helpers.assertCursorAt(0, 10);
1701
}, { value: ''});
1702
testVim('._insert_o', function(cm, vim, helpers) {
1703
helpers.doKeys('o');
1704
cm.replaceRange('z', cm.getCursor());
1705
cm.setCursor(1, 1);
1706
helpers.doInsertModeKeys('Esc');
1707
helpers.doKeys('.');
1708
eq('\nz\nz', cm.getValue());
1709
helpers.assertCursorAt(2, 0);
1710
}, { value: ''});
1711
testVim('._insert_o_repeat', function(cm, vim, helpers) {
1712
helpers.doKeys('o');
1713
cm.replaceRange('z', cm.getCursor());
1714
helpers.doInsertModeKeys('Esc');
1715
cm.setCursor(1, 0);
1716
helpers.doKeys('2', '.');
1717
eq('\nz\nz\nz', cm.getValue());
1718
helpers.assertCursorAt(3, 0);
1719
}, { value: ''});
1720
testVim('._insert_o_indent', function(cm, vim, helpers) {
1721
helpers.doKeys('o');
1722
cm.replaceRange('z', cm.getCursor());
1723
helpers.doInsertModeKeys('Esc');
1724
cm.setCursor(1, 2);
1725
helpers.doKeys('.');
1726
eq('{\n z\n z', cm.getValue());
1727
helpers.assertCursorAt(2, 2);
1728
}, { value: '{'});
1729
testVim('._insert_cw', function(cm, vim, helpers) {
1730
helpers.doKeys('c', 'w');
1731
cm.replaceRange('test', cm.getCursor());
1732
helpers.doInsertModeKeys('Esc');
1733
cm.setCursor(0, 3);
1734
helpers.doKeys('2', 'l');
1735
helpers.doKeys('.');
1736
eq('test test word3', cm.getValue());
1737
helpers.assertCursorAt(0, 8);
1738
}, { value: 'word1 word2 word3' });
1739
testVim('._insert_cw_repeat', function(cm, vim, helpers) {
1740
// For some reason, repeat cw in desktop VIM will does not repeat insert mode
1741
// changes. Will conform to that behavior.
1742
helpers.doKeys('c', 'w');
1743
cm.replaceRange('test', cm.getCursor());
1744
helpers.doInsertModeKeys('Esc');
1745
cm.setCursor(0, 4);
1746
helpers.doKeys('l');
1747
helpers.doKeys('2', '.');
1748
eq('test test', cm.getValue());
1749
helpers.assertCursorAt(0, 8);
1750
}, { value: 'word1 word2 word3' });
1751
testVim('._delete', function(cm, vim, helpers) {
1752
cm.setCursor(0, 5);
1753
helpers.doKeys('i');
1754
helpers.doInsertModeKeys('Backspace', 'Esc');
1755
helpers.doKeys('.');
1756
eq('zace', cm.getValue());
1757
helpers.assertCursorAt(0, 1);
1758
}, { value: 'zabcde'});
1759
testVim('._delete_repeat', function(cm, vim, helpers) {
1760
cm.setCursor(0, 6);
1761
helpers.doKeys('i');
1762
helpers.doInsertModeKeys('Backspace', 'Esc');
1763
helpers.doKeys('2', '.');
1764
eq('zzce', cm.getValue());
1765
helpers.assertCursorAt(0, 1);
1766
}, { value: 'zzabcde'});
1767
testVim('f;', function(cm, vim, helpers) {
1768
cm.setCursor(0, 0);
1769
helpers.doKeys('f', 'x');
1770
helpers.doKeys(';');
1771
helpers.doKeys('2', ';');
1772
eq(9, cm.getCursor().ch);
1773
}, { value: '01x3xx678x'});
1774
testVim('F;', function(cm, vim, helpers) {
1775
cm.setCursor(0, 8);
1776
helpers.doKeys('F', 'x');
1777
helpers.doKeys(';');
1778
helpers.doKeys('2', ';');
1779
eq(2, cm.getCursor().ch);
1780
}, { value: '01x3xx6x8x'});
1781
testVim('t;', function(cm, vim, helpers) {
1782
cm.setCursor(0, 0);
1783
helpers.doKeys('t', 'x');
1784
helpers.doKeys(';');
1785
helpers.doKeys('2', ';');
1786
eq(8, cm.getCursor().ch);
1787
}, { value: '01x3xx678x'});
1788
testVim('T;', function(cm, vim, helpers) {
1789
cm.setCursor(0, 9);
1790
helpers.doKeys('T', 'x');
1791
helpers.doKeys(';');
1792
helpers.doKeys('2', ';');
1793
eq(2, cm.getCursor().ch);
1794
}, { value: '0xx3xx678x'});
1795
testVim('f,', function(cm, vim, helpers) {
1796
cm.setCursor(0, 6);
1797
helpers.doKeys('f', 'x');
1798
helpers.doKeys(',');
1799
helpers.doKeys('2', ',');
1800
eq(2, cm.getCursor().ch);
1801
}, { value: '01x3xx678x'});
1802
testVim('F,', function(cm, vim, helpers) {
1803
cm.setCursor(0, 3);
1804
helpers.doKeys('F', 'x');
1805
helpers.doKeys(',');
1806
helpers.doKeys('2', ',');
1807
eq(9, cm.getCursor().ch);
1808
}, { value: '01x3xx678x'});
1809
testVim('t,', function(cm, vim, helpers) {
1810
cm.setCursor(0, 6);
1811
helpers.doKeys('t', 'x');
1812
helpers.doKeys(',');
1813
helpers.doKeys('2', ',');
1814
eq(3, cm.getCursor().ch);
1815
}, { value: '01x3xx678x'});
1816
testVim('T,', function(cm, vim, helpers) {
1817
cm.setCursor(0, 4);
1818
helpers.doKeys('T', 'x');
1819
helpers.doKeys(',');
1820
helpers.doKeys('2', ',');
1821
eq(8, cm.getCursor().ch);
1822
}, { value: '01x3xx67xx'});
1823
testVim('fd,;', function(cm, vim, helpers) {
1824
cm.setCursor(0, 0);
1825
helpers.doKeys('f', '4');
1826
cm.setCursor(0, 0);
1827
helpers.doKeys('d', ';');
1828
eq('56789', cm.getValue());
1829
helpers.doKeys('u');
1830
cm.setCursor(0, 9);
1831
helpers.doKeys('d', ',');
1832
eq('01239', cm.getValue());
1833
}, { value: '0123456789'});
1834
testVim('Fd,;', function(cm, vim, helpers) {
1835
cm.setCursor(0, 9);
1836
helpers.doKeys('F', '4');
1837
cm.setCursor(0, 9);
1838
helpers.doKeys('d', ';');
1839
eq('01239', cm.getValue());
1840
helpers.doKeys('u');
1841
cm.setCursor(0, 0);
1842
helpers.doKeys('d', ',');
1843
eq('56789', cm.getValue());
1844
}, { value: '0123456789'});
1845
testVim('td,;', function(cm, vim, helpers) {
1846
cm.setCursor(0, 0);
1847
helpers.doKeys('t', '4');
1848
cm.setCursor(0, 0);
1849
helpers.doKeys('d', ';');
1850
eq('456789', cm.getValue());
1851
helpers.doKeys('u');
1852
cm.setCursor(0, 9);
1853
helpers.doKeys('d', ',');
1854
eq('012349', cm.getValue());
1855
}, { value: '0123456789'});
1856
testVim('Td,;', function(cm, vim, helpers) {
1857
cm.setCursor(0, 9);
1858
helpers.doKeys('T', '4');
1859
cm.setCursor(0, 9);
1860
helpers.doKeys('d', ';');
1861
eq('012349', cm.getValue());
1862
helpers.doKeys('u');
1863
cm.setCursor(0, 0);
1864
helpers.doKeys('d', ',');
1865
eq('456789', cm.getValue());
1866
}, { value: '0123456789'});
1867
testVim('fc,;', function(cm, vim, helpers) {
1868
cm.setCursor(0, 0);
1869
helpers.doKeys('f', '4');
1870
cm.setCursor(0, 0);
1871
helpers.doKeys('c', ';', 'Esc');
1872
eq('56789', cm.getValue());
1873
helpers.doKeys('u');
1874
cm.setCursor(0, 9);
1875
helpers.doKeys('c', ',');
1876
eq('01239', cm.getValue());
1877
}, { value: '0123456789'});
1878
testVim('Fc,;', function(cm, vim, helpers) {
1879
cm.setCursor(0, 9);
1880
helpers.doKeys('F', '4');
1881
cm.setCursor(0, 9);
1882
helpers.doKeys('c', ';', 'Esc');
1883
eq('01239', cm.getValue());
1884
helpers.doKeys('u');
1885
cm.setCursor(0, 0);
1886
helpers.doKeys('c', ',');
1887
eq('56789', cm.getValue());
1888
}, { value: '0123456789'});
1889
testVim('tc,;', function(cm, vim, helpers) {
1890
cm.setCursor(0, 0);
1891
helpers.doKeys('t', '4');
1892
cm.setCursor(0, 0);
1893
helpers.doKeys('c', ';', 'Esc');
1894
eq('456789', cm.getValue());
1895
helpers.doKeys('u');
1896
cm.setCursor(0, 9);
1897
helpers.doKeys('c', ',');
1898
eq('012349', cm.getValue());
1899
}, { value: '0123456789'});
1900
testVim('Tc,;', function(cm, vim, helpers) {
1901
cm.setCursor(0, 9);
1902
helpers.doKeys('T', '4');
1903
cm.setCursor(0, 9);
1904
helpers.doKeys('c', ';', 'Esc');
1905
eq('012349', cm.getValue());
1906
helpers.doKeys('u');
1907
cm.setCursor(0, 0);
1908
helpers.doKeys('c', ',');
1909
eq('456789', cm.getValue());
1910
}, { value: '0123456789'});
1911
testVim('fy,;', function(cm, vim, helpers) {
1912
cm.setCursor(0, 0);
1913
helpers.doKeys('f', '4');
1914
cm.setCursor(0, 0);
1915
helpers.doKeys('y', ';', 'P');
1916
eq('012340123456789', cm.getValue());
1917
helpers.doKeys('u');
1918
cm.setCursor(0, 9);
1919
helpers.doKeys('y', ',', 'P');
1920
eq('012345678456789', cm.getValue());
1921
}, { value: '0123456789'});
1922
testVim('Fy,;', function(cm, vim, helpers) {
1923
cm.setCursor(0, 9);
1924
helpers.doKeys('F', '4');
1925
cm.setCursor(0, 9);
1926
helpers.doKeys('y', ';', 'p');
1927
eq('012345678945678', cm.getValue());
1928
helpers.doKeys('u');
1929
cm.setCursor(0, 0);
1930
helpers.doKeys('y', ',', 'P');
1931
eq('012340123456789', cm.getValue());
1932
}, { value: '0123456789'});
1933
testVim('ty,;', function(cm, vim, helpers) {
1934
cm.setCursor(0, 0);
1935
helpers.doKeys('t', '4');
1936
cm.setCursor(0, 0);
1937
helpers.doKeys('y', ';', 'P');
1938
eq('01230123456789', cm.getValue());
1939
helpers.doKeys('u');
1940
cm.setCursor(0, 9);
1941
helpers.doKeys('y', ',', 'p');
1942
eq('01234567895678', cm.getValue());
1943
}, { value: '0123456789'});
1944
testVim('Ty,;', function(cm, vim, helpers) {
1945
cm.setCursor(0, 9);
1946
helpers.doKeys('T', '4');
1947
cm.setCursor(0, 9);
1948
helpers.doKeys('y', ';', 'p');
1949
eq('01234567895678', cm.getValue());
1950
helpers.doKeys('u');
1951
cm.setCursor(0, 0);
1952
helpers.doKeys('y', ',', 'P');
1953
eq('01230123456789', cm.getValue());
1954
}, { value: '0123456789'});
1955
testVim('HML', function(cm, vim, helpers) {
1956
var lines = 35;
1957
var textHeight = cm.defaultTextHeight();
1958
cm.setSize(600, lines*textHeight);
1959
cm.setCursor(120, 0);
1960
helpers.doKeys('H');
1961
helpers.assertCursorAt(86, 2);
1962
helpers.doKeys('L');
1963
helpers.assertCursorAt(120, 4);
1964
helpers.doKeys('M');
1965
helpers.assertCursorAt(103,4);
1966
}, { value: (function(){
1967
var lines = new Array(100);
1968
var upper = ' xx\n';
1969
var lower = ' xx\n';
1970
upper = lines.join(upper);
1971
lower = lines.join(lower);
1972
return upper + lower;
1973
})()});
1974
1975
var zVals = ['zb','zz','zt','z-','z.','z<CR>'].map(function(e, idx){
1976
var lineNum = 250;
1977
var lines = 35;
1978
testVim(e, function(cm, vim, helpers) {
1979
var k1 = e[0];
1980
var k2 = e.substring(1);
1981
var textHeight = cm.defaultTextHeight();
1982
cm.setSize(600, lines*textHeight);
1983
cm.setCursor(lineNum, 0);
1984
helpers.doKeys(k1, k2);
1985
zVals[idx] = cm.getScrollInfo().top;
1986
}, { value: (function(){
1987
return new Array(500).join('\n');
1988
})()});
1989
});
1990
testVim('zb<zz', function(cm, vim, helpers){
1991
eq(zVals[0]<zVals[1], true);
1992
});
1993
testVim('zz<zt', function(cm, vim, helpers){
1994
eq(zVals[1]<zVals[2], true);
1995
});
1996
testVim('zb==z-', function(cm, vim, helpers){
1997
eq(zVals[0], zVals[3]);
1998
});
1999
testVim('zz==z.', function(cm, vim, helpers){
2000
eq(zVals[1], zVals[4]);
2001
});
2002
testVim('zt==z<CR>', function(cm, vim, helpers){
2003
eq(zVals[2], zVals[5]);
2004
});
2005
2006
var scrollMotionSandbox =
2007
'\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'
2008
'\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'
2009
'\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'
2010
'\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';
2011
testVim('scrollMotion', function(cm, vim, helpers){
2012
var prevCursor, prevScrollInfo;
2013
cm.setCursor(0, 0);
2014
// ctrl-y at the top of the file should have no effect.
2015
helpers.doKeys('<C-y>');
2016
eq(0, cm.getCursor().line);
2017
prevScrollInfo = cm.getScrollInfo();
2018
helpers.doKeys('<C-e>');
2019
eq(1, cm.getCursor().line);
2020
eq(true, prevScrollInfo.top < cm.getScrollInfo().top);
2021
// Jump to the end of the sandbox.
2022
cm.setCursor(1000, 0);
2023
prevCursor = cm.getCursor();
2024
// ctrl-e at the bottom of the file should have no effect.
2025
helpers.doKeys('<C-e>');
2026
eq(prevCursor.line, cm.getCursor().line);
2027
prevScrollInfo = cm.getScrollInfo();
2028
helpers.doKeys('<C-y>');
2029
eq(prevCursor.line - 1, cm.getCursor().line);
2030
eq(true, prevScrollInfo.top > cm.getScrollInfo().top);
2031
}, { value: scrollMotionSandbox});
2032
2033
var squareBracketMotionSandbox = ''+
2034
'({\n'+//0
2035
' ({\n'+//11
2036
' /*comment {\n'+//2
2037
' */(\n'+//3
2038
'#else \n'+//4
2039
' /* )\n'+//5
2040
'#if }\n'+//6
2041
' )}*/\n'+//7
2042
')}\n'+//8
2043
'{}\n'+//9
2044
'#else {{\n'+//10
2045
'{}\n'+//11
2046
'}\n'+//12
2047
'{\n'+//13
2048
'#endif\n'+//14
2049
'}\n'+//15
2050
'}\n'+//16
2051
'#else';//17
2052
testVim('[[, ]]', function(cm, vim, helpers) {
2053
cm.setCursor(0, 0);
2054
helpers.doKeys(']', ']');
2055
helpers.assertCursorAt(9,0);
2056
helpers.doKeys('2', ']', ']');
2057
helpers.assertCursorAt(13,0);
2058
helpers.doKeys(']', ']');
2059
helpers.assertCursorAt(17,0);
2060
helpers.doKeys('[', '[');
2061
helpers.assertCursorAt(13,0);
2062
helpers.doKeys('2', '[', '[');
2063
helpers.assertCursorAt(9,0);
2064
helpers.doKeys('[', '[');
2065
helpers.assertCursorAt(0,0);
2066
}, { value: squareBracketMotionSandbox});
2067
testVim('[], ][', function(cm, vim, helpers) {
2068
cm.setCursor(0, 0);
2069
helpers.doKeys(']', '[');
2070
helpers.assertCursorAt(12,0);
2071
helpers.doKeys('2', ']', '[');
2072
helpers.assertCursorAt(16,0);
2073
helpers.doKeys(']', '[');
2074
helpers.assertCursorAt(17,0);
2075
helpers.doKeys('[', ']');
2076
helpers.assertCursorAt(16,0);
2077
helpers.doKeys('2', '[', ']');
2078
helpers.assertCursorAt(12,0);
2079
helpers.doKeys('[', ']');
2080
helpers.assertCursorAt(0,0);
2081
}, { value: squareBracketMotionSandbox});
2082
testVim('[{, ]}', function(cm, vim, helpers) {
2083
cm.setCursor(4, 10);
2084
helpers.doKeys('[', '{');
2085
helpers.assertCursorAt(2,12);
2086
helpers.doKeys('2', '[', '{');
2087
helpers.assertCursorAt(0,1);
2088
cm.setCursor(4, 10);
2089
helpers.doKeys(']', '}');
2090
helpers.assertCursorAt(6,11);
2091
helpers.doKeys('2', ']', '}');
2092
helpers.assertCursorAt(8,1);
2093
cm.setCursor(0,1);
2094
helpers.doKeys(']', '}');
2095
helpers.assertCursorAt(8,1);
2096
helpers.doKeys('[', '{');
2097
helpers.assertCursorAt(0,1);
2098
}, { value: squareBracketMotionSandbox});
2099
testVim('[(, ])', function(cm, vim, helpers) {
2100
cm.setCursor(4, 10);
2101
helpers.doKeys('[', '(');
2102
helpers.assertCursorAt(3,14);
2103
helpers.doKeys('2', '[', '(');
2104
helpers.assertCursorAt(0,0);
2105
cm.setCursor(4, 10);
2106
helpers.doKeys(']', ')');
2107
helpers.assertCursorAt(5,11);
2108
helpers.doKeys('2', ']', ')');
2109
helpers.assertCursorAt(8,0);
2110
helpers.doKeys('[', '(');
2111
helpers.assertCursorAt(0,0);
2112
helpers.doKeys(']', ')');
2113
helpers.assertCursorAt(8,0);
2114
}, { value: squareBracketMotionSandbox});
2115
testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) {
2116
forEach(['*', '/'], function(key){
2117
cm.setCursor(7, 0);
2118
helpers.doKeys('2', '[', key);
2119
helpers.assertCursorAt(2,2);
2120
helpers.doKeys('2', ']', key);
2121
helpers.assertCursorAt(7,5);
2122
});
2123
}, { value: squareBracketMotionSandbox});
2124
testVim('[#, ]#', function(cm, vim, helpers) {
2125
cm.setCursor(10, 3);
2126
helpers.doKeys('2', '[', '#');
2127
helpers.assertCursorAt(4,0);
2128
helpers.doKeys('5', ']', '#');
2129
helpers.assertCursorAt(17,0);
2130
cm.setCursor(10, 3);
2131
helpers.doKeys(']', '#');
2132
helpers.assertCursorAt(14,0);
2133
}, { value: squareBracketMotionSandbox});
2134
testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) {
2135
cm.setCursor(11, 0);
2136
helpers.doKeys('[', 'm');
2137
helpers.assertCursorAt(10,7);
2138
helpers.doKeys('4', '[', 'm');
2139
helpers.assertCursorAt(1,3);
2140
helpers.doKeys('5', ']', 'm');
2141
helpers.assertCursorAt(11,0);
2142
helpers.doKeys('[', 'M');
2143
helpers.assertCursorAt(9,1);
2144
helpers.doKeys('3', ']', 'M');
2145
helpers.assertCursorAt(15,0);
2146
helpers.doKeys('5', '[', 'M');
2147
helpers.assertCursorAt(7,3);
2148
}, { value: squareBracketMotionSandbox});
2149
2150
// Ex mode tests
2151
testVim('ex_go_to_line', function(cm, vim, helpers) {
2152
cm.setCursor(0, 0);
2153
helpers.doEx('4');
2154
helpers.assertCursorAt(3, 0);
2155
}, { value: 'a\nb\nc\nd\ne\n'});
2156
testVim('ex_write', function(cm, vim, helpers) {
2157
var tmp = CodeMirror.commands.save;
2158
var written;
2159
var actualCm;
2160
CodeMirror.commands.save = function(cm) {
2161
written = true;
2162
actualCm = cm;
2163
};
2164
// Test that w, wr, wri ... write all trigger :write.
2165
var command = 'write';
2166
for (var i = 1; i < command.length; i++) {
2167
written = false;
2168
actualCm = null;
2169
helpers.doEx(command.substring(0, i));
2170
eq(written, true);
2171
eq(actualCm, cm);
2172
}
2173
CodeMirror.commands.save = tmp;
2174
});
2175
testVim('ex_sort', function(cm, vim, helpers) {
2176
helpers.doEx('sort');
2177
eq('Z\na\nb\nc\nd', cm.getValue());
2178
}, { value: 'b\nZ\nd\nc\na'});
2179
testVim('ex_sort_reverse', function(cm, vim, helpers) {
2180
helpers.doEx('sort!');
2181
eq('d\nc\nb\na', cm.getValue());
2182
}, { value: 'b\nd\nc\na'});
2183
testVim('ex_sort_range', function(cm, vim, helpers) {
2184
helpers.doEx('2,3sort');
2185
eq('b\nc\nd\na', cm.getValue());
2186
}, { value: 'b\nd\nc\na'});
2187
testVim('ex_sort_oneline', function(cm, vim, helpers) {
2188
helpers.doEx('2sort');
2189
// Expect no change.
2190
eq('b\nd\nc\na', cm.getValue());
2191
}, { value: 'b\nd\nc\na'});
2192
testVim('ex_sort_ignoreCase', function(cm, vim, helpers) {
2193
helpers.doEx('sort i');
2194
eq('a\nb\nc\nd\nZ', cm.getValue());
2195
}, { value: 'b\nZ\nd\nc\na'});
2196
testVim('ex_sort_unique', function(cm, vim, helpers) {
2197
helpers.doEx('sort u');
2198
eq('Z\na\nb\nc\nd', cm.getValue());
2199
}, { value: 'b\nZ\na\na\nd\na\nc\na'});
2200
testVim('ex_sort_decimal', function(cm, vim, helpers) {
2201
helpers.doEx('sort d');
2202
eq('d3\n s5\n6\n.9', cm.getValue());
2203
}, { value: '6\nd3\n s5\n.9'});
2204
testVim('ex_sort_decimal_negative', function(cm, vim, helpers) {
2205
helpers.doEx('sort d');
2206
eq('z-9\nd3\n s5\n6\n.9', cm.getValue());
2207
}, { value: '6\nd3\n s5\n.9\nz-9'});
2208
testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) {
2209
helpers.doEx('sort! d');
2210
eq('.9\n6\n s5\nd3', cm.getValue());
2211
}, { value: '6\nd3\n s5\n.9'});
2212
testVim('ex_sort_hex', function(cm, vim, helpers) {
2213
helpers.doEx('sort x');
2214
eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue());
2215
}, { value: '6\nd3\n s5\n&0xB\n.9'});
2216
testVim('ex_sort_octal', function(cm, vim, helpers) {
2217
helpers.doEx('sort o');
2218
eq('.8\n.9\nd3\n s5\n6', cm.getValue());
2219
}, { value: '6\nd3\n s5\n.9\n.8'});
2220
testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) {
2221
helpers.doEx('sort d');
2222
eq('y\nz\nc1\nb2\na3', cm.getValue());
2223
}, { value: 'a3\nz\nc1\ny\nb2'});
2224
testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) {
2225
helpers.doEx('sort! d');
2226
eq('a3\nb2\nc1\nz\ny', cm.getValue());
2227
}, { value: 'a3\nz\nc1\ny\nb2'});
2228
testVim('ex_substitute_same_line', function(cm, vim, helpers) {
2229
cm.setCursor(1, 0);
2230
helpers.doEx('s/one/two');
2231
eq('one one\n two two', cm.getValue());
2232
}, { value: 'one one\n one one'});
2233
testVim('ex_substitute_global', function(cm, vim, helpers) {
2234
cm.setCursor(1, 0);
2235
helpers.doEx('%s/one/two');
2236
eq('two two\n two two', cm.getValue());
2237
}, { value: 'one one\n one one'});
2238
testVim('ex_substitute_input_range', function(cm, vim, helpers) {
2239
cm.setCursor(1, 0);
2240
helpers.doEx('1,3s/\\d/0');
2241
eq('0\n0\n0\n4', cm.getValue());
2242
}, { value: '1\n2\n3\n4' });
2243
testVim('ex_substitute_visual_range', function(cm, vim, helpers) {
2244
cm.setCursor(1, 0);
2245
// Set last visual mode selection marks '< and '> at lines 2 and 4
2246
helpers.doKeys('V', '2', 'j', 'v');
2247
helpers.doEx('\'<,\'>s/\\d/0');
2248
eq('1\n0\n0\n0\n5', cm.getValue());
2249
}, { value: '1\n2\n3\n4\n5' });
2250
testVim('ex_substitute_capture', function(cm, vim, helpers) {
2251
cm.setCursor(1, 0);
2252
helpers.doEx('s/(\\d+)/$1$1/')
2253
eq('a1111 a1212 a1313', cm.getValue());
2254
}, { value: 'a11 a12 a13' });
2255
testVim('ex_substitute_empty_query', function(cm, vim, helpers) {
2256
// If the query is empty, use last query.
2257
cm.setCursor(1, 0);
2258
cm.openDialog = helpers.fakeOpenDialog('1');
2259
helpers.doKeys('/');
2260
helpers.doEx('s//b');
2261
eq('abb ab2 ab3', cm.getValue());
2262
}, { value: 'a11 a12 a13' });
2263
testVim('ex_substitute_count', function(cm, vim, helpers) {
2264
cm.setCursor(1, 0);
2265
helpers.doEx('s/\\d/0/i 2');
2266
eq('1\n0\n0\n4', cm.getValue());
2267
}, { value: '1\n2\n3\n4' });
2268
testVim('ex_substitute_count_with_range', function(cm, vim, helpers) {
2269
cm.setCursor(1, 0);
2270
helpers.doEx('1,3s/\\d/0/ 3');
2271
eq('1\n2\n0\n0', cm.getValue());
2272
}, { value: '1\n2\n3\n4' });
2273
function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) {
2274
testVim(name, function(cm, vim, helpers) {
2275
var savedOpenDialog = cm.openDialog;
2276
var savedKeyName = CodeMirror.keyName;
2277
var onKeyDown;
2278
var recordedCallback;
2279
var closed = true; // Start out closed, set false on second openDialog.
2280
function close() {
2281
closed = true;
2282
}
2283
// First openDialog should save callback.
2284
cm.openDialog = function(template, callback, options) {
2285
recordedCallback = callback;
2286
}
2287
// Do first openDialog.
2288
helpers.doKeys(':');
2289
// Second openDialog should save keyDown handler.
2290
cm.openDialog = function(template, callback, options) {
2291
onKeyDown = options.onKeyDown;
2292
closed = false;
2293
};
2294
// Return the command to Vim and trigger second openDialog.
2295
recordedCallback(command);
2296
// The event should really use keyCode, but here just mock it out and use
2297
// key and replace keyName to just return key.
2298
CodeMirror.keyName = function (e) { return e.key; }
2299
keys = keys.toUpperCase();
2300
for (var i = 0; i < keys.length; i++) {
2301
is(!closed);
2302
onKeyDown({ key: keys.charAt(i) }, '', close);
2303
}
2304
try {
2305
eq(expectedValue, cm.getValue());
2306
helpers.assertCursorAt(finalPos);
2307
is(closed);
2308
} catch(e) {
2309
throw e
2310
} finally {
2311
// Restore overriden functions.
2312
CodeMirror.keyName = savedKeyName;
2313
cm.openDialog = savedOpenDialog;
2314
}
2315
}, { value: initialValue });
2316
};
2317
testSubstituteConfirm('ex_substitute_confirm_emptydoc',
2318
'%s/x/b/c', '', '', '', makeCursor(0, 0));
2319
testSubstituteConfirm('ex_substitute_confirm_nomatch',
2320
'%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0));
2321
testSubstituteConfirm('ex_substitute_confirm_accept',
2322
'%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1));
2323
testSubstituteConfirm('ex_substitute_confirm_random_keys',
2324
'%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1));
2325
testSubstituteConfirm('ex_substitute_confirm_some',
2326
'%s/a/b/c', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1));
2327
testSubstituteConfirm('ex_substitute_confirm_all',
2328
'%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1));
2329
testSubstituteConfirm('ex_substitute_confirm_accept_then_all',
2330
'%s/a/b/c', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1));
2331
testSubstituteConfirm('ex_substitute_confirm_quit',
2332
'%s/a/b/c', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3));
2333
testSubstituteConfirm('ex_substitute_confirm_last',
2334
'%s/a/b/c', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
2335
testSubstituteConfirm('ex_substitute_confirm_oneline',
2336
'1s/a/b/c', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
2337
testSubstituteConfirm('ex_substitute_confirm_range_accept',
2338
'1,2s/a/b/c', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0));
2339
testSubstituteConfirm('ex_substitute_confirm_range_some',
2340
'1,3s/a/b/c', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0));
2341
testSubstituteConfirm('ex_substitute_confirm_range_all',
2342
'1,3s/a/b/c', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0));
2343
testSubstituteConfirm('ex_substitute_confirm_range_last',
2344
'1,3s/a/b/c', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0));
2345
//:noh should clear highlighting of search-results but allow to resume search through n
2346
testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) {
2347
cm.openDialog = helpers.fakeOpenDialog('match');
2348
helpers.doKeys('?');
2349
helpers.doEx('noh');
2350
eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared');
2351
helpers.doKeys('n');
2352
helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting');
2353
}, { value: 'match nope match \n nope Match' });
2354
// TODO: Reset key maps after each test.
2355
testVim('ex_map_key2key', function(cm, vim, helpers) {
2356
helpers.doEx('map a x');
2357
helpers.doKeys('a');
2358
helpers.assertCursorAt(0, 0);
2359
eq('bc', cm.getValue());
2360
}, { value: 'abc' });
2361
testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) {
2362
helpers.doEx('map ; :');
2363
var dialogOpened = false;
2364
cm.openDialog = function() {
2365
dialogOpened = true;
2366
}
2367
helpers.doKeys(';');
2368
eq(dialogOpened, true);
2369
});
2370
testVim('ex_map_ex2key:', function(cm, vim, helpers) {
2371
helpers.doEx('map :del x');
2372
helpers.doEx('del');
2373
helpers.assertCursorAt(0, 0);
2374
eq('bc', cm.getValue());
2375
}, { value: 'abc' });
2376
testVim('ex_map_ex2ex', function(cm, vim, helpers) {
2377
helpers.doEx('map :del :w');
2378
var tmp = CodeMirror.commands.save;
2379
var written = false;
2380
var actualCm;
2381
CodeMirror.commands.save = function(cm) {
2382
written = true;
2383
actualCm = cm;
2384
};
2385
helpers.doEx('del');
2386
CodeMirror.commands.save = tmp;
2387
eq(written, true);
2388
eq(actualCm, cm);
2389
});
2390
testVim('ex_map_key2ex', function(cm, vim, helpers) {
2391
helpers.doEx('map a :w');
2392
var tmp = CodeMirror.commands.save;
2393
var written = false;
2394
var actualCm;
2395
CodeMirror.commands.save = function(cm) {
2396
written = true;
2397
actualCm = cm;
2398
};
2399
helpers.doKeys('a');
2400
CodeMirror.commands.save = tmp;
2401
eq(written, true);
2402
eq(actualCm, cm);
2403
});
2404
testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) {
2405
CodeMirror.Vim.map('b', ':w', 'visual');
2406
var tmp = CodeMirror.commands.save;
2407
var written = false;
2408
var actualCm;
2409
CodeMirror.commands.save = function(cm) {
2410
written = true;
2411
actualCm = cm;
2412
};
2413
// Mapping should not work in normal mode.
2414
helpers.doKeys('b');
2415
eq(written, false);
2416
// Mapping should work in visual mode.
2417
helpers.doKeys('v', 'b');
2418
eq(written, true);
2419
eq(actualCm, cm);
2420
2421
CodeMirror.commands.save = tmp;
2422
});
2423
2424
// Testing registration of functions as ex-commands and mapping to <Key>-keys
2425
testVim('ex_api_test', function(cm, vim, helpers) {
2426
var res=false;
2427
var val='from';
2428
CodeMirror.Vim.defineEx('extest','ext',function(cm,params){
2429
if(params.args)val=params.args[0];
2430
else res=true;
2431
});
2432
helpers.doEx(':ext to');
2433
eq(val,'to','Defining ex-command failed');
2434
CodeMirror.Vim.map('<C-CR><Space>',':ext');
2435
helpers.doKeys('<C-CR>','<Space>');
2436
is(res,'Mapping to key failed');
2437
});
2438
// For now, this test needs to be last because it messes up : for future tests.
2439
testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) {
2440
helpers.doEx('map : x');
2441
helpers.doKeys(':');
2442
helpers.assertCursorAt(0, 0);
2443
eq('bc', cm.getValue());
2444
}, { value: 'abc' });
2445
2446