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