]> git.r.bdr.sh - rbdr/dotfiles/blob - atom/packages/vim-mode/spec/operators-spec.coffee
a41edb361b38f5ce6106b401c1379e366a79b6ac
[rbdr/dotfiles] / atom / packages / vim-mode / spec / operators-spec.coffee
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'