1" Test for textobjects
2
3source check.vim
4CheckFeature textobjects
5
6func CpoM(line, useM, expected)
7  new
8
9  if a:useM
10    set cpoptions+=M
11  else
12    set cpoptions-=M
13  endif
14
15  call setline(1, a:line)
16
17  call setreg('"', '')
18  normal! ggfrmavi)y
19  call assert_equal(getreg('"'), a:expected[0])
20
21  call setreg('"', '')
22  normal! `afbmavi)y
23  call assert_equal(getreg('"'), a:expected[1])
24
25  call setreg('"', '')
26  normal! `afgmavi)y
27  call assert_equal(getreg('"'), a:expected[2])
28
29  q!
30endfunc
31
32func Test_inner_block_without_cpo_M()
33  call CpoM('(red \(blue) green)', 0, ['red \(blue', 'red \(blue', ''])
34endfunc
35
36func Test_inner_block_with_cpo_M_left_backslash()
37  call CpoM('(red \(blue) green)', 1, ['red \(blue) green', 'blue', 'red \(blue) green'])
38endfunc
39
40func Test_inner_block_with_cpo_M_right_backslash()
41  call CpoM('(red (blue\) green)', 1, ['red (blue\) green', 'blue\', 'red (blue\) green'])
42endfunc
43
44func Test_quote_selection_selection_exclusive()
45  new
46  call setline(1, "a 'bcde' f")
47  set selection=exclusive
48
49  exe "norm! fdvhi'y"
50  call assert_equal('bcde', @")
51
52  let @"='dummy'
53  exe "norm! $gevi'y"
54  call assert_equal('bcde', @")
55
56  let @"='dummy'
57  exe "norm! 0fbhvi'y"
58  call assert_equal('bcde', @")
59
60  set selection&vim
61  bw!
62endfunc
63
64func Test_quote_selection_selection_exclusive_abort()
65  new
66  set selection=exclusive
67  call setline(1, "'abzzc'")
68  let exp_curs = [0, 1, 6, 0]
69  call cursor(1,1)
70  exe 'norm! fcdvi"'
71  " make sure to end visual mode to have a clear state
72  exe "norm! \<esc>"
73  call assert_equal(exp_curs, getpos('.'))
74  call cursor(1,1)
75  exe 'norm! fcvi"'
76  exe "norm! \<esc>"
77  call assert_equal(exp_curs, getpos('.'))
78  call cursor(1,2)
79  exe 'norm! vfcoi"'
80  exe "norm! \<esc>"
81  let exp_curs = [0, 1, 2, 0]
82  let exp_visu = [0, 1, 7, 0]
83  call assert_equal(exp_curs, getpos('.'))
84  call assert_equal(exp_visu, getpos("'>"))
85  set selection&vim
86  bw!
87endfunc
88
89" Tests for string and html text objects
90func Test_string_html_objects()
91  enew!
92
93  let t = '"wo\"rd\\" foo'
94  put =t
95  normal! da"
96  call assert_equal('foo', getline('.'))
97
98  let t = "'foo' 'bar' 'piep'"
99  put =t
100  normal! 0va'a'rx
101  call assert_equal("xxxxxxxxxxxx'piep'", getline('.'))
102
103  let t = "bla bla `quote` blah"
104  put =t
105  normal! 02f`da`
106  call assert_equal("bla bla blah", getline('.'))
107
108  let t = 'out " in "noXno"'
109  put =t
110  normal! 0fXdi"
111  call assert_equal('out " in ""', getline('.'))
112
113  let t = "\"'\" 'blah' rep 'buh'"
114  put =t
115  normal! 03f'vi'ry
116  call assert_equal("\"'\" 'blah'yyyyy'buh'", getline('.'))
117
118  set quoteescape=+*-
119  let t = "bla `s*`d-`+++`l**` b`la"
120  put =t
121  normal! di`
122  call assert_equal("bla `` b`la", getline('.'))
123
124  let t = 'voo "nah" sdf " asdf" sdf " sdf" sd'
125  put =t
126  normal! $F"va"oha"i"rz
127  call assert_equal('voo "zzzzzzzzzzzzzzzzzzzzzzzzzzzzsd', getline('.'))
128
129  let t = "-<b>asdf<i>Xasdf</i>asdf</b>-"
130  put =t
131  normal! fXdit
132  call assert_equal('-<b>asdf<i></i>asdf</b>-', getline('.'))
133
134  let t = "-<b>asdX<i>a<i />sdf</i>asdf</b>-"
135  put =t
136  normal! 0fXdit
137  call assert_equal('-<b></b>-', getline('.'))
138
139  let t = "-<b>asdf<i>Xasdf</i>asdf</b>-"
140  put =t
141  normal! fXdat
142  call assert_equal('-<b>asdfasdf</b>-', getline('.'))
143
144  let t = "-<b>asdX<i>as<b />df</i>asdf</b>-"
145  put =t
146  normal! 0fXdat
147  call assert_equal('--', getline('.'))
148
149  let t = "-<b>\ninnertext object\n</b>"
150  put =t
151  normal! dit
152  call assert_equal('-<b></b>', getline('.'))
153
154  " copy the tag block from leading indentation before the start tag
155  let t = "    <b>\ntext\n</b>"
156  $put =t
157  normal! 2kvaty
158  call assert_equal("<b>\ntext\n</b>", @")
159
160  " copy the tag block from the end tag
161  let t = "<title>\nwelcome\n</title>"
162  $put =t
163  normal! $vaty
164  call assert_equal("<title>\nwelcome\n</title>", @")
165
166  " copy the outer tag block from a tag without an end tag
167  let t = "<html>\n<title>welcome\n</html>"
168  $put =t
169  normal! k$vaty
170  call assert_equal("<html>\n<title>welcome\n</html>", @")
171
172  " nested tag that has < in a different line from >
173  let t = "<div><div\n></div></div>"
174  $put =t
175  normal! k0vaty
176  call assert_equal("<div><div\n></div></div>", @")
177
178  " nested tag with attribute that has < in a different line from >
179  let t = "<div><div\nattr=\"attr\"\n></div></div>"
180  $put =t
181  normal! 2k0vaty
182  call assert_equal("<div><div\nattr=\"attr\"\n></div></div>", @")
183
184  set quoteescape&
185  enew!
186endfunc
187
188func Test_empty_html_tag()
189  new
190  call setline(1, '<div></div>')
191  normal 0citxxx
192  call assert_equal('<div>xxx</div>', getline(1))
193
194  call setline(1, '<div></div>')
195  normal 0f<cityyy
196  call assert_equal('<div>yyy</div>', getline(1))
197
198  call setline(1, '<div></div>')
199  normal 0f<vitsaaa
200  call assert_equal('aaa', getline(1))
201
202  " selecting a tag block in an non-empty blank line should fail
203  call setline(1, '    ')
204  call assert_beeps('normal $vaty')
205
206  bwipe!
207endfunc
208
209" Tests for match() and matchstr()
210func Test_match()
211  call assert_equal("b", matchstr("abcd", ".", 0, 2))
212  call assert_equal("bc", matchstr("abcd", "..", 0, 2))
213  call assert_equal("c", matchstr("abcd", ".", 2, 0))
214  call assert_equal("a", matchstr("abcd", ".", 0, -1))
215  call assert_equal(-1, match("abcd", ".", 0, 5))
216  call assert_equal(0, match("abcd", ".", 0, -1))
217  call assert_equal(0, match('abc', '.', 0, 1))
218  call assert_equal(1, match('abc', '.', 0, 2))
219  call assert_equal(2, match('abc', '.', 0, 3))
220  call assert_equal(-1, match('abc', '.', 0, 4))
221  call assert_equal(1, match('abc', '.', 1, 1))
222  call assert_equal(2, match('abc', '.', 2, 1))
223  call assert_equal(-1, match('abc', '.', 3, 1))
224  call assert_equal(3, match('abc', '$', 0, 1))
225  call assert_equal(-1, match('abc', '$', 0, 2))
226  call assert_equal(3, match('abc', '$', 1, 1))
227  call assert_equal(3, match('abc', '$', 2, 1))
228  call assert_equal(3, match('abc', '$', 3, 1))
229  call assert_equal(-1, match('abc', '$', 4, 1))
230  call assert_equal(0, match('abc', '\zs', 0, 1))
231  call assert_equal(1, match('abc', '\zs', 0, 2))
232  call assert_equal(2, match('abc', '\zs', 0, 3))
233  call assert_equal(3, match('abc', '\zs', 0, 4))
234  call assert_equal(-1, match('abc', '\zs', 0, 5))
235  call assert_equal(1, match('abc', '\zs', 1, 1))
236  call assert_equal(2, match('abc', '\zs', 2, 1))
237  call assert_equal(3, match('abc', '\zs', 3, 1))
238  call assert_equal(-1, match('abc', '\zs', 4, 1))
239endfunc
240
241" This was causing an illegal memory access
242func Test_inner_tag()
243  new
244  norm ixxx
245  call feedkeys("v", 'xt')
246  insert
247x
248x
249.
250  norm it
251  q!
252endfunc
253
254func Test_sentence()
255  enew!
256  call setline(1, 'A sentence.  A sentence?  A sentence!')
257
258  normal yis
259  call assert_equal('A sentence.', @")
260  normal yas
261  call assert_equal('A sentence.  ', @")
262
263  normal )
264
265  normal yis
266  call assert_equal('A sentence?', @")
267  normal yas
268  call assert_equal('A sentence?  ', @")
269
270  normal )
271
272  normal yis
273  call assert_equal('A sentence!', @")
274  normal yas
275  call assert_equal('  A sentence!', @")
276
277  normal 0
278  normal 2yis
279  call assert_equal('A sentence.  ', @")
280  normal 3yis
281  call assert_equal('A sentence.  A sentence?', @")
282  normal 2yas
283  call assert_equal('A sentence.  A sentence?  ', @")
284
285  %delete _
286endfunc
287
288func Test_sentence_with_quotes()
289  enew!
290  call setline(1, 'A "sentence."  A sentence.')
291
292  normal yis
293  call assert_equal('A "sentence."', @")
294  normal yas
295  call assert_equal('A "sentence."  ', @")
296
297  normal )
298
299  normal yis
300  call assert_equal('A sentence.', @")
301  normal yas
302  call assert_equal('  A sentence.', @")
303
304  %delete _
305endfunc
306
307func Test_sentence_with_cursor_on_delimiter()
308  enew!
309  call setline(1, "A '([sentence.])'  A sentence.")
310
311  normal! 15|yis
312  call assert_equal("A '([sentence.])'", @")
313  normal! 15|yas
314  call assert_equal("A '([sentence.])'  ", @")
315
316  normal! 16|yis
317  call assert_equal("A '([sentence.])'", @")
318  normal! 16|yas
319  call assert_equal("A '([sentence.])'  ", @")
320
321  normal! 17|yis
322  call assert_equal("A '([sentence.])'", @")
323  normal! 17|yas
324  call assert_equal("A '([sentence.])'  ", @")
325
326  " don't get stuck on a quote at the start of a sentence
327  %delete _
328  call setline(1, ['A sentence.', '"A sentence"?', 'A sentence!'])
329  normal gg))
330  call assert_equal(3, getcurpos()[1])
331
332  %delete _
333  call setline(1, ['A sentence.', "'A sentence'?", 'A sentence!'])
334  normal gg))
335  call assert_equal(3, getcurpos()[1])
336
337  %delete _
338endfunc
339
340" Test for the paragraph (ap) text object
341func Test_paragraph()
342  new
343  call setline(1, ['First line.', 'Second line.', 'Third line.'])
344  call cursor(2, 1)
345  normal vapy
346  call assert_equal("First line.\nSecond line.\nThird line.\n", @")
347
348  call cursor(2, 1)
349  call assert_beeps('normal vapapy')
350
351  call setline(1, ['First line.', 'Second line.', '  ', ''])
352  call cursor(1, 1)
353  normal vapy
354  call assert_equal("First line.\nSecond line.\n  \n\n", @")
355
356  call setline(1, ['', '', '', 'First line.', 'Second line.'])
357  call cursor(2, 1)
358  normal yap
359  call assert_equal("\n\n\nFirst line.\nSecond line.\n", @")
360  call assert_beeps('normal 3yap')
361  exe "normal \<C-C>"
362
363  %d
364  call setline(1, ['  ', '  ', '  '])
365  call cursor(2, 1)
366  normal Vipy
367  call assert_equal("  \n  \n  \n", @")
368  call cursor(2, 1)
369  call assert_beeps("normal Vipip")
370  exe "normal \<C-C>"
371
372  close!
373endfunc
374
375" Tests for text object aw
376func Test_textobj_a_word()
377  new
378  call append(0, ['foobar,eins,foobar', 'foo,zwei,foo    '])
379  " diw
380  norm! 1gg0diw
381  call assert_equal([',eins,foobar', 'foo,zwei,foo    ', ''], getline(1,'$'))
382  " daw
383  norm! 2ggEdaw
384  call assert_equal([',eins,foobar', 'foo,zwei,', ''], getline(1, '$'))
385  " daw the last word in a line
386  call setline(1, ['foo bar', 'foo bar', ''])
387  call cursor(1, 5)
388  normal daw
389  call assert_equal('foo', getline(1))
390  " aw in visual mode
391  call cursor(2, 5)
392  normal! vawx
393  call assert_equal('foo', getline(2))
394  %d
395  call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo   "])
396  " diW
397  norm! 2ggwd2iW
398  call assert_equal(['foo	eins	foobar', 'foo	foo   ', ''], getline(1,'$'))
399  " daW
400  norm! 1ggd2aW
401  call assert_equal(['foobar', 'foo	foo   ', ''], getline(1,'$'))
402
403  %d
404  call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo   "])
405  " aw in visual line mode switches to characterwise mode
406  norm! 2gg$Vawd
407  call assert_equal(['foo	eins	foobar', 'foo	zwei	foo'], getline(1,'$'))
408  norm! 1gg$Viwd
409  call assert_equal(['foo	eins	', 'foo	zwei	foo'], getline(1,'$'))
410
411  " visually selecting a tab before a word with 'selection' set to 'exclusive'
412  set selection=exclusive
413  normal gg3lvlawy
414  call assert_equal("\teins", @")
415  " visually selecting a tab before a word with 'selection' set to 'inclusive'
416  set selection=inclusive
417  normal gg3lvlawy
418  call assert_equal("\teins\t", @")
419  set selection&
420
421  " selecting a word with no non-space characters in a buffer fails
422  %d
423  call setline(1, '    ')
424  call assert_beeps('normal 3lyaw')
425
426  " visually selecting words backwards with no more words to select
427  call setline(1, 'one two')
428  call assert_beeps('normal 2lvh2aw')
429  exe "normal \<C-C>"
430  call assert_beeps('normal $vh3aw')
431  exe "normal \<C-C>"
432  call setline(1, ['', 'one two'])
433  call assert_beeps('normal 2G2lvh3aw')
434  exe "normal \<C-C>"
435
436  " selecting words forward with no more words to select
437  %d
438  call setline(1, 'one a')
439  call assert_beeps('normal 0y3aw')
440  call setline(1, 'one two ')
441  call assert_beeps('normal 0y3aw')
442  call assert_beeps('normal 03ly2aw')
443
444  " clean up
445  bw!
446endfunc
447
448" Test for is and as text objects
449func Test_textobj_sentence()
450  new
451  call append(0, ['This is a test. With some sentences!', '',
452        \ 'Even with a question? And one more. And no sentence here'])
453  " Test for dis - does not remove trailing whitespace
454  norm! 1gg0dis
455  call assert_equal([' With some sentences!', '',
456        \ 'Even with a question? And one more. And no sentence here', ''],
457        \ getline(1,'$'))
458  " Test for das - removes leading whitespace
459  norm! 3ggf?ldas
460  call assert_equal([' With some sentences!', '',
461        \ 'Even with a question? And no sentence here', ''], getline(1,'$'))
462  " when used in visual mode, is made characterwise
463  norm! 3gg$Visy
464  call assert_equal('v', visualmode())
465  " reset visualmode()
466  norm! 3ggVy
467  norm! 3gg$Vasy
468  call assert_equal('v', visualmode())
469  " basic testing for textobjects a< and at
470  %d
471  call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>','    </div>', ' '])
472  " a<
473  norm! 1gg0da<
474  call assert_equal([' ', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
475  norm! 1pj
476  call assert_equal([' <div>', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
477  " at
478  norm! d2at
479  call assert_equal([' '], getline(1,'$'))
480  %d
481  call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>','    </div>', ' '])
482  " i<
483  norm! 1gg0di<
484  call assert_equal(['<> ', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
485  norm! 1Pj
486  call assert_equal(['<div> ', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
487  norm! d2it
488  call assert_equal(['<div></div>',' '], getline(1,'$'))
489  " basic testing for a[ and i[ text object
490  %d
491  call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
492  norm! 3gg0di[
493  call assert_equal([' ', '[', ']'], getline(1,'$'))
494  call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
495  norm! 3gg0ftd2a[
496  call assert_equal([' '], getline(1,'$'))
497
498  " clean up
499  bw!
500endfunc
501
502" Test for quote (', " and `) textobjects
503func Test_textobj_quote()
504  new
505
506  " Test for i" when cursor is in front of a quoted object
507  call append(0, 'foo "bar"')
508  norm! 1gg0di"
509  call assert_equal(['foo ""', ''], getline(1,'$'))
510
511  " Test for visually selecting an inner quote
512  %d
513  " extend visual selection from one quote to the next
514  call setline(1, 'color "red" color "blue"')
515  call cursor(1, 7)
516  normal v4li"y
517  call assert_equal('"red" color "blue', @")
518
519  " try to extend visual selection from one quote to a non-existing quote
520  call setline(1, 'color "red" color blue')
521  call cursor(1, 7)
522  call feedkeys('v4li"y', 'xt')
523  call assert_equal('"red"', @")
524
525  " try to extend visual selection from one quote to a next partial quote
526  call setline(1, 'color "red" color "blue')
527  call cursor(1, 7)
528  normal v4li"y
529  call assert_equal('"red" color ', @")
530
531  " select a quote backwards in visual mode
532  call cursor(1, 12)
533  normal vhi"y
534  call assert_equal('red" ', @")
535  call assert_equal(8, col('.'))
536
537  " select a quote backwards in visual mode from outside the quote
538  call cursor(1, 17)
539  normal v2hi"y
540  call assert_equal('red', @")
541  call assert_equal(8, col('.'))
542
543  " visually selecting a quote with 'selection' set to 'exclusive'
544  call setline(1, 'He said "How are you?"')
545  set selection=exclusive
546  normal 012lv2li"y
547  call assert_equal('How are you?', @")
548  set selection&
549
550  " try copy a quote object with a single quote in the line
551  call setline(1, "Smith's car")
552  call cursor(1, 6)
553  call assert_beeps("normal yi'")
554  call assert_beeps("normal 2lyi'")
555
556  " selecting space before and after a quoted string
557  call setline(1, "some    'special'    string")
558  normal 0ya'
559  call assert_equal("'special'    ", @")
560  call setline(1, "some    'special'string")
561  normal 0ya'
562  call assert_equal("    'special'", @")
563
564  close!
565endfunc
566
567" Test for i(, i<, etc. when cursor is in front of a block
568func Test_textobj_find_paren_forward()
569  new
570
571  " i< and a> when cursor is in front of a block
572  call setline(1, '#include <foo.h>')
573  normal 0yi<
574  call assert_equal('foo.h', @")
575  normal 0ya>
576  call assert_equal('<foo.h>', @")
577
578  " 2i(, 3i( in front of a block enters second/third nested '('
579  call setline(1, 'foo (bar (baz (quux)))')
580  normal 0yi)
581  call assert_equal('bar (baz (quux))', @")
582  normal 02yi)
583  call assert_equal('baz (quux)', @")
584  normal 03yi)
585  call assert_equal('quux', @")
586
587  " 3i( in front of a block doesn't enter third but un-nested '('
588  call setline(1, 'foo (bar (baz) (quux))')
589  normal 03di)
590  call assert_equal('foo (bar (baz) (quux))', getline(1))
591  normal 02di)
592  call assert_equal('foo (bar () (quux))', getline(1))
593  normal 0di)
594  call assert_equal('foo ()', getline(1))
595
596  close!
597endfunc
598
599" vim: shiftwidth=2 sts=2 expandtab
600