1 helpers = require './spec-helper'
4 [editor, editorElement, vimState] = []
7 vimMode = atom.packages.loadPackage('vim-mode')
8 vimMode.activateResources()
10 helpers.getEditorElement (element) ->
11 editorElement = element
12 editor = editorElement.getModel()
13 vimState = editorElement.vimState
14 vimState.activateNormalMode()
15 vimState.resetNormalMode()
17 keydown = (key, options={}) ->
18 options.element ?= editorElement
19 helpers.keydown(key, options)
21 normalModeInputKeydown = (key, opts = {}) ->
22 theEditor = opts.editor or editor
23 theEditor.normalModeInputView.editorElement.getModel().setText(key)
25 submitNormalModeInputText = (text) ->
26 inputEditor = editor.normalModeInputView.editorElement
27 inputEditor.getModel().setText(text)
28 atom.commands.dispatch(inputEditor, "core:confirm")
30 describe "simple motions", ->
32 editor.setText("12345\nabcd\nABCDE")
33 editor.setCursorScreenPosition([1, 1])
35 describe "the h keybinding", ->
36 describe "as a motion", ->
37 it "moves the cursor left, but not to the previous line", ->
39 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
42 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
44 it "moves the cursor to the previous line if wrapLeftRightMotion is true", ->
45 atom.config.set('vim-mode.wrapLeftRightMotion', true)
48 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
50 describe "as a selection", ->
51 it "selects the character to the left", ->
55 expect(vimState.getRegister('"').text).toBe 'a'
56 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
58 describe "the j keybinding", ->
59 it "moves the cursor down, but not to the end of the last line", ->
61 expect(editor.getCursorScreenPosition()).toEqual [2, 1]
64 expect(editor.getCursorScreenPosition()).toEqual [2, 1]
66 it "moves the cursor to the end of the line, not past it", ->
67 editor.setCursorScreenPosition([0, 4])
70 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
72 it "remembers the position it column it was in after moving to shorter line", ->
73 editor.setCursorScreenPosition([0, 4])
76 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
79 expect(editor.getCursorScreenPosition()).toEqual [2, 4]
81 describe "when visual mode", ->
84 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
86 it "moves the cursor down", ->
88 expect(editor.getCursorScreenPosition()).toEqual [2, 2]
90 it "doesn't go over after the last line", ->
92 expect(editor.getCursorScreenPosition()).toEqual [2, 2]
94 it "selects the text while moving", ->
96 expect(editor.getSelectedText()).toBe "bcd\nAB"
98 describe "the k keybinding", ->
99 it "moves the cursor up, but not to the beginning of the first line", ->
101 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
104 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
106 describe "the l keybinding", ->
107 beforeEach -> editor.setCursorScreenPosition([1, 2])
109 it "moves the cursor right, but not to the next line", ->
111 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
114 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
116 it "moves the cursor to the next line if wrapLeftRightMotion is true", ->
117 atom.config.set('vim-mode.wrapLeftRightMotion', true)
120 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
122 describe "on a blank line", ->
123 it "doesn't move the cursor", ->
124 editor.setText("\n\n\n")
125 editor.setCursorBufferPosition([1, 0])
127 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
129 describe "the w keybinding", ->
130 beforeEach -> editor.setText("ab cde1+- \n xyz\n\nzip")
132 describe "as a motion", ->
133 beforeEach -> editor.setCursorScreenPosition([0, 0])
135 it "moves the cursor to the beginning of the next word", ->
137 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
140 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
143 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
146 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
149 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
152 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
154 # When the cursor gets to the EOF, it should stay there.
156 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
158 it "moves the cursor to the end of the word if last word in file", ->
159 editor.setText("abc")
160 editor.setCursorScreenPosition([0, 0])
162 expect(editor.getCursorScreenPosition()).toEqual([0, 2])
164 describe "as a selection", ->
165 describe "within a word", ->
167 editor.setCursorScreenPosition([0, 0])
171 it "selects to the end of the word", ->
172 expect(vimState.getRegister('"').text).toBe 'ab '
174 describe "between words", ->
176 editor.setCursorScreenPosition([0, 2])
180 it "selects the whitespace", ->
181 expect(vimState.getRegister('"').text).toBe ' '
183 describe "the W keybinding", ->
184 beforeEach -> editor.setText("cde1+- ab \n xyz\n\nzip")
186 describe "as a motion", ->
187 beforeEach -> editor.setCursorScreenPosition([0, 0])
189 it "moves the cursor to the beginning of the next word", ->
190 keydown('W', shift: true)
191 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
193 keydown('W', shift: true)
194 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
196 keydown('W', shift: true)
197 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
199 keydown('W', shift: true)
200 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
202 describe "as a selection", ->
203 describe "within a word", ->
204 it "selects to the end of the whole word", ->
205 editor.setCursorScreenPosition([0, 0])
207 keydown('W', shift: true)
208 expect(vimState.getRegister('"').text).toBe 'cde1+- '
210 it "continues past blank lines", ->
211 editor.setCursorScreenPosition([2, 0])
214 keydown('W', shift: true)
215 expect(editor.getText()).toBe "cde1+- ab \n xyz\nzip"
216 expect(vimState.getRegister('"').text).toBe '\n'
218 it "doesn't go past the end of the file", ->
219 editor.setCursorScreenPosition([3, 0])
222 keydown('W', shift: true)
223 expect(editor.getText()).toBe "cde1+- ab \n xyz\n\n"
224 expect(vimState.getRegister('"').text).toBe 'zip'
226 describe "the e keybinding", ->
227 beforeEach -> editor.setText("ab cde1+- \n xyz\n\nzip")
229 describe "as a motion", ->
230 beforeEach -> editor.setCursorScreenPosition([0, 0])
232 it "moves the cursor to the end of the current word", ->
234 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
237 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
240 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
243 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
246 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
248 describe "as selection", ->
249 describe "within a word", ->
251 editor.setCursorScreenPosition([0, 0])
255 it "selects to the end of the current word", ->
256 expect(vimState.getRegister('"').text).toBe 'ab'
258 describe "between words", ->
260 editor.setCursorScreenPosition([0, 2])
264 it "selects to the end of the next word", ->
265 expect(vimState.getRegister('"').text).toBe ' cde1'
267 describe "the E keybinding", ->
268 beforeEach -> editor.setText("ab cde1+- \n xyz \n\nzip\n")
270 describe "as a motion", ->
271 beforeEach -> editor.setCursorScreenPosition([0, 0])
273 it "moves the cursor to the end of the current word", ->
274 keydown('E', shift: true)
275 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
277 keydown('E', shift: true)
278 expect(editor.getCursorScreenPosition()).toEqual [0, 9]
280 keydown('E', shift: true)
281 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
283 keydown('E', shift: true)
284 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
286 keydown('E', shift: true)
287 expect(editor.getCursorScreenPosition()).toEqual [4, 0]
289 describe "as selection", ->
290 describe "within a word", ->
292 editor.setCursorScreenPosition([0, 0])
294 keydown('E', shift: true)
296 it "selects to the end of the current word", ->
297 expect(vimState.getRegister('"').text).toBe 'ab'
299 describe "between words", ->
301 editor.setCursorScreenPosition([0, 2])
303 keydown('E', shift: true)
305 it "selects to the end of the next word", ->
306 expect(vimState.getRegister('"').text).toBe ' cde1+-'
308 describe "press more than once", ->
310 editor.setCursorScreenPosition([0, 0])
312 keydown('E', shift: true)
313 keydown('E', shift: true)
316 it "selects to the end of the current word", ->
317 expect(vimState.getRegister('"').text).toBe 'ab cde1+-'
319 describe "the } keybinding", ->
321 editor.setText("abcde\n\nfghij\nhijk\n xyz \n\nzip\n\n \nthe end")
322 editor.setCursorScreenPosition([0, 0])
324 describe "as a motion", ->
325 it "moves the cursor to the end of the paragraph", ->
327 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
330 expect(editor.getCursorScreenPosition()).toEqual [5, 0]
333 expect(editor.getCursorScreenPosition()).toEqual [7, 0]
336 expect(editor.getCursorScreenPosition()).toEqual [9, 6]
338 describe "as a selection", ->
343 it 'selects to the end of the current paragraph', ->
344 expect(vimState.getRegister('"').text).toBe "abcde\n"
346 describe "the { keybinding", ->
348 editor.setText("abcde\n\nfghij\nhijk\n xyz \n\nzip\n\n \nthe end")
349 editor.setCursorScreenPosition([9, 0])
351 describe "as a motion", ->
352 it "moves the cursor to the beginning of the paragraph", ->
354 expect(editor.getCursorScreenPosition()).toEqual [7, 0]
357 expect(editor.getCursorScreenPosition()).toEqual [5, 0]
360 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
363 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
365 describe "as a selection", ->
367 editor.setCursorScreenPosition([7, 0])
371 it 'selects to the beginning of the current paragraph', ->
372 expect(vimState.getRegister('"').text).toBe "\nzip\n"
374 describe "the b keybinding", ->
375 beforeEach -> editor.setText(" ab cde1+- \n xyz\n\nzip }\n last")
377 describe "as a motion", ->
378 beforeEach -> editor.setCursorScreenPosition([4, 1])
380 it "moves the cursor to the beginning of the previous word", ->
382 expect(editor.getCursorScreenPosition()).toEqual [3, 4]
385 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
388 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
391 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
394 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
397 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
400 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
402 # Go to start of the file, after moving past the first word
404 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
406 # Stay at the start of the file
408 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
410 describe "as a selection", ->
411 describe "within a word", ->
413 editor.setCursorScreenPosition([0, 2])
417 it "selects to the beginning of the current word", ->
418 expect(vimState.getRegister('"').text).toBe 'a'
419 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
421 describe "between words", ->
423 editor.setCursorScreenPosition([0, 4])
427 it "selects to the beginning of the last word", ->
428 expect(vimState.getRegister('"').text).toBe 'ab '
429 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
431 describe "the B keybinding", ->
432 beforeEach -> editor.setText("cde1+- ab \n\t xyz-123\n\n zip")
434 describe "as a motion", ->
435 beforeEach -> editor.setCursorScreenPosition([4, 1])
437 it "moves the cursor to the beginning of the previous word", ->
438 keydown('B', shift: true)
439 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
441 keydown('B', shift: true)
442 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
444 keydown('B', shift: true)
445 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
447 keydown('B', shift: true)
448 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
450 keydown('B', shift: true)
451 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
453 describe "as a selection", ->
454 it "selects to the beginning of the whole word", ->
455 editor.setCursorScreenPosition([1, 9])
457 keydown('B', shift: true)
458 expect(vimState.getRegister('"').text).toBe 'xyz-12'
460 it "doesn't go past the beginning of the file", ->
461 editor.setCursorScreenPosition([0, 0])
462 vimState.setRegister('"', text: 'abc')
464 keydown('B', shift: true)
465 expect(vimState.getRegister('"').text).toBe 'abc'
467 describe "the ^ keybinding", ->
469 editor.setText(" abcde")
471 describe "from the beginning of the line", ->
472 beforeEach -> editor.setCursorScreenPosition([0, 0])
474 describe "as a motion", ->
475 beforeEach -> keydown('^')
477 it "moves the cursor to the first character of the line", ->
478 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
480 describe "as a selection", ->
485 it 'selects to the first character of the line', ->
486 expect(editor.getText()).toBe 'abcde'
487 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
489 describe "from the first character of the line", ->
490 beforeEach -> editor.setCursorScreenPosition([0, 2])
492 describe "as a motion", ->
493 beforeEach -> keydown('^')
496 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
498 describe "as a selection", ->
503 it "does nothing", ->
504 expect(editor.getText()).toBe ' abcde'
505 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
507 describe "from the middle of a word", ->
508 beforeEach -> editor.setCursorScreenPosition([0, 4])
510 describe "as a motion", ->
511 beforeEach -> keydown('^')
513 it "moves the cursor to the first character of the line", ->
514 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
516 describe "as a selection", ->
521 it 'selects to the first character of the line', ->
522 expect(editor.getText()).toBe ' cde'
523 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
525 describe "the 0 keybinding", ->
527 editor.setText(" abcde")
528 editor.setCursorScreenPosition([0, 4])
530 describe "as a motion", ->
531 beforeEach -> keydown('0')
533 it "moves the cursor to the first column", ->
534 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
536 describe "as a selection", ->
541 it 'selects to the first column of the line', ->
542 expect(editor.getText()).toBe 'cde'
543 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
545 describe "the $ keybinding", ->
547 editor.setText(" abcde\n\n1234567890")
548 editor.setCursorScreenPosition([0, 4])
550 describe "as a motion from empty line", ->
551 beforeEach -> editor.setCursorScreenPosition([1, 0])
553 it "moves the cursor to the end of the line", ->
554 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
556 describe "as a motion", ->
557 beforeEach -> keydown('$')
559 # FIXME: See atom/vim-mode#2
560 it "moves the cursor to the end of the line", ->
561 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
563 it "should remain in the last column when moving down", ->
565 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
568 expect(editor.getCursorScreenPosition()).toEqual [2, 9]
570 describe "as a selection", ->
575 it "selects to the beginning of the lines", ->
576 expect(editor.getText()).toBe " ab\n\n1234567890"
577 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
579 describe "the 0 keybinding", ->
581 editor.setText(" a\n")
582 editor.setCursorScreenPosition([0, 2])
584 describe "as a motion", ->
585 beforeEach -> keydown('0')
587 it "moves the cursor to the beginning of the line", ->
588 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
590 describe "the - keybinding", ->
592 editor.setText("abcdefg\n abc\n abc\n")
594 describe "from the middle of a line", ->
595 beforeEach -> editor.setCursorScreenPosition([1, 3])
597 describe "as a motion", ->
598 beforeEach -> keydown('-')
600 it "moves the cursor to the first character of the previous line", ->
601 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
603 describe "as a selection", ->
608 it "deletes the current and previous line", ->
609 expect(editor.getText()).toBe " abc\n"
610 # commented out because the column is wrong due to a bug in `k`; re-enable when `k` is fixed
611 #expect(editor.getCursorScreenPosition()).toEqual [0, 3]
613 describe "from the first character of a line indented the same as the previous one", ->
614 beforeEach -> editor.setCursorScreenPosition([2, 2])
616 describe "as a motion", ->
617 beforeEach -> keydown('-')
619 it "moves to the first character of the previous line (directly above)", ->
620 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
622 describe "as a selection", ->
627 it "selects to the first character of the previous line (directly above)", ->
628 expect(editor.getText()).toBe "abcdefg\n"
629 # commented out because the column is wrong due to a bug in `k`; re-enable when `k` is fixed
630 #expect(editor.getCursorScreenPosition()).toEqual [0, 2]
632 describe "from the beginning of a line preceded by an indented line", ->
633 beforeEach -> editor.setCursorScreenPosition([2, 0])
635 describe "as a motion", ->
636 beforeEach -> keydown('-')
638 it "moves the cursor to the first character of the previous line", ->
639 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
641 describe "as a selection", ->
646 it "selects to the first character of the previous line", ->
647 expect(editor.getText()).toBe "abcdefg\n"
648 # commented out because the column is wrong due to a bug in `k`; re-enable when `k` is fixed
649 #expect(editor.getCursorScreenPosition()).toEqual [0, 0]
651 describe "with a count", ->
653 editor.setText("1\n2\n3\n4\n5\n6\n")
654 editor.setCursorScreenPosition([4, 0])
656 describe "as a motion", ->
661 it "moves the cursor to the first character of that many lines previous", ->
662 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
664 describe "as a selection", ->
670 it "deletes the current line plus that many previous lines", ->
671 expect(editor.getText()).toBe "1\n6\n"
672 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
674 describe "the + keybinding", ->
676 editor.setText(" abc\n abc\nabcdefg\n")
678 describe "from the middle of a line", ->
679 beforeEach -> editor.setCursorScreenPosition([1, 3])
681 describe "as a motion", ->
682 beforeEach -> keydown('+')
684 it "moves the cursor to the first character of the next line", ->
685 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
687 describe "as a selection", ->
692 it "deletes the current and next line", ->
693 expect(editor.getText()).toBe " abc\n"
694 # commented out because the column is wrong due to a bug in `j`; re-enable when `j` is fixed
695 #expect(editor.getCursorScreenPosition()).toEqual [0, 3]
697 describe "from the first character of a line indented the same as the next one", ->
698 beforeEach -> editor.setCursorScreenPosition([0, 2])
700 describe "as a motion", ->
701 beforeEach -> keydown('+')
703 it "moves to the first character of the next line (directly below)", ->
704 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
706 describe "as a selection", ->
711 it "selects to the first character of the next line (directly below)", ->
712 expect(editor.getText()).toBe "abcdefg\n"
713 # commented out because the column is wrong due to a bug in `j`; re-enable when `j` is fixed
714 #expect(editor.getCursorScreenPosition()).toEqual [0, 2]
716 describe "from the beginning of a line followed by an indented line", ->
717 beforeEach -> editor.setCursorScreenPosition([0, 0])
719 describe "as a motion", ->
720 beforeEach -> keydown('+')
722 it "moves the cursor to the first character of the next line", ->
723 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
725 describe "as a selection", ->
730 it "selects to the first character of the next line", ->
731 expect(editor.getText()).toBe "abcdefg\n"
732 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
734 describe "with a count", ->
736 editor.setText("1\n2\n3\n4\n5\n6\n")
737 editor.setCursorScreenPosition([1, 0])
739 describe "as a motion", ->
744 it "moves the cursor to the first character of that many lines following", ->
745 expect(editor.getCursorScreenPosition()).toEqual [4, 0]
747 describe "as a selection", ->
753 it "deletes the current line plus that many following lines", ->
754 expect(editor.getText()).toBe "1\n6\n"
755 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
757 describe "the _ keybinding", ->
759 editor.setText(" abc\n abc\nabcdefg\n")
761 describe "from the middle of a line", ->
762 beforeEach -> editor.setCursorScreenPosition([1, 3])
764 describe "as a motion", ->
765 beforeEach -> keydown('_')
767 it "moves the cursor to the first character of the current line", ->
768 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
770 describe "as a selection", ->
775 it "deletes the current line", ->
776 expect(editor.getText()).toBe " abc\nabcdefg\n"
777 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
779 describe "with a count", ->
781 editor.setText("1\n2\n3\n4\n5\n6\n")
782 editor.setCursorScreenPosition([1, 0])
784 describe "as a motion", ->
789 it "moves the cursor to the first character of that many lines following", ->
790 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
792 describe "as a selection", ->
798 it "deletes the current line plus that many following lines", ->
799 expect(editor.getText()).toBe "1\n5\n6\n"
800 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
802 describe "the enter keybinding", ->
803 keydownCodeForEnter = '\r' # 'enter' does not work
804 startingText = " abc\n abc\nabcdefg\n"
806 describe "from the middle of a line", ->
807 startingCursorPosition = [1, 3]
809 describe "as a motion", ->
810 it "acts the same as the + keybinding", ->
811 # do it with + and save the results
812 editor.setText(startingText)
813 editor.setCursorScreenPosition(startingCursorPosition)
815 referenceCursorPosition = editor.getCursorScreenPosition()
816 # do it again with enter and compare the results
817 editor.setText(startingText)
818 editor.setCursorScreenPosition(startingCursorPosition)
819 keydown(keydownCodeForEnter)
820 expect(editor.getCursorScreenPosition()).toEqual referenceCursorPosition
822 describe "as a selection", ->
823 it "acts the same as the + keybinding", ->
824 # do it with + and save the results
825 editor.setText(startingText)
826 editor.setCursorScreenPosition(startingCursorPosition)
829 referenceText = editor.getText()
830 referenceCursorPosition = editor.getCursorScreenPosition()
831 # do it again with enter and compare the results
832 editor.setText(startingText)
833 editor.setCursorScreenPosition(startingCursorPosition)
835 keydown(keydownCodeForEnter)
836 expect(editor.getText()).toEqual referenceText
837 expect(editor.getCursorScreenPosition()).toEqual referenceCursorPosition
839 describe "the gg keybinding", ->
841 editor.setText(" 1abc\n 2\n3\n")
842 editor.setCursorScreenPosition([0, 2])
844 describe "as a motion", ->
845 describe "in normal mode", ->
850 it "moves the cursor to the beginning of the first line", ->
851 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
853 describe "in linewise visual mode", ->
855 editor.setCursorScreenPosition([1, 0])
856 vimState.activateVisualMode('linewise')
860 it "selects to the first line in the file", ->
861 expect(editor.getSelectedText()).toBe " 1abc\n 2\n"
863 it "moves the cursor to a specified line", ->
864 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
866 describe "in characterwise visual mode", ->
868 editor.setCursorScreenPosition([1, 1])
869 vimState.activateVisualMode()
873 it "selects to the first line in the file", ->
874 expect(editor.getSelectedText()).toBe "1abc\n 2"
876 it "moves the cursor to a specified line", ->
877 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
879 describe "as a repeated motion", ->
880 describe "in normal mode", ->
886 it "moves the cursor to a specified line", ->
887 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
889 describe "in linewise visual motion", ->
891 editor.setCursorScreenPosition([2, 0])
892 vimState.activateVisualMode('linewise')
897 it "selects to a specified line", ->
898 expect(editor.getSelectedText()).toBe " 2\n3\n"
900 it "moves the cursor to a specified line", ->
901 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
903 describe "in characterwise visual motion", ->
905 editor.setCursorScreenPosition([2, 0])
906 vimState.activateVisualMode()
911 it "selects to a first character of specified line", ->
912 expect(editor.getSelectedText()).toBe "2\n3"
914 it "moves the cursor to a specified line", ->
915 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
917 describe "the g_ keybinding", ->
919 editor.setText("1 \n 2 \n 3abc\n ")
921 describe "as a motion", ->
922 it "moves the cursor to the last nonblank character", ->
923 editor.setCursorScreenPosition([1, 0])
926 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
928 it "will move the cursor to the beginning of the line if necessary", ->
929 editor.setCursorScreenPosition([0, 2])
932 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
934 describe "as a repeated motion", ->
935 it "moves the cursor downward and outward", ->
936 editor.setCursorScreenPosition([0, 0])
940 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
942 describe "as a selection", ->
943 it "selects the current line excluding whitespace", ->
944 editor.setCursorScreenPosition([1, 2])
945 vimState.activateVisualMode()
949 expect(editor.getSelectedText()).toEqual " 2 \n 3abc"
951 describe "the G keybinding", ->
953 editor.setText("1\n 2\n 3abc\n ")
954 editor.setCursorScreenPosition([0, 2])
956 describe "as a motion", ->
957 beforeEach -> keydown('G', shift: true)
959 it "moves the cursor to the last line after whitespace", ->
960 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
962 describe "as a repeated motion", ->
965 keydown('G', shift: true)
967 it "moves the cursor to a specified line", ->
968 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
970 describe "as a selection", ->
972 editor.setCursorScreenPosition([1, 0])
973 vimState.activateVisualMode()
974 keydown('G', shift: true)
976 it "selects to the last line in the file", ->
977 expect(editor.getSelectedText()).toBe " 2\n 3abc\n "
979 it "moves the cursor to the last line after whitespace", ->
980 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
982 describe "the / keybinding", ->
986 pane = {activate: jasmine.createSpy("activate")}
987 spyOn(atom.workspace, 'getActivePane').andReturn(pane)
989 editor.setText("abc\ndef\nabc\ndef\n")
990 editor.setCursorBufferPosition([0, 0])
992 # clear search history
993 vimState.globalVimState.searchHistory = []
994 vimState.globalVimState.currentSearch = {}
996 describe "as a motion", ->
997 it "beeps when repeating nonexistent last search", ->
999 submitNormalModeInputText ''
1000 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1001 expect(atom.beep).toHaveBeenCalled()
1003 it "moves the cursor to the specified search pattern", ->
1006 submitNormalModeInputText 'def'
1008 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1009 expect(pane.activate).toHaveBeenCalled()
1010 expect(atom.beep).not.toHaveBeenCalled()
1012 it "loops back around", ->
1013 editor.setCursorBufferPosition([3, 0])
1015 submitNormalModeInputText 'def'
1017 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1018 expect(atom.beep).not.toHaveBeenCalled()
1020 it "uses a valid regex as a regex", ->
1022 # Cycle through the 'abc' on the first line with a character pattern
1023 submitNormalModeInputText '[abc]'
1024 expect(editor.getCursorBufferPosition()).toEqual [0, 1]
1026 expect(editor.getCursorBufferPosition()).toEqual [0, 2]
1027 expect(atom.beep).not.toHaveBeenCalled()
1029 it "uses an invalid regex as a literal string", ->
1030 # Go straight to the literal [abc
1031 editor.setText("abc\n[abc]\n")
1033 submitNormalModeInputText '[abc'
1034 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1036 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1037 expect(atom.beep).not.toHaveBeenCalled()
1039 it "uses ? as a literal string", ->
1040 editor.setText("abc\n[a?c?\n")
1042 submitNormalModeInputText '?'
1043 expect(editor.getCursorBufferPosition()).toEqual [1, 2]
1045 expect(editor.getCursorBufferPosition()).toEqual [1, 4]
1046 expect(atom.beep).not.toHaveBeenCalled()
1048 it 'works with selection in visual mode', ->
1049 editor.setText('one two three')
1052 submitNormalModeInputText 'th'
1053 expect(editor.getCursorBufferPosition()).toEqual [0, 9]
1055 expect(editor.getText()).toBe 'hree'
1056 expect(atom.beep).not.toHaveBeenCalled()
1058 it 'extends selection when repeating search in visual mode', ->
1059 editor.setText('line1\nline2\nline3')
1062 submitNormalModeInputText 'line'
1063 {start, end} = editor.getSelectedBufferRange()
1064 expect(start.row).toEqual 0
1065 expect(end.row).toEqual 1
1067 {start, end} = editor.getSelectedBufferRange()
1068 expect(start.row).toEqual 0
1069 expect(end.row).toEqual 2
1070 expect(atom.beep).not.toHaveBeenCalled()
1072 describe "case sensitivity", ->
1074 editor.setText("\nabc\nABC\n")
1075 editor.setCursorBufferPosition([0, 0])
1078 it "works in case sensitive mode", ->
1079 submitNormalModeInputText 'ABC'
1080 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1082 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1083 expect(atom.beep).not.toHaveBeenCalled()
1085 it "works in case insensitive mode", ->
1086 submitNormalModeInputText '\\cAbC'
1087 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1089 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1090 expect(atom.beep).not.toHaveBeenCalled()
1092 it "works in case insensitive mode wherever \\c is", ->
1093 submitNormalModeInputText 'AbC\\c'
1094 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1096 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1097 expect(atom.beep).not.toHaveBeenCalled()
1099 it "uses case insensitive search if useSmartcaseForSearch is true and searching lowercase", ->
1100 atom.config.set 'vim-mode.useSmartcaseForSearch', true
1101 submitNormalModeInputText 'abc'
1102 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1104 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1105 expect(atom.beep).not.toHaveBeenCalled()
1107 it "uses case sensitive search if useSmartcaseForSearch is true and searching uppercase", ->
1108 atom.config.set 'vim-mode.useSmartcaseForSearch', true
1109 submitNormalModeInputText 'ABC'
1110 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1112 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1113 expect(atom.beep).not.toHaveBeenCalled()
1115 describe "repeating", ->
1116 it "does nothing with no search history", ->
1117 editor.setCursorBufferPosition([0, 0])
1119 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1120 expect(atom.beep).toHaveBeenCalled()
1122 editor.setCursorBufferPosition([1, 1])
1124 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1125 expect(atom.beep.callCount).toBe 2
1127 describe "repeating with search history", ->
1130 submitNormalModeInputText 'def'
1132 it "repeats previous search with /<enter>", ->
1134 submitNormalModeInputText('')
1135 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1136 expect(atom.beep).not.toHaveBeenCalled()
1138 it "repeats previous search with //", ->
1140 submitNormalModeInputText('/')
1141 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1142 expect(atom.beep).not.toHaveBeenCalled()
1144 describe "the n keybinding", ->
1145 it "repeats the last search", ->
1147 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1148 expect(atom.beep).not.toHaveBeenCalled()
1150 describe "the N keybinding", ->
1151 it "repeats the last search backwards", ->
1152 editor.setCursorBufferPosition([0, 0])
1153 keydown('N', shift: true)
1154 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1155 keydown('N', shift: true)
1156 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1157 expect(atom.beep).not.toHaveBeenCalled()
1159 describe "composing", ->
1160 it "composes with operators", ->
1163 submitNormalModeInputText('def')
1164 expect(editor.getText()).toEqual "def\nabc\ndef\n"
1165 expect(atom.beep).not.toHaveBeenCalled()
1167 it "repeats correctly with operators", ->
1170 submitNormalModeInputText('def')
1173 expect(editor.getText()).toEqual "def\n"
1174 expect(atom.beep).not.toHaveBeenCalled()
1176 describe "when reversed as ?", ->
1177 it "moves the cursor backwards to the specified search pattern", ->
1179 submitNormalModeInputText('def')
1180 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1181 expect(atom.beep).not.toHaveBeenCalled()
1183 it "accepts / as a literal search pattern", ->
1184 editor.setText("abc\nd/f\nabc\nd/f\n")
1185 editor.setCursorBufferPosition([0, 0])
1187 submitNormalModeInputText('/')
1188 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1190 submitNormalModeInputText('/')
1191 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1192 expect(atom.beep).not.toHaveBeenCalled()
1194 describe "repeating", ->
1197 submitNormalModeInputText('def')
1199 it "repeats previous search as reversed with ?<enter>", ->
1201 submitNormalModeInputText('')
1202 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1203 expect(atom.beep).not.toHaveBeenCalled()
1205 it "repeats previous search as reversed with ??", ->
1207 submitNormalModeInputText('?')
1208 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1209 expect(atom.beep).not.toHaveBeenCalled()
1211 describe 'the n keybinding', ->
1212 it "repeats the last search backwards", ->
1213 editor.setCursorBufferPosition([0, 0])
1215 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1216 expect(atom.beep).not.toHaveBeenCalled()
1218 describe 'the N keybinding', ->
1219 it "repeats the last search forwards", ->
1220 editor.setCursorBufferPosition([0, 0])
1221 keydown('N', shift: true)
1222 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1223 expect(atom.beep).not.toHaveBeenCalled()
1225 describe "using search history", ->
1230 submitNormalModeInputText('def')
1231 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1234 submitNormalModeInputText('abc')
1235 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1237 inputEditor = editor.normalModeInputView.editorElement
1239 it "allows searching history in the search field", ->
1241 atom.commands.dispatch(inputEditor, 'core:move-up')
1242 expect(inputEditor.getModel().getText()).toEqual('abc')
1243 atom.commands.dispatch(inputEditor, 'core:move-up')
1244 expect(inputEditor.getModel().getText()).toEqual('def')
1245 atom.commands.dispatch(inputEditor, 'core:move-up')
1246 expect(inputEditor.getModel().getText()).toEqual('def')
1247 expect(atom.beep).not.toHaveBeenCalled()
1249 it "resets the search field to empty when scrolling back", ->
1251 atom.commands.dispatch(inputEditor, 'core:move-up')
1252 expect(inputEditor.getModel().getText()).toEqual('abc')
1253 atom.commands.dispatch(inputEditor, 'core:move-up')
1254 expect(inputEditor.getModel().getText()).toEqual('def')
1255 atom.commands.dispatch(inputEditor, 'core:move-down')
1256 expect(inputEditor.getModel().getText()).toEqual('abc')
1257 atom.commands.dispatch(inputEditor, 'core:move-down')
1258 expect(inputEditor.getModel().getText()).toEqual ''
1259 expect(atom.beep).not.toHaveBeenCalled()
1261 describe "the * keybinding", ->
1263 editor.setText("abd\n@def\nabd\ndef\n")
1264 editor.setCursorBufferPosition([0, 0])
1266 describe "as a motion", ->
1267 it "moves cursor to next occurence of word under cursor", ->
1269 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1271 it "repeats with the n key", ->
1273 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1275 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1277 it "doesn't move cursor unless next occurence is the exact word (no partial matches)", ->
1278 editor.setText("abc\ndef\nghiabc\njkl\nabcdef")
1279 editor.setCursorBufferPosition([0, 0])
1281 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1283 describe "with words that contain 'non-word' characters", ->
1284 it "moves cursor to next occurence of word under cursor", ->
1285 editor.setText("abc\n@def\nabc\n@def\n")
1286 editor.setCursorBufferPosition([1, 0])
1288 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1290 it "doesn't move cursor unless next match has exact word ending", ->
1291 editor.setText("abc\n@def\nabc\n@def1\n")
1292 editor.setCursorBufferPosition([1, 1])
1294 # this is because of the default isKeyword value of vim-mode that includes @
1295 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1297 # FIXME: This behavior is different from the one found in
1298 # vim. This is because the word boundary match in Javascript
1299 # ignores starting 'non-word' characters.
1301 # in Vim: /\<def\>/.test("@def") => false
1302 # in Javascript: /\bdef\b/.test("@def") => true
1303 it "moves cursor to the start of valid word char", ->
1304 editor.setText("abc\ndef\nabc\n@def\n")
1305 editor.setCursorBufferPosition([1, 0])
1307 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1309 describe "when cursor is on non-word char column", ->
1310 it "matches only the non-word char", ->
1311 editor.setText("abc\n@def\nabc\n@def\n")
1312 editor.setCursorBufferPosition([1, 0])
1314 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1316 describe "when cursor is not on a word", ->
1317 it "does a match with the next word", ->
1318 editor.setText("abc\na @def\n abc\n @def")
1319 editor.setCursorBufferPosition([1, 1])
1321 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1323 describe "when cursor is at EOF", ->
1324 it "doesn't try to do any match", ->
1325 editor.setText("abc\n@def\nabc\n ")
1326 editor.setCursorBufferPosition([3, 0])
1328 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1330 describe "the hash keybinding", ->
1331 describe "as a motion", ->
1332 it "moves cursor to previous occurence of word under cursor", ->
1333 editor.setText("abc\n@def\nabc\ndef\n")
1334 editor.setCursorBufferPosition([2, 1])
1336 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1338 it "repeats with n", ->
1339 editor.setText("abc\n@def\nabc\ndef\nabc\n")
1340 editor.setCursorBufferPosition([2, 1])
1342 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1344 expect(editor.getCursorBufferPosition()).toEqual [4, 0]
1346 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1348 it "doesn't move cursor unless next occurence is the exact word (no partial matches)", ->
1349 editor.setText("abc\ndef\nghiabc\njkl\nabcdef")
1350 editor.setCursorBufferPosition([0, 0])
1352 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1354 describe "with words that containt 'non-word' characters", ->
1355 it "moves cursor to next occurence of word under cursor", ->
1356 editor.setText("abc\n@def\nabc\n@def\n")
1357 editor.setCursorBufferPosition([3, 0])
1359 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1361 it "moves cursor to the start of valid word char", ->
1362 editor.setText("abc\n@def\nabc\ndef\n")
1363 editor.setCursorBufferPosition([3, 0])
1365 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1367 describe "when cursor is on non-word char column", ->
1368 it "matches only the non-word char", ->
1369 editor.setText("abc\n@def\nabc\n@def\n")
1370 editor.setCursorBufferPosition([1, 0])
1372 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1374 describe "the H keybinding", ->
1376 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1377 editor.setCursorScreenPosition([8, 0])
1378 spyOn(editor.getLastCursor(), 'setScreenPosition')
1380 it "moves the cursor to the first row if visible", ->
1381 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(0)
1382 keydown('H', shift: true)
1383 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([0, 0])
1385 it "moves the cursor to the first visible row plus offset", ->
1386 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(2)
1387 keydown('H', shift: true)
1388 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([4, 0])
1390 it "respects counts", ->
1391 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(0)
1393 keydown('H', shift: true)
1394 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([2, 0])
1396 describe "the L keybinding", ->
1398 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1399 editor.setCursorScreenPosition([8, 0])
1400 spyOn(editor.getLastCursor(), 'setScreenPosition')
1402 it "moves the cursor to the first row if visible", ->
1403 spyOn(editor, 'getLastVisibleScreenRow').andReturn(10)
1404 keydown('L', shift: true)
1405 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([10, 0])
1407 it "moves the cursor to the first visible row plus offset", ->
1408 spyOn(editor, 'getLastVisibleScreenRow').andReturn(6)
1409 keydown('L', shift: true)
1410 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([4, 0])
1412 it "respects counts", ->
1413 spyOn(editor, 'getLastVisibleScreenRow').andReturn(10)
1415 keydown('L', shift: true)
1416 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([8, 0])
1418 describe "the M keybinding", ->
1420 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1421 editor.setCursorScreenPosition([8, 0])
1422 spyOn(editor.getLastCursor(), 'setScreenPosition')
1423 spyOn(editor, 'getLastVisibleScreenRow').andReturn(10)
1424 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(0)
1426 it "moves the cursor to the first row if visible", ->
1427 keydown('M', shift: true)
1428 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([5, 0])
1430 describe 'the mark keybindings', ->
1432 editor.setText(' 12\n 34\n56\n')
1433 editor.setCursorBufferPosition([0, 1])
1435 it 'moves to the beginning of the line of a mark', ->
1436 editor.setCursorBufferPosition([1, 1])
1438 normalModeInputKeydown('a')
1439 editor.setCursorBufferPosition([0, 0])
1441 normalModeInputKeydown('a')
1442 expect(editor.getCursorBufferPosition()).toEqual [1, 4]
1444 it 'moves literally to a mark', ->
1445 editor.setCursorBufferPosition([1, 1])
1447 normalModeInputKeydown('a')
1448 editor.setCursorBufferPosition([0, 0])
1450 normalModeInputKeydown('a')
1451 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1453 it 'deletes to a mark by line', ->
1454 editor.setCursorBufferPosition([1, 5])
1456 normalModeInputKeydown('a')
1457 editor.setCursorBufferPosition([0, 0])
1460 normalModeInputKeydown('a')
1461 expect(editor.getText()).toEqual '56\n'
1463 it 'deletes before to a mark literally', ->
1464 editor.setCursorBufferPosition([1, 5])
1466 normalModeInputKeydown('a')
1467 editor.setCursorBufferPosition([0, 1])
1470 normalModeInputKeydown('a')
1471 expect(editor.getText()).toEqual ' 4\n56\n'
1473 it 'deletes after to a mark literally', ->
1474 editor.setCursorBufferPosition([1, 5])
1476 normalModeInputKeydown('a')
1477 editor.setCursorBufferPosition([2, 1])
1480 normalModeInputKeydown('a')
1481 expect(editor.getText()).toEqual ' 12\n 36\n'
1483 it 'moves back to previous', ->
1484 editor.setCursorBufferPosition([1, 5])
1486 normalModeInputKeydown('`')
1487 editor.setCursorBufferPosition([2, 1])
1489 normalModeInputKeydown('`')
1490 expect(editor.getCursorBufferPosition()).toEqual [1, 5]
1492 describe 'the f/F keybindings', ->
1494 editor.setText("abcabcabcabc\n")
1495 editor.setCursorScreenPosition([0, 0])
1497 it 'moves to the first specified character it finds', ->
1499 normalModeInputKeydown('c')
1500 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1502 it 'moves backwards to the first specified character it finds', ->
1503 editor.setCursorScreenPosition([0, 2])
1504 keydown('F', shift: true)
1505 normalModeInputKeydown('a')
1506 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1508 it 'respects count forward', ->
1511 normalModeInputKeydown('a')
1512 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1514 it 'respects count backward', ->
1515 editor.setCursorScreenPosition([0, 6])
1517 keydown('F', shift: true)
1518 normalModeInputKeydown('a')
1519 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1521 it "doesn't move if the character specified isn't found", ->
1523 normalModeInputKeydown('d')
1524 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1525 expect(atom.beep).not.toHaveBeenCalled()
1527 it "doesn't move if there aren't the specified count of the specified character", ->
1531 normalModeInputKeydown('a')
1532 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1533 # a bug was making this behaviour depend on the count
1537 normalModeInputKeydown('a')
1538 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1540 editor.setCursorScreenPosition([0, 6])
1543 keydown('F', shift: true)
1544 normalModeInputKeydown('a')
1545 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1548 keydown('F', shift: true)
1549 normalModeInputKeydown('a')
1550 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1552 it "composes with d", ->
1553 editor.setCursorScreenPosition([0, 3])
1557 normalModeInputKeydown('a')
1558 expect(editor.getText()).toEqual 'abcbc\n'
1560 it "cancels c when no match found", ->
1563 normalModeInputKeydown('d')
1564 expect(editor.getText()).toBe("abcabcabcabc\n")
1565 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1566 expect(vimState.mode).toBe "normal"
1568 describe 'with accented characters', ->
1569 buildIMECompositionEvent = (event, {data, target}={}) ->
1570 event = new Event(event)
1572 Object.defineProperty(event, 'target', get: -> target)
1575 buildTextInputEvent = ({data, target}) ->
1576 event = new Event('textInput')
1578 Object.defineProperty(event, 'target', get: -> target)
1582 editor.setText("abcébcabcébc\n")
1583 editor.setCursorScreenPosition([0, 0])
1585 it 'works with IME composition', ->
1587 normalModeEditor = editor.normalModeInputView.editorElement
1588 jasmine.attachToDOM(normalModeEditor)
1589 domNode = normalModeEditor.component.domNode
1590 inputNode = domNode.querySelector('.hidden-input')
1591 domNode.dispatchEvent(buildIMECompositionEvent('compositionstart', target: inputNode))
1592 domNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: "´", target: inputNode))
1593 expect(normalModeEditor.getModel().getText()).toEqual '´'
1594 domNode.dispatchEvent(buildIMECompositionEvent('compositionend', data: "é", target: inputNode))
1595 domNode.dispatchEvent(buildTextInputEvent(data: 'é', target: inputNode))
1596 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1598 describe 'the t/T keybindings', ->
1600 editor.setText("abcabcabcabc\n")
1601 editor.setCursorScreenPosition([0, 0])
1603 it 'moves to the character previous to the first specified character it finds', ->
1605 normalModeInputKeydown('a')
1606 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1607 # or stays put when it's already there
1609 normalModeInputKeydown('a')
1610 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1612 it 'moves backwards to the character after the first specified character it finds', ->
1613 editor.setCursorScreenPosition([0, 2])
1614 keydown('T', shift: true)
1615 normalModeInputKeydown('a')
1616 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1618 it 'respects count forward', ->
1621 normalModeInputKeydown('a')
1622 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1624 it 'respects count backward', ->
1625 editor.setCursorScreenPosition([0, 6])
1627 keydown('T', shift: true)
1628 normalModeInputKeydown('a')
1629 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1631 it "doesn't move if the character specified isn't found", ->
1633 normalModeInputKeydown('d')
1634 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1635 expect(atom.beep).not.toHaveBeenCalled()
1637 it "doesn't move if there aren't the specified count of the specified character", ->
1641 normalModeInputKeydown('a')
1642 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1643 # a bug was making this behaviour depend on the count
1647 normalModeInputKeydown('a')
1648 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1650 editor.setCursorScreenPosition([0, 6])
1653 keydown('T', shift: true)
1654 normalModeInputKeydown('a')
1655 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1658 keydown('T', shift: true)
1659 normalModeInputKeydown('a')
1660 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1662 it "composes with d", ->
1663 editor.setCursorScreenPosition([0, 3])
1667 normalModeInputKeydown('b')
1668 expect(editor.getText()).toBe 'abcbcabc\n'
1670 it "selects character under cursor even when no movement happens", ->
1671 editor.setCursorBufferPosition([0, 0])
1674 normalModeInputKeydown('b')
1675 expect(editor.getText()).toBe 'bcabcabcabc\n'
1677 describe 'the v keybinding', ->
1679 editor.setText("01\n002\n0003\n00004\n000005\n")
1680 editor.setCursorScreenPosition([1, 1])
1682 it "selects down a line", ->
1686 expect(editor.getSelectedText()).toBe "02\n0003\n00"
1687 expect(editor.getSelectedBufferRange().isSingleLine()).toBeFalsy()
1689 it "selects right", ->
1692 expect(editor.getSelectedText()).toBe "02"
1693 expect(editor.getSelectedBufferRange().isSingleLine()).toBeTruthy()
1695 describe 'the V keybinding', ->
1697 editor.setText("01\n002\n0003\n00004\n000005\n")
1698 editor.setCursorScreenPosition([1, 1])
1700 it "selects down a line", ->
1701 keydown('V', shift: true)
1702 expect(editor.getSelectedBufferRange().isSingleLine()).toBeFalsy()
1705 expect(editor.getSelectedText()).toBe "002\n0003\n00004\n"
1706 expect(editor.getSelectedBufferRange().isSingleLine()).toBeFalsy()
1708 it "selects up a line", ->
1709 keydown('V', shift: true)
1711 expect(editor.getSelectedText()).toBe "01\n002\n"
1713 describe 'the ; and , keybindings', ->
1715 editor.setText("abcabcabcabc\n")
1716 editor.setCursorScreenPosition([0, 0])
1718 it "repeat f in same direction", ->
1720 normalModeInputKeydown('c')
1721 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1723 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1725 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1727 it "repeat F in same direction", ->
1728 editor.setCursorScreenPosition([0, 10])
1729 keydown('F', shift: true)
1730 normalModeInputKeydown('c')
1731 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1733 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1735 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1737 it "repeat f in opposite direction", ->
1738 editor.setCursorScreenPosition([0, 6])
1740 normalModeInputKeydown('c')
1741 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1743 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1745 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1747 it "repeat F in opposite direction", ->
1748 editor.setCursorScreenPosition([0, 4])
1749 keydown('F', shift: true)
1750 normalModeInputKeydown('c')
1751 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1753 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1755 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1757 it "alternate repeat f in same direction and reverse", ->
1759 normalModeInputKeydown('c')
1760 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1762 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1764 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1766 it "alternate repeat F in same direction and reverse", ->
1767 editor.setCursorScreenPosition([0, 10])
1768 keydown('F', shift: true)
1769 normalModeInputKeydown('c')
1770 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1772 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1774 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1776 it "repeat t in same direction", ->
1778 normalModeInputKeydown('c')
1779 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1781 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1783 it "repeat T in same direction", ->
1784 editor.setCursorScreenPosition([0, 10])
1785 keydown('T', shift: true)
1786 normalModeInputKeydown('c')
1787 expect(editor.getCursorScreenPosition()).toEqual [0, 9]
1789 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1791 it "repeat t in opposite direction first, and then reverse", ->
1792 editor.setCursorScreenPosition([0, 3])
1794 normalModeInputKeydown('c')
1795 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1797 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1799 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1801 it "repeat T in opposite direction first, and then reverse", ->
1802 editor.setCursorScreenPosition([0, 4])
1803 keydown('T', shift: true)
1804 normalModeInputKeydown('c')
1805 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1807 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1809 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1811 it "repeat with count in same direction", ->
1812 editor.setCursorScreenPosition([0, 0])
1814 normalModeInputKeydown('c')
1815 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1818 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1820 it "repeat with count in reverse direction", ->
1821 editor.setCursorScreenPosition([0, 6])
1823 normalModeInputKeydown('c')
1824 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1827 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1829 it "shares the most recent find/till command with other editors", ->
1830 helpers.getEditorElement (otherEditorElement) ->
1831 otherEditor = otherEditorElement.getModel()
1833 editor.setText("a baz bar\n")
1834 editor.setCursorScreenPosition([0, 0])
1836 otherEditor.setText("foo bar baz")
1837 otherEditor.setCursorScreenPosition([0, 0])
1839 # by default keyDown and such go in the usual editor
1841 normalModeInputKeydown('b')
1842 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1843 expect(otherEditor.getCursorScreenPosition()).toEqual [0, 0]
1845 # replay same find in the other editor
1846 keydown(';', element: otherEditorElement)
1847 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1848 expect(otherEditor.getCursorScreenPosition()).toEqual [0, 4]
1850 # do a till in the other editor
1851 keydown('t', element: otherEditorElement)
1852 normalModeInputKeydown('r', editor: otherEditor)
1853 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1854 expect(otherEditor.getCursorScreenPosition()).toEqual [0, 5]
1856 # and replay in the normal editor
1858 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
1859 expect(otherEditor.getCursorScreenPosition()).toEqual [0, 5]
1860 expect(atom.beep).not.toHaveBeenCalled()
1862 describe 'the % motion', ->
1864 editor.setText("( ( ) )--{ text in here; and a function call(with parameters) }\n")
1865 editor.setCursorScreenPosition([0, 0])
1867 it 'matches the correct parenthesis', ->
1869 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1871 it 'matches the correct brace', ->
1872 editor.setCursorScreenPosition([0, 9])
1874 expect(editor.getCursorScreenPosition()).toEqual [0, 62]
1876 it 'composes correctly with d', ->
1877 editor.setCursorScreenPosition([0, 9])
1880 expect(editor.getText()).toEqual "( ( ) )--\n"
1882 it 'moves correctly when composed with v going forward', ->
1886 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
1888 it 'moves correctly when composed with v going backward', ->
1889 editor.setCursorScreenPosition([0, 5])
1892 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1894 it 'it moves appropriately to find the nearest matching action', ->
1895 editor.setCursorScreenPosition([0, 3])
1897 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1898 expect(editor.getText()).toEqual "( ( ) )--{ text in here; and a function call(with parameters) }\n"
1900 it 'it moves appropriately to find the nearest matching action', ->
1901 editor.setCursorScreenPosition([0, 26])
1903 expect(editor.getCursorScreenPosition()).toEqual [0, 60]
1904 expect(editor.getText()).toEqual "( ( ) )--{ text in here; and a function call(with parameters) }\n"
1906 it "finds matches across multiple lines", ->
1907 editor.setText("...(\n...)")
1908 editor.setCursorScreenPosition([0, 0])
1910 expect(editor.getCursorScreenPosition()).toEqual([1, 3])
1912 it "does not affect search history", ->
1914 submitNormalModeInputText 'func'
1915 expect(editor.getCursorBufferPosition()).toEqual [0, 31]
1917 expect(editor.getCursorBufferPosition()).toEqual [0, 60]
1919 expect(editor.getCursorBufferPosition()).toEqual [0, 31]
1921 describe "scrolling screen and keeping cursor in the same screen position", ->
1923 editor.setText([0...80].join("\n"))
1924 editor.setHeight(20 * 10)
1925 editor.setLineHeightInPixels(10)
1926 editor.setScrollTop(40 * 10)
1927 editor.setCursorBufferPosition([42, 0])
1929 describe "the ctrl-u keybinding", ->
1930 it "moves the screen down by half screen size and keeps cursor onscreen", ->
1931 keydown('u', ctrl: true)
1932 expect(editor.getScrollTop()).toEqual 300
1933 expect(editor.getCursorBufferPosition()).toEqual [32, 0]
1935 it "selects on visual mode", ->
1936 editor.setCursorBufferPosition([42, 1])
1937 vimState.activateVisualMode()
1938 keydown('u', ctrl: true)
1939 expect(editor.getSelectedText()).toEqual [32..42].join("\n")
1941 it "selects on linewise mode", ->
1942 vimState.activateVisualMode('linewise')
1943 keydown('u', ctrl: true)
1944 expect(editor.getSelectedText()).toEqual [32..42].join("\n").concat("\n")
1946 describe "the ctrl-b keybinding", ->
1947 it "moves screen up one page", ->
1948 keydown('b', ctrl: true)
1949 expect(editor.getScrollTop()).toEqual 200
1950 expect(editor.getCursorScreenPosition()).toEqual [22, 0]
1952 it "selects on visual mode", ->
1953 editor.setCursorBufferPosition([42, 1])
1954 vimState.activateVisualMode()
1955 keydown('b', ctrl: true)
1956 expect(editor.getSelectedText()).toEqual [22..42].join("\n")
1958 it "selects on linewise mode", ->
1959 vimState.activateVisualMode('linewise')
1960 keydown('b', ctrl: true)
1961 expect(editor.getSelectedText()).toEqual [22..42].join("\n").concat("\n")
1964 describe "the ctrl-d keybinding", ->
1965 it "moves the screen down by half screen size and keeps cursor onscreen", ->
1966 keydown('d', ctrl: true)
1967 expect(editor.getScrollTop()).toEqual 500
1968 expect(editor.getCursorBufferPosition()).toEqual [52, 0]
1970 it "selects on visual mode", ->
1971 editor.setCursorBufferPosition([42, 1])
1972 vimState.activateVisualMode()
1973 keydown('d', ctrl: true)
1974 expect(editor.getSelectedText()).toEqual [42..52].join("\n").slice(1, -1)
1976 it "selects on linewise mode", ->
1977 vimState.activateVisualMode('linewise')
1978 keydown('d', ctrl: true)
1979 expect(editor.getSelectedText()).toEqual [42..52].join("\n").concat("\n")
1981 describe "the ctrl-f keybinding", ->
1982 it "moves screen down one page", ->
1983 keydown('f', ctrl: true)
1984 expect(editor.getScrollTop()).toEqual 600
1985 expect(editor.getCursorScreenPosition()).toEqual [62, 0]
1987 it "selects on visual mode", ->
1988 editor.setCursorBufferPosition([42, 1])
1989 vimState.activateVisualMode()
1990 keydown('f', ctrl: true)
1991 expect(editor.getSelectedText()).toEqual [42..62].join("\n").slice(1, -1)
1993 it "selects on linewise mode", ->
1994 vimState.activateVisualMode('linewise')
1995 keydown('f', ctrl: true)
1996 expect(editor.getSelectedText()).toEqual [42..62].join("\n").concat("\n")