]>
Commit | Line | Data |
---|---|---|
24c7594d BB |
1 | helpers = require './spec-helper' |
2 | settings = require '../lib/settings' | |
3 | ||
4 | describe "Operators", -> | |
5 | [editor, editorElement, vimState] = [] | |
6 | ||
7 | beforeEach -> | |
8 | vimMode = atom.packages.loadPackage('vim-mode') | |
9 | vimMode.activateResources() | |
10 | ||
11 | helpers.getEditorElement (element) -> | |
12 | editorElement = element | |
13 | editor = editorElement.getModel() | |
14 | vimState = editorElement.vimState | |
15 | vimState.activateCommandMode() | |
16 | vimState.resetCommandMode() | |
17 | ||
18 | keydown = (key, options={}) -> | |
19 | options.element ?= editorElement | |
20 | helpers.keydown(key, options) | |
21 | ||
22 | commandModeInputKeydown = (key, opts = {}) -> | |
23 | editor.commandModeInputView.editorElement.getModel().setText(key) | |
24 | ||
25 | describe "cancelling operations", -> | |
26 | it "does not throw an error even if no operation is pending", -> | |
27 | # cancel operation pushes an empty input operation | |
28 | # doing this without a pending operation throws an exception | |
29 | expect(-> vimState.pushOperations(new Input(''))).toThrow() | |
30 | ||
31 | # make sure commandModeInputView is created | |
32 | keydown('/') | |
33 | expect(vimState.isOperatorPending()).toBe true | |
34 | editor.commandModeInputView.viewModel.cancel() | |
35 | ||
36 | expect(vimState.isOperatorPending()).toBe false | |
37 | expect(-> editor.commandModeInputView.viewModel.cancel()).not.toThrow() | |
38 | ||
39 | describe "the x keybinding", -> | |
40 | describe "on a line with content", -> | |
41 | describe "without vim-mode.wrapLeftRightMotion", -> | |
42 | beforeEach -> | |
43 | editor.setText("abc\n012345\n\nxyz") | |
44 | editor.setCursorScreenPosition([1, 4]) | |
45 | ||
46 | it "deletes a character", -> | |
47 | keydown('x') | |
48 | expect(editor.getText()).toBe 'abc\n01235\n\nxyz' | |
49 | expect(editor.getCursorScreenPosition()).toEqual [1, 4] | |
50 | expect(vimState.getRegister('"').text).toBe '4' | |
51 | ||
52 | keydown('x') | |
53 | expect(editor.getText()).toBe 'abc\n0123\n\nxyz' | |
54 | expect(editor.getCursorScreenPosition()).toEqual [1, 3] | |
55 | expect(vimState.getRegister('"').text).toBe '5' | |
56 | ||
57 | keydown('x') | |
58 | expect(editor.getText()).toBe 'abc\n012\n\nxyz' | |
59 | expect(editor.getCursorScreenPosition()).toEqual [1, 2] | |
60 | expect(vimState.getRegister('"').text).toBe '3' | |
61 | ||
62 | keydown('x') | |
63 | expect(editor.getText()).toBe 'abc\n01\n\nxyz' | |
64 | expect(editor.getCursorScreenPosition()).toEqual [1, 1] | |
65 | expect(vimState.getRegister('"').text).toBe '2' | |
66 | ||
67 | keydown('x') | |
68 | expect(editor.getText()).toBe 'abc\n0\n\nxyz' | |
69 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
70 | expect(vimState.getRegister('"').text).toBe '1' | |
71 | ||
72 | keydown('x') | |
73 | expect(editor.getText()).toBe 'abc\n\n\nxyz' | |
74 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
75 | expect(vimState.getRegister('"').text).toBe '0' | |
76 | ||
77 | it "deletes multiple characters with a count", -> | |
78 | keydown('2') | |
79 | keydown('x') | |
80 | expect(editor.getText()).toBe 'abc\n0123\n\nxyz' | |
81 | expect(editor.getCursorScreenPosition()).toEqual [1, 3] | |
82 | expect(vimState.getRegister('"').text).toBe '45' | |
83 | ||
84 | editor.setCursorScreenPosition([0, 1]) | |
85 | keydown('3') | |
86 | keydown('x') | |
87 | expect(editor.getText()).toBe 'a\n0123\n\nxyz' | |
88 | expect(editor.getCursorScreenPosition()).toEqual [0, 0] | |
89 | expect(vimState.getRegister('"').text).toBe 'bc' | |
90 | ||
91 | describe "with vim-mode.wrapLeftRightMotion", -> | |
92 | beforeEach -> | |
93 | editor.setText("abc\n012345\n\nxyz") | |
94 | editor.setCursorScreenPosition([1, 4]) | |
95 | atom.config.set('vim-mode.wrapLeftRightMotion', true) | |
96 | ||
97 | it "deletes a character", -> | |
98 | # copy of the earlier test because wrapLeftRightMotion should not affect it | |
99 | keydown('x') | |
100 | expect(editor.getText()).toBe 'abc\n01235\n\nxyz' | |
101 | expect(editor.getCursorScreenPosition()).toEqual [1, 4] | |
102 | expect(vimState.getRegister('"').text).toBe '4' | |
103 | ||
104 | keydown('x') | |
105 | expect(editor.getText()).toBe 'abc\n0123\n\nxyz' | |
106 | expect(editor.getCursorScreenPosition()).toEqual [1, 3] | |
107 | expect(vimState.getRegister('"').text).toBe '5' | |
108 | ||
109 | keydown('x') | |
110 | expect(editor.getText()).toBe 'abc\n012\n\nxyz' | |
111 | expect(editor.getCursorScreenPosition()).toEqual [1, 2] | |
112 | expect(vimState.getRegister('"').text).toBe '3' | |
113 | ||
114 | keydown('x') | |
115 | expect(editor.getText()).toBe 'abc\n01\n\nxyz' | |
116 | expect(editor.getCursorScreenPosition()).toEqual [1, 1] | |
117 | expect(vimState.getRegister('"').text).toBe '2' | |
118 | ||
119 | keydown('x') | |
120 | expect(editor.getText()).toBe 'abc\n0\n\nxyz' | |
121 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
122 | expect(vimState.getRegister('"').text).toBe '1' | |
123 | ||
124 | keydown('x') | |
125 | expect(editor.getText()).toBe 'abc\n\n\nxyz' | |
126 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
127 | expect(vimState.getRegister('"').text).toBe '0' | |
128 | ||
129 | it "deletes multiple characters and newlines with a count", -> | |
130 | atom.config.set('vim-mode.wrapLeftRightMotion', true) | |
131 | keydown('2') | |
132 | keydown('x') | |
133 | expect(editor.getText()).toBe 'abc\n0123\n\nxyz' | |
134 | expect(editor.getCursorScreenPosition()).toEqual [1, 3] | |
135 | expect(vimState.getRegister('"').text).toBe '45' | |
136 | ||
137 | editor.setCursorScreenPosition([0, 1]) | |
138 | keydown('3') | |
139 | keydown('x') | |
140 | expect(editor.getText()).toBe 'a0123\n\nxyz' | |
141 | expect(editor.getCursorScreenPosition()).toEqual [0, 1] | |
142 | expect(vimState.getRegister('"').text).toBe 'bc\n' | |
143 | ||
144 | keydown('7') | |
145 | keydown('x') | |
146 | expect(editor.getText()).toBe 'ayz' | |
147 | expect(editor.getCursorScreenPosition()).toEqual [0, 1] | |
148 | expect(vimState.getRegister('"').text).toBe '0123\n\nx' | |
149 | ||
150 | ||
151 | describe "on an empty line", -> | |
152 | beforeEach -> | |
153 | editor.setText("abc\n012345\n\nxyz") | |
154 | editor.setCursorScreenPosition([2, 0]) | |
155 | ||
156 | it "deletes nothing on an empty line when vim-mode.wrapLeftRightMotion is false", -> | |
157 | atom.config.set('vim-mode.wrapLeftRightMotion', false) | |
158 | keydown('x') | |
159 | expect(editor.getText()).toBe "abc\n012345\n\nxyz" | |
160 | expect(editor.getCursorScreenPosition()).toEqual [2, 0] | |
161 | ||
162 | it "deletes an empty line when vim-mode.wrapLeftRightMotion is true", -> | |
163 | atom.config.set('vim-mode.wrapLeftRightMotion', true) | |
164 | keydown('x') | |
165 | expect(editor.getText()).toBe "abc\n012345\nxyz" | |
166 | expect(editor.getCursorScreenPosition()).toEqual [2, 0] | |
167 | ||
168 | ||
169 | describe "the X keybinding", -> | |
170 | describe "on a line with content", -> | |
171 | beforeEach -> | |
172 | editor.setText("ab\n012345") | |
173 | editor.setCursorScreenPosition([1, 2]) | |
174 | ||
175 | it "deletes a character", -> | |
176 | keydown('X', shift: true) | |
177 | expect(editor.getText()).toBe 'ab\n02345' | |
178 | expect(editor.getCursorScreenPosition()).toEqual [1, 1] | |
179 | expect(vimState.getRegister('"').text).toBe '1' | |
180 | ||
181 | keydown('X', shift: true) | |
182 | expect(editor.getText()).toBe 'ab\n2345' | |
183 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
184 | expect(vimState.getRegister('"').text).toBe '0' | |
185 | ||
186 | keydown('X', shift: true) | |
187 | expect(editor.getText()).toBe 'ab\n2345' | |
188 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
189 | expect(vimState.getRegister('"').text).toBe '0' | |
190 | ||
191 | atom.config.set('vim-mode.wrapLeftRightMotion', true) | |
192 | keydown('X', shift: true) | |
193 | expect(editor.getText()).toBe 'ab2345' | |
194 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
195 | expect(vimState.getRegister('"').text).toBe '\n' | |
196 | ||
197 | ||
198 | describe "on an empty line", -> | |
199 | beforeEach -> | |
200 | editor.setText("012345\n\nabcdef") | |
201 | editor.setCursorScreenPosition([1, 0]) | |
202 | ||
203 | it "deletes nothing when vim-mode.wrapLeftRightMotion is false", -> | |
204 | atom.config.set('vim-mode.wrapLeftRightMotion', false) | |
205 | keydown('X', shift: true) | |
206 | expect(editor.getText()).toBe "012345\n\nabcdef" | |
207 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
208 | ||
209 | it "deletes the newline when wrapLeftRightMotion is true", -> | |
210 | atom.config.set('vim-mode.wrapLeftRightMotion', true) | |
211 | keydown('X', shift: true) | |
212 | expect(editor.getText()).toBe "012345\nabcdef" | |
213 | expect(editor.getCursorScreenPosition()).toEqual [0, 5] | |
214 | ||
215 | describe "the s keybinding", -> | |
216 | beforeEach -> | |
217 | editor.setText('012345') | |
218 | editor.setCursorScreenPosition([0, 1]) | |
219 | ||
220 | it "deletes the character to the right and enters insert mode", -> | |
221 | keydown('s') | |
222 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
223 | expect(editor.getText()).toBe '02345' | |
224 | expect(editor.getCursorScreenPosition()).toEqual [0, 1] | |
225 | expect(vimState.getRegister('"').text).toBe '1' | |
226 | ||
227 | it "is repeatable", -> | |
228 | editor.setCursorScreenPosition([0, 0]) | |
229 | keydown('3') | |
230 | keydown('s') | |
231 | editor.insertText("ab") | |
232 | keydown('escape') | |
233 | expect(editor.getText()).toBe 'ab345' | |
234 | editor.setCursorScreenPosition([0, 2]) | |
235 | keydown('.') | |
236 | expect(editor.getText()).toBe 'abab' | |
237 | ||
238 | it "is undoable", -> | |
239 | editor.setCursorScreenPosition([0, 0]) | |
240 | keydown('3') | |
241 | keydown('s') | |
242 | editor.insertText("ab") | |
243 | keydown('escape') | |
244 | expect(editor.getText()).toBe 'ab345' | |
245 | keydown('u') | |
246 | expect(editor.getText()).toBe '012345' | |
247 | expect(editor.getSelectedText()).toBe '' | |
248 | ||
249 | describe "in visual mode", -> | |
250 | beforeEach -> | |
251 | keydown('v') | |
252 | editor.selectRight() | |
253 | keydown('s') | |
254 | ||
255 | it "deletes the selected characters and enters insert mode", -> | |
256 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
257 | expect(editor.getText()).toBe '0345' | |
258 | expect(editor.getCursorScreenPosition()).toEqual [0, 1] | |
259 | expect(vimState.getRegister('"').text).toBe '12' | |
260 | ||
261 | describe "the S keybinding", -> | |
262 | beforeEach -> | |
263 | editor.setText("12345\nabcde\nABCDE") | |
264 | editor.setCursorScreenPosition([1, 3]) | |
265 | ||
266 | it "deletes the entire line and enters insert mode", -> | |
267 | keydown('S', shift: true) | |
268 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
269 | expect(editor.getText()).toBe "12345\n\nABCDE" | |
270 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
271 | expect(vimState.getRegister('"').text).toBe "abcde\n" | |
272 | expect(vimState.getRegister('"').type).toBe 'linewise' | |
273 | ||
274 | it "is repeatable", -> | |
275 | keydown('S', shift: true) | |
276 | editor.insertText("abc") | |
277 | keydown 'escape' | |
278 | expect(editor.getText()).toBe "12345\nabc\nABCDE" | |
279 | editor.setCursorScreenPosition([2, 3]) | |
280 | keydown '.' | |
281 | expect(editor.getText()).toBe "12345\nabc\nabc\n" | |
282 | ||
283 | it "is undoable", -> | |
284 | keydown('S', shift: true) | |
285 | editor.insertText("abc") | |
286 | keydown 'escape' | |
287 | expect(editor.getText()).toBe "12345\nabc\nABCDE" | |
288 | keydown 'u' | |
289 | expect(editor.getText()).toBe "12345\nabcde\nABCDE" | |
290 | expect(editor.getSelectedText()).toBe '' | |
291 | ||
292 | it "works when the cursor's goal column is greater than its current column", -> | |
293 | editor.setText("\n12345") | |
294 | editor.setCursorBufferPosition([1, Infinity]) | |
295 | editor.moveUp() | |
296 | keydown("S", shift: true) | |
297 | expect(editor.getText()).toBe("\n12345") | |
298 | ||
299 | # Can't be tested without setting grammar of test buffer | |
300 | xit "respects indentation", -> | |
301 | ||
302 | describe "the d keybinding", -> | |
303 | it "enters operator-pending mode", -> | |
304 | keydown('d') | |
305 | expect(editorElement.classList.contains('operator-pending-mode')).toBe(true) | |
306 | expect(editorElement.classList.contains('command-mode')).toBe(false) | |
307 | ||
308 | describe "when followed by a d", -> | |
309 | it "deletes the current line and exits operator-pending mode", -> | |
310 | editor.setText("12345\nabcde\n\nABCDE") | |
311 | editor.setCursorScreenPosition([1, 1]) | |
312 | ||
313 | keydown('d') | |
314 | keydown('d') | |
315 | ||
316 | expect(editor.getText()).toBe "12345\n\nABCDE" | |
317 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
318 | expect(vimState.getRegister('"').text).toBe "abcde\n" | |
319 | expect(editorElement.classList.contains('operator-pending-mode')).toBe(false) | |
320 | expect(editorElement.classList.contains('command-mode')).toBe(true) | |
321 | ||
322 | it "deletes the last line", -> | |
323 | editor.setText("12345\nabcde\nABCDE") | |
324 | editor.setCursorScreenPosition([2, 1]) | |
325 | ||
326 | keydown('d') | |
327 | keydown('d') | |
328 | ||
329 | expect(editor.getText()).toBe "12345\nabcde\n" | |
330 | expect(editor.getCursorScreenPosition()).toEqual [2, 0] | |
331 | ||
332 | it "leaves the cursor on the first nonblank character", -> | |
333 | editor.setText("12345\n abcde\n") | |
334 | editor.setCursorScreenPosition([0, 4]) | |
335 | ||
336 | keydown('d') | |
337 | keydown('d') | |
338 | ||
339 | expect(editor.getText()).toBe " abcde\n" | |
340 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
341 | ||
342 | describe "undo behavior", -> | |
343 | beforeEach -> | |
344 | editor.setText("12345\nabcde\nABCDE\nQWERT") | |
345 | editor.setCursorScreenPosition([1, 1]) | |
346 | ||
347 | keydown('d') | |
348 | keydown('2') | |
349 | keydown('d') | |
350 | ||
351 | keydown('u') | |
352 | ||
353 | it "undoes both lines", -> | |
354 | expect(editor.getText()).toBe "12345\nabcde\nABCDE\nQWERT" | |
355 | expect(editor.getSelectedText()).toBe '' | |
356 | ||
357 | describe "when followed by a w", -> | |
358 | it "deletes the next word until the end of the line and exits operator-pending mode", -> | |
359 | editor.setText("abcd efg\nabc") | |
360 | editor.setCursorScreenPosition([0, 5]) | |
361 | ||
362 | keydown('d') | |
363 | keydown('w') | |
364 | ||
365 | # Incompatibility with VIM. In vim, `w` behaves differently as an | |
366 | # operator than as a motion; it stops at the end of a line.expect(editor.getText()).toBe "abcd abc" | |
367 | expect(editor.getText()).toBe "abcd abc" | |
368 | expect(editor.getCursorScreenPosition()).toEqual [0, 5] | |
369 | ||
370 | expect(editorElement.classList.contains('operator-pending-mode')).toBe(false) | |
371 | expect(editorElement.classList.contains('command-mode')).toBe(true) | |
372 | ||
373 | it "deletes to the beginning of the next word", -> | |
374 | editor.setText('abcd efg') | |
375 | editor.setCursorScreenPosition([0, 2]) | |
376 | ||
377 | keydown('d') | |
378 | keydown('w') | |
379 | ||
380 | expect(editor.getText()).toBe 'abefg' | |
381 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
382 | ||
383 | editor.setText('one two three four') | |
384 | editor.setCursorScreenPosition([0, 0]) | |
385 | ||
386 | keydown('d') | |
387 | keydown('3') | |
388 | keydown('w') | |
389 | ||
390 | expect(editor.getText()).toBe 'four' | |
391 | expect(editor.getCursorScreenPosition()).toEqual [0, 0] | |
392 | ||
393 | describe "when followed by an iw", -> | |
394 | it "deletes the containing word", -> | |
395 | editor.setText("12345 abcde ABCDE") | |
396 | editor.setCursorScreenPosition([0, 9]) | |
397 | ||
398 | keydown('d') | |
399 | expect(editorElement.classList.contains('operator-pending-mode')).toBe(true) | |
400 | keydown('i') | |
401 | keydown('w') | |
402 | ||
403 | expect(editor.getText()).toBe "12345 ABCDE" | |
404 | expect(editor.getCursorScreenPosition()).toEqual [0, 6] | |
405 | expect(vimState.getRegister('"').text).toBe "abcde" | |
406 | expect(editorElement.classList.contains('operator-pending-mode')).toBe(false) | |
407 | expect(editorElement.classList.contains('command-mode')).toBe(true) | |
408 | ||
409 | describe "when followed by an j", -> | |
410 | beforeEach -> | |
411 | originalText = "12345\nabcde\nABCDE" | |
412 | editor.setText(originalText) | |
413 | ||
414 | describe "on the beginning of the file", -> | |
415 | editor.setCursorScreenPosition([0, 0]) | |
416 | it "deletes the next two lines", -> | |
417 | keydown('d') | |
418 | keydown('j') | |
419 | expect(editor.getText()).toBe("ABCDE") | |
420 | ||
421 | describe "on the end of the file", -> | |
422 | editor.setCursorScreenPosition([4, 2]) | |
423 | it "deletes nothing", -> | |
424 | keydown('d') | |
425 | keydown('j') | |
426 | expect(editor.getText()).toBe(originalText) | |
427 | ||
428 | describe "on the middle of second line", -> | |
429 | editor.setCursorScreenPosition([2, 1]) | |
430 | it "deletes the last two lines", -> | |
431 | keydown('d') | |
432 | keydown('j') | |
433 | expect(editor.getText()).toBe("12345") | |
434 | ||
435 | describe "when followed by an k", -> | |
436 | beforeEach -> | |
437 | originalText = "12345\nabcde\nABCDE" | |
438 | editor.setText(originalText) | |
439 | ||
440 | describe "on the end of the file", -> | |
441 | editor.setCursorScreenPosition([4, 2]) | |
442 | it "deletes the bottom two lines", -> | |
443 | keydown('d') | |
444 | keydown('k') | |
445 | expect(editor.getText()).toBe("ABCDE") | |
446 | ||
447 | describe "on the beginning of the file", -> | |
448 | editor.setCursorScreenPosition([0, 0]) | |
449 | it "deletes nothing", -> | |
450 | keydown('d') | |
451 | keydown('k') | |
452 | expect(editor.getText()).toBe(originalText) | |
453 | ||
454 | describe "when on the middle of second line", -> | |
455 | editor.setCursorScreenPosition([2, 1]) | |
456 | it "deletes the first two lines", -> | |
457 | keydown('d') | |
458 | keydown('k') | |
459 | expect(editor.getText()).toBe("12345") | |
460 | ||
461 | describe "when followed by a G", -> | |
462 | beforeEach -> | |
463 | originalText = "12345\nabcde\nABCDE" | |
464 | editor.setText(originalText) | |
465 | ||
466 | describe "on the beginning of the second line", -> | |
467 | it "deletes the bottom two lines", -> | |
468 | editor.setCursorScreenPosition([1, 0]) | |
469 | keydown('d') | |
470 | keydown('G', shift: true) | |
471 | expect(editor.getText()).toBe("12345\n") | |
472 | ||
473 | describe "on the middle of the second line", -> | |
474 | it "deletes the bottom two lines", -> | |
475 | editor.setCursorScreenPosition([1, 2]) | |
476 | keydown('d') | |
477 | keydown('G', shift: true) | |
478 | expect(editor.getText()).toBe("12345\n") | |
479 | ||
480 | describe "when followed by a goto line G", -> | |
481 | beforeEach -> | |
482 | originalText = "12345\nabcde\nABCDE" | |
483 | editor.setText(originalText) | |
484 | ||
485 | describe "on the beginning of the second line", -> | |
486 | it "deletes the bottom two lines", -> | |
487 | editor.setCursorScreenPosition([1, 0]) | |
488 | keydown('d') | |
489 | keydown('2') | |
490 | keydown('G', shift: true) | |
491 | expect(editor.getText()).toBe("12345\nABCDE") | |
492 | ||
493 | describe "on the middle of the second line", -> | |
494 | it "deletes the bottom two lines", -> | |
495 | editor.setCursorScreenPosition([1, 2]) | |
496 | keydown('d') | |
497 | keydown('2') | |
498 | keydown('G', shift: true) | |
499 | expect(editor.getText()).toBe("12345\nABCDE") | |
500 | ||
501 | describe "when followed by a t)", -> | |
502 | describe "with the entire line yanked before", -> | |
503 | beforeEach -> | |
504 | editor.setText("test (xyz)") | |
505 | editor.setCursorScreenPosition([0, 6]) | |
506 | ||
507 | it "deletes until the closing parenthesis", -> | |
508 | keydown('y') | |
509 | keydown('y') | |
510 | keydown('d') | |
511 | keydown('t') | |
512 | commandModeInputKeydown(')') | |
513 | expect(editor.getText()).toBe("test ()") | |
514 | expect(editor.getCursorScreenPosition()).toEqual [0, 6] | |
515 | ||
516 | describe "with multiple cursors", -> | |
517 | it "deletes each selection", -> | |
518 | editor.setText("abcd\n1234\nABCD\n") | |
519 | editor.setCursorBufferPosition([0, 1]) | |
520 | editor.addCursorAtBufferPosition([1, 2]) | |
521 | editor.addCursorAtBufferPosition([2, 3]) | |
522 | ||
523 | keydown('d') | |
524 | keydown('e') | |
525 | ||
526 | expect(editor.getText()).toBe "a\n12\nABC" | |
527 | expect(editor.getCursorBufferPositions()).toEqual [ | |
528 | [0, 0], | |
529 | [1, 1], | |
530 | [2, 2], | |
531 | ] | |
532 | ||
533 | it "doesn't delete empty selections", -> | |
534 | editor.setText("abcd\nabc\nabd") | |
535 | editor.setCursorBufferPosition([0, 0]) | |
536 | editor.addCursorAtBufferPosition([1, 0]) | |
537 | editor.addCursorAtBufferPosition([2, 0]) | |
538 | ||
539 | keydown('d') | |
540 | keydown('t') | |
541 | commandModeInputKeydown('d') | |
542 | ||
543 | expect(editor.getText()).toBe "d\nabc\nd" | |
544 | expect(editor.getCursorBufferPositions()).toEqual [ | |
545 | [0, 0], | |
546 | [1, 0], | |
547 | [2, 0], | |
548 | ] | |
549 | ||
550 | describe "the D keybinding", -> | |
551 | beforeEach -> | |
552 | editor.getBuffer().setText("012\n") | |
553 | editor.setCursorScreenPosition([0, 1]) | |
554 | keydown('D', shift: true) | |
555 | ||
556 | it "deletes the contents until the end of the line", -> | |
557 | expect(editor.getText()).toBe "0\n" | |
558 | ||
559 | describe "the c keybinding", -> | |
560 | beforeEach -> | |
561 | editor.setText("12345\nabcde\nABCDE") | |
562 | ||
563 | describe "when followed by a c", -> | |
564 | it "deletes the current line and enters insert mode", -> | |
565 | editor.setCursorScreenPosition([1, 1]) | |
566 | ||
567 | keydown('c') | |
568 | keydown('c') | |
569 | ||
570 | expect(editor.getText()).toBe "12345\n\nABCDE" | |
571 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
572 | expect(editorElement.classList.contains('command-mode')).toBe(false) | |
573 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
574 | ||
575 | describe "when the cursor is on the last line", -> | |
576 | it "deletes the line's content and enters insert mode on the last line", -> | |
577 | editor.setCursorScreenPosition([2, 1]) | |
578 | ||
579 | keydown('c') | |
580 | keydown('c') | |
581 | ||
582 | expect(editor.getText()).toBe "12345\nabcde\n\n" | |
583 | expect(editor.getCursorScreenPosition()).toEqual [2, 0] | |
584 | expect(editorElement.classList.contains('command-mode')).toBe(false) | |
585 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
586 | ||
587 | describe "when the cursor is on the only line", -> | |
588 | it "deletes the line's content and enters insert mode", -> | |
589 | editor.setText("12345") | |
590 | editor.setCursorScreenPosition([0, 2]) | |
591 | ||
592 | keydown('c') | |
593 | keydown('c') | |
594 | ||
595 | expect(editor.getText()).toBe "\n" | |
596 | expect(editor.getCursorScreenPosition()).toEqual [0, 0] | |
597 | expect(editorElement.classList.contains('command-mode')).toBe(false) | |
598 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
599 | ||
600 | describe "when followed by i w", -> | |
601 | it "undo's and redo's completely", -> | |
602 | editor.setCursorScreenPosition([1, 1]) | |
603 | ||
604 | keydown('c') | |
605 | keydown('i') | |
606 | keydown('w') | |
607 | expect(editor.getText()).toBe "12345\n\nABCDE" | |
608 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
609 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
610 | ||
611 | # Just cannot get "typing" to work correctly in test. | |
612 | editor.setText("12345\nfg\nABCDE") | |
613 | keydown('escape') | |
614 | expect(editorElement.classList.contains('command-mode')).toBe(true) | |
615 | expect(editor.getText()).toBe "12345\nfg\nABCDE" | |
616 | ||
617 | keydown('u') | |
618 | expect(editor.getText()).toBe "12345\nabcde\nABCDE" | |
619 | keydown('r', ctrl: true) | |
620 | expect(editor.getText()).toBe "12345\nfg\nABCDE" | |
621 | ||
622 | describe "when followed by a w", -> | |
623 | it "changes the word", -> | |
624 | editor.setText("word1 word2 word3") | |
625 | editor.setCursorBufferPosition([0, "word1 w".length]) | |
626 | ||
627 | keydown("c") | |
628 | keydown("w") | |
629 | keydown("escape") | |
630 | ||
631 | expect(editor.getText()).toBe "word1 w word3" | |
632 | ||
633 | describe "when followed by a G", -> | |
634 | beforeEach -> | |
635 | originalText = "12345\nabcde\nABCDE" | |
636 | editor.setText(originalText) | |
637 | ||
638 | describe "on the beginning of the second line", -> | |
639 | it "deletes the bottom two lines", -> | |
640 | editor.setCursorScreenPosition([1, 0]) | |
641 | keydown('c') | |
642 | keydown('G', shift: true) | |
643 | keydown('escape') | |
644 | expect(editor.getText()).toBe("12345\n\n") | |
645 | ||
646 | describe "on the middle of the second line", -> | |
647 | it "deletes the bottom two lines", -> | |
648 | editor.setCursorScreenPosition([1, 2]) | |
649 | keydown('c') | |
650 | keydown('G', shift: true) | |
651 | keydown('escape') | |
652 | expect(editor.getText()).toBe("12345\n\n") | |
653 | ||
654 | describe "when followed by a goto line G", -> | |
655 | beforeEach -> | |
656 | editor.setText "12345\nabcde\nABCDE" | |
657 | ||
658 | describe "on the beginning of the second line", -> | |
659 | it "deletes all the text on the line", -> | |
660 | editor.setCursorScreenPosition([1, 0]) | |
661 | keydown('c') | |
662 | keydown('2') | |
663 | keydown('G', shift: true) | |
664 | keydown('escape') | |
665 | expect(editor.getText()).toBe("12345\n\nABCDE") | |
666 | ||
667 | describe "on the middle of the second line", -> | |
668 | it "deletes all the text on the line", -> | |
669 | editor.setCursorScreenPosition([1, 2]) | |
670 | keydown('c') | |
671 | keydown('2') | |
672 | keydown('G', shift: true) | |
673 | keydown('escape') | |
674 | expect(editor.getText()).toBe("12345\n\nABCDE") | |
675 | ||
676 | describe "the C keybinding", -> | |
677 | beforeEach -> | |
678 | editor.getBuffer().setText("012\n") | |
679 | editor.setCursorScreenPosition([0, 1]) | |
680 | keydown('C', shift: true) | |
681 | ||
682 | it "deletes the contents until the end of the line and enters insert mode", -> | |
683 | expect(editor.getText()).toBe "0\n" | |
684 | expect(editor.getCursorScreenPosition()).toEqual [0, 1] | |
685 | expect(editorElement.classList.contains('command-mode')).toBe(false) | |
686 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
687 | ||
688 | describe "the y keybinding", -> | |
689 | beforeEach -> | |
690 | editor.getBuffer().setText("012 345\nabc\n") | |
691 | editor.setCursorScreenPosition([0, 4]) | |
692 | ||
693 | describe "when selected lines in visual linewise mode", -> | |
694 | beforeEach -> | |
695 | keydown('V', shift: true) | |
696 | keydown('j') | |
697 | keydown('y') | |
698 | ||
699 | it "is in linewise motion", -> | |
700 | expect(vimState.getRegister('"').type).toEqual "linewise" | |
701 | ||
702 | it "saves the lines to the default register", -> | |
703 | expect(vimState.getRegister('"').text).toBe "012 345\nabc\n" | |
704 | ||
705 | it "places the cursor at the beginning of the selection", -> | |
706 | expect(editor.getCursorBufferPositions()).toEqual([[0, 0]]) | |
707 | ||
708 | describe "when followed by a second y ", -> | |
709 | beforeEach -> | |
710 | keydown('y') | |
711 | keydown('y') | |
712 | ||
713 | it "saves the line to the default register", -> | |
714 | expect(vimState.getRegister('"').text).toBe "012 345\n" | |
715 | ||
716 | it "leaves the cursor at the starting position", -> | |
717 | expect(editor.getCursorScreenPosition()).toEqual [0, 4] | |
718 | ||
719 | describe "when useClipboardAsDefaultRegister enabled", -> | |
720 | it "writes to clipboard", -> | |
721 | atom.config.set 'vim-mode.useClipboardAsDefaultRegister', true | |
722 | keydown('y') | |
723 | keydown('y') | |
724 | expect(atom.clipboard.read()).toBe '012 345\n' | |
725 | ||
726 | describe "when followed with a repeated y", -> | |
727 | beforeEach -> | |
728 | keydown('y') | |
729 | keydown('2') | |
730 | keydown('y') | |
731 | ||
732 | it "copies n lines, starting from the current", -> | |
733 | expect(vimState.getRegister('"').text).toBe "012 345\nabc\n" | |
734 | ||
735 | it "leaves the cursor at the starting position", -> | |
736 | expect(editor.getCursorScreenPosition()).toEqual [0, 4] | |
737 | ||
738 | describe "with a register", -> | |
739 | beforeEach -> | |
740 | keydown('"') | |
741 | keydown('a') | |
742 | keydown('y') | |
743 | keydown('y') | |
744 | ||
745 | it "saves the line to the a register", -> | |
746 | expect(vimState.getRegister('a').text).toBe "012 345\n" | |
747 | ||
748 | it "appends the line to the A register", -> | |
749 | keydown('"') | |
750 | keydown('A', shift: true) | |
751 | keydown('y') | |
752 | keydown('y') | |
753 | expect(vimState.getRegister('a').text).toBe "012 345\n012 345\n" | |
754 | ||
755 | describe "with a forward motion", -> | |
756 | beforeEach -> | |
757 | keydown('y') | |
758 | keydown('e') | |
759 | ||
760 | it "saves the selected text to the default register", -> | |
761 | expect(vimState.getRegister('"').text).toBe '345' | |
762 | ||
763 | it "leaves the cursor at the starting position", -> | |
764 | expect(editor.getCursorScreenPosition()).toEqual [0, 4] | |
765 | ||
766 | it "does not yank when motion fails", -> | |
767 | keydown('y') | |
768 | keydown('t') | |
769 | commandModeInputKeydown('x') | |
770 | expect(vimState.getRegister('"').text).toBe '345' | |
771 | ||
772 | describe "with a text object", -> | |
773 | it "moves the cursor to the beginning of the text object", -> | |
774 | editor.setCursorBufferPosition([0, 5]) | |
775 | keydown("y") | |
776 | keydown("i") | |
777 | keydown("w") | |
778 | expect(editor.getCursorBufferPositions()).toEqual([[0, 4]]) | |
779 | ||
780 | describe "with a left motion", -> | |
781 | beforeEach -> | |
782 | keydown('y') | |
783 | keydown('h') | |
784 | ||
785 | it "saves the left letter to the default register", -> | |
786 | expect(vimState.getRegister('"').text).toBe " " | |
787 | ||
788 | it "moves the cursor position to the left", -> | |
789 | expect(editor.getCursorScreenPosition()).toEqual [0, 3] | |
790 | ||
791 | describe "with a down motion", -> | |
792 | beforeEach -> | |
793 | keydown 'y' | |
794 | keydown 'j' | |
795 | ||
796 | it "saves both full lines to the default register", -> | |
797 | expect(vimState.getRegister('"').text).toBe "012 345\nabc\n" | |
798 | ||
799 | it "leaves the cursor at the starting position", -> | |
800 | expect(editor.getCursorScreenPosition()).toEqual [0, 4] | |
801 | ||
802 | describe "when followed by a G", -> | |
803 | beforeEach -> | |
804 | originalText = "12345\nabcde\nABCDE" | |
805 | editor.setText(originalText) | |
806 | ||
807 | describe "on the beginning of the second line", -> | |
808 | it "deletes the bottom two lines", -> | |
809 | editor.setCursorScreenPosition([1, 0]) | |
810 | keydown('y') | |
811 | keydown('G', shift: true) | |
812 | keydown('P', shift: true) | |
813 | expect(editor.getText()).toBe("12345\nabcde\nABCDE\nabcde\nABCDE") | |
814 | ||
815 | describe "on the middle of the second line", -> | |
816 | it "deletes the bottom two lines", -> | |
817 | editor.setCursorScreenPosition([1, 2]) | |
818 | keydown('y') | |
819 | keydown('G', shift: true) | |
820 | keydown('P', shift: true) | |
821 | expect(editor.getText()).toBe("12345\nabcde\nABCDE\nabcde\nABCDE") | |
822 | ||
823 | describe "when followed by a goto line G", -> | |
824 | beforeEach -> | |
825 | originalText = "12345\nabcde\nABCDE" | |
826 | editor.setText(originalText) | |
827 | ||
828 | describe "on the beginning of the second line", -> | |
829 | it "deletes the bottom two lines", -> | |
830 | editor.setCursorScreenPosition([1, 0]) | |
831 | keydown('y') | |
832 | keydown('2') | |
833 | keydown('G', shift: true) | |
834 | keydown('P', shift: true) | |
835 | expect(editor.getText()).toBe("12345\nabcde\nabcde\nABCDE") | |
836 | ||
837 | describe "on the middle of the second line", -> | |
838 | it "deletes the bottom two lines", -> | |
839 | editor.setCursorScreenPosition([1, 2]) | |
840 | keydown('y') | |
841 | keydown('2') | |
842 | keydown('G', shift: true) | |
843 | keydown('P', shift: true) | |
844 | expect(editor.getText()).toBe("12345\nabcde\nabcde\nABCDE") | |
845 | ||
846 | describe "with multiple cursors", -> | |
847 | it "moves each cursor and copies the last selection's text", -> | |
848 | editor.setText " abcd\n 1234" | |
849 | editor.setCursorBufferPosition([0, 0]) | |
850 | editor.addCursorAtBufferPosition([1, 5]) | |
851 | ||
852 | keydown("y") | |
853 | keydown("^") | |
854 | ||
855 | expect(vimState.getRegister('"').text).toBe '123' | |
856 | expect(editor.getCursorBufferPositions()).toEqual [[0, 0], [1, 2]] | |
857 | ||
858 | describe "the yy keybinding", -> | |
859 | describe "on a single line file", -> | |
860 | beforeEach -> | |
861 | editor.getBuffer().setText "exclamation!\n" | |
862 | editor.setCursorScreenPosition [0, 0] | |
863 | ||
864 | it "copies the entire line and pastes it correctly", -> | |
865 | keydown('y') | |
866 | keydown('y') | |
867 | keydown('p') | |
868 | ||
869 | expect(vimState.getRegister('"').text).toBe "exclamation!\n" | |
870 | expect(editor.getText()).toBe "exclamation!\nexclamation!\n" | |
871 | ||
872 | describe "on a single line file with no newline", -> | |
873 | beforeEach -> | |
874 | editor.getBuffer().setText "no newline!" | |
875 | editor.setCursorScreenPosition [0, 0] | |
876 | ||
877 | it "copies the entire line and pastes it correctly", -> | |
878 | keydown('y') | |
879 | keydown('y') | |
880 | keydown('p') | |
881 | ||
882 | expect(vimState.getRegister('"').text).toBe "no newline!\n" | |
883 | expect(editor.getText()).toBe "no newline!\nno newline!" | |
884 | ||
885 | it "copies the entire line and pastes it respecting count and new lines", -> | |
886 | keydown('y') | |
887 | keydown('y') | |
888 | keydown('2') | |
889 | keydown('p') | |
890 | ||
891 | expect(vimState.getRegister('"').text).toBe "no newline!\n" | |
892 | expect(editor.getText()).toBe "no newline!\nno newline!\nno newline!" | |
893 | ||
894 | describe "the Y keybinding", -> | |
895 | beforeEach -> | |
896 | editor.getBuffer().setText "012 345\nabc\n" | |
897 | editor.setCursorScreenPosition [0, 4] | |
898 | ||
899 | it "saves the line to the default register", -> | |
900 | keydown('Y', shift: true) | |
901 | ||
902 | expect(vimState.getRegister('"').text).toBe "012 345\n" | |
903 | expect(editor.getCursorScreenPosition()).toEqual [0, 4] | |
904 | ||
905 | describe "the p keybinding", -> | |
906 | describe "with character contents", -> | |
907 | beforeEach -> | |
908 | editor.getBuffer().setText "012\n" | |
909 | editor.setCursorScreenPosition [0, 0] | |
910 | vimState.setRegister('"', text: '345') | |
911 | vimState.setRegister('a', text: 'a') | |
912 | atom.clipboard.write "clip" | |
913 | ||
914 | describe "from the default register", -> | |
915 | beforeEach -> keydown('p') | |
916 | ||
917 | it "inserts the contents", -> | |
918 | expect(editor.getText()).toBe "034512\n" | |
919 | expect(editor.getCursorScreenPosition()).toEqual [0, 3] | |
920 | ||
921 | describe "when useClipboardAsDefaultRegister enabled", -> | |
922 | it "inserts contents from clipboard", -> | |
923 | atom.config.set 'vim-mode.useClipboardAsDefaultRegister', true | |
924 | keydown('p') | |
925 | expect(editor.getText()).toBe "0clip12\n" | |
926 | ||
927 | describe "from a specified register", -> | |
928 | beforeEach -> | |
929 | keydown('"') | |
930 | keydown('a') | |
931 | keydown('p') | |
932 | ||
933 | it "inserts the contents of the 'a' register", -> | |
934 | expect(editor.getText()).toBe "0a12\n" | |
935 | expect(editor.getCursorScreenPosition()).toEqual [0, 1] | |
936 | ||
937 | describe "at the end of a line", -> | |
938 | it "inserts before the current line's newline", -> | |
939 | editor.setText("abcde\none two three") | |
940 | editor.setCursorScreenPosition([1, 4]) | |
941 | ||
942 | keydown 'd' | |
943 | keydown '$' | |
944 | keydown 'k' | |
945 | keydown '$' | |
946 | keydown 'p' | |
947 | ||
948 | expect(editor.getText()).toBe "abcdetwo three\none " | |
949 | ||
950 | describe "with a selection", -> | |
951 | beforeEach -> | |
952 | editor.selectRight() | |
953 | keydown('p') | |
954 | ||
955 | it "replaces the current selection", -> | |
956 | expect(editor.getText()).toBe "34512\n" | |
957 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
958 | ||
959 | describe "with linewise contents", -> | |
960 | describe "on a single line", -> | |
961 | beforeEach -> | |
962 | editor.getBuffer().setText("012") | |
963 | editor.setCursorScreenPosition([0, 1]) | |
964 | vimState.setRegister('"', text: " 345\n", type: 'linewise') | |
965 | ||
966 | it "inserts the contents of the default register", -> | |
967 | keydown('p') | |
968 | ||
969 | expect(editor.getText()).toBe "012\n 345" | |
970 | expect(editor.getCursorScreenPosition()).toEqual [1, 1] | |
971 | ||
972 | it "replaces the current selection", -> | |
973 | editor.selectRight() | |
974 | keydown('p') | |
975 | ||
976 | expect(editor.getText()).toBe "0 345\n2" | |
977 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
978 | ||
979 | describe "on multiple lines", -> | |
980 | beforeEach -> | |
981 | editor.getBuffer().setText("012\n 345") | |
982 | vimState.setRegister('"', text: " 456\n", type: 'linewise') | |
983 | ||
984 | it "inserts the contents of the default register at middle line", -> | |
985 | editor.setCursorScreenPosition([0, 1]) | |
986 | keydown('p') | |
987 | ||
988 | expect(editor.getText()).toBe "012\n 456\n 345" | |
989 | expect(editor.getCursorScreenPosition()).toEqual [1, 1] | |
990 | ||
991 | it "inserts the contents of the default register at end of line", -> | |
992 | editor.setCursorScreenPosition([1, 1]) | |
993 | keydown('p') | |
994 | ||
995 | expect(editor.getText()).toBe "012\n 345\n 456" | |
996 | expect(editor.getCursorScreenPosition()).toEqual [2, 1] | |
997 | ||
998 | describe "with multiple linewise contents", -> | |
999 | beforeEach -> | |
1000 | editor.getBuffer().setText("012\nabc") | |
1001 | editor.setCursorScreenPosition([1, 0]) | |
1002 | vimState.setRegister('"', text: " 345\n 678\n", type: 'linewise') | |
1003 | keydown('p') | |
1004 | ||
1005 | it "inserts the contents of the default register", -> | |
1006 | expect(editor.getText()).toBe "012\nabc\n 345\n 678" | |
1007 | expect(editor.getCursorScreenPosition()).toEqual [2, 1] | |
1008 | ||
1009 | describe "pasting twice", -> | |
1010 | beforeEach -> | |
1011 | editor.setText("12345\nabcde\nABCDE\nQWERT") | |
1012 | editor.setCursorScreenPosition([1, 1]) | |
1013 | vimState.setRegister('"', text: '123') | |
1014 | keydown('2') | |
1015 | keydown('p') | |
1016 | ||
1017 | it "inserts the same line twice", -> | |
1018 | expect(editor.getText()).toBe "12345\nab123123cde\nABCDE\nQWERT" | |
1019 | ||
1020 | describe "when undone", -> | |
1021 | beforeEach -> | |
1022 | keydown('u') | |
1023 | ||
1024 | it "removes both lines", -> | |
1025 | expect(editor.getText()).toBe "12345\nabcde\nABCDE\nQWERT" | |
1026 | ||
1027 | describe "the P keybinding", -> | |
1028 | describe "with character contents", -> | |
1029 | beforeEach -> | |
1030 | editor.getBuffer().setText("012\n") | |
1031 | editor.setCursorScreenPosition([0, 0]) | |
1032 | vimState.setRegister('"', text: '345') | |
1033 | vimState.setRegister('a', text: 'a') | |
1034 | keydown('P', shift: true) | |
1035 | ||
1036 | it "inserts the contents of the default register above", -> | |
1037 | expect(editor.getText()).toBe "345012\n" | |
1038 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
1039 | ||
1040 | describe "the O keybinding", -> | |
1041 | beforeEach -> | |
1042 | spyOn(editor, 'shouldAutoIndent').andReturn(true) | |
1043 | spyOn(editor, 'autoIndentBufferRow').andCallFake (line) -> | |
1044 | editor.indent() | |
1045 | ||
1046 | editor.getBuffer().setText(" abc\n 012\n") | |
1047 | editor.setCursorScreenPosition([1, 1]) | |
1048 | ||
1049 | it "switches to insert and adds a newline above the current one", -> | |
1050 | keydown('O', shift: true) | |
1051 | expect(editor.getText()).toBe " abc\n \n 012\n" | |
1052 | expect(editor.getCursorScreenPosition()).toEqual [1, 2] | |
1053 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
1054 | ||
1055 | it "is repeatable", -> | |
1056 | editor.getBuffer().setText(" abc\n 012\n 4spaces\n") | |
1057 | editor.setCursorScreenPosition([1, 1]) | |
1058 | keydown('O', shift: true) | |
1059 | editor.insertText "def" | |
1060 | keydown 'escape' | |
1061 | expect(editor.getText()).toBe " abc\n def\n 012\n 4spaces\n" | |
1062 | editor.setCursorScreenPosition([1, 1]) | |
1063 | keydown '.' | |
1064 | expect(editor.getText()).toBe " abc\n def\n def\n 012\n 4spaces\n" | |
1065 | editor.setCursorScreenPosition([4, 1]) | |
1066 | keydown '.' | |
1067 | expect(editor.getText()).toBe " abc\n def\n def\n 012\n def\n 4spaces\n" | |
1068 | ||
1069 | it "is undoable", -> | |
1070 | keydown('O', shift: true) | |
1071 | editor.insertText "def" | |
1072 | keydown 'escape' | |
1073 | expect(editor.getText()).toBe " abc\n def\n 012\n" | |
1074 | keydown 'u' | |
1075 | expect(editor.getText()).toBe " abc\n 012\n" | |
1076 | ||
1077 | describe "the o keybinding", -> | |
1078 | beforeEach -> | |
1079 | spyOn(editor, 'shouldAutoIndent').andReturn(true) | |
1080 | spyOn(editor, 'autoIndentBufferRow').andCallFake (line) -> | |
1081 | editor.indent() | |
1082 | ||
1083 | editor.getBuffer().setText("abc\n 012\n") | |
1084 | editor.setCursorScreenPosition([1, 2]) | |
1085 | ||
1086 | it "switches to insert and adds a newline above the current one", -> | |
1087 | keydown('o') | |
1088 | expect(editor.getText()).toBe "abc\n 012\n \n" | |
1089 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
1090 | expect(editor.getCursorScreenPosition()).toEqual [2, 2] | |
1091 | ||
1092 | # This works in practice, but the editor doesn't respect the indentation | |
1093 | # rules without a syntax grammar. Need to set the editor's grammar | |
1094 | # to fix it. | |
1095 | xit "is repeatable", -> | |
1096 | editor.getBuffer().setText(" abc\n 012\n 4spaces\n") | |
1097 | editor.setCursorScreenPosition([1, 1]) | |
1098 | keydown('o') | |
1099 | editor.insertText "def" | |
1100 | keydown 'escape' | |
1101 | expect(editor.getText()).toBe " abc\n 012\n def\n 4spaces\n" | |
1102 | keydown '.' | |
1103 | expect(editor.getText()).toBe " abc\n 012\n def\n def\n 4spaces\n" | |
1104 | editor.setCursorScreenPosition([4, 1]) | |
1105 | keydown '.' | |
1106 | expect(editor.getText()).toBe " abc\n def\n def\n 012\n 4spaces\n def\n" | |
1107 | ||
1108 | it "is undoable", -> | |
1109 | keydown('o') | |
1110 | editor.insertText "def" | |
1111 | keydown 'escape' | |
1112 | expect(editor.getText()).toBe "abc\n 012\n def\n" | |
1113 | keydown 'u' | |
1114 | expect(editor.getText()).toBe "abc\n 012\n" | |
1115 | ||
1116 | describe "the a keybinding", -> | |
1117 | beforeEach -> | |
1118 | editor.getBuffer().setText("012\n") | |
1119 | ||
1120 | describe "at the beginning of the line", -> | |
1121 | beforeEach -> | |
1122 | editor.setCursorScreenPosition([0, 0]) | |
1123 | keydown('a') | |
1124 | ||
1125 | it "switches to insert mode and shifts to the right", -> | |
1126 | expect(editor.getCursorScreenPosition()).toEqual [0, 1] | |
1127 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
1128 | ||
1129 | describe "at the end of the line", -> | |
1130 | beforeEach -> | |
1131 | editor.setCursorScreenPosition([0, 3]) | |
1132 | keydown('a') | |
1133 | ||
1134 | it "doesn't linewrap", -> | |
1135 | expect(editor.getCursorScreenPosition()).toEqual [0, 3] | |
1136 | ||
1137 | describe "the A keybinding", -> | |
1138 | beforeEach -> | |
1139 | editor.getBuffer().setText("11\n22\n") | |
1140 | ||
1141 | describe "at the beginning of a line", -> | |
1142 | it "switches to insert mode at the end of the line", -> | |
1143 | editor.setCursorScreenPosition([0, 0]) | |
1144 | keydown('A', shift: true) | |
1145 | ||
1146 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
1147 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
1148 | ||
1149 | it "repeats always as insert at the end of the line", -> | |
1150 | editor.setCursorScreenPosition([0, 0]) | |
1151 | keydown('A', shift: true) | |
1152 | editor.insertText("abc") | |
1153 | keydown 'escape' | |
1154 | editor.setCursorScreenPosition([1, 0]) | |
1155 | keydown '.' | |
1156 | ||
1157 | expect(editor.getText()).toBe "11abc\n22abc\n" | |
1158 | expect(editorElement.classList.contains('insert-mode')).toBe(false) | |
1159 | expect(editor.getCursorScreenPosition()).toEqual [1, 4] | |
1160 | ||
1161 | describe "the I keybinding", -> | |
1162 | beforeEach -> | |
1163 | editor.getBuffer().setText("11\n 22\n") | |
1164 | ||
1165 | describe "at the end of a line", -> | |
1166 | it "switches to insert mode at the beginning of the line", -> | |
1167 | editor.setCursorScreenPosition([0, 2]) | |
1168 | keydown('I', shift: true) | |
1169 | ||
1170 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
1171 | expect(editor.getCursorScreenPosition()).toEqual [0, 0] | |
1172 | ||
1173 | it "switches to insert mode after leading whitespace", -> | |
1174 | editor.setCursorScreenPosition([1, 4]) | |
1175 | keydown('I', shift: true) | |
1176 | ||
1177 | expect(editorElement.classList.contains('insert-mode')).toBe(true) | |
1178 | expect(editor.getCursorScreenPosition()).toEqual [1, 2] | |
1179 | ||
1180 | it "repeats always as insert at the first character of the line", -> | |
1181 | editor.setCursorScreenPosition([0, 2]) | |
1182 | keydown('I', shift: true) | |
1183 | editor.insertText("abc") | |
1184 | keydown 'escape' | |
1185 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
1186 | editor.setCursorScreenPosition([1, 4]) | |
1187 | keydown '.' | |
1188 | ||
1189 | expect(editor.getText()).toBe "abc11\n abc22\n" | |
1190 | expect(editorElement.classList.contains('insert-mode')).toBe(false) | |
1191 | expect(editor.getCursorScreenPosition()).toEqual [1, 4] | |
1192 | ||
1193 | describe "the J keybinding", -> | |
1194 | beforeEach -> | |
1195 | editor.getBuffer().setText("012\n 456\n") | |
1196 | editor.setCursorScreenPosition([0, 1]) | |
1197 | ||
1198 | describe "without repeating", -> | |
1199 | beforeEach -> keydown('J', shift: true) | |
1200 | ||
1201 | it "joins the contents of the current line with the one below it", -> | |
1202 | expect(editor.getText()).toBe "012 456\n" | |
1203 | ||
1204 | describe "with repeating", -> | |
1205 | beforeEach -> | |
1206 | editor.setText("12345\nabcde\nABCDE\nQWERT") | |
1207 | editor.setCursorScreenPosition([1, 1]) | |
1208 | keydown('2') | |
1209 | keydown('J', shift: true) | |
1210 | ||
1211 | describe "undo behavior", -> | |
1212 | beforeEach -> keydown('u') | |
1213 | ||
1214 | it "handles repeats", -> | |
1215 | expect(editor.getText()).toBe "12345\nabcde\nABCDE\nQWERT" | |
1216 | ||
1217 | describe "the > keybinding", -> | |
1218 | beforeEach -> | |
1219 | editor.setText("12345\nabcde\nABCDE") | |
1220 | ||
1221 | describe "on the last line", -> | |
1222 | beforeEach -> | |
1223 | editor.setCursorScreenPosition([2, 0]) | |
1224 | ||
1225 | describe "when followed by a >", -> | |
1226 | beforeEach -> | |
1227 | keydown('>') | |
1228 | keydown('>') | |
1229 | ||
1230 | it "indents the current line", -> | |
1231 | expect(editor.getText()).toBe "12345\nabcde\n ABCDE" | |
1232 | expect(editor.getCursorScreenPosition()).toEqual [2, 2] | |
1233 | ||
1234 | describe "on the first line", -> | |
1235 | beforeEach -> | |
1236 | editor.setCursorScreenPosition([0, 0]) | |
1237 | ||
1238 | describe "when followed by a >", -> | |
1239 | beforeEach -> | |
1240 | keydown('>') | |
1241 | keydown('>') | |
1242 | ||
1243 | it "indents the current line", -> | |
1244 | expect(editor.getText()).toBe " 12345\nabcde\nABCDE" | |
1245 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
1246 | ||
1247 | describe "when followed by a repeating >", -> | |
1248 | beforeEach -> | |
1249 | keydown('3') | |
1250 | keydown('>') | |
1251 | keydown('>') | |
1252 | ||
1253 | it "indents multiple lines at once", -> | |
1254 | expect(editor.getText()).toBe " 12345\n abcde\n ABCDE" | |
1255 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
1256 | ||
1257 | describe "undo behavior", -> | |
1258 | beforeEach -> keydown('u') | |
1259 | ||
1260 | it "outdents all three lines", -> | |
1261 | expect(editor.getText()).toBe "12345\nabcde\nABCDE" | |
1262 | ||
1263 | describe "in visual mode", -> | |
1264 | beforeEach -> | |
1265 | editor.setCursorScreenPosition([0, 0]) | |
1266 | keydown('v', shift: true) | |
1267 | keydown('>') | |
1268 | ||
1269 | it "indents the current line and remains in visual mode", -> | |
1270 | expect(editorElement.classList.contains('visual-mode')).toBe(true) | |
1271 | expect(editor.getText()).toBe " 12345\nabcde\nABCDE" | |
1272 | expect(editor.getSelectedText()).toBe " 12345\n" | |
1273 | ||
1274 | it "allows repeating the operation", -> | |
1275 | keydown("escape") | |
1276 | keydown(".") | |
1277 | expect(editorElement.classList.contains('command-mode')).toBe(true) | |
1278 | expect(editor.getText()).toBe " 12345\nabcde\nABCDE" | |
1279 | ||
1280 | describe "the < keybinding", -> | |
1281 | beforeEach -> | |
1282 | editor.setText(" 12345\n abcde\nABCDE") | |
1283 | editor.setCursorScreenPosition([0, 0]) | |
1284 | ||
1285 | describe "when followed by a <", -> | |
1286 | beforeEach -> | |
1287 | keydown('<') | |
1288 | keydown('<') | |
1289 | ||
1290 | it "indents the current line", -> | |
1291 | expect(editor.getText()).toBe "12345\n abcde\nABCDE" | |
1292 | expect(editor.getCursorScreenPosition()).toEqual [0, 0] | |
1293 | ||
1294 | describe "when followed by a repeating <", -> | |
1295 | beforeEach -> | |
1296 | keydown('2') | |
1297 | keydown('<') | |
1298 | keydown('<') | |
1299 | ||
1300 | it "indents multiple lines at once", -> | |
1301 | expect(editor.getText()).toBe "12345\nabcde\nABCDE" | |
1302 | expect(editor.getCursorScreenPosition()).toEqual [0, 0] | |
1303 | ||
1304 | describe "undo behavior", -> | |
1305 | beforeEach -> keydown('u') | |
1306 | ||
1307 | it "indents both lines", -> | |
1308 | expect(editor.getText()).toBe " 12345\n abcde\nABCDE" | |
1309 | ||
1310 | describe "in visual mode", -> | |
1311 | beforeEach -> | |
1312 | keydown('v', shift: true) | |
1313 | keydown('<') | |
1314 | ||
1315 | it "indents the current line and remains in visual mode", -> | |
1316 | expect(editorElement.classList.contains('visual-mode')).toBe(true) | |
1317 | expect(editor.getText()).toBe "12345\n abcde\nABCDE" | |
1318 | expect(editor.getSelectedText()).toBe "12345\n" | |
1319 | ||
1320 | describe "the = keybinding", -> | |
1321 | oldGrammar = [] | |
1322 | ||
1323 | beforeEach -> | |
1324 | waitsForPromise -> | |
1325 | atom.packages.activatePackage('language-javascript') | |
1326 | ||
1327 | oldGrammar = editor.getGrammar() | |
1328 | editor.setText("foo\n bar\n baz") | |
1329 | editor.setCursorScreenPosition([1, 0]) | |
1330 | ||
1331 | describe "when used in a scope that supports auto-indent", -> | |
1332 | beforeEach -> | |
1333 | jsGrammar = atom.grammars.grammarForScopeName('source.js') | |
1334 | editor.setGrammar(jsGrammar) | |
1335 | ||
1336 | afterEach -> | |
1337 | editor.setGrammar(oldGrammar) | |
1338 | ||
1339 | describe "when followed by a =", -> | |
1340 | beforeEach -> | |
1341 | keydown('=') | |
1342 | keydown('=') | |
1343 | ||
1344 | it "indents the current line", -> | |
1345 | expect(editor.indentationForBufferRow(1)).toBe 0 | |
1346 | ||
1347 | describe "when followed by a repeating =", -> | |
1348 | beforeEach -> | |
1349 | keydown('2') | |
1350 | keydown('=') | |
1351 | keydown('=') | |
1352 | ||
1353 | it "autoindents multiple lines at once", -> | |
1354 | expect(editor.getText()).toBe "foo\nbar\nbaz" | |
1355 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
1356 | ||
1357 | describe "undo behavior", -> | |
1358 | beforeEach -> keydown('u') | |
1359 | ||
1360 | it "indents both lines", -> | |
1361 | expect(editor.getText()).toBe "foo\n bar\n baz" | |
1362 | ||
1363 | describe "the . keybinding", -> | |
1364 | beforeEach -> | |
1365 | editor.setText("12\n34\n56\n78") | |
1366 | editor.setCursorScreenPosition([0, 0]) | |
1367 | ||
1368 | it "repeats the last operation", -> | |
1369 | keydown '2' | |
1370 | keydown 'd' | |
1371 | keydown 'd' | |
1372 | keydown '.' | |
1373 | ||
1374 | expect(editor.getText()).toBe "" | |
1375 | ||
1376 | it "composes with motions", -> | |
1377 | keydown 'd' | |
1378 | keydown 'd' | |
1379 | keydown '2' | |
1380 | keydown '.' | |
1381 | ||
1382 | expect(editor.getText()).toBe "78" | |
1383 | ||
1384 | describe "the r keybinding", -> | |
1385 | beforeEach -> | |
1386 | editor.setText("12\n34\n\n") | |
1387 | editor.setCursorBufferPosition([0, 0]) | |
1388 | editor.addCursorAtBufferPosition([1, 0]) | |
1389 | ||
1390 | it "replaces a single character", -> | |
1391 | keydown('r') | |
1392 | commandModeInputKeydown('x') | |
1393 | expect(editor.getText()).toBe 'x2\nx4\n\n' | |
1394 | ||
1395 | it "does nothing when cancelled", -> | |
1396 | keydown('r') | |
1397 | expect(editorElement.classList.contains('operator-pending-mode')).toBe(true) | |
1398 | keydown('escape') | |
1399 | expect(editor.getText()).toBe '12\n34\n\n' | |
1400 | expect(editorElement.classList.contains('command-mode')).toBe(true) | |
1401 | ||
1402 | it "replaces a single character with a line break", -> | |
1403 | keydown('r') | |
1404 | atom.commands.dispatch(editor.commandModeInputView.editorElement, 'core:confirm') | |
1405 | expect(editor.getText()).toBe '\n2\n\n4\n\n' | |
1406 | expect(editor.getCursorBufferPositions()).toEqual [[1, 0], [3, 0]] | |
1407 | ||
1408 | it "composes properly with motions", -> | |
1409 | keydown('2') | |
1410 | keydown('r') | |
1411 | commandModeInputKeydown('x') | |
1412 | expect(editor.getText()).toBe 'xx\nxx\n\n' | |
1413 | ||
1414 | it "does nothing on an empty line", -> | |
1415 | editor.setCursorBufferPosition([2, 0]) | |
1416 | keydown('r') | |
1417 | commandModeInputKeydown('x') | |
1418 | expect(editor.getText()).toBe '12\n34\n\n' | |
1419 | ||
1420 | it "does nothing if asked to replace more characters than there are on a line", -> | |
1421 | keydown('3') | |
1422 | keydown('r') | |
1423 | commandModeInputKeydown('x') | |
1424 | expect(editor.getText()).toBe '12\n34\n\n' | |
1425 | ||
1426 | describe "when in visual mode", -> | |
1427 | beforeEach -> | |
1428 | keydown('v') | |
1429 | keydown('e') | |
1430 | ||
1431 | it "replaces the entire selection with the given character", -> | |
1432 | keydown('r') | |
1433 | commandModeInputKeydown('x') | |
1434 | expect(editor.getText()).toBe 'xx\nxx\n\n' | |
1435 | ||
1436 | it "leaves the cursor at the beginning of the selection", -> | |
1437 | keydown('r') | |
1438 | commandModeInputKeydown('x') | |
1439 | expect(editor.getCursorBufferPositions()).toEqual [[0, 0], [1, 0]] | |
1440 | ||
1441 | describe 'the m keybinding', -> | |
1442 | beforeEach -> | |
1443 | editor.setText('12\n34\n56\n') | |
1444 | editor.setCursorBufferPosition([0, 1]) | |
1445 | ||
1446 | it 'marks a position', -> | |
1447 | keydown('m') | |
1448 | commandModeInputKeydown('a') | |
1449 | expect(vimState.getMark('a')).toEqual [0, 1] | |
1450 | ||
1451 | describe 'the ~ keybinding', -> | |
1452 | beforeEach -> | |
1453 | editor.setText('aBc\nXyZ') | |
1454 | editor.setCursorBufferPosition([0, 0]) | |
1455 | editor.addCursorAtBufferPosition([1, 0]) | |
1456 | ||
1457 | it 'toggles the case and moves right', -> | |
1458 | keydown('~') | |
1459 | expect(editor.getText()).toBe 'ABc\nxyZ' | |
1460 | expect(editor.getCursorScreenPositions()).toEqual [[0, 1], [1, 1]] | |
1461 | ||
1462 | keydown('~') | |
1463 | expect(editor.getText()).toBe 'Abc\nxYZ' | |
1464 | expect(editor.getCursorScreenPositions()).toEqual [[0, 2], [1, 2]] | |
1465 | ||
1466 | keydown('~') | |
1467 | expect(editor.getText()).toBe 'AbC\nxYz' | |
1468 | expect(editor.getCursorScreenPositions()).toEqual [[0, 2], [1, 2]] | |
1469 | ||
1470 | it 'takes a count', -> | |
1471 | keydown('4') | |
1472 | keydown('~') | |
1473 | ||
1474 | expect(editor.getText()).toBe 'AbC\nxYz' | |
1475 | expect(editor.getCursorScreenPositions()).toEqual [[0, 2], [1, 2]] | |
1476 | ||
1477 | describe "in visual mode", -> | |
1478 | it "toggles the case of the selected text", -> | |
1479 | editor.setCursorBufferPosition([0, 0]) | |
1480 | keydown("V", shift: true) | |
1481 | keydown("~") | |
1482 | expect(editor.getText()).toBe 'AbC\nXyZ' | |
1483 | ||
1484 | describe "with g and motion", -> | |
1485 | it "toggles the case of text", -> | |
1486 | editor.setCursorBufferPosition([0, 0]) | |
1487 | keydown("g") | |
1488 | keydown("~") | |
1489 | keydown("2") | |
1490 | keydown("l") | |
1491 | expect(editor.getText()).toBe 'Abc\nXyZ' | |
1492 | ||
1493 | describe 'the U keybinding', -> | |
1494 | beforeEach -> | |
1495 | editor.setText('aBc\nXyZ') | |
1496 | editor.setCursorBufferPosition([0, 0]) | |
1497 | ||
1498 | it "makes text uppercase with g and motion", -> | |
1499 | keydown("g") | |
1500 | keydown("U", shift: true) | |
1501 | keydown("l") | |
1502 | expect(editor.getText()).toBe 'ABc\nXyZ' | |
1503 | ||
1504 | keydown("g") | |
1505 | keydown("U", shift: true) | |
1506 | keydown("e") | |
1507 | expect(editor.getText()).toBe 'ABC\nXyZ' | |
1508 | ||
1509 | editor.setCursorBufferPosition([1, 0]) | |
1510 | keydown("g") | |
1511 | keydown("U", shift: true) | |
1512 | keydown("$") | |
1513 | expect(editor.getText()).toBe 'ABC\nXYZ' | |
1514 | expect(editor.getCursorScreenPosition()).toEqual [1, 2] | |
1515 | ||
1516 | it "makes the selected text uppercase in visual mode", -> | |
1517 | keydown("V", shift: true) | |
1518 | keydown("U", shift: true) | |
1519 | expect(editor.getText()).toBe 'ABC\nXyZ' | |
1520 | ||
1521 | describe 'the u keybinding', -> | |
1522 | beforeEach -> | |
1523 | editor.setText('aBc\nXyZ') | |
1524 | editor.setCursorBufferPosition([0, 0]) | |
1525 | ||
1526 | it "makes text lowercase with g and motion", -> | |
1527 | keydown("g") | |
1528 | keydown("u") | |
1529 | keydown("$") | |
1530 | expect(editor.getText()).toBe 'abc\nXyZ' | |
1531 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
1532 | ||
1533 | it "makes the selected text lowercase in visual mode", -> | |
1534 | keydown("V", shift: true) | |
1535 | keydown("u") | |
1536 | expect(editor.getText()).toBe 'abc\nXyZ' | |
1537 | ||
1538 | describe "the i keybinding", -> | |
1539 | beforeEach -> | |
1540 | editor.setText('123\n4567') | |
1541 | editor.setCursorBufferPosition([0, 0]) | |
1542 | editor.addCursorAtBufferPosition([1, 0]) | |
1543 | ||
1544 | it "allows undoing an entire batch of typing", -> | |
1545 | keydown 'i' | |
1546 | editor.insertText("abcXX") | |
1547 | editor.backspace() | |
1548 | editor.backspace() | |
1549 | keydown 'escape' | |
1550 | expect(editor.getText()).toBe "abc123\nabc4567" | |
1551 | ||
1552 | keydown 'i' | |
1553 | editor.insertText "d" | |
1554 | editor.insertText "e" | |
1555 | editor.insertText "f" | |
1556 | keydown 'escape' | |
1557 | expect(editor.getText()).toBe "abdefc123\nabdefc4567" | |
1558 | ||
1559 | keydown 'u' | |
1560 | expect(editor.getText()).toBe "abc123\nabc4567" | |
1561 | ||
1562 | keydown 'u' | |
1563 | expect(editor.getText()).toBe "123\n4567" | |
1564 | ||
1565 | it "allows repeating typing", -> | |
1566 | keydown 'i' | |
1567 | editor.insertText("abcXX") | |
1568 | editor.backspace() | |
1569 | editor.backspace() | |
1570 | keydown 'escape' | |
1571 | expect(editor.getText()).toBe "abc123\nabc4567" | |
1572 | ||
1573 | keydown '.' | |
1574 | expect(editor.getText()).toBe "ababcc123\nababcc4567" | |
1575 | ||
1576 | keydown '.' | |
1577 | expect(editor.getText()).toBe "abababccc123\nabababccc4567" | |
1578 | ||
1579 | describe 'with nonlinear input', -> | |
1580 | beforeEach -> | |
1581 | editor.setText '' | |
1582 | editor.setCursorBufferPosition [0, 0] | |
1583 | ||
1584 | it 'deals with auto-matched brackets', -> | |
1585 | keydown 'i' | |
1586 | # this sequence simulates what the bracket-matcher package does | |
1587 | # when the user types (a)b<enter> | |
1588 | editor.insertText '()' | |
1589 | editor.moveLeft() | |
1590 | editor.insertText 'a' | |
1591 | editor.moveRight() | |
1592 | editor.insertText 'b\n' | |
1593 | keydown 'escape' | |
1594 | expect(editor.getCursorScreenPosition()).toEqual [1, 0] | |
1595 | ||
1596 | keydown '.' | |
1597 | expect(editor.getText()).toBe '(a)b\n(a)b\n' | |
1598 | expect(editor.getCursorScreenPosition()).toEqual [2, 0] | |
1599 | ||
1600 | it 'deals with autocomplete', -> | |
1601 | keydown 'i' | |
1602 | # this sequence simulates autocompletion of 'add' to 'addFoo' | |
1603 | editor.insertText 'a' | |
1604 | editor.insertText 'd' | |
1605 | editor.insertText 'd' | |
1606 | editor.setTextInBufferRange [[0, 0], [0, 3]], 'addFoo' | |
1607 | keydown 'escape' | |
1608 | expect(editor.getCursorScreenPosition()).toEqual [0, 5] | |
1609 | expect(editor.getText()).toBe 'addFoo' | |
1610 | ||
1611 | keydown '.' | |
1612 | expect(editor.getText()).toBe 'addFoaddFooo' | |
1613 | expect(editor.getCursorScreenPosition()).toEqual [0, 10] | |
1614 | ||
1615 | describe 'the a keybinding', -> | |
1616 | beforeEach -> | |
1617 | editor.setText('') | |
1618 | editor.setCursorBufferPosition([0, 0]) | |
1619 | ||
1620 | it "can be undone in one go", -> | |
1621 | keydown 'a' | |
1622 | editor.insertText("abc") | |
1623 | keydown 'escape' | |
1624 | expect(editor.getText()).toBe "abc" | |
1625 | keydown 'u' | |
1626 | expect(editor.getText()).toBe "" | |
1627 | ||
1628 | it "repeats correctly", -> | |
1629 | keydown 'a' | |
1630 | editor.insertText("abc") | |
1631 | keydown 'escape' | |
1632 | expect(editor.getText()).toBe "abc" | |
1633 | expect(editor.getCursorScreenPosition()).toEqual [0, 2] | |
1634 | keydown '.' | |
1635 | expect(editor.getText()).toBe "abcabc" | |
1636 | expect(editor.getCursorScreenPosition()).toEqual [0, 5] | |
1637 | ||
1638 | describe "the ctrl-a/ctrl-x keybindings", -> | |
1639 | beforeEach -> | |
1640 | atom.config.set 'vim-mode.numberRegex', settings.config.numberRegex.default | |
1641 | editor.setText('123\nab45\ncd-67ef\nab-5\na-bcdef') | |
1642 | editor.setCursorBufferPosition [0, 0] | |
1643 | editor.addCursorAtBufferPosition [1, 0] | |
1644 | editor.addCursorAtBufferPosition [2, 0] | |
1645 | editor.addCursorAtBufferPosition [3, 3] | |
1646 | editor.addCursorAtBufferPosition [4, 0] | |
1647 | ||
1648 | describe "increasing numbers", -> | |
1649 | it "increases the next number", -> | |
1650 | keydown('a', ctrl: true) | |
1651 | expect(editor.getCursorBufferPositions()).toEqual [[0, 2], [1, 3], [2, 4], [3, 3], [4, 0]] | |
1652 | expect(editor.getText()).toBe '124\nab46\ncd-66ef\nab-4\na-bcdef' | |
1653 | ||
1654 | it "repeats with .", -> | |
1655 | keydown 'a', ctrl: true | |
1656 | keydown '.' | |
1657 | expect(editor.getCursorBufferPositions()).toEqual [[0, 2], [1, 3], [2, 4], [3, 3], [4, 0]] | |
1658 | expect(editor.getText()).toBe '125\nab47\ncd-65ef\nab-3\na-bcdef' | |
1659 | ||
1660 | it "can have a count", -> | |
1661 | keydown '5' | |
1662 | keydown 'a', ctrl: true | |
1663 | expect(editor.getCursorBufferPositions()).toEqual [[0, 2], [1, 3], [2, 4], [3, 2], [4, 0]] | |
1664 | expect(editor.getText()).toBe '128\nab50\ncd-62ef\nab0\na-bcdef' | |
1665 | ||
1666 | it "can make a negative number positive, change number of digits", -> | |
1667 | keydown '9' | |
1668 | keydown '9' | |
1669 | keydown 'a', ctrl: true | |
1670 | expect(editor.getCursorBufferPositions()).toEqual [[0, 2], [1, 4], [2, 3], [3, 3], [4, 0]] | |
1671 | expect(editor.getText()).toBe '222\nab144\ncd32ef\nab94\na-bcdef' | |
1672 | ||
1673 | it "does nothing when cursor is after the number", -> | |
1674 | editor.setCursorBufferPosition [2, 5] | |
1675 | keydown 'a', ctrl: true | |
1676 | expect(editor.getCursorBufferPositions()).toEqual [[2, 5]] | |
1677 | expect(editor.getText()).toBe '123\nab45\ncd-67ef\nab-5\na-bcdef' | |
1678 | ||
1679 | it "does nothing on an empty line", -> | |
1680 | editor.setText('\n') | |
1681 | editor.setCursorBufferPosition [0, 0] | |
1682 | editor.addCursorAtBufferPosition [1, 0] | |
1683 | keydown 'a', ctrl: true | |
1684 | expect(editor.getCursorBufferPositions()).toEqual [[0, 0], [1, 0]] | |
1685 | expect(editor.getText()).toBe '\n' | |
1686 | ||
1687 | it "honours the vim-mode:numberRegex setting", -> | |
1688 | editor.setText('123\nab45\ncd -67ef\nab-5\na-bcdef') | |
1689 | editor.setCursorBufferPosition [0, 0] | |
1690 | editor.addCursorAtBufferPosition [1, 0] | |
1691 | editor.addCursorAtBufferPosition [2, 0] | |
1692 | editor.addCursorAtBufferPosition [3, 3] | |
1693 | editor.addCursorAtBufferPosition [4, 0] | |
1694 | atom.config.set('vim-mode.numberRegex', '(?:\\B-)?[0-9]+') | |
1695 | keydown('a', ctrl: true) | |
1696 | expect(editor.getCursorBufferPositions()).toEqual [[0, 2], [1, 3], [2, 5], [3, 3], [4, 0]] | |
1697 | expect(editor.getText()).toBe '124\nab46\ncd -66ef\nab-6\na-bcdef' | |
1698 | ||
1699 | describe "decreasing numbers", -> | |
1700 | it "decreases the next number", -> | |
1701 | keydown('x', ctrl: true) | |
1702 | expect(editor.getCursorBufferPositions()).toEqual [[0, 2], [1, 3], [2, 4], [3, 3], [4, 0]] | |
1703 | expect(editor.getText()).toBe '122\nab44\ncd-68ef\nab-6\na-bcdef' | |
1704 | ||
1705 | it "repeats with .", -> | |
1706 | keydown 'x', ctrl: true | |
1707 | keydown '.' | |
1708 | expect(editor.getCursorBufferPositions()).toEqual [[0, 2], [1, 3], [2, 4], [3, 3], [4, 0]] | |
1709 | expect(editor.getText()).toBe '121\nab43\ncd-69ef\nab-7\na-bcdef' | |
1710 | ||
1711 | it "can have a count", -> | |
1712 | keydown '5' | |
1713 | keydown 'x', ctrl: true | |
1714 | expect(editor.getCursorBufferPositions()).toEqual [[0, 2], [1, 3], [2, 4], [3, 4], [4, 0]] | |
1715 | expect(editor.getText()).toBe '118\nab40\ncd-72ef\nab-10\na-bcdef' | |
1716 | ||
1717 | it "can make a positive number negative, change number of digits", -> | |
1718 | keydown '9' | |
1719 | keydown '9' | |
1720 | keydown 'x', ctrl: true | |
1721 | expect(editor.getCursorBufferPositions()).toEqual [[0, 1], [1, 4], [2, 5], [3, 5], [4, 0]] | |
1722 | expect(editor.getText()).toBe '24\nab-54\ncd-166ef\nab-104\na-bcdef' | |
1723 | ||
1724 | it "does nothing when cursor is after the number", -> | |
1725 | editor.setCursorBufferPosition [2, 5] | |
1726 | keydown 'x', ctrl: true | |
1727 | expect(editor.getCursorBufferPositions()).toEqual [[2, 5]] | |
1728 | expect(editor.getText()).toBe '123\nab45\ncd-67ef\nab-5\na-bcdef' | |
1729 | ||
1730 | it "does nothing on an empty line", -> | |
1731 | editor.setText('\n') | |
1732 | editor.setCursorBufferPosition [0, 0] | |
1733 | editor.addCursorAtBufferPosition [1, 0] | |
1734 | keydown 'x', ctrl: true | |
1735 | expect(editor.getCursorBufferPositions()).toEqual [[0, 0], [1, 0]] | |
1736 | expect(editor.getText()).toBe '\n' | |
1737 | ||
1738 | it "honours the vim-mode:numberRegex setting", -> | |
1739 | editor.setText('123\nab45\ncd -67ef\nab-5\na-bcdef') | |
1740 | editor.setCursorBufferPosition [0, 0] | |
1741 | editor.addCursorAtBufferPosition [1, 0] | |
1742 | editor.addCursorAtBufferPosition [2, 0] | |
1743 | editor.addCursorAtBufferPosition [3, 3] | |
1744 | editor.addCursorAtBufferPosition [4, 0] | |
1745 | atom.config.set('vim-mode.numberRegex', '(?:\\B-)?[0-9]+') | |
1746 | keydown('x', ctrl: true) | |
1747 | expect(editor.getCursorBufferPositions()).toEqual [[0, 2], [1, 3], [2, 5], [3, 3], [4, 0]] | |
1748 | expect(editor.getText()).toBe '122\nab44\ncd -68ef\nab-4\na-bcdef' |