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  set quoteescape&
173  enew!
174endfunc
175
176func Test_empty_html_tag()
177  new
178  call setline(1, '<div></div>')
179  normal 0citxxx
180  call assert_equal('<div>xxx</div>', getline(1))
181
182  call setline(1, '<div></div>')
183  normal 0f<cityyy
184  call assert_equal('<div>yyy</div>', getline(1))
185
186  call setline(1, '<div></div>')
187  normal 0f<vitsaaa
188  call assert_equal('aaa', getline(1))
189
190  " selecting a tag block in an non-empty blank line should fail
191  call setline(1, '    ')
192  call assert_beeps('normal $vaty')
193
194  bwipe!
195endfunc
196
197" Tests for match() and matchstr()
198func Test_match()
199  call assert_equal("b", matchstr("abcd", ".", 0, 2))
200  call assert_equal("bc", matchstr("abcd", "..", 0, 2))
201  call assert_equal("c", matchstr("abcd", ".", 2, 0))
202  call assert_equal("a", matchstr("abcd", ".", 0, -1))
203  call assert_equal(-1, match("abcd", ".", 0, 5))
204  call assert_equal(0 , match("abcd", ".", 0, -1))
205  call assert_equal(0 , match('abc', '.', 0, 1))
206  call assert_equal(1 , match('abc', '.', 0, 2))
207  call assert_equal(2 , match('abc', '.', 0, 3))
208  call assert_equal(-1, match('abc', '.', 0, 4))
209  call assert_equal(1 , match('abc', '.', 1, 1))
210  call assert_equal(2 , match('abc', '.', 2, 1))
211  call assert_equal(-1, match('abc', '.', 3, 1))
212  call assert_equal(3 , match('abc', '$', 0, 1))
213  call assert_equal(-1, match('abc', '$', 0, 2))
214  call assert_equal(3 , match('abc', '$', 1, 1))
215  call assert_equal(3 , match('abc', '$', 2, 1))
216  call assert_equal(3 , match('abc', '$', 3, 1))
217  call assert_equal(-1, match('abc', '$', 4, 1))
218  call assert_equal(0 , match('abc', '\zs', 0, 1))
219  call assert_equal(1 , match('abc', '\zs', 0, 2))
220  call assert_equal(2 , match('abc', '\zs', 0, 3))
221  call assert_equal(3 , match('abc', '\zs', 0, 4))
222  call assert_equal(-1, match('abc', '\zs', 0, 5))
223  call assert_equal(1 , match('abc', '\zs', 1, 1))
224  call assert_equal(2 , match('abc', '\zs', 2, 1))
225  call assert_equal(3 , match('abc', '\zs', 3, 1))
226  call assert_equal(-1, match('abc', '\zs', 4, 1))
227endfunc
228
229" This was causing an illegal memory access
230func Test_inner_tag()
231  new
232  norm ixxx
233  call feedkeys("v", 'xt')
234  insert
235x
236x
237.
238  norm it
239  q!
240endfunc
241
242func Test_sentence()
243  enew!
244  call setline(1, 'A sentence.  A sentence?  A sentence!')
245
246  normal yis
247  call assert_equal('A sentence.', @")
248  normal yas
249  call assert_equal('A sentence.  ', @")
250
251  normal )
252
253  normal yis
254  call assert_equal('A sentence?', @")
255  normal yas
256  call assert_equal('A sentence?  ', @")
257
258  normal )
259
260  normal yis
261  call assert_equal('A sentence!', @")
262  normal yas
263  call assert_equal('  A sentence!', @")
264
265  normal 0
266  normal 2yis
267  call assert_equal('A sentence.  ', @")
268  normal 3yis
269  call assert_equal('A sentence.  A sentence?', @")
270  normal 2yas
271  call assert_equal('A sentence.  A sentence?  ', @")
272
273  %delete _
274endfunc
275
276func Test_sentence_with_quotes()
277  enew!
278  call setline(1, 'A "sentence."  A sentence.')
279
280  normal yis
281  call assert_equal('A "sentence."', @")
282  normal yas
283  call assert_equal('A "sentence."  ', @")
284
285  normal )
286
287  normal yis
288  call assert_equal('A sentence.', @")
289  normal yas
290  call assert_equal('  A sentence.', @")
291
292  %delete _
293endfunc
294
295func Test_sentence_with_cursor_on_delimiter()
296  enew!
297  call setline(1, "A '([sentence.])'  A sentence.")
298
299  normal! 15|yis
300  call assert_equal("A '([sentence.])'", @")
301  normal! 15|yas
302  call assert_equal("A '([sentence.])'  ", @")
303
304  normal! 16|yis
305  call assert_equal("A '([sentence.])'", @")
306  normal! 16|yas
307  call assert_equal("A '([sentence.])'  ", @")
308
309  normal! 17|yis
310  call assert_equal("A '([sentence.])'", @")
311  normal! 17|yas
312  call assert_equal("A '([sentence.])'  ", @")
313
314  " don't get stuck on a quote at the start of a sentence
315  %delete _
316  call setline(1, ['A sentence.', '"A sentence"?', 'A sentence!'])
317  normal gg))
318  call assert_equal(3, getcurpos()[1])
319
320  %delete _
321  call setline(1, ['A sentence.', "'A sentence'?", 'A sentence!'])
322  normal gg))
323  call assert_equal(3, getcurpos()[1])
324
325  %delete _
326endfunc
327
328" Test for the paragraph (ap) text object
329func Test_paragraph()
330  new
331  call setline(1, ['First line.', 'Second line.', 'Third line.'])
332  call cursor(2, 1)
333  normal vapy
334  call assert_equal("First line.\nSecond line.\nThird line.\n", @")
335
336  call cursor(2, 1)
337  call assert_beeps('normal vapapy')
338
339  call setline(1, ['First line.', 'Second line.', '  ', ''])
340  call cursor(1, 1)
341  normal vapy
342  call assert_equal("First line.\nSecond line.\n  \n\n", @")
343
344  call setline(1, ['', '', '', 'First line.', 'Second line.'])
345  call cursor(2, 1)
346  normal yap
347  call assert_equal("\n\n\nFirst line.\nSecond line.\n", @")
348  call assert_beeps('normal 3yap')
349  exe "normal \<C-C>"
350
351  %d
352  call setline(1, ['  ', '  ', '  '])
353  call cursor(2, 1)
354  normal Vipy
355  call assert_equal("  \n  \n  \n", @")
356  call cursor(2, 1)
357  call assert_beeps("normal Vipip")
358  exe "normal \<C-C>"
359
360  close!
361endfunc
362
363" Tests for text object aw
364func Test_textobj_a_word()
365  new
366  call append(0, ['foobar,eins,foobar', 'foo,zwei,foo    '])
367  " diw
368  norm! 1gg0diw
369  call assert_equal([',eins,foobar', 'foo,zwei,foo    ', ''], getline(1,'$'))
370  " daw
371  norm! 2ggEdaw
372  call assert_equal([',eins,foobar', 'foo,zwei,', ''], getline(1, '$'))
373  " daw the last word in a line
374  call setline(1, ['foo bar', 'foo bar', ''])
375  call cursor(1, 5)
376  normal daw
377  call assert_equal('foo', getline(1))
378  " aw in visual mode
379  call cursor(2, 5)
380  normal! vawx
381  call assert_equal('foo', getline(2))
382  %d
383  call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo   "])
384  " diW
385  norm! 2ggwd2iW
386  call assert_equal(['foo	eins	foobar', 'foo	foo   ', ''], getline(1,'$'))
387  " daW
388  norm! 1ggd2aW
389  call assert_equal(['foobar', 'foo	foo   ', ''], getline(1,'$'))
390
391  %d
392  call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo   "])
393  " aw in visual line mode switches to characterwise mode
394  norm! 2gg$Vawd
395  call assert_equal(['foo	eins	foobar', 'foo	zwei	foo'], getline(1,'$'))
396  norm! 1gg$Viwd
397  call assert_equal(['foo	eins	', 'foo	zwei	foo'], getline(1,'$'))
398
399  " visually selecting a tab before a word with 'selection' set to 'exclusive'
400  set selection=exclusive
401  normal gg3lvlawy
402  call assert_equal("\teins", @")
403  " visually selecting a tab before a word with 'selection' set to 'inclusive'
404  set selection=inclusive
405  normal gg3lvlawy
406  call assert_equal("\teins\t", @")
407  set selection&
408
409  " selecting a word with no non-space characters in a buffer fails
410  %d
411  call setline(1, '    ')
412  call assert_beeps('normal 3lyaw')
413
414  " visually selecting words backwards with no more words to select
415  call setline(1, 'one two')
416  call assert_beeps('normal 2lvh2aw')
417  exe "normal \<C-C>"
418  call assert_beeps('normal $vh3aw')
419  exe "normal \<C-C>"
420  call setline(1, ['', 'one two'])
421  call assert_beeps('normal 2G2lvh3aw')
422  exe "normal \<C-C>"
423
424  " selecting words forward with no more words to select
425  %d
426  call setline(1, 'one a')
427  call assert_beeps('normal 0y3aw')
428  call setline(1, 'one two ')
429  call assert_beeps('normal 0y3aw')
430  call assert_beeps('normal 03ly2aw')
431
432  " clean up
433  bw!
434endfunc
435
436" Test for is and as text objects
437func Test_textobj_sentence()
438  new
439  call append(0, ['This is a test. With some sentences!', '',
440        \ 'Even with a question? And one more. And no sentence here'])
441  " Test for dis - does not remove trailing whitespace
442  norm! 1gg0dis
443  call assert_equal([' With some sentences!', '',
444        \ 'Even with a question? And one more. And no sentence here', ''],
445        \ getline(1,'$'))
446  " Test for das - removes leading whitespace
447  norm! 3ggf?ldas
448  call assert_equal([' With some sentences!', '',
449        \ 'Even with a question? And no sentence here', ''], getline(1,'$'))
450  " when used in visual mode, is made characterwise
451  norm! 3gg$Visy
452  call assert_equal('v', visualmode())
453  " reset visualmode()
454  norm! 3ggVy
455  norm! 3gg$Vasy
456  call assert_equal('v', visualmode())
457  " basic testing for textobjects a< and at
458  %d
459  call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>','    </div>', ' '])
460  " a<
461  norm! 1gg0da<
462  call assert_equal([' ', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
463  norm! 1pj
464  call assert_equal([' <div>', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
465  " at
466  norm! d2at
467  call assert_equal([' '], getline(1,'$'))
468  %d
469  call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>','    </div>', ' '])
470  " i<
471  norm! 1gg0di<
472  call assert_equal(['<> ', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
473  norm! 1Pj
474  call assert_equal(['<div> ', '<a href="foobar" class="foo">xyz</a>', '    </div>', ' '], getline(1,'$'))
475  norm! d2it
476  call assert_equal(['<div></div>',' '], getline(1,'$'))
477  " basic testing for a[ and i[ text object
478  %d
479  call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
480  norm! 3gg0di[
481  call assert_equal([' ', '[', ']'], getline(1,'$'))
482  call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
483  norm! 3gg0ftd2a[
484  call assert_equal([' '], getline(1,'$'))
485
486  " clean up
487  bw!
488endfunc
489
490" Test for quote (', " and `) textobjects
491func Test_textobj_quote()
492  new
493
494  " Test for i" when cursor is in front of a quoted object
495  call append(0, 'foo "bar"')
496  norm! 1gg0di"
497  call assert_equal(['foo ""', ''], getline(1,'$'))
498
499  " Test for visually selecting an inner quote
500  %d
501  " extend visual selection from one quote to the next
502  call setline(1, 'color "red" color "blue"')
503  call cursor(1, 7)
504  normal v4li"y
505  call assert_equal('"red" color "blue', @")
506
507  " try to extend visual selection from one quote to a non-existing quote
508  call setline(1, 'color "red" color blue')
509  call cursor(1, 7)
510  call feedkeys('v4li"y', 'xt')
511  call assert_equal('"red"', @")
512
513  " try to extend visual selection from one quote to a next partial quote
514  call setline(1, 'color "red" color "blue')
515  call cursor(1, 7)
516  normal v4li"y
517  call assert_equal('"red" color ', @")
518
519  " select a quote backwards in visual mode
520  call cursor(1, 12)
521  normal vhi"y
522  call assert_equal('red" ', @")
523  call assert_equal(8, col('.'))
524
525  " select a quote backwards in visual mode from outside the quote
526  call cursor(1, 17)
527  normal v2hi"y
528  call assert_equal('red', @")
529  call assert_equal(8, col('.'))
530
531  " visually selecting a quote with 'selection' set to 'exclusive'
532  call setline(1, 'He said "How are you?"')
533  set selection=exclusive
534  normal 012lv2li"y
535  call assert_equal('How are you?', @")
536  set selection&
537
538  " try copy a quote object with a single quote in the line
539  call setline(1, "Smith's car")
540  call cursor(1, 6)
541  call assert_beeps("normal yi'")
542  call assert_beeps("normal 2lyi'")
543
544  " selecting space before and after a quoted string
545  call setline(1, "some    'special'    string")
546  normal 0ya'
547  call assert_equal("'special'    ", @")
548  call setline(1, "some    'special'string")
549  normal 0ya'
550  call assert_equal("    'special'", @")
551
552  close!
553endfunc
554
555" vim: shiftwidth=2 sts=2 expandtab
556