]> git.r.bdr.sh - rbdr/dotfiles/blob - atom/packages/vim-mode/spec/motions-spec.coffee
Adds atom
[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.activateCommandMode()
15 vimState.resetCommandMode()
16
17 keydown = (key, options={}) ->
18 options.element ?= editorElement
19 helpers.keydown(key, options)
20
21 commandModeInputKeydown = (key, opts = {}) ->
22 editor.commandModeInputView.editorElement.getModel().setText(key)
23
24 submitCommandModeInputText = (text) ->
25 commandEditor = editor.commandModeInputView.editorElement
26 commandEditor.getModel().setText(text)
27 atom.commands.dispatch(commandEditor, "core:confirm")
28
29 describe "simple motions", ->
30 beforeEach ->
31 editor.setText("12345\nabcd\nABCDE")
32 editor.setCursorScreenPosition([1, 1])
33
34 describe "the h keybinding", ->
35 describe "as a motion", ->
36 it "moves the cursor left, but not to the previous line", ->
37 keydown('h')
38 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
39
40 keydown('h')
41 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
42
43 it "moves the cursor to the previous line if wrapLeftRightMotion is true", ->
44 atom.config.set('vim-mode.wrapLeftRightMotion', true)
45 keydown('h')
46 keydown('h')
47 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
48
49 describe "as a selection", ->
50 it "selects the character to the left", ->
51 keydown('y')
52 keydown('h')
53
54 expect(vimState.getRegister('"').text).toBe 'a'
55 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
56
57 describe "the j keybinding", ->
58 it "moves the cursor down, but not to the end of the last line", ->
59 keydown('j')
60 expect(editor.getCursorScreenPosition()).toEqual [2, 1]
61
62 keydown('j')
63 expect(editor.getCursorScreenPosition()).toEqual [2, 1]
64
65 it "moves the cursor to the end of the line, not past it", ->
66 editor.setCursorScreenPosition([0, 4])
67
68 keydown('j')
69 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
70
71 it "remembers the position it column it was in after moving to shorter line", ->
72 editor.setCursorScreenPosition([0, 4])
73
74 keydown('j')
75 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
76
77 keydown('j')
78 expect(editor.getCursorScreenPosition()).toEqual [2, 4]
79
80 describe "when visual mode", ->
81 beforeEach ->
82 keydown('v')
83 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
84
85 it "moves the cursor down", ->
86 keydown('j')
87 expect(editor.getCursorScreenPosition()).toEqual [2, 2]
88
89 it "doesn't go over after the last line", ->
90 keydown('j')
91 expect(editor.getCursorScreenPosition()).toEqual [2, 2]
92
93 it "selects the text while moving", ->
94 keydown('j')
95 expect(editor.getSelectedText()).toBe "bcd\nAB"
96
97 describe "the k keybinding", ->
98 it "moves the cursor up, but not to the beginning of the first line", ->
99 keydown('k')
100 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
101
102 keydown('k')
103 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
104
105 describe "the l keybinding", ->
106 beforeEach -> editor.setCursorScreenPosition([1, 2])
107
108 it "moves the cursor right, but not to the next line", ->
109 keydown('l')
110 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
111
112 keydown('l')
113 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
114
115 it "moves the cursor to the next line if wrapLeftRightMotion is true", ->
116 atom.config.set('vim-mode.wrapLeftRightMotion', true)
117 keydown('l')
118 keydown('l')
119 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
120
121 describe "on a blank line", ->
122 it "doesn't move the cursor", ->
123 editor.setText("\n\n\n")
124 editor.setCursorBufferPosition([1, 0])
125 keydown('l')
126 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
127
128 describe "the w keybinding", ->
129 beforeEach -> editor.setText("ab cde1+- \n xyz\n\nzip")
130
131 describe "as a motion", ->
132 beforeEach -> editor.setCursorScreenPosition([0, 0])
133
134 it "moves the cursor to the beginning of the next word", ->
135 keydown('w')
136 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
137
138 keydown('w')
139 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
140
141 keydown('w')
142 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
143
144 keydown('w')
145 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
146
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).
150 #
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.
154 #
155 # See atom/vim-mode#3
156 keydown('w')
157 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
158
159 keydown('w')
160 expect(editor.getCursorScreenPosition()).toEqual [3, 3]
161
162 # After cursor gets to the EOF, it should stay there.
163 keydown('w')
164 expect(editor.getCursorScreenPosition()).toEqual [3, 3]
165
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])
169 keydown('w')
170 expect(editor.getCursorScreenPosition()).toEqual([0, 3])
171
172 describe "as a selection", ->
173 describe "within a word", ->
174 beforeEach ->
175 editor.setCursorScreenPosition([0, 0])
176 keydown('y')
177 keydown('w')
178
179 it "selects to the end of the word", ->
180 expect(vimState.getRegister('"').text).toBe 'ab '
181
182 describe "between words", ->
183 beforeEach ->
184 editor.setCursorScreenPosition([0, 2])
185 keydown('y')
186 keydown('w')
187
188 it "selects the whitespace", ->
189 expect(vimState.getRegister('"').text).toBe ' '
190
191 describe "the W keybinding", ->
192 beforeEach -> editor.setText("cde1+- ab \n xyz\n\nzip")
193
194 describe "as a motion", ->
195 beforeEach -> editor.setCursorScreenPosition([0, 0])
196
197 it "moves the cursor to the beginning of the next word", ->
198 keydown('W', shift: true)
199 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
200
201 keydown('W', shift: true)
202 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
203
204 keydown('W', shift: true)
205 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
206
207 keydown('W', shift: true)
208 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
209
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])
214 keydown('y')
215 keydown('W', shift: true)
216 expect(vimState.getRegister('"').text).toBe 'cde1+- '
217
218 it "continues past blank lines", ->
219 editor.setCursorScreenPosition([2, 0])
220
221 keydown('d')
222 keydown('W', shift: true)
223 expect(editor.getText()).toBe "cde1+- ab \n xyz\nzip"
224 expect(vimState.getRegister('"').text).toBe '\n'
225
226 it "doesn't go past the end of the file", ->
227 editor.setCursorScreenPosition([3, 0])
228
229 keydown('d')
230 keydown('W', shift: true)
231 expect(editor.getText()).toBe "cde1+- ab \n xyz\n\n"
232 expect(vimState.getRegister('"').text).toBe 'zip'
233
234 describe "the e keybinding", ->
235 beforeEach -> editor.setText("ab cde1+- \n xyz\n\nzip")
236
237 describe "as a motion", ->
238 beforeEach -> editor.setCursorScreenPosition([0, 0])
239
240 it "moves the cursor to the end of the current word", ->
241 keydown('e')
242 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
243
244 keydown('e')
245 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
246
247 keydown('e')
248 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
249
250 keydown('e')
251 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
252
253 keydown('e')
254 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
255
256 describe "as selection", ->
257 describe "within a word", ->
258 beforeEach ->
259 editor.setCursorScreenPosition([0, 0])
260 keydown('y')
261 keydown('e')
262
263 it "selects to the end of the current word", ->
264 expect(vimState.getRegister('"').text).toBe 'ab'
265
266 describe "between words", ->
267 beforeEach ->
268 editor.setCursorScreenPosition([0, 2])
269 keydown('y')
270 keydown('e')
271
272 it "selects to the end of the next word", ->
273 expect(vimState.getRegister('"').text).toBe ' cde1'
274
275 describe "the E keybinding", ->
276 beforeEach -> editor.setText("ab cde1+- \n xyz \n\nzip\n")
277
278 describe "as a motion", ->
279 beforeEach -> editor.setCursorScreenPosition([0, 0])
280
281 it "moves the cursor to the end of the current word", ->
282 keydown('E', shift: true)
283 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
284
285 keydown('E', shift: true)
286 expect(editor.getCursorScreenPosition()).toEqual [0, 9]
287
288 keydown('E', shift: true)
289 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
290
291 keydown('E', shift: true)
292 expect(editor.getCursorScreenPosition()).toEqual [3, 2]
293
294 keydown('E', shift: true)
295 expect(editor.getCursorScreenPosition()).toEqual [4, 0]
296
297 describe "as selection", ->
298 describe "within a word", ->
299 beforeEach ->
300 editor.setCursorScreenPosition([0, 0])
301 keydown('y')
302 keydown('E', shift: true)
303
304 it "selects to the end of the current word", ->
305 expect(vimState.getRegister('"').text).toBe 'ab'
306
307 describe "between words", ->
308 beforeEach ->
309 editor.setCursorScreenPosition([0, 2])
310 keydown('y')
311 keydown('E', shift: true)
312
313 it "selects to the end of the next word", ->
314 expect(vimState.getRegister('"').text).toBe ' cde1+-'
315
316 describe "press more than once", ->
317 beforeEach ->
318 editor.setCursorScreenPosition([0, 0])
319 keydown('v')
320 keydown('E', shift: true)
321 keydown('E', shift: true)
322 keydown('y')
323
324 it "selects to the end of the current word", ->
325 expect(vimState.getRegister('"').text).toBe 'ab cde1+-'
326
327 describe "the } keybinding", ->
328 beforeEach ->
329 editor.setText("abcde\n\nfghij\nhijk\n xyz \n\nzip\n\n \nthe end")
330 editor.setCursorScreenPosition([0, 0])
331
332 describe "as a motion", ->
333 it "moves the cursor to the end of the paragraph", ->
334 keydown('}')
335 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
336
337 keydown('}')
338 expect(editor.getCursorScreenPosition()).toEqual [5, 0]
339
340 keydown('}')
341 expect(editor.getCursorScreenPosition()).toEqual [7, 0]
342
343 keydown('}')
344 expect(editor.getCursorScreenPosition()).toEqual [9, 6]
345
346 describe "as a selection", ->
347 beforeEach ->
348 keydown('y')
349 keydown('}')
350
351 it 'selects to the end of the current paragraph', ->
352 expect(vimState.getRegister('"').text).toBe "abcde\n"
353
354 describe "the { keybinding", ->
355 beforeEach ->
356 editor.setText("abcde\n\nfghij\nhijk\n xyz \n\nzip\n\n \nthe end")
357 editor.setCursorScreenPosition([9, 0])
358
359 describe "as a motion", ->
360 it "moves the cursor to the beginning of the paragraph", ->
361 keydown('{')
362 expect(editor.getCursorScreenPosition()).toEqual [7, 0]
363
364 keydown('{')
365 expect(editor.getCursorScreenPosition()).toEqual [5, 0]
366
367 keydown('{')
368 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
369
370 keydown('{')
371 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
372
373 describe "as a selection", ->
374 beforeEach ->
375 editor.setCursorScreenPosition([7, 0])
376 keydown('y')
377 keydown('{')
378
379 it 'selects to the beginning of the current paragraph', ->
380 expect(vimState.getRegister('"').text).toBe "\nzip\n"
381
382 describe "the b keybinding", ->
383 beforeEach -> editor.setText(" ab cde1+- \n xyz\n\nzip }\n last")
384
385 describe "as a motion", ->
386 beforeEach -> editor.setCursorScreenPosition([4, 1])
387
388 it "moves the cursor to the beginning of the previous word", ->
389 keydown('b')
390 expect(editor.getCursorScreenPosition()).toEqual [3, 4]
391
392 keydown('b')
393 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
394
395 keydown('b')
396 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
397
398 keydown('b')
399 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
400
401 keydown('b')
402 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
403
404 keydown('b')
405 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
406
407 keydown('b')
408 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
409
410 # Go to start of the file, after moving past the first word
411 keydown('b')
412 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
413
414 # Stay at the start of the file
415 keydown('b')
416 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
417
418 describe "as a selection", ->
419 describe "within a word", ->
420 beforeEach ->
421 editor.setCursorScreenPosition([0, 2])
422 keydown('y')
423 keydown('b')
424
425 it "selects to the beginning of the current word", ->
426 expect(vimState.getRegister('"').text).toBe 'a'
427 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
428
429 describe "between words", ->
430 beforeEach ->
431 editor.setCursorScreenPosition([0, 4])
432 keydown('y')
433 keydown('b')
434
435 it "selects to the beginning of the last word", ->
436 expect(vimState.getRegister('"').text).toBe 'ab '
437 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
438
439 describe "the B keybinding", ->
440 beforeEach -> editor.setText("cde1+- ab \n\t xyz-123\n\n zip")
441
442 describe "as a motion", ->
443 beforeEach -> editor.setCursorScreenPosition([4, 1])
444
445 it "moves the cursor to the beginning of the previous word", ->
446 keydown('B', shift: true)
447 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
448
449 keydown('B', shift: true)
450 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
451
452 keydown('B', shift: true)
453 expect(editor.getCursorScreenPosition()).toEqual [1, 3]
454
455 keydown('B', shift: true)
456 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
457
458 keydown('B', shift: true)
459 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
460
461 describe "as a selection", ->
462 it "selects to the beginning of the whole word", ->
463 editor.setCursorScreenPosition([1, 10])
464 keydown('y')
465 keydown('B', shift: true)
466 expect(vimState.getRegister('"').text).toBe 'xyz-123'
467
468 it "doesn't go past the beginning of the file", ->
469 editor.setCursorScreenPosition([0, 0])
470 vimState.setRegister('"', text: 'abc')
471 keydown('y')
472 keydown('B', shift: true)
473 expect(vimState.getRegister('"').text).toBe 'abc'
474
475 describe "the ^ keybinding", ->
476 beforeEach ->
477 editor.setText(" abcde")
478
479 describe "from the beginning of the line", ->
480 beforeEach -> editor.setCursorScreenPosition([0, 0])
481
482 describe "as a motion", ->
483 beforeEach -> keydown('^')
484
485 it "moves the cursor to the first character of the line", ->
486 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
487
488 describe "as a selection", ->
489 beforeEach ->
490 keydown('d')
491 keydown('^')
492
493 it 'selects to the first character of the line', ->
494 expect(editor.getText()).toBe 'abcde'
495 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
496
497 describe "from the first character of the line", ->
498 beforeEach -> editor.setCursorScreenPosition([0, 2])
499
500 describe "as a motion", ->
501 beforeEach -> keydown('^')
502
503 it "stays put", ->
504 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
505
506 describe "as a selection", ->
507 beforeEach ->
508 keydown('d')
509 keydown('^')
510
511 it "does nothing", ->
512 expect(editor.getText()).toBe ' abcde'
513 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
514
515 describe "from the middle of a word", ->
516 beforeEach -> editor.setCursorScreenPosition([0, 4])
517
518 describe "as a motion", ->
519 beforeEach -> keydown('^')
520
521 it "moves the cursor to the first character of the line", ->
522 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
523
524 describe "as a selection", ->
525 beforeEach ->
526 keydown('d')
527 keydown('^')
528
529 it 'selects to the first character of the line', ->
530 expect(editor.getText()).toBe ' cde'
531 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
532
533 describe "the 0 keybinding", ->
534 beforeEach ->
535 editor.setText(" abcde")
536 editor.setCursorScreenPosition([0, 4])
537
538 describe "as a motion", ->
539 beforeEach -> keydown('0')
540
541 it "moves the cursor to the first column", ->
542 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
543
544 describe "as a selection", ->
545 beforeEach ->
546 keydown('d')
547 keydown('0')
548
549 it 'selects to the first column of the line', ->
550 expect(editor.getText()).toBe 'cde'
551 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
552
553 describe "the $ keybinding", ->
554 beforeEach ->
555 editor.setText(" abcde\n\n1234567890")
556 editor.setCursorScreenPosition([0, 4])
557
558 describe "as a motion from empty line", ->
559 beforeEach -> editor.setCursorScreenPosition([1, 0])
560
561 it "moves the cursor to the end of the line", ->
562 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
563
564 describe "as a motion", ->
565 beforeEach -> keydown('$')
566
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]
570
571 it "should remain in the last column when moving down", ->
572 keydown('j')
573 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
574
575 keydown('j')
576 expect(editor.getCursorScreenPosition()).toEqual [2, 9]
577
578 describe "as a selection", ->
579 beforeEach ->
580 keydown('d')
581 keydown('$')
582
583 it "selects to the beginning of the lines", ->
584 expect(editor.getText()).toBe " ab\n\n1234567890"
585 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
586
587 describe "the 0 keybinding", ->
588 beforeEach ->
589 editor.setText(" a\n")
590 editor.setCursorScreenPosition([0, 2])
591
592 describe "as a motion", ->
593 beforeEach -> keydown('0')
594
595 it "moves the cursor to the beginning of the line", ->
596 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
597
598 describe "the - keybinding", ->
599 beforeEach ->
600 editor.setText("abcdefg\n abc\n abc\n")
601
602 describe "from the middle of a line", ->
603 beforeEach -> editor.setCursorScreenPosition([1, 3])
604
605 describe "as a motion", ->
606 beforeEach -> keydown('-')
607
608 it "moves the cursor to the first character of the previous line", ->
609 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
610
611 describe "as a selection", ->
612 beforeEach ->
613 keydown('d')
614 keydown('-')
615
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]
620
621 describe "from the first character of a line indented the same as the previous one", ->
622 beforeEach -> editor.setCursorScreenPosition([2, 2])
623
624 describe "as a motion", ->
625 beforeEach -> keydown('-')
626
627 it "moves to the first character of the previous line (directly above)", ->
628 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
629
630 describe "as a selection", ->
631 beforeEach ->
632 keydown('d')
633 keydown('-')
634
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]
639
640 describe "from the beginning of a line preceded by an indented line", ->
641 beforeEach -> editor.setCursorScreenPosition([2, 0])
642
643 describe "as a motion", ->
644 beforeEach -> keydown('-')
645
646 it "moves the cursor to the first character of the previous line", ->
647 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
648
649 describe "as a selection", ->
650 beforeEach ->
651 keydown('d')
652 keydown('-')
653
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]
658
659 describe "with a count", ->
660 beforeEach ->
661 editor.setText("1\n2\n3\n4\n5\n6\n")
662 editor.setCursorScreenPosition([4, 0])
663
664 describe "as a motion", ->
665 beforeEach ->
666 keydown('3')
667 keydown('-')
668
669 it "moves the cursor to the first character of that many lines previous", ->
670 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
671
672 describe "as a selection", ->
673 beforeEach ->
674 keydown('d')
675 keydown('3')
676 keydown('-')
677
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]
681
682 describe "the + keybinding", ->
683 beforeEach ->
684 editor.setText(" abc\n abc\nabcdefg\n")
685
686 describe "from the middle of a line", ->
687 beforeEach -> editor.setCursorScreenPosition([1, 3])
688
689 describe "as a motion", ->
690 beforeEach -> keydown('+')
691
692 it "moves the cursor to the first character of the next line", ->
693 expect(editor.getCursorScreenPosition()).toEqual [2, 0]
694
695 describe "as a selection", ->
696 beforeEach ->
697 keydown('d')
698 keydown('+')
699
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]
704
705 describe "from the first character of a line indented the same as the next one", ->
706 beforeEach -> editor.setCursorScreenPosition([0, 2])
707
708 describe "as a motion", ->
709 beforeEach -> keydown('+')
710
711 it "moves to the first character of the next line (directly below)", ->
712 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
713
714 describe "as a selection", ->
715 beforeEach ->
716 keydown('d')
717 keydown('+')
718
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]
723
724 describe "from the beginning of a line followed by an indented line", ->
725 beforeEach -> editor.setCursorScreenPosition([0, 0])
726
727 describe "as a motion", ->
728 beforeEach -> keydown('+')
729
730 it "moves the cursor to the first character of the next line", ->
731 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
732
733 describe "as a selection", ->
734 beforeEach ->
735 keydown('d')
736 keydown('+')
737
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]
741
742 describe "with a count", ->
743 beforeEach ->
744 editor.setText("1\n2\n3\n4\n5\n6\n")
745 editor.setCursorScreenPosition([1, 0])
746
747 describe "as a motion", ->
748 beforeEach ->
749 keydown('3')
750 keydown('+')
751
752 it "moves the cursor to the first character of that many lines following", ->
753 expect(editor.getCursorScreenPosition()).toEqual [4, 0]
754
755 describe "as a selection", ->
756 beforeEach ->
757 keydown('d')
758 keydown('3')
759 keydown('+')
760
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]
764
765 describe "the _ keybinding", ->
766 beforeEach ->
767 editor.setText(" abc\n abc\nabcdefg\n")
768
769 describe "from the middle of a line", ->
770 beforeEach -> editor.setCursorScreenPosition([1, 3])
771
772 describe "as a motion", ->
773 beforeEach -> keydown('_')
774
775 it "moves the cursor to the first character of the current line", ->
776 expect(editor.getCursorScreenPosition()).toEqual [1, 2]
777
778 describe "as a selection", ->
779 beforeEach ->
780 keydown('d')
781 keydown('_')
782
783 it "deletes the current line", ->
784 expect(editor.getText()).toBe " abc\nabcdefg\n"
785 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
786
787 describe "with a count", ->
788 beforeEach ->
789 editor.setText("1\n2\n3\n4\n5\n6\n")
790 editor.setCursorScreenPosition([1, 0])
791
792 describe "as a motion", ->
793 beforeEach ->
794 keydown('3')
795 keydown('_')
796
797 it "moves the cursor to the first character of that many lines following", ->
798 expect(editor.getCursorScreenPosition()).toEqual [3, 0]
799
800 describe "as a selection", ->
801 beforeEach ->
802 keydown('d')
803 keydown('3')
804 keydown('_')
805
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]
809
810 describe "the enter keybinding", ->
811 keydownCodeForEnter = '\r' # 'enter' does not work
812 startingText = " abc\n abc\nabcdefg\n"
813
814 describe "from the middle of a line", ->
815 startingCursorPosition = [1, 3]
816
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)
822 keydown('+')
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
829
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)
835 keydown('d')
836 keydown('+')
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)
842 keydown('d')
843 keydown(keydownCodeForEnter)
844 expect(editor.getText()).toEqual referenceText
845 expect(editor.getCursorScreenPosition()).toEqual referenceCursorPosition
846
847 describe "the gg keybinding", ->
848 beforeEach ->
849 editor.setText(" 1abc\n 2\n3\n")
850 editor.setCursorScreenPosition([0, 2])
851
852 describe "as a motion", ->
853 describe "in command mode", ->
854 beforeEach ->
855 keydown('g')
856 keydown('g')
857
858 it "moves the cursor to the beginning of the first line", ->
859 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
860
861 describe "in linewise visual mode", ->
862 beforeEach ->
863 editor.setCursorScreenPosition([1, 0])
864 vimState.activateVisualMode('linewise')
865 keydown('g')
866 keydown('g')
867
868 it "selects to the first line in the file", ->
869 expect(editor.getSelectedText()).toBe " 1abc\n 2\n"
870
871 it "moves the cursor to a specified line", ->
872 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
873
874 describe "in characterwise visual mode", ->
875 beforeEach ->
876 editor.setCursorScreenPosition([1, 1])
877 vimState.activateVisualMode()
878 keydown('g')
879 keydown('g')
880
881 it "selects to the first line in the file", ->
882 expect(editor.getSelectedText()).toBe "1abc\n 2"
883
884 it "moves the cursor to a specified line", ->
885 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
886
887 describe "as a repeated motion", ->
888 describe "in command mode", ->
889 beforeEach ->
890 keydown('2')
891 keydown('g')
892 keydown('g')
893
894 it "moves the cursor to a specified line", ->
895 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
896
897 describe "in linewise visual motion", ->
898 beforeEach ->
899 editor.setCursorScreenPosition([2, 0])
900 vimState.activateVisualMode('linewise')
901 keydown('2')
902 keydown('g')
903 keydown('g')
904
905 it "selects to a specified line", ->
906 expect(editor.getSelectedText()).toBe " 2\n3\n"
907
908 it "moves the cursor to a specified line", ->
909 expect(editor.getCursorScreenPosition()).toEqual [1, 0]
910
911 describe "in characterwise visual motion", ->
912 beforeEach ->
913 editor.setCursorScreenPosition([2, 0])
914 vimState.activateVisualMode()
915 keydown('2')
916 keydown('g')
917 keydown('g')
918
919 it "selects to a first character of specified line", ->
920 expect(editor.getSelectedText()).toBe "2\n3"
921
922 it "moves the cursor to a specified line", ->
923 expect(editor.getCursorScreenPosition()).toEqual [1, 1]
924
925 describe "the g_ keybinding", ->
926 beforeEach ->
927 editor.setText("1 \n 2 \n 3abc\n ")
928
929 describe "as a motion", ->
930 it "moves the cursor to the last nonblank character", ->
931 editor.setCursorScreenPosition([1, 0])
932 keydown('g')
933 keydown('_')
934 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
935
936 it "will move the cursor to the beginning of the line if necessary", ->
937 editor.setCursorScreenPosition([0, 2])
938 keydown('g')
939 keydown('_')
940 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
941
942 describe "as a repeated motion", ->
943 it "moves the cursor downward and outward", ->
944 editor.setCursorScreenPosition([0, 0])
945 keydown('2')
946 keydown('g')
947 keydown('_')
948 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
949
950 describe "as a selection", ->
951 it "selects the current line excluding whitespace", ->
952 editor.setCursorScreenPosition([1, 2])
953 vimState.activateVisualMode()
954 keydown('2')
955 keydown('g')
956 keydown('_')
957 expect(editor.getSelectedText()).toEqual " 2 \n 3abc"
958
959 describe "the G keybinding", ->
960 beforeEach ->
961 editor.setText("1\n 2\n 3abc\n ")
962 editor.setCursorScreenPosition([0, 2])
963
964 describe "as a motion", ->
965 beforeEach -> keydown('G', shift: true)
966
967 it "moves the cursor to the last line after whitespace", ->
968 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
969
970 describe "as a repeated motion", ->
971 beforeEach ->
972 keydown('2')
973 keydown('G', shift: true)
974
975 it "moves the cursor to a specified line", ->
976 expect(editor.getCursorScreenPosition()).toEqual [1, 4]
977
978 describe "as a selection", ->
979 beforeEach ->
980 editor.setCursorScreenPosition([1, 0])
981 vimState.activateVisualMode()
982 keydown('G', shift: true)
983
984 it "selects to the last line in the file", ->
985 expect(editor.getSelectedText()).toBe " 2\n 3abc\n "
986
987 it "moves the cursor to the last line after whitespace", ->
988 expect(editor.getCursorScreenPosition()).toEqual [3, 1]
989
990 describe "the / keybinding", ->
991 pane = null
992
993 beforeEach ->
994 pane = {activate: jasmine.createSpy("activate")}
995 spyOn(atom.workspace, 'getActivePane').andReturn(pane)
996
997 editor.setText("abc\ndef\nabc\ndef\n")
998 editor.setCursorBufferPosition([0, 0])
999
1000 describe "as a motion", ->
1001 it "moves the cursor to the specified search pattern", ->
1002 keydown('/')
1003
1004 submitCommandModeInputText 'def'
1005
1006 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1007 expect(pane.activate).toHaveBeenCalled()
1008
1009 it "loops back around", ->
1010 editor.setCursorBufferPosition([3, 0])
1011 keydown('/')
1012 submitCommandModeInputText 'def'
1013
1014 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1015
1016 it "uses a valid regex as a regex", ->
1017 keydown('/')
1018 # Cycle through the 'abc' on the first line with a character pattern
1019 submitCommandModeInputText '[abc]'
1020 expect(editor.getCursorBufferPosition()).toEqual [0, 1]
1021 keydown('n')
1022 expect(editor.getCursorBufferPosition()).toEqual [0, 2]
1023
1024 it "uses an invalid regex as a literal string", ->
1025 # Go straight to the literal [abc
1026 editor.setText("abc\n[abc]\n")
1027 keydown('/')
1028 submitCommandModeInputText '[abc'
1029 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1030 keydown('n')
1031 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1032
1033 it "uses ? as a literal string", ->
1034 editor.setText("abc\n[a?c?\n")
1035 keydown('/')
1036 submitCommandModeInputText '?'
1037 expect(editor.getCursorBufferPosition()).toEqual [1, 2]
1038 keydown('n')
1039 expect(editor.getCursorBufferPosition()).toEqual [1, 4]
1040
1041 it 'works with selection in visual mode', ->
1042 editor.setText('one two three')
1043 keydown('v')
1044 keydown('/')
1045 submitCommandModeInputText 'th'
1046 expect(editor.getCursorBufferPosition()).toEqual [0, 9]
1047 keydown('d')
1048 expect(editor.getText()).toBe 'hree'
1049
1050 it 'extends selection when repeating search in visual mode', ->
1051 editor.setText('line1\nline2\nline3')
1052 keydown('v')
1053 keydown('/')
1054 submitCommandModeInputText 'line'
1055 {start, end} = editor.getSelectedBufferRange()
1056 expect(start.row).toEqual 0
1057 expect(end.row).toEqual 1
1058 keydown('n')
1059 {start, end} = editor.getSelectedBufferRange()
1060 expect(start.row).toEqual 0
1061 expect(end.row).toEqual 2
1062
1063 describe "case sensitivity", ->
1064 beforeEach ->
1065 editor.setText("\nabc\nABC\n")
1066 editor.setCursorBufferPosition([0, 0])
1067 keydown('/')
1068
1069 it "works in case sensitive mode", ->
1070 submitCommandModeInputText 'ABC'
1071 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1072 keydown('n')
1073 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1074
1075 it "works in case insensitive mode", ->
1076 submitCommandModeInputText '\\cAbC'
1077 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1078 keydown('n')
1079 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1080
1081 it "works in case insensitive mode wherever \\c is", ->
1082 submitCommandModeInputText 'AbC\\c'
1083 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1084 keydown('n')
1085 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1086
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]
1091 keydown('n')
1092 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1093
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]
1098 keydown('n')
1099 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1100
1101 describe "repeating", ->
1102 it "does nothing with no search history", ->
1103 # This tests that no exception is raised
1104 keydown('n')
1105
1106 beforeEach ->
1107 keydown('/')
1108 submitCommandModeInputText 'def'
1109
1110 it "repeats previous search with /<enter>", ->
1111 keydown('/')
1112 submitCommandModeInputText('')
1113 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1114
1115 it "repeats previous search with //", ->
1116 keydown('/')
1117 submitCommandModeInputText('/')
1118 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1119
1120 describe "the n keybinding", ->
1121 it "repeats the last search", ->
1122 keydown('n')
1123 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1124
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]
1132
1133 describe "composing", ->
1134 it "composes with operators", ->
1135 keydown('d')
1136 keydown('/')
1137 submitCommandModeInputText('def')
1138 expect(editor.getText()).toEqual "def\nabc\ndef\n"
1139
1140 it "repeats correctly with operators", ->
1141 keydown('d')
1142 keydown('/')
1143 submitCommandModeInputText('def')
1144
1145 keydown('.')
1146 expect(editor.getText()).toEqual "def\n"
1147
1148 describe "when reversed as ?", ->
1149 it "moves the cursor backwards to the specified search pattern", ->
1150 keydown('?')
1151 submitCommandModeInputText('def')
1152 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1153
1154 it "accepts / as a literal search pattern", ->
1155 editor.setText("abc\nd/f\nabc\nd/f\n")
1156 editor.setCursorBufferPosition([0, 0])
1157 keydown('?')
1158 submitCommandModeInputText('/')
1159 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1160 keydown('?')
1161 submitCommandModeInputText('/')
1162 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1163
1164 describe "repeating", ->
1165 beforeEach ->
1166 keydown('?')
1167 submitCommandModeInputText('def')
1168
1169 it "repeats previous search as reversed with ?<enter>", ->
1170 keydown('?')
1171 submitCommandModeInputText('')
1172 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1173
1174 it "repeats previous search as reversed with ??", ->
1175 keydown('?')
1176 submitCommandModeInputText('?')
1177 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1178
1179 describe 'the n keybinding', ->
1180 it "repeats the last search backwards", ->
1181 editor.setCursorBufferPosition([0, 0])
1182 keydown('n')
1183 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1184
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]
1190
1191 describe "using search history", ->
1192 commandEditor = null
1193
1194 beforeEach ->
1195 keydown('/')
1196 submitCommandModeInputText('def')
1197 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1198
1199 keydown('/')
1200 submitCommandModeInputText('abc')
1201 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1202
1203 commandEditor = editor.commandModeInputView.editorElement
1204
1205 it "allows searching history in the search field", ->
1206 keydown('/')
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')
1213
1214 it "resets the search field to empty when scrolling back", ->
1215 keydown('/')
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 ''
1224
1225 describe "the * keybinding", ->
1226 beforeEach ->
1227 editor.setText("abd\n@def\nabd\ndef\n")
1228 editor.setCursorBufferPosition([0, 0])
1229
1230 describe "as a motion", ->
1231 it "moves cursor to next occurence of word under cursor", ->
1232 keydown("*")
1233 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1234
1235 it "repeats with the n key", ->
1236 keydown("*")
1237 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1238 keydown("n")
1239 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1240
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])
1244 keydown("*")
1245 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1246
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])
1251 keydown("*")
1252 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1253
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])
1263 keydown("*")
1264 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1265
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.
1269 # e.g.
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])
1275 keydown("*")
1276 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1277
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])
1282 keydown("*")
1283 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1284
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])
1289 keydown("*")
1290 expect(editor.getCursorBufferPosition()).toEqual [3, 1]
1291
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])
1296 keydown("*")
1297 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1298
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])
1304 keydown("#")
1305 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1306
1307 it "repeats with n", ->
1308 editor.setText("abc\n@def\nabc\ndef\nabc\n")
1309 editor.setCursorBufferPosition([2, 1])
1310 keydown("#")
1311 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1312 keydown("n")
1313 expect(editor.getCursorBufferPosition()).toEqual [4, 0]
1314 keydown("n")
1315 expect(editor.getCursorBufferPosition()).toEqual [2, 0]
1316
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])
1320 keydown("#")
1321 expect(editor.getCursorBufferPosition()).toEqual [0, 0]
1322
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])
1327 keydown("#")
1328 expect(editor.getCursorBufferPosition()).toEqual [1, 0]
1329
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])
1333 keydown("#")
1334 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1335
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])
1340 keydown("*")
1341 expect(editor.getCursorBufferPosition()).toEqual [3, 0]
1342
1343 describe "the H keybinding", ->
1344 beforeEach ->
1345 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1346 editor.setCursorScreenPosition([8, 0])
1347 spyOn(editor.getLastCursor(), 'setScreenPosition')
1348
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])
1353
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])
1358
1359 it "respects counts", ->
1360 spyOn(editor, 'getFirstVisibleScreenRow').andReturn(0)
1361 keydown('3')
1362 keydown('H', shift: true)
1363 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([2, 0])
1364
1365 describe "the L keybinding", ->
1366 beforeEach ->
1367 editor.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
1368 editor.setCursorScreenPosition([8, 0])
1369 spyOn(editor.getLastCursor(), 'setScreenPosition')
1370
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])
1375
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])
1380
1381 it "respects counts", ->
1382 spyOn(editor, 'getLastVisibleScreenRow').andReturn(10)
1383 keydown('3')
1384 keydown('L', shift: true)
1385 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([8, 0])
1386
1387 describe "the M keybinding", ->
1388 beforeEach ->
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)
1394
1395 it "moves the cursor to the first row if visible", ->
1396 keydown('M', shift: true)
1397 expect(editor.getLastCursor().setScreenPosition).toHaveBeenCalledWith([5, 0])
1398
1399 describe 'the mark keybindings', ->
1400 beforeEach ->
1401 editor.setText(' 12\n 34\n56\n')
1402 editor.setCursorBufferPosition([0, 1])
1403
1404 it 'moves to the beginning of the line of a mark', ->
1405 editor.setCursorBufferPosition([1, 1])
1406 keydown('m')
1407 commandModeInputKeydown('a')
1408 editor.setCursorBufferPosition([0, 0])
1409 keydown('\'')
1410 commandModeInputKeydown('a')
1411 expect(editor.getCursorBufferPosition()).toEqual [1, 4]
1412
1413 it 'moves literally to a mark', ->
1414 editor.setCursorBufferPosition([1, 1])
1415 keydown('m')
1416 commandModeInputKeydown('a')
1417 editor.setCursorBufferPosition([0, 0])
1418 keydown('`')
1419 commandModeInputKeydown('a')
1420 expect(editor.getCursorBufferPosition()).toEqual [1, 1]
1421
1422 it 'deletes to a mark by line', ->
1423 editor.setCursorBufferPosition([1, 5])
1424 keydown('m')
1425 commandModeInputKeydown('a')
1426 editor.setCursorBufferPosition([0, 0])
1427 keydown('d')
1428 keydown('\'')
1429 commandModeInputKeydown('a')
1430 expect(editor.getText()).toEqual '56\n'
1431
1432 it 'deletes before to a mark literally', ->
1433 editor.setCursorBufferPosition([1, 5])
1434 keydown('m')
1435 commandModeInputKeydown('a')
1436 editor.setCursorBufferPosition([0, 1])
1437 keydown('d')
1438 keydown('`')
1439 commandModeInputKeydown('a')
1440 expect(editor.getText()).toEqual ' 4\n56\n'
1441
1442 it 'deletes after to a mark literally', ->
1443 editor.setCursorBufferPosition([1, 5])
1444 keydown('m')
1445 commandModeInputKeydown('a')
1446 editor.setCursorBufferPosition([2, 1])
1447 keydown('d')
1448 keydown('`')
1449 commandModeInputKeydown('a')
1450 expect(editor.getText()).toEqual ' 12\n 36\n'
1451
1452 it 'moves back to previous', ->
1453 editor.setCursorBufferPosition([1, 5])
1454 keydown('`')
1455 commandModeInputKeydown('`')
1456 editor.setCursorBufferPosition([2, 1])
1457 keydown('`')
1458 commandModeInputKeydown('`')
1459 expect(editor.getCursorBufferPosition()).toEqual [1, 5]
1460
1461 describe 'the f/F keybindings', ->
1462 beforeEach ->
1463 editor.setText("abcabcabcabc\n")
1464 editor.setCursorScreenPosition([0, 0])
1465
1466 it 'moves to the first specified character it finds', ->
1467 keydown('f')
1468 commandModeInputKeydown('c')
1469 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1470
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]
1476
1477 it 'respects count forward', ->
1478 keydown('2')
1479 keydown('f')
1480 commandModeInputKeydown('a')
1481 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1482
1483 it 'respects count backward', ->
1484 editor.setCursorScreenPosition([0, 6])
1485 keydown('2')
1486 keydown('F', shift: true)
1487 commandModeInputKeydown('a')
1488 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1489
1490 it "doesn't move if the character specified isn't found", ->
1491 keydown('f')
1492 commandModeInputKeydown('d')
1493 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1494
1495 it "doesn't move if there aren't the specified count of the specified character", ->
1496 keydown('1')
1497 keydown('0')
1498 keydown('f')
1499 commandModeInputKeydown('a')
1500 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1501 # a bug was making this behaviour depend on the count
1502 keydown('1')
1503 keydown('1')
1504 keydown('f')
1505 commandModeInputKeydown('a')
1506 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1507 # and backwards now
1508 editor.setCursorScreenPosition([0, 6])
1509 keydown('1')
1510 keydown('0')
1511 keydown('F', shift: true)
1512 commandModeInputKeydown('a')
1513 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1514 keydown('1')
1515 keydown('1')
1516 keydown('F', shift: true)
1517 commandModeInputKeydown('a')
1518 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1519
1520 it "composes with d", ->
1521 editor.setCursorScreenPosition([0, 3])
1522 keydown('d')
1523 keydown('2')
1524 keydown('f')
1525 commandModeInputKeydown('a')
1526 expect(editor.getText()).toEqual 'abcbc\n'
1527
1528 describe 'the t/T keybindings', ->
1529 beforeEach ->
1530 editor.setText("abcabcabcabc\n")
1531 editor.setCursorScreenPosition([0, 0])
1532
1533 it 'moves to the character previous to the first specified character it finds', ->
1534 keydown('t')
1535 commandModeInputKeydown('a')
1536 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1537 # or stays put when it's already there
1538 keydown('t')
1539 commandModeInputKeydown('a')
1540 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1541
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]
1547
1548 it 'respects count forward', ->
1549 keydown('2')
1550 keydown('t')
1551 commandModeInputKeydown('a')
1552 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1553
1554 it 'respects count backward', ->
1555 editor.setCursorScreenPosition([0, 6])
1556 keydown('2')
1557 keydown('T', shift: true)
1558 commandModeInputKeydown('a')
1559 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1560
1561 it "doesn't move if the character specified isn't found", ->
1562 keydown('t')
1563 commandModeInputKeydown('d')
1564 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1565
1566 it "doesn't move if there aren't the specified count of the specified character", ->
1567 keydown('1')
1568 keydown('0')
1569 keydown('t')
1570 commandModeInputKeydown('a')
1571 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1572 # a bug was making this behaviour depend on the count
1573 keydown('1')
1574 keydown('1')
1575 keydown('t')
1576 commandModeInputKeydown('a')
1577 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1578 # and backwards now
1579 editor.setCursorScreenPosition([0, 6])
1580 keydown('1')
1581 keydown('0')
1582 keydown('T', shift: true)
1583 commandModeInputKeydown('a')
1584 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1585 keydown('1')
1586 keydown('1')
1587 keydown('T', shift: true)
1588 commandModeInputKeydown('a')
1589 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1590
1591 it "composes with d", ->
1592 editor.setCursorScreenPosition([0, 3])
1593 keydown('d')
1594 keydown('2')
1595 keydown('t')
1596 commandModeInputKeydown('b')
1597 expect(editor.getText()).toBe 'abcbcabc\n'
1598
1599 describe 'the V keybinding', ->
1600 beforeEach ->
1601 editor.setText("01\n002\n0003\n00004\n000005\n")
1602 editor.setCursorScreenPosition([1, 1])
1603
1604 it "selects down a line", ->
1605 keydown('V', shift: true)
1606 keydown('j')
1607 keydown('j')
1608 expect(editor.getSelectedText()).toBe "002\n0003\n00004\n"
1609
1610 it "selects up a line", ->
1611 keydown('V', shift: true)
1612 keydown('k')
1613 expect(editor.getSelectedText()).toBe "01\n002\n"
1614
1615 describe 'the ; and , keybindings', ->
1616 beforeEach ->
1617 editor.setText("abcabcabcabc\n")
1618 editor.setCursorScreenPosition([0, 0])
1619
1620 it "repeat f in same direction", ->
1621 keydown('f')
1622 commandModeInputKeydown('c')
1623 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1624 keydown(';')
1625 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1626 keydown(';')
1627 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1628
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]
1634 keydown(';')
1635 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1636 keydown(';')
1637 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1638
1639 it "repeat f in opposite direction", ->
1640 editor.setCursorScreenPosition([0, 6])
1641 keydown('f')
1642 commandModeInputKeydown('c')
1643 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1644 keydown(',')
1645 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1646 keydown(',')
1647 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1648
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]
1654 keydown(',')
1655 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1656 keydown(',')
1657 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1658
1659 it "alternate repeat f in same direction and reverse", ->
1660 keydown('f')
1661 commandModeInputKeydown('c')
1662 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1663 keydown(';')
1664 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1665 keydown(',')
1666 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1667
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]
1673 keydown(';')
1674 expect(editor.getCursorScreenPosition()).toEqual [0, 5]
1675 keydown(',')
1676 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1677
1678 it "repeat t in same direction", ->
1679 keydown('t')
1680 commandModeInputKeydown('c')
1681 expect(editor.getCursorScreenPosition()).toEqual [0, 1]
1682 keydown(';')
1683 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1684
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]
1690 keydown(';')
1691 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1692
1693 it "repeat t in opposite direction first, and then reverse", ->
1694 editor.setCursorScreenPosition([0, 3])
1695 keydown('t')
1696 commandModeInputKeydown('c')
1697 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1698 keydown(',')
1699 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1700 keydown(';')
1701 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1702
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]
1708 keydown(',')
1709 expect(editor.getCursorScreenPosition()).toEqual [0, 4]
1710 keydown(';')
1711 expect(editor.getCursorScreenPosition()).toEqual [0, 3]
1712
1713 it "repeat with count in same direction", ->
1714 editor.setCursorScreenPosition([0, 0])
1715 keydown('f')
1716 commandModeInputKeydown('c')
1717 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1718 keydown('2')
1719 keydown(';')
1720 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1721
1722 it "repeat with count in reverse direction", ->
1723 editor.setCursorScreenPosition([0, 6])
1724 keydown('f')
1725 commandModeInputKeydown('c')
1726 expect(editor.getCursorScreenPosition()).toEqual [0, 8]
1727 keydown('2')
1728 keydown(',')
1729 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1730
1731 describe 'the % motion', ->
1732 beforeEach ->
1733 editor.setText("( ( ) )--{ text in here; and a function call(with parameters) }\n")
1734 editor.setCursorScreenPosition([0, 0])
1735
1736 it 'matches the correct parenthesis', ->
1737 keydown('%')
1738 expect(editor.getCursorScreenPosition()).toEqual [0, 6]
1739
1740 it 'matches the correct brace', ->
1741 editor.setCursorScreenPosition([0, 9])
1742 keydown('%')
1743 expect(editor.getCursorScreenPosition()).toEqual [0, 62]
1744
1745 it 'composes correctly with d', ->
1746 editor.setCursorScreenPosition([0, 9])
1747 keydown('d')
1748 keydown('%')
1749 expect(editor.getText()).toEqual "( ( ) )--\n"
1750
1751 it 'moves correctly when composed with v going forward', ->
1752 keydown('v')
1753 keydown('h')
1754 keydown('%')
1755 expect(editor.getCursorScreenPosition()).toEqual [0, 7]
1756
1757 it 'moves correctly when composed with v going backward', ->
1758 editor.setCursorScreenPosition([0, 5])
1759 keydown('v')
1760 keydown('%')
1761 expect(editor.getCursorScreenPosition()).toEqual [0, 0]
1762
1763 it 'it moves appropriately to find the nearest matching action', ->
1764 editor.setCursorScreenPosition([0, 3])
1765 keydown('%')
1766 expect(editor.getCursorScreenPosition()).toEqual [0, 2]
1767 expect(editor.getText()).toEqual "( ( ) )--{ text in here; and a function call(with parameters) }\n"
1768
1769 it 'it moves appropriately to find the nearest matching action', ->
1770 editor.setCursorScreenPosition([0, 26])
1771 keydown('%')
1772 expect(editor.getCursorScreenPosition()).toEqual [0, 60]
1773 expect(editor.getText()).toEqual "( ( ) )--{ text in here; and a function call(with parameters) }\n"
1774
1775 it "finds matches across multiple lines", ->
1776 editor.setText("...(\n...)")
1777 editor.setCursorScreenPosition([0, 0])
1778 keydown("%")
1779 expect(editor.getCursorScreenPosition()).toEqual([1, 3])
1780
1781 it "does not affect search history", ->
1782 keydown('/')
1783 submitCommandModeInputText 'func'
1784 expect(editor.getCursorBufferPosition()).toEqual [0, 31]
1785 keydown('%')
1786 expect(editor.getCursorBufferPosition()).toEqual [0, 60]
1787 keydown('n')
1788 expect(editor.getCursorBufferPosition()).toEqual [0, 31]
1789
1790 describe "scrolling screen and keeping cursor in the same screen position", ->
1791 beforeEach ->
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])
1797
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]
1803
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")
1809
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")
1814
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]
1820
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")
1826
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")
1831
1832
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]
1838
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)
1844
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")
1849
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]
1855
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)
1861
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")