]>
Commit | Line | Data |
---|---|---|
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") |