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.activateCommandMode()
15 vimState.resetCommandMode()
17 keydown = (key, options={}) ->
18 options.element ?= editorElement
19 helpers.keydown(key, options)
21 commandModeInputKeydown = (key, opts = {}) ->
22 editor.commandModeInputView.editorElement.getModel().setText(key)
24 submitCommandModeInputText = (text) ->
25 commandEditor = editor.commandModeInputView.editorElement
26 commandEditor.getModel().setText(text)
27 atom.commands.dispatch(commandEditor, "core:confirm")
29 describe "simple motions", ->
31 editor.setText("12345\nabcd\nABCDE")
32 editor.setCursorScreenPosition([1, 1])
34 describe "the h keybinding", ->
35 describe "as a motion", ->
36 it "moves the cursor left, but not to the previous line", ->
38 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
41 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
43 it "moves the cursor to the previous line if wrapLeftRightMotion is true", ->
44 atom.config.set('vim-mode.wrapLeftRightMotion', true)
47 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
49 describe "as a selection", ->
50 it "selects the character to the left", ->
54 expect(vimState.getRegister('"').text).toBe 'a'
55 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
57 describe "the j keybinding", ->
58 it "moves the cursor down, but not to the end of the last line", ->
60 expect(editor.getCursorScreenPosition()).toEqual [2, 1]
63 expect(editor.getCursorScreenPosition()).toEqual [2, 1]
65 it "moves the cursor to the end of the line, not past it", ->
66 editor.setCursorScreenPosition([0, 4])
69 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
71 it "remembers the position it column it was in after moving to shorter line", ->
72 editor.setCursorScreenPosition([0, 4])
75 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
78 expect(editor.getCursorScreenPosition()).toEqual [2, 4]
80 describe "when visual mode", ->
83 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
85 it "moves the cursor down", ->
87 expect(editor.getCursorScreenPosition()).toEqual [2, 2]
89 it "doesn't go over after the last line", ->
91 expect(editor.getCursorScreenPosition()).toEqual [2, 2]
93 it "selects the text while moving", ->
95 expect(editor.getSelectedText()).toBe "bcd\nAB"
97 describe "the k keybinding", ->
98 it "moves the cursor up, but not to the beginning of the first line", ->
100 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
103 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
105 describe "the l keybinding", ->
106 beforeEach -> editor.setCursorScreenPosition([1, 2])
108 it "moves the cursor right, but not to the next line", ->
110 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
113 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
115 it "moves the cursor to the next line if wrapLeftRightMotion is true", ->
116 atom.config.set('vim-mode.wrapLeftRightMotion', true)
119 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
121 describe "on a blank line", ->
122 it "doesn't move the cursor", ->
123 editor.setText("\n\n\n")
124 editor.setCursorBufferPosition([1, 0])
126 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
128 describe "the w keybinding", ->
129 beforeEach -> editor.setText("ab cde1+- \n xyz\n\nzip")
131 describe "as a motion", ->
132 beforeEach -> editor.setCursorScreenPosition([0, 0])
134 it "moves the cursor to the beginning of the next word", ->
136 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
139 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
142 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
145 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
147 # FIXME: The definition of Cursor#getEndOfCurrentWordBufferPosition,
148 # means that the end of the word can't be the current cursor
149 # position (even though it is when your cursor is on a new line).
151 # Therefore it picks the end of the next word here (which is [3,3])
152 # to start looking for the next word, which is also the end of the
153 # buffer so the cursor never advances.
155 # See atom/vim-mode#3
157 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
160 expect(editor.getCursorScreenPosition()).toEqual [3, 3]
162 # After cursor gets to the EOF, it should stay there.
164 expect(editor.getCursorScreenPosition()).toEqual [3, 3]
166 it "moves the cursor to the end of the word if last word in file", ->
167 editor.setText("abc")
168 editor.setCursorScreenPosition([0, 0])
170 expect(editor.getCursorScreenPosition()).toEqual([0, 3])
172 describe "as a selection", ->
173 describe "within a word", ->
175 editor.setCursorScreenPosition([0, 0])
179 it "selects to the end of the word", ->
180 expect(vimState.getRegister('"').text).toBe 'ab '
182 describe "between words", ->
184 editor.setCursorScreenPosition([0, 2])
188 it "selects the whitespace", ->
189 expect(vimState.getRegister('"').text).toBe ' '
191 describe "the W keybinding", ->
192 beforeEach -> editor.setText("cde1+- ab \n xyz\n\nzip")
194 describe "as a motion", ->
195 beforeEach -> editor.setCursorScreenPosition([0, 0])
197 it "moves the cursor to the beginning of the next word", ->
198 keydown('W', shift: true)
199 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
201 keydown('W', shift: true)
202 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
204 keydown('W', shift: true)
205 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
207 keydown('W', shift: true)
208 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
210 describe "as a selection", ->
211 describe "within a word", ->
212 it "selects to the end of the whole word", ->
213 editor.setCursorScreenPosition([0, 0])
215 keydown('W', shift: true)
216 expect(vimState.getRegister('"').text).toBe 'cde1+- '
218 it "continues past blank lines", ->
219 editor.setCursorScreenPosition([2, 0])
222 keydown('W', shift: true)
223 expect(editor.getText()).toBe "cde1+- ab \n xyz\nzip"
224 expect(vimState.getRegister('"').text).toBe '\n'
226 it "doesn't go past the end of the file", ->
227 editor.setCursorScreenPosition([3, 0])
230 keydown('W', shift: true)
231 expect(editor.getText()).toBe "cde1+- ab \n xyz\n\n"
232 expect(vimState.getRegister('"').text).toBe 'zip'
234 describe "the e keybinding", ->
235 beforeEach -> editor.setText("ab cde1+- \n xyz\n\nzip")
237 describe "as a motion", ->
238 beforeEach -> editor.setCursorScreenPosition([0, 0])
240 it "moves the cursor to the end of the current word", ->
242 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
245 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
248 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
251 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
254 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
256 describe "as selection", ->
257 describe "within a word", ->
259 editor.setCursorScreenPosition([0, 0])
263 it "selects to the end of the current word", ->
264 expect(vimState.getRegister('"').text).toBe 'ab'
266 describe "between words", ->
268 editor.setCursorScreenPosition([0, 2])
272 it "selects to the end of the next word", ->
273 expect(vimState.getRegister('"').text).toBe ' cde1'
275 describe "the E keybinding", ->
276 beforeEach -> editor.setText("ab cde1+- \n xyz \n\nzip\n")
278 describe "as a motion", ->
279 beforeEach -> editor.setCursorScreenPosition([0, 0])
281 it "moves the cursor to the end of the current word", ->
282 keydown('E', shift: true)
283 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
285 keydown('E', shift: true)
286 expect(editor.getCursorScreenPosition()).toEqual [0, 9]
288 keydown('E', shift: true)
289 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
291 keydown('E', shift: true)
292 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
294 keydown('E', shift: true)
295 expect(editor.getCursorScreenPosition()).toEqual [4, 0]
297 describe "as selection", ->
298 describe "within a word", ->
300 editor.setCursorScreenPosition([0, 0])
302 keydown('E', shift: true)
304 it "selects to the end of the current word", ->
305 expect(vimState.getRegister('"').text).toBe 'ab'
307 describe "between words", ->
309 editor.setCursorScreenPosition([0, 2])
311 keydown('E', shift: true)
313 it "selects to the end of the next word", ->
314 expect(vimState.getRegister('"').text).toBe ' cde1+-'
316 describe "press more than once", ->
318 editor.setCursorScreenPosition([0, 0])
320 keydown('E', shift: true)
321 keydown('E', shift: true)
324 it "selects to the end of the current word", ->
325 expect(vimState.getRegister('"').text).toBe 'ab cde1+-'
327 describe "the } keybinding", ->
329 editor.setText("abcde\n\nfghij\nhijk\n xyz \n\nzip\n\n \nthe end")
330 editor.setCursorScreenPosition([0, 0])
332 describe "as a motion", ->
333 it "moves the cursor to the end of the paragraph", ->
335 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
338 expect(editor.getCursorScreenPosition()).toEqual [5, 0]
341 expect(editor.getCursorScreenPosition()).toEqual [7, 0]
344 expect(editor.getCursorScreenPosition()).toEqual [9, 6]
346 describe "as a selection", ->
351 it 'selects to the end of the current paragraph', ->
352 expect(vimState.getRegister('"').text).toBe "abcde\n"
354 describe "the { keybinding", ->
356 editor.setText("abcde\n\nfghij\nhijk\n xyz \n\nzip\n\n \nthe end")
357 editor.setCursorScreenPosition([9, 0])
359 describe "as a motion", ->
360 it "moves the cursor to the beginning of the paragraph", ->
362 expect(editor.getCursorScreenPosition()).toEqual [7, 0]
365 expect(editor.getCursorScreenPosition()).toEqual [5, 0]
368 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
371 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
373 describe "as a selection", ->
375 editor.setCursorScreenPosition([7, 0])
379 it 'selects to the beginning of the current paragraph', ->
380 expect(vimState.getRegister('"').text).toBe "\nzip\n"
382 describe "the b keybinding", ->
383 beforeEach -> editor.setText(" ab cde1+- \n xyz\n\nzip }\n last")
385 describe "as a motion", ->
386 beforeEach -> editor.setCursorScreenPosition([4, 1])
388 it "moves the cursor to the beginning of the previous word", ->
390 expect(editor.getCursorScreenPosition()).toEqual [3, 4]
393 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
396 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
399 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
402 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
405 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
408 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
410 # Go to start of the file, after moving past the first word
412 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
414 # Stay at the start of the file
416 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
418 describe "as a selection", ->
419 describe "within a word", ->
421 editor.setCursorScreenPosition([0, 2])
425 it "selects to the beginning of the current word", ->
426 expect(vimState.getRegister('"').text).toBe 'a'
427 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
429 describe "between words", ->
431 editor.setCursorScreenPosition([0, 4])
435 it "selects to the beginning of the last word", ->
436 expect(vimState.getRegister('"').text).toBe 'ab '
437 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
439 describe "the B keybinding", ->
440 beforeEach -> editor.setText("cde1+- ab \n\t xyz-123\n\n zip")
442 describe "as a motion", ->
443 beforeEach -> editor.setCursorScreenPosition([4, 1])
445 it "moves the cursor to the beginning of the previous word", ->
446 keydown('B', shift: true)
447 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
449 keydown('B', shift: true)
450 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
452 keydown('B', shift: true)
453 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
455 keydown('B', shift: true)
456 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
458 keydown('B', shift: true)
459 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
461 describe "as a selection", ->
462 it "selects to the beginning of the whole word", ->
463 editor.setCursorScreenPosition([1, 10])
465 keydown('B', shift: true)
466 expect(vimState.getRegister('"').text).toBe 'xyz-123'
468 it "doesn't go past the beginning of the file", ->
469 editor.setCursorScreenPosition([0, 0])
470 vimState.setRegister('"', text: 'abc')
472 keydown('B', shift: true)
473 expect(vimState.getRegister('"').text).toBe 'abc'
475 describe "the ^ keybinding", ->
477 editor.setText(" abcde")
479 describe "from the beginning of the line", ->
480 beforeEach -> editor.setCursorScreenPosition([0, 0])
482 describe "as a motion", ->
483 beforeEach -> keydown('^')
485 it "moves the cursor to the first character of the line", ->
486 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
488 describe "as a selection", ->
493 it 'selects to the first character of the line', ->
494 expect(editor.getText()).toBe 'abcde'
495 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
497 describe "from the first character of the line", ->
498 beforeEach -> editor.setCursorScreenPosition([0, 2])
500 describe "as a motion", ->
501 beforeEach -> keydown('^')
504 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
506 describe "as a selection", ->
511 it "does nothing", ->
512 expect(editor.getText()).toBe ' abcde'
513 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
515 describe "from the middle of a word", ->
516 beforeEach -> editor.setCursorScreenPosition([0, 4])
518 describe "as a motion", ->
519 beforeEach -> keydown('^')
521 it "moves the cursor to the first character of the line", ->
522 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
524 describe "as a selection", ->
529 it 'selects to the first character of the line', ->
530 expect(editor.getText()).toBe ' cde'
531 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
533 describe "the 0 keybinding", ->
535 editor.setText(" abcde")
536 editor.setCursorScreenPosition([0, 4])
538 describe "as a motion", ->
539 beforeEach -> keydown('0')
541 it "moves the cursor to the first column", ->
542 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
544 describe "as a selection", ->
549 it 'selects to the first column of the line', ->
550 expect(editor.getText()).toBe 'cde'
551 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
553 describe "the $ keybinding", ->
555 editor.setText(" abcde\n\n1234567890")
556 editor.setCursorScreenPosition([0, 4])
558 describe "as a motion from empty line", ->
559 beforeEach -> editor.setCursorScreenPosition([1, 0])
561 it "moves the cursor to the end of the line", ->
562 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
564 describe "as a motion", ->
565 beforeEach -> keydown('$')
567 # FIXME: See atom/vim-mode#2
568 it "moves the cursor to the end of the line", ->
569 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
571 it "should remain in the last column when moving down", ->
573 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
576 expect(editor.getCursorScreenPosition()).toEqual [2, 9]
578 describe "as a selection", ->
583 it "selects to the beginning of the lines", ->
584 expect(editor.getText()).toBe " ab\n\n1234567890"
585 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
587 describe "the 0 keybinding", ->
589 editor.setText(" a\n")
590 editor.setCursorScreenPosition([0, 2])
592 describe "as a motion", ->
593 beforeEach -> keydown('0')
595 it "moves the cursor to the beginning of the line", ->
596 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
598 describe "the - keybinding", ->
600 editor.setText("abcdefg\n abc\n abc\n")
602 describe "from the middle of a line", ->
603 beforeEach -> editor.setCursorScreenPosition([1, 3])
605 describe "as a motion", ->
606 beforeEach -> keydown('-')
608 it "moves the cursor to the first character of the previous line", ->
609 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
611 describe "as a selection", ->
616 it "deletes the current and previous line", ->
617 expect(editor.getText()).toBe " abc\n"
618 # commented out because the column is wrong due to a bug in `k`; re-enable when `k` is fixed
619 #expect(editor.getCursorScreenPosition()).toEqual [0, 3]
621 describe "from the first character of a line indented the same as the previous one", ->
622 beforeEach -> editor.setCursorScreenPosition([2, 2])
624 describe "as a motion", ->
625 beforeEach -> keydown('-')
627 it "moves to the first character of the previous line (directly above)", ->
628 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
630 describe "as a selection", ->
635 it "selects to the first character of the previous line (directly above)", ->
636 expect(editor.getText()).toBe "abcdefg\n"
637 # commented out because the column is wrong due to a bug in `k`; re-enable when `k` is fixed
638 #expect(editor.getCursorScreenPosition()).toEqual [0, 2]
640 describe "from the beginning of a line preceded by an indented line", ->
641 beforeEach -> editor.setCursorScreenPosition([2, 0])
643 describe "as a motion", ->
644 beforeEach -> keydown('-')
646 it "moves the cursor to the first character of the previous line", ->
647 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
649 describe "as a selection", ->
654 it "selects to the first character of the previous line", ->
655 expect(editor.getText()).toBe "abcdefg\n"
656 # commented out because the column is wrong due to a bug in `k`; re-enable when `k` is fixed
657 #expect(editor.getCursorScreenPosition()).toEqual [0, 0]
659 describe "with a count", ->
661 editor.setText("1\n2\n3\n4\n5\n6\n")
662 editor.setCursorScreenPosition([4, 0])
664 describe "as a motion", ->
669 it "moves the cursor to the first character of that many lines previous", ->
670 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
672 describe "as a selection", ->
678 it "deletes the current line plus that many previous lines", ->
679 expect(editor.getText()).toBe "1\n6\n"
680 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
682 describe "the + keybinding", ->
684 editor.setText(" abc\n abc\nabcdefg\n")
686 describe "from the middle of a line", ->
687 beforeEach -> editor.setCursorScreenPosition([1, 3])
689 describe "as a motion", ->
690 beforeEach -> keydown('+')
692 it "moves the cursor to the first character of the next line", ->
693 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
695 describe "as a selection", ->
700 it "deletes the current and next line", ->
701 expect(editor.getText()).toBe " abc\n"
702 # commented out because the column is wrong due to a bug in `j`; re-enable when `j` is fixed
703 #expect(editor.getCursorScreenPosition()).toEqual [0, 3]
705 describe "from the first character of a line indented the same as the next one", ->
706 beforeEach -> editor.setCursorScreenPosition([0, 2])
708 describe "as a motion", ->
709 beforeEach -> keydown('+')
711 it "moves to the first character of the next line (directly below)", ->
712 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
714 describe "as a selection", ->
719 it "selects to the first character of the next line (directly below)", ->
720 expect(editor.getText()).toBe "abcdefg\n"
721 # commented out because the column is wrong due to a bug in `j`; re-enable when `j` is fixed
722 #expect(editor.getCursorScreenPosition()).toEqual [0, 2]
724 describe "from the beginning of a line followed by an indented line", ->
725 beforeEach -> editor.setCursorScreenPosition([0, 0])
727 describe "as a motion", ->
728 beforeEach -> keydown('+')
730 it "moves the cursor to the first character of the next line", ->
731 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
733 describe "as a selection", ->
738 it "selects to the first character of the next line", ->
739 expect(editor.getText()).toBe "abcdefg\n"
740 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
742 describe "with a count", ->
744 editor.setText("1\n2\n3\n4\n5\n6\n")
745 editor.setCursorScreenPosition([1, 0])
747 describe "as a motion", ->
752 it "moves the cursor to the first character of that many lines following", ->
753 expect(editor.getCursorScreenPosition()).toEqual [4, 0]
755 describe "as a selection", ->
761 it "deletes the current line plus that many following lines", ->
762 expect(editor.getText()).toBe "1\n6\n"
763 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
765 describe "the _ keybinding", ->
767 editor.setText(" abc\n abc\nabcdefg\n")
769 describe "from the middle of a line", ->
770 beforeEach -> editor.setCursorScreenPosition([1, 3])
772 describe "as a motion", ->
773 beforeEach -> keydown('_')
775 it "moves the cursor to the first character of the current line", ->
776 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
778 describe "as a selection", ->
783 it "deletes the current line", ->
784 expect(editor.getText()).toBe " abc\nabcdefg\n"
785 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
787 describe "with a count", ->
789 editor.setText("1\n2\n3\n4\n5\n6\n")
790 editor.setCursorScreenPosition([1, 0])
792 describe "as a motion", ->
797 it "moves the cursor to the first character of that many lines following", ->
798 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
800 describe "as a selection", ->
806 it "deletes the current line plus that many following lines", ->
807 expect(editor.getText()).toBe "1\n5\n6\n"
808 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
810 describe "the enter keybinding", ->
811 keydownCodeForEnter = '\r' # 'enter' does not work
812 startingText = " abc\n abc\nabcdefg\n"
814 describe "from the middle of a line", ->
815 startingCursorPosition = [1, 3]
817 describe "as a motion", ->
818 it "acts the same as the + keybinding", ->
819 # do it with + and save the results
820 editor.setText(startingText)
821 editor.setCursorScreenPosition(startingCursorPosition)
823 referenceCursorPosition = editor.getCursorScreenPosition()
824 # do it again with enter and compare the results
825 editor.setText(startingText)
826 editor.setCursorScreenPosition(startingCursorPosition)
827 keydown(keydownCodeForEnter)
828 expect(editor.getCursorScreenPosition()).toEqual referenceCursorPosition
830 describe "as a selection", ->
831 it "acts the same as the + keybinding", ->
832 # do it with + and save the results
833 editor.setText(startingText)
834 editor.setCursorScreenPosition(startingCursorPosition)
837 referenceText = editor.getText()
838 referenceCursorPosition = editor.getCursorScreenPosition()
839 # do it again with enter and compare the results
840 editor.setText(startingText)
841 editor.setCursorScreenPosition(startingCursorPosition)
843 keydown(keydownCodeForEnter)
844 expect(editor.getText()).toEqual referenceText
845 expect(editor.getCursorScreenPosition()).toEqual referenceCursorPosition
847 describe "the gg keybinding", ->
849 editor.setText(" 1abc\n 2\n3\n")
850 editor.setCursorScreenPosition([0, 2])
852 describe "as a motion", ->
853 describe "in command mode", ->
858 it "moves the cursor to the beginning of the first line", ->
859 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
861 describe "in linewise visual mode", ->
863 editor.setCursorScreenPosition([1, 0])
864 vimState.activateVisualMode('linewise')
868 it "selects to the first line in the file", ->
869 expect(editor.getSelectedText()).toBe " 1abc\n 2\n"
871 it "moves the cursor to a specified line", ->
872 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
874 describe "in characterwise visual mode", ->
876 editor.setCursorScreenPosition([1, 1])
877 vimState.activateVisualMode()
881 it "selects to the first line in the file", ->
882 expect(editor.getSelectedText()).toBe "1abc\n 2"
884 it "moves the cursor to a specified line", ->
885 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
887 describe "as a repeated motion", ->
888 describe "in command mode", ->
894 it "moves the cursor to a specified line", ->
895 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
897 describe "in linewise visual motion", ->
899 editor.setCursorScreenPosition([2, 0])
900 vimState.activateVisualMode('linewise')
905 it "selects to a specified line", ->
906 expect(editor.getSelectedText()).toBe " 2\n3\n"
908 it "moves the cursor to a specified line", ->
909 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
911 describe "in characterwise visual motion", ->
913 editor.setCursorScreenPosition([2, 0])
914 vimState.activateVisualMode()
919 it "selects to a first character of specified line", ->
920 expect(editor.getSelectedText()).toBe "2\n3"
922 it "moves the cursor to a specified line", ->
923 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
925 describe "the g_ keybinding", ->
927 editor.setText("1 \n 2 \n 3abc\n ")
929 describe "as a motion", ->
930 it "moves the cursor to the last nonblank character", ->
931 editor.setCursorScreenPosition([1, 0])
934 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
936 it "will move the cursor to the beginning of the line if necessary", ->
937 editor.setCursorScreenPosition([0, 2])
940 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
942 describe "as a repeated motion", ->
943 it "moves the cursor downward and outward", ->
944 editor.setCursorScreenPosition([0, 0])
948 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
950 describe "as a selection", ->
951 it "selects the current line excluding whitespace", ->
952 editor.setCursorScreenPosition([1, 2])
953 vimState.activateVisualMode()
957 expect(editor.getSelectedText()).toEqual " 2 \n 3abc"
959 describe "the G keybinding", ->
961 editor.setText("1\n 2\n 3abc\n ")
962 editor.setCursorScreenPosition([0, 2])
964 describe "as a motion", ->
965 beforeEach -> keydown('G', shift: true)
967 it "moves the cursor to the last line after whitespace", ->
968 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
970 describe "as a repeated motion", ->
973 keydown('G', shift: true)
975 it "moves the cursor to a specified line", ->
976 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
978 describe "as a selection", ->
980 editor.setCursorScreenPosition([1, 0])
981 vimState.activateVisualMode()
982 keydown('G', shift: true)
984 it "selects to the last line in the file", ->
985 expect(editor.getSelectedText()).toBe " 2\n 3abc\n "
987 it "moves the cursor to the last line after whitespace", ->
988 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
990 describe "the / keybinding", ->
994 pane = {activate: jasmine.createSpy("activate")}
995 spyOn(atom.workspace, 'getActivePane').andReturn(pane)
997 editor.setText("abc\ndef\nabc\ndef\n")
998 editor.setCursorBufferPosition([0, 0])
1000 describe "as a motion", ->
1001 it "moves the cursor to the specified search pattern", ->
1004 submitCommandModeInputText 'def'
1006 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1007 expect(pane.activate).toHaveBeenCalled()
1009 it "loops back around", ->
1010 editor.setCursorBufferPosition([3, 0])
1012 submitCommandModeInputText 'def'
1014 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1016 it "uses a valid regex as a regex", ->
1018 # Cycle through the 'abc' on the first line with a character pattern
1019 submitCommandModeInputText '[abc]'
1020 expect(editor.getCursorBufferPosition()).toEqual [0, 1]
1022 expect(editor.getCursorBufferPosition()).toEqual [0, 2]
1024 it "uses an invalid regex as a literal string", ->
1025 # Go straight to the literal [abc
1026 editor.setText("abc\n[abc]\n")
1028 submitCommandModeInputText '[abc'
1029 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1031 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1033 it "uses ? as a literal string", ->
1034 editor.setText("abc\n[a?c?\n")
1036 submitCommandModeInputText '?'
1037 expect(editor.getCursorBufferPosition()).toEqual [1, 2]
1039 expect(editor.getCursorBufferPosition()).toEqual [1, 4]
1041 it 'works with selection in visual mode', ->
1042 editor.setText('one two three')
1045 submitCommandModeInputText 'th'
1046 expect(editor.getCursorBufferPosition()).toEqual [0, 9]
1048 expect(editor.getText()).toBe 'hree'
1050 it 'extends selection when repeating search in visual mode', ->
1051 editor.setText('line1\nline2\nline3')
1054 submitCommandModeInputText 'line'
1055 {start, end} = editor.getSelectedBufferRange()
1056 expect(start.row).toEqual 0
1057 expect(end.row).toEqual 1
1059 {start, end} = editor.getSelectedBufferRange()
1060 expect(start.row).toEqual 0
1061 expect(end.row).toEqual 2
1063 describe "case sensitivity", ->
1065 editor.setText("\nabc\nABC\n")
1066 editor.setCursorBufferPosition([0, 0])
1069 it "works in case sensitive mode", ->
1070 submitCommandModeInputText 'ABC'
1071 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1073 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1075 it "works in case insensitive mode", ->
1076 submitCommandModeInputText '\\cAbC'
1077 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1079 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1081 it "works in case insensitive mode wherever \\c is", ->
1082 submitCommandModeInputText 'AbC\\c'
1083 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1085 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1087 it "uses case insensitive search if useSmartcaseForSearch is true and searching lowercase", ->
1088 atom.config.set 'vim-mode.useSmartcaseForSearch', true
1089 submitCommandModeInputText 'abc'
1090 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1092 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1094 it "uses case sensitive search if useSmartcaseForSearch is true and searching uppercase", ->
1095 atom.config.set 'vim-mode.useSmartcaseForSearch', true
1096 submitCommandModeInputText 'ABC'
1097 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1099 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1101 describe "repeating", ->
1102 it "does nothing with no search history", ->
1103 # This tests that no exception is raised
1108 submitCommandModeInputText 'def'
1110 it "repeats previous search with /<enter>", ->
1112 submitCommandModeInputText('')
1113 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1115 it "repeats previous search with //", ->
1117 submitCommandModeInputText('/')
1118 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1120 describe "the n keybinding", ->
1121 it "repeats the last search", ->
1123 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1125 describe "the N keybinding", ->
1126 it "repeats the last search backwards", ->
1127 editor.setCursorBufferPosition([0, 0])
1128 keydown('N', shift: true)
1129 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1130 keydown('N', shift: true)
1131 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1133 describe "composing", ->
1134 it "composes with operators", ->
1137 submitCommandModeInputText('def')
1138 expect(editor.getText()).toEqual "def\nabc\ndef\n"
1140 it "repeats correctly with operators", ->
1143 submitCommandModeInputText('def')
1146 expect(editor.getText()).toEqual "def\n"
1148 describe "when reversed as ?", ->
1149 it "moves the cursor backwards to the specified search pattern", ->
1151 submitCommandModeInputText('def')
1152 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1154 it "accepts / as a literal search pattern", ->
1155 editor.setText("abc\nd/f\nabc\nd/f\n")
1156 editor.setCursorBufferPosition([0, 0])
1158 submitCommandModeInputText('/')
1159 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1161 submitCommandModeInputText('/')
1162 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1164 describe "repeating", ->
1167 submitCommandModeInputText('def')
1169 it "repeats previous search as reversed with ?<enter>", ->
1171 submitCommandModeInputText('')
1172 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1174 it "repeats previous search as reversed with ??", ->
1176 submitCommandModeInputText('?')
1177 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1179 describe 'the n keybinding', ->
1180 it "repeats the last search backwards", ->
1181 editor.setCursorBufferPosition([0, 0])
1183 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1185 describe 'the N keybinding', ->
1186 it "repeats the last search forwards", ->
1187 editor.setCursorBufferPosition([0, 0])
1188 keydown('N', shift: true)
1189 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1191 describe "using search history", ->
1192 commandEditor = null
1196 submitCommandModeInputText('def')
1197 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1200 submitCommandModeInputText('abc')
1201 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1203 commandEditor = editor.commandModeInputView.editorElement
1205 it "allows searching history in the search field", ->
1207 atom.commands.dispatch(commandEditor, 'core:move-up')
1208 expect(commandEditor.getModel().getText()).toEqual('abc')
1209 atom.commands.dispatch(commandEditor, 'core:move-up')
1210 expect(commandEditor.getModel().getText()).toEqual('def')
1211 atom.commands.dispatch(commandEditor, 'core:move-up')
1212 expect(commandEditor.getModel().getText()).toEqual('def')
1214 it "resets the search field to empty when scrolling back", ->
1216 atom.commands.dispatch(commandEditor, 'core:move-up')
1217 expect(commandEditor.getModel().getText()).toEqual('abc')
1218 atom.commands.dispatch(commandEditor, 'core:move-up')
1219 expect(commandEditor.getModel().getText()).toEqual('def')
1220 atom.commands.dispatch(commandEditor, 'core:move-down')
1221 expect(commandEditor.getModel().getText()).toEqual('abc')
1222 atom.commands.dispatch(commandEditor, 'core:move-down')
1223 expect(commandEditor.getModel().getText()).toEqual ''
1225 describe "the * keybinding", ->
1227 editor.setText("abd\n@def\nabd\ndef\n")
1228 editor.setCursorBufferPosition([0, 0])
1230 describe "as a motion", ->
1231 it "moves cursor to next occurence of word under cursor", ->
1233 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1235 it "repeats with the n key", ->
1237 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1239 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1241 it "doesn't move cursor unless next occurence is the exact word (no partial matches)", ->
1242 editor.setText("abc\ndef\nghiabc\njkl\nabcdef")
1243 editor.setCursorBufferPosition([0, 0])
1245 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1247 describe "with words that contain 'non-word' characters", ->
1248 it "moves cursor to next occurence of word under cursor", ->
1249 editor.setText("abc\n@def\nabc\n@def\n")
1250 editor.setCursorBufferPosition([1, 0])
1252 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1254 it "doesn't move cursor unless next match has exact word ending", ->
1255 editor.setText("abc\n@def\nabc\n@def1\n")
1256 # FIXME: I suspect there is a bug laying around
1257 # Cursor#getEndOfCurrentWordBufferPosition, this function
1258 # is returning '@' as a word, instead of returning the whole
1259 # word '@def', this behavior is avoided in this test, when we
1260 # execute the '*' command when cursor is on character after '@'
1261 # (in this particular example, the 'd' char)
1262 editor.setCursorBufferPosition([1, 1])
1264 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1266 # FIXME: This behavior is different from the one found in
1267 # vim. This is because the word boundary match in Javascript
1268 # ignores starting 'non-word' characters.
1270 # in Vim: /\<def\>/.test("@def") => false
1271 # in Javascript: /\bdef\b/.test("@def") => true
1272 it "moves cursor to the start of valid word char", ->
1273 editor.setText("abc\ndef\nabc\n@def\n")
1274 editor.setCursorBufferPosition([1, 0])
1276 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1278 describe "when cursor is on non-word char column", ->
1279 it "matches only the non-word char", ->
1280 editor.setText("abc\n@def\nabc\n@def\n")
1281 editor.setCursorBufferPosition([1, 0])
1283 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1285 describe "when cursor is not on a word", ->
1286 it "does a match with the next word", ->
1287 editor.setText("abc\na @def\n abc\n @def")
1288 editor.setCursorBufferPosition([1, 1])
1290 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1292 describe "when cursor is at EOF", ->
1293 it "doesn't try to do any match", ->
1294 editor.setText("abc\n@def\nabc\n ")
1295 editor.setCursorBufferPosition([3, 0])
1297 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1299 describe "the hash keybinding", ->
1300 describe "as a motion", ->
1301 it "moves cursor to previous occurence of word under cursor", ->
1302 editor.setText("abc\n@def\nabc\ndef\n")
1303 editor.setCursorBufferPosition([2, 1])
1305 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1307 it "repeats with n", ->
1308 editor.setText("abc\n@def\nabc\ndef\nabc\n")
1309 editor.setCursorBufferPosition([2, 1])
1311 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1313 expect(editor.getCursorBufferPosition()).toEqual [4, 0]
1315 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1317 it "doesn't move cursor unless next occurence is the exact word (no partial matches)", ->
1318 editor.setText("abc\ndef\nghiabc\njkl\nabcdef")
1319 editor.setCursorBufferPosition([0, 0])
1321 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1323 describe "with words that containt 'non-word' characters", ->
1324 it "moves cursor to next occurence of word under cursor", ->
1325 editor.setText("abc\n@def\nabc\n@def\n")
1326 editor.setCursorBufferPosition([3, 0])
1328 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1330 it "moves cursor to the start of valid word char", ->
1331 editor.setText("abc\n@def\nabc\ndef\n")
1332 editor.setCursorBufferPosition([3, 0])
1334 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1336 describe "when cursor is on non-word char column", ->
1337 it "matches only the non-word char", ->
1338 editor.setText("abc\n@def\nabc\n@def\n")
1339 editor.setCursorBufferPosition([1, 0])
1341 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1343 describe "the H keybinding", ->
1345 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1346 editor.setCursorScreenPosition([8, 0])
1347 spyOn(editor.getLastCursor(), 'setScreenPosition')
1349 it "moves the cursor to the first row if visible", ->
1350 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(0)
1351 keydown('H', shift: true)
1352 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([0, 0])
1354 it "moves the cursor to the first visible row plus offset", ->
1355 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(2)
1356 keydown('H', shift: true)
1357 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([4, 0])
1359 it "respects counts", ->
1360 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(0)
1362 keydown('H', shift: true)
1363 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([2, 0])
1365 describe "the L keybinding", ->
1367 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1368 editor.setCursorScreenPosition([8, 0])
1369 spyOn(editor.getLastCursor(), 'setScreenPosition')
1371 it "moves the cursor to the first row if visible", ->
1372 spyOn(editor, 'getLastVisibleScreenRow').andReturn(10)
1373 keydown('L', shift: true)
1374 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([10, 0])
1376 it "moves the cursor to the first visible row plus offset", ->
1377 spyOn(editor, 'getLastVisibleScreenRow').andReturn(6)
1378 keydown('L', shift: true)
1379 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([4, 0])
1381 it "respects counts", ->
1382 spyOn(editor, 'getLastVisibleScreenRow').andReturn(10)
1384 keydown('L', shift: true)
1385 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([8, 0])
1387 describe "the M keybinding", ->
1389 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1390 editor.setCursorScreenPosition([8, 0])
1391 spyOn(editor.getLastCursor(), 'setScreenPosition')
1392 spyOn(editor, 'getLastVisibleScreenRow').andReturn(10)
1393 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(0)
1395 it "moves the cursor to the first row if visible", ->
1396 keydown('M', shift: true)
1397 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([5, 0])
1399 describe 'the mark keybindings', ->
1401 editor.setText(' 12\n 34\n56\n')
1402 editor.setCursorBufferPosition([0, 1])
1404 it 'moves to the beginning of the line of a mark', ->
1405 editor.setCursorBufferPosition([1, 1])
1407 commandModeInputKeydown('a')
1408 editor.setCursorBufferPosition([0, 0])
1410 commandModeInputKeydown('a')
1411 expect(editor.getCursorBufferPosition()).toEqual [1, 4]
1413 it 'moves literally to a mark', ->
1414 editor.setCursorBufferPosition([1, 1])
1416 commandModeInputKeydown('a')
1417 editor.setCursorBufferPosition([0, 0])
1419 commandModeInputKeydown('a')
1420 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1422 it 'deletes to a mark by line', ->
1423 editor.setCursorBufferPosition([1, 5])
1425 commandModeInputKeydown('a')
1426 editor.setCursorBufferPosition([0, 0])
1429 commandModeInputKeydown('a')
1430 expect(editor.getText()).toEqual '56\n'
1432 it 'deletes before to a mark literally', ->
1433 editor.setCursorBufferPosition([1, 5])
1435 commandModeInputKeydown('a')
1436 editor.setCursorBufferPosition([0, 1])
1439 commandModeInputKeydown('a')
1440 expect(editor.getText()).toEqual ' 4\n56\n'
1442 it 'deletes after to a mark literally', ->
1443 editor.setCursorBufferPosition([1, 5])
1445 commandModeInputKeydown('a')
1446 editor.setCursorBufferPosition([2, 1])
1449 commandModeInputKeydown('a')
1450 expect(editor.getText()).toEqual ' 12\n 36\n'
1452 it 'moves back to previous', ->
1453 editor.setCursorBufferPosition([1, 5])
1455 commandModeInputKeydown('`')
1456 editor.setCursorBufferPosition([2, 1])
1458 commandModeInputKeydown('`')
1459 expect(editor.getCursorBufferPosition()).toEqual [1, 5]
1461 describe 'the f/F keybindings', ->
1463 editor.setText("abcabcabcabc\n")
1464 editor.setCursorScreenPosition([0, 0])
1466 it 'moves to the first specified character it finds', ->
1468 commandModeInputKeydown('c')
1469 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1471 it 'moves backwards to the first specified character it finds', ->
1472 editor.setCursorScreenPosition([0, 2])
1473 keydown('F', shift: true)
1474 commandModeInputKeydown('a')
1475 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1477 it 'respects count forward', ->
1480 commandModeInputKeydown('a')
1481 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1483 it 'respects count backward', ->
1484 editor.setCursorScreenPosition([0, 6])
1486 keydown('F', shift: true)
1487 commandModeInputKeydown('a')
1488 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1490 it "doesn't move if the character specified isn't found", ->
1492 commandModeInputKeydown('d')
1493 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1495 it "doesn't move if there aren't the specified count of the specified character", ->
1499 commandModeInputKeydown('a')
1500 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1501 # a bug was making this behaviour depend on the count
1505 commandModeInputKeydown('a')
1506 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1508 editor.setCursorScreenPosition([0, 6])
1511 keydown('F', shift: true)
1512 commandModeInputKeydown('a')
1513 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1516 keydown('F', shift: true)
1517 commandModeInputKeydown('a')
1518 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1520 it "composes with d", ->
1521 editor.setCursorScreenPosition([0, 3])
1525 commandModeInputKeydown('a')
1526 expect(editor.getText()).toEqual 'abcbc\n'
1528 describe 'the t/T keybindings', ->
1530 editor.setText("abcabcabcabc\n")
1531 editor.setCursorScreenPosition([0, 0])
1533 it 'moves to the character previous to the first specified character it finds', ->
1535 commandModeInputKeydown('a')
1536 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1537 # or stays put when it's already there
1539 commandModeInputKeydown('a')
1540 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1542 it 'moves backwards to the character after the first specified character it finds', ->
1543 editor.setCursorScreenPosition([0, 2])
1544 keydown('T', shift: true)
1545 commandModeInputKeydown('a')
1546 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1548 it 'respects count forward', ->
1551 commandModeInputKeydown('a')
1552 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1554 it 'respects count backward', ->
1555 editor.setCursorScreenPosition([0, 6])
1557 keydown('T', shift: true)
1558 commandModeInputKeydown('a')
1559 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1561 it "doesn't move if the character specified isn't found", ->
1563 commandModeInputKeydown('d')
1564 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1566 it "doesn't move if there aren't the specified count of the specified character", ->
1570 commandModeInputKeydown('a')
1571 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1572 # a bug was making this behaviour depend on the count
1576 commandModeInputKeydown('a')
1577 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1579 editor.setCursorScreenPosition([0, 6])
1582 keydown('T', shift: true)
1583 commandModeInputKeydown('a')
1584 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1587 keydown('T', shift: true)
1588 commandModeInputKeydown('a')
1589 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1591 it "composes with d", ->
1592 editor.setCursorScreenPosition([0, 3])
1596 commandModeInputKeydown('b')
1597 expect(editor.getText()).toBe 'abcbcabc\n'
1599 describe 'the V keybinding', ->
1601 editor.setText("01\n002\n0003\n00004\n000005\n")
1602 editor.setCursorScreenPosition([1, 1])
1604 it "selects down a line", ->
1605 keydown('V', shift: true)
1608 expect(editor.getSelectedText()).toBe "002\n0003\n00004\n"
1610 it "selects up a line", ->
1611 keydown('V', shift: true)
1613 expect(editor.getSelectedText()).toBe "01\n002\n"
1615 describe 'the ; and , keybindings', ->
1617 editor.setText("abcabcabcabc\n")
1618 editor.setCursorScreenPosition([0, 0])
1620 it "repeat f in same direction", ->
1622 commandModeInputKeydown('c')
1623 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1625 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1627 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1629 it "repeat F in same direction", ->
1630 editor.setCursorScreenPosition([0, 10])
1631 keydown('F', shift: true)
1632 commandModeInputKeydown('c')
1633 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1635 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1637 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1639 it "repeat f in opposite direction", ->
1640 editor.setCursorScreenPosition([0, 6])
1642 commandModeInputKeydown('c')
1643 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1645 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1647 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1649 it "repeat F in opposite direction", ->
1650 editor.setCursorScreenPosition([0, 4])
1651 keydown('F', shift: true)
1652 commandModeInputKeydown('c')
1653 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1655 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1657 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1659 it "alternate repeat f in same direction and reverse", ->
1661 commandModeInputKeydown('c')
1662 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1664 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1666 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1668 it "alternate repeat F in same direction and reverse", ->
1669 editor.setCursorScreenPosition([0, 10])
1670 keydown('F', shift: true)
1671 commandModeInputKeydown('c')
1672 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1674 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1676 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1678 it "repeat t in same direction", ->
1680 commandModeInputKeydown('c')
1681 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1683 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1685 it "repeat T in same direction", ->
1686 editor.setCursorScreenPosition([0, 10])
1687 keydown('T', shift: true)
1688 commandModeInputKeydown('c')
1689 expect(editor.getCursorScreenPosition()).toEqual [0, 9]
1691 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1693 it "repeat t in opposite direction first, and then reverse", ->
1694 editor.setCursorScreenPosition([0, 3])
1696 commandModeInputKeydown('c')
1697 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1699 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1701 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1703 it "repeat T in opposite direction first, and then reverse", ->
1704 editor.setCursorScreenPosition([0, 4])
1705 keydown('T', shift: true)
1706 commandModeInputKeydown('c')
1707 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1709 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1711 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1713 it "repeat with count in same direction", ->
1714 editor.setCursorScreenPosition([0, 0])
1716 commandModeInputKeydown('c')
1717 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1720 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1722 it "repeat with count in reverse direction", ->
1723 editor.setCursorScreenPosition([0, 6])
1725 commandModeInputKeydown('c')
1726 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1729 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1731 describe 'the % motion', ->
1733 editor.setText("( ( ) )--{ text in here; and a function call(with parameters) }\n")
1734 editor.setCursorScreenPosition([0, 0])
1736 it 'matches the correct parenthesis', ->
1738 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1740 it 'matches the correct brace', ->
1741 editor.setCursorScreenPosition([0, 9])
1743 expect(editor.getCursorScreenPosition()).toEqual [0, 62]
1745 it 'composes correctly with d', ->
1746 editor.setCursorScreenPosition([0, 9])
1749 expect(editor.getText()).toEqual "( ( ) )--\n"
1751 it 'moves correctly when composed with v going forward', ->
1755 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
1757 it 'moves correctly when composed with v going backward', ->
1758 editor.setCursorScreenPosition([0, 5])
1761 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1763 it 'it moves appropriately to find the nearest matching action', ->
1764 editor.setCursorScreenPosition([0, 3])
1766 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1767 expect(editor.getText()).toEqual "( ( ) )--{ text in here; and a function call(with parameters) }\n"
1769 it 'it moves appropriately to find the nearest matching action', ->
1770 editor.setCursorScreenPosition([0, 26])
1772 expect(editor.getCursorScreenPosition()).toEqual [0, 60]
1773 expect(editor.getText()).toEqual "( ( ) )--{ text in here; and a function call(with parameters) }\n"
1775 it "finds matches across multiple lines", ->
1776 editor.setText("...(\n...)")
1777 editor.setCursorScreenPosition([0, 0])
1779 expect(editor.getCursorScreenPosition()).toEqual([1, 3])
1781 it "does not affect search history", ->
1783 submitCommandModeInputText 'func'
1784 expect(editor.getCursorBufferPosition()).toEqual [0, 31]
1786 expect(editor.getCursorBufferPosition()).toEqual [0, 60]
1788 expect(editor.getCursorBufferPosition()).toEqual [0, 31]
1790 describe "scrolling screen and keeping cursor in the same screen position", ->
1792 editor.setText([0...80].join("\n"))
1793 editor.setHeight(20 * 10)
1794 editor.setLineHeightInPixels(10)
1795 editor.setScrollTop(40 * 10)
1796 editor.setCursorBufferPosition([42, 0])
1798 describe "the ctrl-u keybinding", ->
1799 it "moves the screen down by half screen size and keeps cursor onscreen", ->
1800 keydown('u', ctrl: true)
1801 expect(editor.getScrollTop()).toEqual 300
1802 expect(editor.getCursorBufferPosition()).toEqual [32, 0]
1804 it "selects on visual mode", ->
1805 editor.setCursorBufferPosition([42, 1])
1806 vimState.activateVisualMode()
1807 keydown('u', ctrl: true)
1808 expect(editor.getSelectedText()).toEqual [32..42].join("\n")
1810 it "selects on linewise mode", ->
1811 vimState.activateVisualMode('linewise')
1812 keydown('u', ctrl: true)
1813 expect(editor.getSelectedText()).toEqual [32..42].join("\n").concat("\n")
1815 describe "the ctrl-b keybinding", ->
1816 it "moves screen up one page", ->
1817 keydown('b', ctrl: true)
1818 expect(editor.getScrollTop()).toEqual 200
1819 expect(editor.getCursorScreenPosition()).toEqual [22, 0]
1821 it "selects on visual mode", ->
1822 editor.setCursorBufferPosition([42, 1])
1823 vimState.activateVisualMode()
1824 keydown('b', ctrl: true)
1825 expect(editor.getSelectedText()).toEqual [22..42].join("\n")
1827 it "selects on linewise mode", ->
1828 vimState.activateVisualMode('linewise')
1829 keydown('b', ctrl: true)
1830 expect(editor.getSelectedText()).toEqual [22..42].join("\n").concat("\n")
1833 describe "the ctrl-d keybinding", ->
1834 it "moves the screen down by half screen size and keeps cursor onscreen", ->
1835 keydown('d', ctrl: true)
1836 expect(editor.getScrollTop()).toEqual 500
1837 expect(editor.getCursorBufferPosition()).toEqual [52, 0]
1839 it "selects on visual mode", ->
1840 editor.setCursorBufferPosition([42, 1])
1841 vimState.activateVisualMode()
1842 keydown('d', ctrl: true)
1843 expect(editor.getSelectedText()).toEqual [42..52].join("\n").slice(1, -1)
1845 it "selects on linewise mode", ->
1846 vimState.activateVisualMode('linewise')
1847 keydown('d', ctrl: true)
1848 expect(editor.getSelectedText()).toEqual [42..52].join("\n").concat("\n")
1850 describe "the ctrl-f keybinding", ->
1851 it "moves screen down one page", ->
1852 keydown('f', ctrl: true)
1853 expect(editor.getScrollTop()).toEqual 600
1854 expect(editor.getCursorScreenPosition()).toEqual [62, 0]
1856 it "selects on visual mode", ->
1857 editor.setCursorBufferPosition([42, 1])
1858 vimState.activateVisualMode()
1859 keydown('f', ctrl: true)
1860 expect(editor.getSelectedText()).toEqual [42..62].join("\n").slice(1, -1)
1862 it "selects on linewise mode", ->
1863 vimState.activateVisualMode('linewise')
1864 keydown('f', ctrl: true)
1865 expect(editor.getSelectedText()).toEqual [42..62].join("\n").concat("\n")