]> git.r.bdr.sh - rbdr/dotfiles/blob - atom/packages/vim-mode/spec/motions-spec.coffee
Remove vim-snipmate
[rbdr/dotfiles] / atom / packages / vim-mode / spec / motions-spec.coffee
1 helpers = require './spec-helper'
2
3 describe "Motions", ->
4 [editor, editorElement, vimState] = []
5
6 beforeEach ->
7 vimMode = atom.packages.loadPackage('vim-mode')
8 vimMode.activateResources()
9
10 helpers.getEditorElement (element) ->
11 editorElement = element
12 editor = editorElement.getModel()
13 vimState = editorElement.vimState
14 vimState.activateNormalMode()
15 vimState.resetNormalMode()
16
17 keydown = (key, options={}) ->
18 options.element ?= editorElement
19 helpers.keydown(key, options)
20
21 normalModeInputKeydown = (key, opts = {}) ->
22 theEditor = opts.editor or editor
23 theEditor.normalModeInputView.editorElement.getModel().setText(key)
24
25 submitNormalModeInputText = (text) ->
26 inputEditor = editor.normalModeInputView.editorElement
27 inputEditor.getModel().setText(text)
28 atom.commands.dispatch(inputEditor, "core:confirm")
29
30 describe "simple motions", ->
31 beforeEach ->
32 editor.setText("12345\nabcd\nABCDE")
33 editor.setCursorScreenPosition([1, 1])
34
35 describe "the h keybinding", ->
36 describe "as a motion", ->
37 it "moves the cursor left, but not to the previous line", ->
38 keydown('h')
39 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
40
41 keydown('h')
42 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
43
44 it "moves the cursor to the previous line if wrapLeftRightMotion is true", ->
45 atom.config.set('vim-mode.wrapLeftRightMotion', true)
46 keydown('h')
47 keydown('h')
48 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
49
50 describe "as a selection", ->
51 it "selects the character to the left", ->
52 keydown('y')
53 keydown('h')
54
55 expect(vimState.getRegister('"').text).toBe 'a'
56 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
57
58 describe "the j keybinding", ->
59 it "moves the cursor down, but not to the end of the last line", ->
60 keydown('j')
61 expect(editor.getCursorScreenPosition()).toEqual [2, 1]
62
63 keydown('j')
64 expect(editor.getCursorScreenPosition()).toEqual [2, 1]
65
66 it "moves the cursor to the end of the line, not past it", ->
67 editor.setCursorScreenPosition([0, 4])
68
69 keydown('j')
70 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
71
72 it "remembers the position it column it was in after moving to shorter line", ->
73 editor.setCursorScreenPosition([0, 4])
74
75 keydown('j')
76 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
77
78 keydown('j')
79 expect(editor.getCursorScreenPosition()).toEqual [2, 4]
80
81 describe "when visual mode", ->
82 beforeEach ->
83 keydown('v')
84 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
85
86 it "moves the cursor down", ->
87 keydown('j')
88 expect(editor.getCursorScreenPosition()).toEqual [2, 2]
89
90 it "doesn't go over after the last line", ->
91 keydown('j')
92 expect(editor.getCursorScreenPosition()).toEqual [2, 2]
93
94 it "selects the text while moving", ->
95 keydown('j')
96 expect(editor.getSelectedText()).toBe "bcd\nAB"
97
98 describe "the k keybinding", ->
99 it "moves the cursor up, but not to the beginning of the first line", ->
100 keydown('k')
101 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
102
103 keydown('k')
104 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
105
106 describe "the l keybinding", ->
107 beforeEach -> editor.setCursorScreenPosition([1, 2])
108
109 it "moves the cursor right, but not to the next line", ->
110 keydown('l')
111 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
112
113 keydown('l')
114 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
115
116 it "moves the cursor to the next line if wrapLeftRightMotion is true", ->
117 atom.config.set('vim-mode.wrapLeftRightMotion', true)
118 keydown('l')
119 keydown('l')
120 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
121
122 describe "on a blank line", ->
123 it "doesn't move the cursor", ->
124 editor.setText("\n\n\n")
125 editor.setCursorBufferPosition([1, 0])
126 keydown('l')
127 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
128
129 describe "the w keybinding", ->
130 beforeEach -> editor.setText("ab cde1+- \n xyz\n\nzip")
131
132 describe "as a motion", ->
133 beforeEach -> editor.setCursorScreenPosition([0, 0])
134
135 it "moves the cursor to the beginning of the next word", ->
136 keydown('w')
137 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
138
139 keydown('w')
140 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
141
142 keydown('w')
143 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
144
145 keydown('w')
146 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
147
148 keydown('w')
149 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
150
151 keydown('w')
152 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
153
154 # When the cursor gets to the EOF, it should stay there.
155 keydown('w')
156 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
157
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])
161 keydown('w')
162 expect(editor.getCursorScreenPosition()).toEqual([0, 2])
163
164 describe "as a selection", ->
165 describe "within a word", ->
166 beforeEach ->
167 editor.setCursorScreenPosition([0, 0])
168 keydown('y')
169 keydown('w')
170
171 it "selects to the end of the word", ->
172 expect(vimState.getRegister('"').text).toBe 'ab '
173
174 describe "between words", ->
175 beforeEach ->
176 editor.setCursorScreenPosition([0, 2])
177 keydown('y')
178 keydown('w')
179
180 it "selects the whitespace", ->
181 expect(vimState.getRegister('"').text).toBe ' '
182
183 describe "the W keybinding", ->
184 beforeEach -> editor.setText("cde1+- ab \n xyz\n\nzip")
185
186 describe "as a motion", ->
187 beforeEach -> editor.setCursorScreenPosition([0, 0])
188
189 it "moves the cursor to the beginning of the next word", ->
190 keydown('W', shift: true)
191 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
192
193 keydown('W', shift: true)
194 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
195
196 keydown('W', shift: true)
197 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
198
199 keydown('W', shift: true)
200 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
201
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])
206 keydown('y')
207 keydown('W', shift: true)
208 expect(vimState.getRegister('"').text).toBe 'cde1+- '
209
210 it "continues past blank lines", ->
211 editor.setCursorScreenPosition([2, 0])
212
213 keydown('d')
214 keydown('W', shift: true)
215 expect(editor.getText()).toBe "cde1+- ab \n xyz\nzip"
216 expect(vimState.getRegister('"').text).toBe '\n'
217
218 it "doesn't go past the end of the file", ->
219 editor.setCursorScreenPosition([3, 0])
220
221 keydown('d')
222 keydown('W', shift: true)
223 expect(editor.getText()).toBe "cde1+- ab \n xyz\n\n"
224 expect(vimState.getRegister('"').text).toBe 'zip'
225
226 describe "the e keybinding", ->
227 beforeEach -> editor.setText("ab cde1+- \n xyz\n\nzip")
228
229 describe "as a motion", ->
230 beforeEach -> editor.setCursorScreenPosition([0, 0])
231
232 it "moves the cursor to the end of the current word", ->
233 keydown('e')
234 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
235
236 keydown('e')
237 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
238
239 keydown('e')
240 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
241
242 keydown('e')
243 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
244
245 keydown('e')
246 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
247
248 describe "as selection", ->
249 describe "within a word", ->
250 beforeEach ->
251 editor.setCursorScreenPosition([0, 0])
252 keydown('y')
253 keydown('e')
254
255 it "selects to the end of the current word", ->
256 expect(vimState.getRegister('"').text).toBe 'ab'
257
258 describe "between words", ->
259 beforeEach ->
260 editor.setCursorScreenPosition([0, 2])
261 keydown('y')
262 keydown('e')
263
264 it "selects to the end of the next word", ->
265 expect(vimState.getRegister('"').text).toBe ' cde1'
266
267 describe "the E keybinding", ->
268 beforeEach -> editor.setText("ab cde1+- \n xyz \n\nzip\n")
269
270 describe "as a motion", ->
271 beforeEach -> editor.setCursorScreenPosition([0, 0])
272
273 it "moves the cursor to the end of the current word", ->
274 keydown('E', shift: true)
275 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
276
277 keydown('E', shift: true)
278 expect(editor.getCursorScreenPosition()).toEqual [0, 9]
279
280 keydown('E', shift: true)
281 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
282
283 keydown('E', shift: true)
284 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
285
286 keydown('E', shift: true)
287 expect(editor.getCursorScreenPosition()).toEqual [4, 0]
288
289 describe "as selection", ->
290 describe "within a word", ->
291 beforeEach ->
292 editor.setCursorScreenPosition([0, 0])
293 keydown('y')
294 keydown('E', shift: true)
295
296 it "selects to the end of the current word", ->
297 expect(vimState.getRegister('"').text).toBe 'ab'
298
299 describe "between words", ->
300 beforeEach ->
301 editor.setCursorScreenPosition([0, 2])
302 keydown('y')
303 keydown('E', shift: true)
304
305 it "selects to the end of the next word", ->
306 expect(vimState.getRegister('"').text).toBe ' cde1+-'
307
308 describe "press more than once", ->
309 beforeEach ->
310 editor.setCursorScreenPosition([0, 0])
311 keydown('v')
312 keydown('E', shift: true)
313 keydown('E', shift: true)
314 keydown('y')
315
316 it "selects to the end of the current word", ->
317 expect(vimState.getRegister('"').text).toBe 'ab cde1+-'
318
319 describe "the } keybinding", ->
320 beforeEach ->
321 editor.setText("abcde\n\nfghij\nhijk\n xyz \n\nzip\n\n \nthe end")
322 editor.setCursorScreenPosition([0, 0])
323
324 describe "as a motion", ->
325 it "moves the cursor to the end of the paragraph", ->
326 keydown('}')
327 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
328
329 keydown('}')
330 expect(editor.getCursorScreenPosition()).toEqual [5, 0]
331
332 keydown('}')
333 expect(editor.getCursorScreenPosition()).toEqual [7, 0]
334
335 keydown('}')
336 expect(editor.getCursorScreenPosition()).toEqual [9, 6]
337
338 describe "as a selection", ->
339 beforeEach ->
340 keydown('y')
341 keydown('}')
342
343 it 'selects to the end of the current paragraph', ->
344 expect(vimState.getRegister('"').text).toBe "abcde\n"
345
346 describe "the { keybinding", ->
347 beforeEach ->
348 editor.setText("abcde\n\nfghij\nhijk\n xyz \n\nzip\n\n \nthe end")
349 editor.setCursorScreenPosition([9, 0])
350
351 describe "as a motion", ->
352 it "moves the cursor to the beginning of the paragraph", ->
353 keydown('{')
354 expect(editor.getCursorScreenPosition()).toEqual [7, 0]
355
356 keydown('{')
357 expect(editor.getCursorScreenPosition()).toEqual [5, 0]
358
359 keydown('{')
360 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
361
362 keydown('{')
363 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
364
365 describe "as a selection", ->
366 beforeEach ->
367 editor.setCursorScreenPosition([7, 0])
368 keydown('y')
369 keydown('{')
370
371 it 'selects to the beginning of the current paragraph', ->
372 expect(vimState.getRegister('"').text).toBe "\nzip\n"
373
374 describe "the b keybinding", ->
375 beforeEach -> editor.setText(" ab cde1+- \n xyz\n\nzip }\n last")
376
377 describe "as a motion", ->
378 beforeEach -> editor.setCursorScreenPosition([4, 1])
379
380 it "moves the cursor to the beginning of the previous word", ->
381 keydown('b')
382 expect(editor.getCursorScreenPosition()).toEqual [3, 4]
383
384 keydown('b')
385 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
386
387 keydown('b')
388 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
389
390 keydown('b')
391 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
392
393 keydown('b')
394 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
395
396 keydown('b')
397 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
398
399 keydown('b')
400 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
401
402 # Go to start of the file, after moving past the first word
403 keydown('b')
404 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
405
406 # Stay at the start of the file
407 keydown('b')
408 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
409
410 describe "as a selection", ->
411 describe "within a word", ->
412 beforeEach ->
413 editor.setCursorScreenPosition([0, 2])
414 keydown('y')
415 keydown('b')
416
417 it "selects to the beginning of the current word", ->
418 expect(vimState.getRegister('"').text).toBe 'a'
419 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
420
421 describe "between words", ->
422 beforeEach ->
423 editor.setCursorScreenPosition([0, 4])
424 keydown('y')
425 keydown('b')
426
427 it "selects to the beginning of the last word", ->
428 expect(vimState.getRegister('"').text).toBe 'ab '
429 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
430
431 describe "the B keybinding", ->
432 beforeEach -> editor.setText("cde1+- ab \n\t xyz-123\n\n zip")
433
434 describe "as a motion", ->
435 beforeEach -> editor.setCursorScreenPosition([4, 1])
436
437 it "moves the cursor to the beginning of the previous word", ->
438 keydown('B', shift: true)
439 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
440
441 keydown('B', shift: true)
442 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
443
444 keydown('B', shift: true)
445 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
446
447 keydown('B', shift: true)
448 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
449
450 keydown('B', shift: true)
451 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
452
453 describe "as a selection", ->
454 it "selects to the beginning of the whole word", ->
455 editor.setCursorScreenPosition([1, 9])
456 keydown('y')
457 keydown('B', shift: true)
458 expect(vimState.getRegister('"').text).toBe 'xyz-12'
459
460 it "doesn't go past the beginning of the file", ->
461 editor.setCursorScreenPosition([0, 0])
462 vimState.setRegister('"', text: 'abc')
463 keydown('y')
464 keydown('B', shift: true)
465 expect(vimState.getRegister('"').text).toBe 'abc'
466
467 describe "the ^ keybinding", ->
468 beforeEach ->
469 editor.setText(" abcde")
470
471 describe "from the beginning of the line", ->
472 beforeEach -> editor.setCursorScreenPosition([0, 0])
473
474 describe "as a motion", ->
475 beforeEach -> keydown('^')
476
477 it "moves the cursor to the first character of the line", ->
478 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
479
480 describe "as a selection", ->
481 beforeEach ->
482 keydown('d')
483 keydown('^')
484
485 it 'selects to the first character of the line', ->
486 expect(editor.getText()).toBe 'abcde'
487 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
488
489 describe "from the first character of the line", ->
490 beforeEach -> editor.setCursorScreenPosition([0, 2])
491
492 describe "as a motion", ->
493 beforeEach -> keydown('^')
494
495 it "stays put", ->
496 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
497
498 describe "as a selection", ->
499 beforeEach ->
500 keydown('d')
501 keydown('^')
502
503 it "does nothing", ->
504 expect(editor.getText()).toBe ' abcde'
505 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
506
507 describe "from the middle of a word", ->
508 beforeEach -> editor.setCursorScreenPosition([0, 4])
509
510 describe "as a motion", ->
511 beforeEach -> keydown('^')
512
513 it "moves the cursor to the first character of the line", ->
514 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
515
516 describe "as a selection", ->
517 beforeEach ->
518 keydown('d')
519 keydown('^')
520
521 it 'selects to the first character of the line', ->
522 expect(editor.getText()).toBe ' cde'
523 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
524
525 describe "the 0 keybinding", ->
526 beforeEach ->
527 editor.setText(" abcde")
528 editor.setCursorScreenPosition([0, 4])
529
530 describe "as a motion", ->
531 beforeEach -> keydown('0')
532
533 it "moves the cursor to the first column", ->
534 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
535
536 describe "as a selection", ->
537 beforeEach ->
538 keydown('d')
539 keydown('0')
540
541 it 'selects to the first column of the line', ->
542 expect(editor.getText()).toBe 'cde'
543 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
544
545 describe "the $ keybinding", ->
546 beforeEach ->
547 editor.setText(" abcde\n\n1234567890")
548 editor.setCursorScreenPosition([0, 4])
549
550 describe "as a motion from empty line", ->
551 beforeEach -> editor.setCursorScreenPosition([1, 0])
552
553 it "moves the cursor to the end of the line", ->
554 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
555
556 describe "as a motion", ->
557 beforeEach -> keydown('$')
558
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]
562
563 it "should remain in the last column when moving down", ->
564 keydown('j')
565 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
566
567 keydown('j')
568 expect(editor.getCursorScreenPosition()).toEqual [2, 9]
569
570 describe "as a selection", ->
571 beforeEach ->
572 keydown('d')
573 keydown('$')
574
575 it "selects to the beginning of the lines", ->
576 expect(editor.getText()).toBe " ab\n\n1234567890"
577 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
578
579 describe "the 0 keybinding", ->
580 beforeEach ->
581 editor.setText(" a\n")
582 editor.setCursorScreenPosition([0, 2])
583
584 describe "as a motion", ->
585 beforeEach -> keydown('0')
586
587 it "moves the cursor to the beginning of the line", ->
588 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
589
590 describe "the - keybinding", ->
591 beforeEach ->
592 editor.setText("abcdefg\n abc\n abc\n")
593
594 describe "from the middle of a line", ->
595 beforeEach -> editor.setCursorScreenPosition([1, 3])
596
597 describe "as a motion", ->
598 beforeEach -> keydown('-')
599
600 it "moves the cursor to the first character of the previous line", ->
601 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
602
603 describe "as a selection", ->
604 beforeEach ->
605 keydown('d')
606 keydown('-')
607
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]
612
613 describe "from the first character of a line indented the same as the previous one", ->
614 beforeEach -> editor.setCursorScreenPosition([2, 2])
615
616 describe "as a motion", ->
617 beforeEach -> keydown('-')
618
619 it "moves to the first character of the previous line (directly above)", ->
620 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
621
622 describe "as a selection", ->
623 beforeEach ->
624 keydown('d')
625 keydown('-')
626
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]
631
632 describe "from the beginning of a line preceded by an indented line", ->
633 beforeEach -> editor.setCursorScreenPosition([2, 0])
634
635 describe "as a motion", ->
636 beforeEach -> keydown('-')
637
638 it "moves the cursor to the first character of the previous line", ->
639 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
640
641 describe "as a selection", ->
642 beforeEach ->
643 keydown('d')
644 keydown('-')
645
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]
650
651 describe "with a count", ->
652 beforeEach ->
653 editor.setText("1\n2\n3\n4\n5\n6\n")
654 editor.setCursorScreenPosition([4, 0])
655
656 describe "as a motion", ->
657 beforeEach ->
658 keydown('3')
659 keydown('-')
660
661 it "moves the cursor to the first character of that many lines previous", ->
662 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
663
664 describe "as a selection", ->
665 beforeEach ->
666 keydown('d')
667 keydown('3')
668 keydown('-')
669
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]
673
674 describe "the + keybinding", ->
675 beforeEach ->
676 editor.setText(" abc\n abc\nabcdefg\n")
677
678 describe "from the middle of a line", ->
679 beforeEach -> editor.setCursorScreenPosition([1, 3])
680
681 describe "as a motion", ->
682 beforeEach -> keydown('+')
683
684 it "moves the cursor to the first character of the next line", ->
685 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
686
687 describe "as a selection", ->
688 beforeEach ->
689 keydown('d')
690 keydown('+')
691
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]
696
697 describe "from the first character of a line indented the same as the next one", ->
698 beforeEach -> editor.setCursorScreenPosition([0, 2])
699
700 describe "as a motion", ->
701 beforeEach -> keydown('+')
702
703 it "moves to the first character of the next line (directly below)", ->
704 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
705
706 describe "as a selection", ->
707 beforeEach ->
708 keydown('d')
709 keydown('+')
710
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]
715
716 describe "from the beginning of a line followed by an indented line", ->
717 beforeEach -> editor.setCursorScreenPosition([0, 0])
718
719 describe "as a motion", ->
720 beforeEach -> keydown('+')
721
722 it "moves the cursor to the first character of the next line", ->
723 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
724
725 describe "as a selection", ->
726 beforeEach ->
727 keydown('d')
728 keydown('+')
729
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]
733
734 describe "with a count", ->
735 beforeEach ->
736 editor.setText("1\n2\n3\n4\n5\n6\n")
737 editor.setCursorScreenPosition([1, 0])
738
739 describe "as a motion", ->
740 beforeEach ->
741 keydown('3')
742 keydown('+')
743
744 it "moves the cursor to the first character of that many lines following", ->
745 expect(editor.getCursorScreenPosition()).toEqual [4, 0]
746
747 describe "as a selection", ->
748 beforeEach ->
749 keydown('d')
750 keydown('3')
751 keydown('+')
752
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]
756
757 describe "the _ keybinding", ->
758 beforeEach ->
759 editor.setText(" abc\n abc\nabcdefg\n")
760
761 describe "from the middle of a line", ->
762 beforeEach -> editor.setCursorScreenPosition([1, 3])
763
764 describe "as a motion", ->
765 beforeEach -> keydown('_')
766
767 it "moves the cursor to the first character of the current line", ->
768 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
769
770 describe "as a selection", ->
771 beforeEach ->
772 keydown('d')
773 keydown('_')
774
775 it "deletes the current line", ->
776 expect(editor.getText()).toBe " abc\nabcdefg\n"
777 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
778
779 describe "with a count", ->
780 beforeEach ->
781 editor.setText("1\n2\n3\n4\n5\n6\n")
782 editor.setCursorScreenPosition([1, 0])
783
784 describe "as a motion", ->
785 beforeEach ->
786 keydown('3')
787 keydown('_')
788
789 it "moves the cursor to the first character of that many lines following", ->
790 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
791
792 describe "as a selection", ->
793 beforeEach ->
794 keydown('d')
795 keydown('3')
796 keydown('_')
797
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]
801
802 describe "the enter keybinding", ->
803 keydownCodeForEnter = '\r' # 'enter' does not work
804 startingText = " abc\n abc\nabcdefg\n"
805
806 describe "from the middle of a line", ->
807 startingCursorPosition = [1, 3]
808
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)
814 keydown('+')
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
821
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)
827 keydown('d')
828 keydown('+')
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)
834 keydown('d')
835 keydown(keydownCodeForEnter)
836 expect(editor.getText()).toEqual referenceText
837 expect(editor.getCursorScreenPosition()).toEqual referenceCursorPosition
838
839 describe "the gg keybinding", ->
840 beforeEach ->
841 editor.setText(" 1abc\n 2\n3\n")
842 editor.setCursorScreenPosition([0, 2])
843
844 describe "as a motion", ->
845 describe "in normal mode", ->
846 beforeEach ->
847 keydown('g')
848 keydown('g')
849
850 it "moves the cursor to the beginning of the first line", ->
851 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
852
853 describe "in linewise visual mode", ->
854 beforeEach ->
855 editor.setCursorScreenPosition([1, 0])
856 vimState.activateVisualMode('linewise')
857 keydown('g')
858 keydown('g')
859
860 it "selects to the first line in the file", ->
861 expect(editor.getSelectedText()).toBe " 1abc\n 2\n"
862
863 it "moves the cursor to a specified line", ->
864 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
865
866 describe "in characterwise visual mode", ->
867 beforeEach ->
868 editor.setCursorScreenPosition([1, 1])
869 vimState.activateVisualMode()
870 keydown('g')
871 keydown('g')
872
873 it "selects to the first line in the file", ->
874 expect(editor.getSelectedText()).toBe "1abc\n 2"
875
876 it "moves the cursor to a specified line", ->
877 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
878
879 describe "as a repeated motion", ->
880 describe "in normal mode", ->
881 beforeEach ->
882 keydown('2')
883 keydown('g')
884 keydown('g')
885
886 it "moves the cursor to a specified line", ->
887 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
888
889 describe "in linewise visual motion", ->
890 beforeEach ->
891 editor.setCursorScreenPosition([2, 0])
892 vimState.activateVisualMode('linewise')
893 keydown('2')
894 keydown('g')
895 keydown('g')
896
897 it "selects to a specified line", ->
898 expect(editor.getSelectedText()).toBe " 2\n3\n"
899
900 it "moves the cursor to a specified line", ->
901 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
902
903 describe "in characterwise visual motion", ->
904 beforeEach ->
905 editor.setCursorScreenPosition([2, 0])
906 vimState.activateVisualMode()
907 keydown('2')
908 keydown('g')
909 keydown('g')
910
911 it "selects to a first character of specified line", ->
912 expect(editor.getSelectedText()).toBe "2\n3"
913
914 it "moves the cursor to a specified line", ->
915 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
916
917 describe "the g_ keybinding", ->
918 beforeEach ->
919 editor.setText("1 \n 2 \n 3abc\n ")
920
921 describe "as a motion", ->
922 it "moves the cursor to the last nonblank character", ->
923 editor.setCursorScreenPosition([1, 0])
924 keydown('g')
925 keydown('_')
926 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
927
928 it "will move the cursor to the beginning of the line if necessary", ->
929 editor.setCursorScreenPosition([0, 2])
930 keydown('g')
931 keydown('_')
932 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
933
934 describe "as a repeated motion", ->
935 it "moves the cursor downward and outward", ->
936 editor.setCursorScreenPosition([0, 0])
937 keydown('2')
938 keydown('g')
939 keydown('_')
940 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
941
942 describe "as a selection", ->
943 it "selects the current line excluding whitespace", ->
944 editor.setCursorScreenPosition([1, 2])
945 vimState.activateVisualMode()
946 keydown('2')
947 keydown('g')
948 keydown('_')
949 expect(editor.getSelectedText()).toEqual " 2 \n 3abc"
950
951 describe "the G keybinding", ->
952 beforeEach ->
953 editor.setText("1\n 2\n 3abc\n ")
954 editor.setCursorScreenPosition([0, 2])
955
956 describe "as a motion", ->
957 beforeEach -> keydown('G', shift: true)
958
959 it "moves the cursor to the last line after whitespace", ->
960 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
961
962 describe "as a repeated motion", ->
963 beforeEach ->
964 keydown('2')
965 keydown('G', shift: true)
966
967 it "moves the cursor to a specified line", ->
968 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
969
970 describe "as a selection", ->
971 beforeEach ->
972 editor.setCursorScreenPosition([1, 0])
973 vimState.activateVisualMode()
974 keydown('G', shift: true)
975
976 it "selects to the last line in the file", ->
977 expect(editor.getSelectedText()).toBe " 2\n 3abc\n "
978
979 it "moves the cursor to the last line after whitespace", ->
980 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
981
982 describe "the / keybinding", ->
983 pane = null
984
985 beforeEach ->
986 pane = {activate: jasmine.createSpy("activate")}
987 spyOn(atom.workspace, 'getActivePane').andReturn(pane)
988
989 editor.setText("abc\ndef\nabc\ndef\n")
990 editor.setCursorBufferPosition([0, 0])
991
992 # clear search history
993 vimState.globalVimState.searchHistory = []
994 vimState.globalVimState.currentSearch = {}
995
996 describe "as a motion", ->
997 it "beeps when repeating nonexistent last search", ->
998 keydown '/'
999 submitNormalModeInputText ''
1000 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1001 expect(atom.beep).toHaveBeenCalled()
1002
1003 it "moves the cursor to the specified search pattern", ->
1004 keydown('/')
1005
1006 submitNormalModeInputText 'def'
1007
1008 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1009 expect(pane.activate).toHaveBeenCalled()
1010 expect(atom.beep).not.toHaveBeenCalled()
1011
1012 it "loops back around", ->
1013 editor.setCursorBufferPosition([3, 0])
1014 keydown('/')
1015 submitNormalModeInputText 'def'
1016
1017 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1018 expect(atom.beep).not.toHaveBeenCalled()
1019
1020 it "uses a valid regex as a regex", ->
1021 keydown('/')
1022 # Cycle through the 'abc' on the first line with a character pattern
1023 submitNormalModeInputText '[abc]'
1024 expect(editor.getCursorBufferPosition()).toEqual [0, 1]
1025 keydown('n')
1026 expect(editor.getCursorBufferPosition()).toEqual [0, 2]
1027 expect(atom.beep).not.toHaveBeenCalled()
1028
1029 it "uses an invalid regex as a literal string", ->
1030 # Go straight to the literal [abc
1031 editor.setText("abc\n[abc]\n")
1032 keydown('/')
1033 submitNormalModeInputText '[abc'
1034 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1035 keydown('n')
1036 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1037 expect(atom.beep).not.toHaveBeenCalled()
1038
1039 it "uses ? as a literal string", ->
1040 editor.setText("abc\n[a?c?\n")
1041 keydown('/')
1042 submitNormalModeInputText '?'
1043 expect(editor.getCursorBufferPosition()).toEqual [1, 2]
1044 keydown('n')
1045 expect(editor.getCursorBufferPosition()).toEqual [1, 4]
1046 expect(atom.beep).not.toHaveBeenCalled()
1047
1048 it 'works with selection in visual mode', ->
1049 editor.setText('one two three')
1050 keydown('v')
1051 keydown('/')
1052 submitNormalModeInputText 'th'
1053 expect(editor.getCursorBufferPosition()).toEqual [0, 9]
1054 keydown('d')
1055 expect(editor.getText()).toBe 'hree'
1056 expect(atom.beep).not.toHaveBeenCalled()
1057
1058 it 'extends selection when repeating search in visual mode', ->
1059 editor.setText('line1\nline2\nline3')
1060 keydown('v')
1061 keydown('/')
1062 submitNormalModeInputText 'line'
1063 {start, end} = editor.getSelectedBufferRange()
1064 expect(start.row).toEqual 0
1065 expect(end.row).toEqual 1
1066 keydown('n')
1067 {start, end} = editor.getSelectedBufferRange()
1068 expect(start.row).toEqual 0
1069 expect(end.row).toEqual 2
1070 expect(atom.beep).not.toHaveBeenCalled()
1071
1072 describe "case sensitivity", ->
1073 beforeEach ->
1074 editor.setText("\nabc\nABC\n")
1075 editor.setCursorBufferPosition([0, 0])
1076 keydown('/')
1077
1078 it "works in case sensitive mode", ->
1079 submitNormalModeInputText 'ABC'
1080 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1081 keydown('n')
1082 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1083 expect(atom.beep).not.toHaveBeenCalled()
1084
1085 it "works in case insensitive mode", ->
1086 submitNormalModeInputText '\\cAbC'
1087 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1088 keydown('n')
1089 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1090 expect(atom.beep).not.toHaveBeenCalled()
1091
1092 it "works in case insensitive mode wherever \\c is", ->
1093 submitNormalModeInputText 'AbC\\c'
1094 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1095 keydown('n')
1096 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1097 expect(atom.beep).not.toHaveBeenCalled()
1098
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]
1103 keydown('n')
1104 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1105 expect(atom.beep).not.toHaveBeenCalled()
1106
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]
1111 keydown('n')
1112 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1113 expect(atom.beep).not.toHaveBeenCalled()
1114
1115 describe "repeating", ->
1116 it "does nothing with no search history", ->
1117 editor.setCursorBufferPosition([0, 0])
1118 keydown('n')
1119 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1120 expect(atom.beep).toHaveBeenCalled()
1121
1122 editor.setCursorBufferPosition([1, 1])
1123 keydown('n')
1124 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1125 expect(atom.beep.callCount).toBe 2
1126
1127 describe "repeating with search history", ->
1128 beforeEach ->
1129 keydown('/')
1130 submitNormalModeInputText 'def'
1131
1132 it "repeats previous search with /<enter>", ->
1133 keydown('/')
1134 submitNormalModeInputText('')
1135 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1136 expect(atom.beep).not.toHaveBeenCalled()
1137
1138 it "repeats previous search with //", ->
1139 keydown('/')
1140 submitNormalModeInputText('/')
1141 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1142 expect(atom.beep).not.toHaveBeenCalled()
1143
1144 describe "the n keybinding", ->
1145 it "repeats the last search", ->
1146 keydown('n')
1147 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1148 expect(atom.beep).not.toHaveBeenCalled()
1149
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()
1158
1159 describe "composing", ->
1160 it "composes with operators", ->
1161 keydown('d')
1162 keydown('/')
1163 submitNormalModeInputText('def')
1164 expect(editor.getText()).toEqual "def\nabc\ndef\n"
1165 expect(atom.beep).not.toHaveBeenCalled()
1166
1167 it "repeats correctly with operators", ->
1168 keydown('d')
1169 keydown('/')
1170 submitNormalModeInputText('def')
1171
1172 keydown('.')
1173 expect(editor.getText()).toEqual "def\n"
1174 expect(atom.beep).not.toHaveBeenCalled()
1175
1176 describe "when reversed as ?", ->
1177 it "moves the cursor backwards to the specified search pattern", ->
1178 keydown('?')
1179 submitNormalModeInputText('def')
1180 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1181 expect(atom.beep).not.toHaveBeenCalled()
1182
1183 it "accepts / as a literal search pattern", ->
1184 editor.setText("abc\nd/f\nabc\nd/f\n")
1185 editor.setCursorBufferPosition([0, 0])
1186 keydown('?')
1187 submitNormalModeInputText('/')
1188 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1189 keydown('?')
1190 submitNormalModeInputText('/')
1191 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1192 expect(atom.beep).not.toHaveBeenCalled()
1193
1194 describe "repeating", ->
1195 beforeEach ->
1196 keydown('?')
1197 submitNormalModeInputText('def')
1198
1199 it "repeats previous search as reversed with ?<enter>", ->
1200 keydown('?')
1201 submitNormalModeInputText('')
1202 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1203 expect(atom.beep).not.toHaveBeenCalled()
1204
1205 it "repeats previous search as reversed with ??", ->
1206 keydown('?')
1207 submitNormalModeInputText('?')
1208 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1209 expect(atom.beep).not.toHaveBeenCalled()
1210
1211 describe 'the n keybinding', ->
1212 it "repeats the last search backwards", ->
1213 editor.setCursorBufferPosition([0, 0])
1214 keydown('n')
1215 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1216 expect(atom.beep).not.toHaveBeenCalled()
1217
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()
1224
1225 describe "using search history", ->
1226 inputEditor = null
1227
1228 beforeEach ->
1229 keydown('/')
1230 submitNormalModeInputText('def')
1231 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1232
1233 keydown('/')
1234 submitNormalModeInputText('abc')
1235 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1236
1237 inputEditor = editor.normalModeInputView.editorElement
1238
1239 it "allows searching history in the search field", ->
1240 keydown('/')
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()
1248
1249 it "resets the search field to empty when scrolling back", ->
1250 keydown('/')
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()
1260
1261 describe "the * keybinding", ->
1262 beforeEach ->
1263 editor.setText("abd\n@def\nabd\ndef\n")
1264 editor.setCursorBufferPosition([0, 0])
1265
1266 describe "as a motion", ->
1267 it "moves cursor to next occurence of word under cursor", ->
1268 keydown("*")
1269 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1270
1271 it "repeats with the n key", ->
1272 keydown("*")
1273 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1274 keydown("n")
1275 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1276
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])
1280 keydown("*")
1281 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1282
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])
1287 keydown("*")
1288 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1289
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])
1293 keydown("*")
1294 # this is because of the default isKeyword value of vim-mode that includes @
1295 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1296
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.
1300 # e.g.
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])
1306 keydown("*")
1307 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1308
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])
1313 keydown("*")
1314 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1315
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])
1320 keydown("*")
1321 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1322
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])
1327 keydown("*")
1328 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1329
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])
1335 keydown("#")
1336 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1337
1338 it "repeats with n", ->
1339 editor.setText("abc\n@def\nabc\ndef\nabc\n")
1340 editor.setCursorBufferPosition([2, 1])
1341 keydown("#")
1342 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1343 keydown("n")
1344 expect(editor.getCursorBufferPosition()).toEqual [4, 0]
1345 keydown("n")
1346 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1347
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])
1351 keydown("#")
1352 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1353
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])
1358 keydown("#")
1359 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1360
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])
1364 keydown("#")
1365 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1366
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])
1371 keydown("*")
1372 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1373
1374 describe "the H keybinding", ->
1375 beforeEach ->
1376 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1377 editor.setCursorScreenPosition([8, 0])
1378 spyOn(editor.getLastCursor(), 'setScreenPosition')
1379
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])
1384
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])
1389
1390 it "respects counts", ->
1391 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(0)
1392 keydown('3')
1393 keydown('H', shift: true)
1394 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([2, 0])
1395
1396 describe "the L keybinding", ->
1397 beforeEach ->
1398 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1399 editor.setCursorScreenPosition([8, 0])
1400 spyOn(editor.getLastCursor(), 'setScreenPosition')
1401
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])
1406
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])
1411
1412 it "respects counts", ->
1413 spyOn(editor, 'getLastVisibleScreenRow').andReturn(10)
1414 keydown('3')
1415 keydown('L', shift: true)
1416 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([8, 0])
1417
1418 describe "the M keybinding", ->
1419 beforeEach ->
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)
1425
1426 it "moves the cursor to the first row if visible", ->
1427 keydown('M', shift: true)
1428 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([5, 0])
1429
1430 describe 'the mark keybindings', ->
1431 beforeEach ->
1432 editor.setText(' 12\n 34\n56\n')
1433 editor.setCursorBufferPosition([0, 1])
1434
1435 it 'moves to the beginning of the line of a mark', ->
1436 editor.setCursorBufferPosition([1, 1])
1437 keydown('m')
1438 normalModeInputKeydown('a')
1439 editor.setCursorBufferPosition([0, 0])
1440 keydown('\'')
1441 normalModeInputKeydown('a')
1442 expect(editor.getCursorBufferPosition()).toEqual [1, 4]
1443
1444 it 'moves literally to a mark', ->
1445 editor.setCursorBufferPosition([1, 1])
1446 keydown('m')
1447 normalModeInputKeydown('a')
1448 editor.setCursorBufferPosition([0, 0])
1449 keydown('`')
1450 normalModeInputKeydown('a')
1451 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1452
1453 it 'deletes to a mark by line', ->
1454 editor.setCursorBufferPosition([1, 5])
1455 keydown('m')
1456 normalModeInputKeydown('a')
1457 editor.setCursorBufferPosition([0, 0])
1458 keydown('d')
1459 keydown('\'')
1460 normalModeInputKeydown('a')
1461 expect(editor.getText()).toEqual '56\n'
1462
1463 it 'deletes before to a mark literally', ->
1464 editor.setCursorBufferPosition([1, 5])
1465 keydown('m')
1466 normalModeInputKeydown('a')
1467 editor.setCursorBufferPosition([0, 1])
1468 keydown('d')
1469 keydown('`')
1470 normalModeInputKeydown('a')
1471 expect(editor.getText()).toEqual ' 4\n56\n'
1472
1473 it 'deletes after to a mark literally', ->
1474 editor.setCursorBufferPosition([1, 5])
1475 keydown('m')
1476 normalModeInputKeydown('a')
1477 editor.setCursorBufferPosition([2, 1])
1478 keydown('d')
1479 keydown('`')
1480 normalModeInputKeydown('a')
1481 expect(editor.getText()).toEqual ' 12\n 36\n'
1482
1483 it 'moves back to previous', ->
1484 editor.setCursorBufferPosition([1, 5])
1485 keydown('`')
1486 normalModeInputKeydown('`')
1487 editor.setCursorBufferPosition([2, 1])
1488 keydown('`')
1489 normalModeInputKeydown('`')
1490 expect(editor.getCursorBufferPosition()).toEqual [1, 5]
1491
1492 describe 'the f/F keybindings', ->
1493 beforeEach ->
1494 editor.setText("abcabcabcabc\n")
1495 editor.setCursorScreenPosition([0, 0])
1496
1497 it 'moves to the first specified character it finds', ->
1498 keydown('f')
1499 normalModeInputKeydown('c')
1500 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1501
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]
1507
1508 it 'respects count forward', ->
1509 keydown('2')
1510 keydown('f')
1511 normalModeInputKeydown('a')
1512 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1513
1514 it 'respects count backward', ->
1515 editor.setCursorScreenPosition([0, 6])
1516 keydown('2')
1517 keydown('F', shift: true)
1518 normalModeInputKeydown('a')
1519 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1520
1521 it "doesn't move if the character specified isn't found", ->
1522 keydown('f')
1523 normalModeInputKeydown('d')
1524 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1525 expect(atom.beep).not.toHaveBeenCalled()
1526
1527 it "doesn't move if there aren't the specified count of the specified character", ->
1528 keydown('1')
1529 keydown('0')
1530 keydown('f')
1531 normalModeInputKeydown('a')
1532 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1533 # a bug was making this behaviour depend on the count
1534 keydown('1')
1535 keydown('1')
1536 keydown('f')
1537 normalModeInputKeydown('a')
1538 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1539 # and backwards now
1540 editor.setCursorScreenPosition([0, 6])
1541 keydown('1')
1542 keydown('0')
1543 keydown('F', shift: true)
1544 normalModeInputKeydown('a')
1545 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1546 keydown('1')
1547 keydown('1')
1548 keydown('F', shift: true)
1549 normalModeInputKeydown('a')
1550 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1551
1552 it "composes with d", ->
1553 editor.setCursorScreenPosition([0, 3])
1554 keydown('d')
1555 keydown('2')
1556 keydown('f')
1557 normalModeInputKeydown('a')
1558 expect(editor.getText()).toEqual 'abcbc\n'
1559
1560 it "cancels c when no match found", ->
1561 keydown('c')
1562 keydown('f')
1563 normalModeInputKeydown('d')
1564 expect(editor.getText()).toBe("abcabcabcabc\n")
1565 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1566 expect(vimState.mode).toBe "normal"
1567
1568 describe 'with accented characters', ->
1569 buildIMECompositionEvent = (event, {data, target}={}) ->
1570 event = new Event(event)
1571 event.data = data
1572 Object.defineProperty(event, 'target', get: -> target)
1573 event
1574
1575 buildTextInputEvent = ({data, target}) ->
1576 event = new Event('textInput')
1577 event.data = data
1578 Object.defineProperty(event, 'target', get: -> target)
1579 event
1580
1581 beforeEach ->
1582 editor.setText("abcébcabcébc\n")
1583 editor.setCursorScreenPosition([0, 0])
1584
1585 it 'works with IME composition', ->
1586 keydown('f')
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]
1597
1598 describe 'the t/T keybindings', ->
1599 beforeEach ->
1600 editor.setText("abcabcabcabc\n")
1601 editor.setCursorScreenPosition([0, 0])
1602
1603 it 'moves to the character previous to the first specified character it finds', ->
1604 keydown('t')
1605 normalModeInputKeydown('a')
1606 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1607 # or stays put when it's already there
1608 keydown('t')
1609 normalModeInputKeydown('a')
1610 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1611
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]
1617
1618 it 'respects count forward', ->
1619 keydown('2')
1620 keydown('t')
1621 normalModeInputKeydown('a')
1622 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1623
1624 it 'respects count backward', ->
1625 editor.setCursorScreenPosition([0, 6])
1626 keydown('2')
1627 keydown('T', shift: true)
1628 normalModeInputKeydown('a')
1629 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1630
1631 it "doesn't move if the character specified isn't found", ->
1632 keydown('t')
1633 normalModeInputKeydown('d')
1634 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1635 expect(atom.beep).not.toHaveBeenCalled()
1636
1637 it "doesn't move if there aren't the specified count of the specified character", ->
1638 keydown('1')
1639 keydown('0')
1640 keydown('t')
1641 normalModeInputKeydown('a')
1642 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1643 # a bug was making this behaviour depend on the count
1644 keydown('1')
1645 keydown('1')
1646 keydown('t')
1647 normalModeInputKeydown('a')
1648 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1649 # and backwards now
1650 editor.setCursorScreenPosition([0, 6])
1651 keydown('1')
1652 keydown('0')
1653 keydown('T', shift: true)
1654 normalModeInputKeydown('a')
1655 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1656 keydown('1')
1657 keydown('1')
1658 keydown('T', shift: true)
1659 normalModeInputKeydown('a')
1660 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1661
1662 it "composes with d", ->
1663 editor.setCursorScreenPosition([0, 3])
1664 keydown('d')
1665 keydown('2')
1666 keydown('t')
1667 normalModeInputKeydown('b')
1668 expect(editor.getText()).toBe 'abcbcabc\n'
1669
1670 it "selects character under cursor even when no movement happens", ->
1671 editor.setCursorBufferPosition([0, 0])
1672 keydown('d')
1673 keydown('t')
1674 normalModeInputKeydown('b')
1675 expect(editor.getText()).toBe 'bcabcabcabc\n'
1676
1677 describe 'the v keybinding', ->
1678 beforeEach ->
1679 editor.setText("01\n002\n0003\n00004\n000005\n")
1680 editor.setCursorScreenPosition([1, 1])
1681
1682 it "selects down a line", ->
1683 keydown('v')
1684 keydown('j')
1685 keydown('j')
1686 expect(editor.getSelectedText()).toBe "02\n0003\n00"
1687 expect(editor.getSelectedBufferRange().isSingleLine()).toBeFalsy()
1688
1689 it "selects right", ->
1690 keydown('v')
1691 keydown('l')
1692 expect(editor.getSelectedText()).toBe "02"
1693 expect(editor.getSelectedBufferRange().isSingleLine()).toBeTruthy()
1694
1695 describe 'the V keybinding', ->
1696 beforeEach ->
1697 editor.setText("01\n002\n0003\n00004\n000005\n")
1698 editor.setCursorScreenPosition([1, 1])
1699
1700 it "selects down a line", ->
1701 keydown('V', shift: true)
1702 expect(editor.getSelectedBufferRange().isSingleLine()).toBeFalsy()
1703 keydown('j')
1704 keydown('j')
1705 expect(editor.getSelectedText()).toBe "002\n0003\n00004\n"
1706 expect(editor.getSelectedBufferRange().isSingleLine()).toBeFalsy()
1707
1708 it "selects up a line", ->
1709 keydown('V', shift: true)
1710 keydown('k')
1711 expect(editor.getSelectedText()).toBe "01\n002\n"
1712
1713 describe 'the ; and , keybindings', ->
1714 beforeEach ->
1715 editor.setText("abcabcabcabc\n")
1716 editor.setCursorScreenPosition([0, 0])
1717
1718 it "repeat f in same direction", ->
1719 keydown('f')
1720 normalModeInputKeydown('c')
1721 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1722 keydown(';')
1723 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1724 keydown(';')
1725 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1726
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]
1732 keydown(';')
1733 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1734 keydown(';')
1735 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1736
1737 it "repeat f in opposite direction", ->
1738 editor.setCursorScreenPosition([0, 6])
1739 keydown('f')
1740 normalModeInputKeydown('c')
1741 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1742 keydown(',')
1743 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1744 keydown(',')
1745 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1746
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]
1752 keydown(',')
1753 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1754 keydown(',')
1755 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1756
1757 it "alternate repeat f in same direction and reverse", ->
1758 keydown('f')
1759 normalModeInputKeydown('c')
1760 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1761 keydown(';')
1762 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1763 keydown(',')
1764 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1765
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]
1771 keydown(';')
1772 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1773 keydown(',')
1774 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1775
1776 it "repeat t in same direction", ->
1777 keydown('t')
1778 normalModeInputKeydown('c')
1779 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1780 keydown(';')
1781 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1782
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]
1788 keydown(';')
1789 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1790
1791 it "repeat t in opposite direction first, and then reverse", ->
1792 editor.setCursorScreenPosition([0, 3])
1793 keydown('t')
1794 normalModeInputKeydown('c')
1795 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1796 keydown(',')
1797 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1798 keydown(';')
1799 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1800
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]
1806 keydown(',')
1807 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1808 keydown(';')
1809 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1810
1811 it "repeat with count in same direction", ->
1812 editor.setCursorScreenPosition([0, 0])
1813 keydown('f')
1814 normalModeInputKeydown('c')
1815 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1816 keydown('2')
1817 keydown(';')
1818 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1819
1820 it "repeat with count in reverse direction", ->
1821 editor.setCursorScreenPosition([0, 6])
1822 keydown('f')
1823 normalModeInputKeydown('c')
1824 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1825 keydown('2')
1826 keydown(',')
1827 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1828
1829 it "shares the most recent find/till command with other editors", ->
1830 helpers.getEditorElement (otherEditorElement) ->
1831 otherEditor = otherEditorElement.getModel()
1832
1833 editor.setText("a baz bar\n")
1834 editor.setCursorScreenPosition([0, 0])
1835
1836 otherEditor.setText("foo bar baz")
1837 otherEditor.setCursorScreenPosition([0, 0])
1838
1839 # by default keyDown and such go in the usual editor
1840 keydown('f')
1841 normalModeInputKeydown('b')
1842 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1843 expect(otherEditor.getCursorScreenPosition()).toEqual [0, 0]
1844
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]
1849
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]
1855
1856 # and replay in the normal editor
1857 keydown(';')
1858 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
1859 expect(otherEditor.getCursorScreenPosition()).toEqual [0, 5]
1860 expect(atom.beep).not.toHaveBeenCalled()
1861
1862 describe 'the % motion', ->
1863 beforeEach ->
1864 editor.setText("( ( ) )--{ text in here; and a function call(with parameters) }\n")
1865 editor.setCursorScreenPosition([0, 0])
1866
1867 it 'matches the correct parenthesis', ->
1868 keydown('%')
1869 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1870
1871 it 'matches the correct brace', ->
1872 editor.setCursorScreenPosition([0, 9])
1873 keydown('%')
1874 expect(editor.getCursorScreenPosition()).toEqual [0, 62]
1875
1876 it 'composes correctly with d', ->
1877 editor.setCursorScreenPosition([0, 9])
1878 keydown('d')
1879 keydown('%')
1880 expect(editor.getText()).toEqual "( ( ) )--\n"
1881
1882 it 'moves correctly when composed with v going forward', ->
1883 keydown('v')
1884 keydown('h')
1885 keydown('%')
1886 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
1887
1888 it 'moves correctly when composed with v going backward', ->
1889 editor.setCursorScreenPosition([0, 5])
1890 keydown('v')
1891 keydown('%')
1892 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1893
1894 it 'it moves appropriately to find the nearest matching action', ->
1895 editor.setCursorScreenPosition([0, 3])
1896 keydown('%')
1897 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1898 expect(editor.getText()).toEqual "( ( ) )--{ text in here; and a function call(with parameters) }\n"
1899
1900 it 'it moves appropriately to find the nearest matching action', ->
1901 editor.setCursorScreenPosition([0, 26])
1902 keydown('%')
1903 expect(editor.getCursorScreenPosition()).toEqual [0, 60]
1904 expect(editor.getText()).toEqual "( ( ) )--{ text in here; and a function call(with parameters) }\n"
1905
1906 it "finds matches across multiple lines", ->
1907 editor.setText("...(\n...)")
1908 editor.setCursorScreenPosition([0, 0])
1909 keydown("%")
1910 expect(editor.getCursorScreenPosition()).toEqual([1, 3])
1911
1912 it "does not affect search history", ->
1913 keydown('/')
1914 submitNormalModeInputText 'func'
1915 expect(editor.getCursorBufferPosition()).toEqual [0, 31]
1916 keydown('%')
1917 expect(editor.getCursorBufferPosition()).toEqual [0, 60]
1918 keydown('n')
1919 expect(editor.getCursorBufferPosition()).toEqual [0, 31]
1920
1921 describe "scrolling screen and keeping cursor in the same screen position", ->
1922 beforeEach ->
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])
1928
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]
1934
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")
1940
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")
1945
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]
1951
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")
1957
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")
1962
1963
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]
1969
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)
1975
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")
1980
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]
1986
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)
1992
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")