xref: /vim-8.2.3635/src/testdir/test_fold.vim (revision dad4473f)
1" Test for folding
2
3source check.vim
4source view_util.vim
5source screendump.vim
6
7func PrepIndent(arg)
8  return [a:arg] + repeat(["\t".a:arg], 5)
9endfu
10
11func Test_address_fold()
12  new
13  call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
14	      \ 'after fold 1', 'after fold 2', 'after fold 3'])
15  setl fen fdm=marker
16  " The next commands should all copy the same part of the buffer,
17  " regardless of the addressing type, since the part to be copied
18  " is folded away
19  :1y
20  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
21  :.y
22  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
23  :.+y
24  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
25  :.,.y
26  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
27  :sil .1,.y
28  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
29  " use silent to make E493 go away
30  :sil .+,.y
31  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
32  :,y
33  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
34  :,+y
35  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/','after fold 1'], getreg(0,1,1))
36  " using .+3 as second address should copy the whole folded line + the next 3
37  " lines
38  :.,+3y
39  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/',
40	      \ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1))
41  :sil .,-2y
42  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
43
44  " now test again with folding disabled
45  set nofoldenable
46  :1y
47  call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
48  :.y
49  call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
50  :.+y
51  call assert_equal(['1'], getreg(0,1,1))
52  :.,.y
53  call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
54  " use silent to make E493 go away
55  :sil .1,.y
56  call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
57  " use silent to make E493 go away
58  :sil .+,.y
59  call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
60  :,y
61  call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
62  :,+y
63  call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
64  " using .+3 as second address should copy the whole folded line + the next 3
65  " lines
66  :.,+3y
67  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1))
68  :7
69  :sil .,-2y
70  call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1))
71
72  quit!
73endfunc
74
75func Test_indent_fold()
76    new
77    call setline(1, ['', 'a', '    b', '    c'])
78    setl fen fdm=indent
79    2
80    norm! >>
81    let a=map(range(1,4), 'foldclosed(v:val)')
82    call assert_equal([-1,-1,-1,-1], a)
83    bw!
84endfunc
85
86func Test_indent_fold2()
87    new
88    call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
89    setl fen fdm=marker
90    2
91    norm! >>
92    let a=map(range(1,5), 'v:val->foldclosed()')
93    call assert_equal([-1,-1,-1,4,4], a)
94    bw!
95endfunc
96
97func Test_manual_fold_with_filter()
98  CheckExecutable cat
99  for type in ['manual', 'marker']
100    exe 'set foldmethod=' . type
101    new
102    call setline(1, range(1, 20))
103    4,$fold
104    %foldopen
105    10,$fold
106    %foldopen
107    " This filter command should not have an effect
108    1,8! cat
109    call feedkeys('5ggzdzMGdd', 'xt')
110    call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
111
112    bwipe!
113    set foldmethod&
114  endfor
115endfunc
116
117func Test_indent_fold_with_read()
118  new
119  set foldmethod=indent
120  call setline(1, repeat(["\<Tab>a"], 4))
121  for n in range(1, 4)
122    call assert_equal(1, foldlevel(n))
123  endfor
124
125  call writefile(["a", "", "\<Tab>a"], 'Xfile')
126  foldopen
127  2read Xfile
128  %foldclose
129  call assert_equal(1, foldlevel(1))
130  call assert_equal(2, foldclosedend(1))
131  call assert_equal(0, foldlevel(3))
132  call assert_equal(0, foldlevel(4))
133  call assert_equal(1, foldlevel(5))
134  call assert_equal(7, 5->foldclosedend())
135
136  bwipe!
137  set foldmethod&
138  call delete('Xfile')
139endfunc
140
141func Test_combining_folds_indent()
142  new
143  let one = "\<Tab>a"
144  let zero = 'a'
145  call setline(1, [one, one, zero, zero, zero, one, one, one])
146  set foldmethod=indent
147  3,5d
148  %foldclose
149  call assert_equal(5, foldclosedend(1))
150
151  set foldmethod&
152  bwipe!
153endfunc
154
155func Test_combining_folds_marker()
156  new
157  call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
158  set foldmethod=marker
159  3,5d
160  %foldclose
161  call assert_equal(2, foldclosedend(1))
162
163  set foldmethod&
164  bwipe!
165endfunc
166
167func Test_folds_marker_in_comment()
168  new
169  call setline(1, ['" foo', 'bar', 'baz'])
170  setl fen fdm=marker
171  setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
172  norm! zf2j
173  setl nofen
174  :1y
175  call assert_equal(['" foo{{{'], getreg(0,1,1))
176  :+2y
177  call assert_equal(['baz"}}}'], getreg(0,1,1))
178
179  set foldmethod&
180  bwipe!
181endfunc
182
183func s:TestFoldExpr(lnum)
184  let thisline = getline(a:lnum)
185  if thisline == 'a'
186    return 1
187  elseif thisline == 'b'
188    return 0
189  elseif thisline == 'c'
190    return '<1'
191  elseif thisline == 'd'
192    return '>1'
193  endif
194  return 0
195endfunction
196
197func Test_update_folds_expr_read()
198  new
199  call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
200  set foldmethod=expr
201  set foldexpr=s:TestFoldExpr(v:lnum)
202  2
203  foldopen
204  call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile')
205  read Xfile
206  %foldclose
207  call assert_equal(2, foldclosedend(1))
208  call assert_equal(0, foldlevel(3))
209  call assert_equal(0, 4->foldlevel())
210  call assert_equal(6, foldclosedend(5))
211  call assert_equal(10, foldclosedend(7))
212  call assert_equal(14, foldclosedend(11))
213
214  call delete('Xfile')
215  bwipe!
216  set foldmethod& foldexpr&
217endfunc
218
219func Check_foldlevels(expected)
220  call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)'))
221endfunc
222
223func Test_move_folds_around_manual()
224  new
225  let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
226  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
227  let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
228  " all folds closed
229  set foldenable foldlevel=0 fdm=indent
230  " needs a forced redraw
231  redraw!
232  set fdm=manual
233  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
234  call assert_equal(input, getline(1, '$'))
235  7,12m0
236  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
237  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
238  10,12m0
239  call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] +  PrepIndent("c"), getline(1, '$'))
240  call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
241  " moving should not close the folds
242  %d
243  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
244  set fdm=indent
245  redraw!
246  set fdm=manual
247  call cursor(2, 1)
248  %foldopen
249  7,12m0
250  let folds=repeat([-1], 18)
251  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
252  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
253  norm! zM
254  " folds are not corrupted and all have been closed
255  call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
256  %d
257  call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
258  set fdm=indent
259  redraw!
260  set fdm=manual
261  %foldopen
262  3m4
263  %foldclose
264  call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
265  call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
266  %d
267  call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
268  set fdm=indent foldlevel=0
269  set fdm=manual
270  %foldopen
271  3m1
272  %foldclose
273  call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
274  call assert_equal(0, foldlevel(2))
275  call assert_equal(5, foldclosedend(3))
276  call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
277  2,6m$
278  %foldclose
279  call assert_equal(5, foldclosedend(2))
280  call assert_equal(0, foldlevel(6))
281  call assert_equal(9, foldclosedend(7))
282  call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
283
284  %d
285  " Ensure moving around the edges still works.
286  call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
287  set fdm=indent foldlevel=0
288  set fdm=manual
289  %foldopen
290  6m$
291  " The first fold has been truncated to the 5'th line.
292  " Second fold has been moved up because the moved line is now below it.
293  call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])
294
295  %delete
296  set fdm=indent foldlevel=0
297  call setline(1, [
298	\ "a",
299	\ "\ta",
300	\ "\t\ta",
301	\ "\t\ta",
302	\ "\t\ta",
303	\ "a",
304	\ "a"])
305  set fdm=manual
306  %foldopen!
307  4,5m6
308  call Check_foldlevels([0, 1, 2, 0, 0, 0, 0])
309
310  %delete
311  set fdm=indent
312  call setline(1, [
313	\ "\ta",
314	\ "\t\ta",
315	\ "\t\ta",
316	\ "\t\ta",
317	\ "\ta",
318	\ "\t\ta",
319	\ "\t\ta",
320	\ "\t\ta",
321	\ "\ta",
322	\ "\t\ta",
323	\ "\t\ta",
324	\ "\t\ta",
325	\ "\t\ta",
326	\ "\ta",
327	\ "a"])
328  set fdm=manual
329  %foldopen!
330  13m7
331  call Check_foldlevels([1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0])
332
333  bw!
334endfunc
335
336func Test_move_folds_around_indent()
337  new
338  let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
339  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
340  let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
341  " all folds closed
342  set fdm=indent
343  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
344  call assert_equal(input, getline(1, '$'))
345  7,12m0
346  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
347  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
348  10,12m0
349  call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] +  PrepIndent("c"), getline(1, '$'))
350  call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
351  " moving should not close the folds
352  %d
353  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
354  set fdm=indent
355  call cursor(2, 1)
356  %foldopen
357  7,12m0
358  let folds=repeat([-1], 18)
359  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
360  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
361  norm! zM
362  " folds are not corrupted and all have been closed
363  call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
364  %d
365  call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
366  set fdm=indent
367  %foldopen
368  3m4
369  %foldclose
370  call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
371  call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
372  %d
373  call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
374  set fdm=indent foldlevel=0
375  %foldopen
376  3m1
377  %foldclose
378  call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
379  call assert_equal(1, foldlevel(2))
380  call assert_equal(5, foldclosedend(3))
381  call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
382  2,6m$
383  %foldclose
384  call assert_equal(9, foldclosedend(2))
385  call assert_equal(1, foldlevel(6))
386  call assert_equal(9, foldclosedend(7))
387  call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
388  " Ensure moving around the edges still works.
389  %d
390  call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
391  set fdm=indent foldlevel=0
392  %foldopen
393  6m$
394  " The first fold has been truncated to the 5'th line.
395  " Second fold has been moved up because the moved line is now below it.
396  call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
397  bw!
398endfunc
399
400func Test_folddoopen_folddoclosed()
401  new
402  call setline(1, range(1, 9))
403  set foldmethod=manual
404  1,3 fold
405  6,8 fold
406
407  " Test without range.
408  folddoopen   s/$/o/
409  folddoclosed s/$/c/
410  call assert_equal(['1c', '2c', '3c',
411  \                  '4o', '5o',
412  \                  '6c', '7c', '8c',
413  \                  '9o'], getline(1, '$'))
414
415  " Test with range.
416  call setline(1, range(1, 9))
417  1,8 folddoopen   s/$/o/
418  4,$ folddoclosed s/$/c/
419  call assert_equal(['1',  '2', '3',
420  \                  '4o', '5o',
421  \                  '6c', '7c', '8c',
422  \                  '9'], getline(1, '$'))
423
424  set foldmethod&
425  bw!
426endfunc
427
428func Test_fold_error()
429  new
430  call setline(1, [1, 2])
431
432  for fm in ['indent', 'expr', 'syntax', 'diff']
433    exe 'set foldmethod=' . fm
434    call assert_fails('norm zf', 'E350:')
435    call assert_fails('norm zd', 'E351:')
436    call assert_fails('norm zE', 'E352:')
437  endfor
438
439  set foldmethod=manual
440  call assert_fails('norm zd', 'E490:')
441  call assert_fails('norm zo', 'E490:')
442  call assert_fails('3fold',   'E16:')
443
444  set foldmethod=marker
445  set nomodifiable
446  call assert_fails('1,2fold', 'E21:')
447
448  set modifiable&
449  set foldmethod&
450  bw!
451endfunc
452
453func Test_foldtext_recursive()
454  new
455  call setline(1, ['{{{', 'some text', '}}}'])
456  setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
457  " This was crashing because of endless recursion.
458  2foldclose
459  redraw
460  call assert_equal(1, foldlevel(2))
461  call assert_equal(1, foldclosed(2))
462  call assert_equal(3, foldclosedend(2))
463  bwipe!
464endfunc
465
466" Various fold related tests
467
468" Basic test if a fold can be created, opened, moving to the end and closed
469func Test_fold_manual()
470  enew!
471  set fdm=manual
472
473  let content = ['1 aa', '2 bb', '3 cc']
474  call append(0, content)
475  call cursor(1, 1)
476  normal zf2j
477  call assert_equal('1 aa', getline(foldclosed('.')))
478  normal zo
479  call assert_equal(-1, foldclosed('.'))
480  normal ]z
481  call assert_equal('3 cc', getline('.'))
482  normal zc
483  call assert_equal('1 aa', getline(foldclosed('.')))
484
485  set fdm&
486  enew!
487endfunc
488
489" test folding with markers.
490func Test_fold_marker()
491  enew!
492  set fdm=marker fdl=1 fdc=3
493
494  let content = ['4 dd {{{', '5 ee {{{ }}}', '6 ff }}}']
495  call append(0, content)
496  call cursor(2, 1)
497  call assert_equal(2, foldlevel('.'))
498  normal [z
499  call assert_equal(1, foldlevel('.'))
500  exe "normal jo{{ \<Esc>r{jj"
501  call assert_equal(1, foldlevel('.'))
502  normal kYpj
503  call assert_equal(0, foldlevel('.'))
504
505  set fdm& fdl& fdc&
506  enew!
507endfunc
508
509" test create fold markers with C filetype
510func Test_fold_create_marker_in_C()
511  enew!
512  set fdm=marker fdl=9
513  set filetype=c
514
515  let content =<< trim [CODE]
516    /*
517     * comment
518     *
519     *
520     */
521    int f(int* p) {
522        *p = 3;
523        return 0;
524    }
525  [CODE]
526
527  for c in range(len(content) - 1)
528    bw!
529    call append(0, content)
530    call cursor(c + 1, 1)
531    norm! zfG
532    call assert_equal(content[c] . (c < 4 ? '{{{' : '/*{{{*/'), getline(c + 1))
533  endfor
534
535  set fdm& fdl&
536  enew!
537endfunc
538
539" test folding with indent
540func Test_fold_indent()
541  enew!
542  set fdm=indent sw=2
543
544  let content = ['1 aa', '2 bb', '3 cc']
545  call append(0, content)
546  call cursor(2, 1)
547  exe "normal i  \<Esc>jI    "
548  call assert_equal(2, foldlevel('.'))
549  normal k
550  call assert_equal(1, foldlevel('.'))
551
552  set fdm& sw&
553  enew!
554endfunc
555
556" test syntax folding
557func Test_fold_syntax()
558  CheckFeature syntax
559
560  enew!
561  set fdm=syntax fdl=0
562
563  syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3
564  syn region Fd1 start="ee" end="ff" fold contained
565  syn region Fd2 start="gg" end="hh" fold contained
566  syn region Fd3 start="commentstart" end="commentend" fold contained
567  let content = ['3 cc', '4 dd {{{', '5 ee {{{ }}}', '{{{{', '6 ff }}}',
568	      \ '6 ff }}}', '7 gg', '8 hh', '9 ii']
569  call append(0, content)
570  normal Gzk
571  call assert_equal('9 ii', getline('.'))
572  normal k
573  call assert_equal('3 cc', getline('.'))
574  exe "normal jAcommentstart   \<Esc>Acommentend"
575  set fdl=1
576  normal 3j
577  call assert_equal('7 gg', getline('.'))
578  set fdl=0
579  exe "normal zO\<C-L>j"
580  call assert_equal('8 hh', getline('.'))
581  syn clear Fd1 Fd2 Fd3 Hup
582
583  set fdm& fdl&
584  enew!
585endfunc
586
587func Flvl()
588  let l = getline(v:lnum)
589  if l =~ "bb$"
590    return 2
591  elseif l =~ "gg$"
592    return "s1"
593  elseif l =~ "ii$"
594    return ">2"
595  elseif l =~ "kk$"
596    return "0"
597  endif
598  return "="
599endfun
600
601" test expression folding
602func Test_fold_expr()
603  enew!
604  set fdm=expr fde=Flvl()
605
606  let content = ['1 aa',
607	      \ '2 bb',
608	      \ '3 cc',
609	      \ '4 dd {{{commentstart  commentend',
610	      \ '5 ee {{{ }}}',
611	      \ '{{{',
612	      \ '6 ff }}}',
613	      \ '6 ff }}}',
614	      \ '  7 gg',
615	      \ '    8 hh',
616	      \ '9 ii',
617	      \ 'a jj',
618	      \ 'b kk']
619  call append(0, content)
620  call cursor(1, 1)
621  exe "normal /bb$\<CR>"
622  call assert_equal(2, foldlevel('.'))
623  exe "normal /hh$\<CR>"
624  call assert_equal(1, foldlevel('.'))
625  exe "normal /ii$\<CR>"
626  call assert_equal(2, foldlevel('.'))
627  exe "normal /kk$\<CR>"
628  call assert_equal(0, foldlevel('.'))
629
630  set fdm& fde&
631  enew!
632endfunc
633
634" Bug with fdm=indent and moving folds
635" Moving a fold a few times, messes up the folds below the moved fold.
636" Fixed by 7.4.700
637func Test_fold_move()
638  enew!
639  set fdm=indent sw=2 fdl=0
640
641  let content = ['', '', 'Line1', '  Line2', '  Line3',
642	      \ 'Line4', '  Line5', '  Line6',
643	      \ 'Line7', '  Line8', '  Line9']
644  call append(0, content)
645  normal zM
646  call cursor(4, 1)
647  move 2
648  move 1
649  call assert_equal(7, foldclosed(7))
650  call assert_equal(8, foldclosedend(7))
651  call assert_equal(0, foldlevel(9))
652  call assert_equal(10, foldclosed(10))
653  call assert_equal(11, foldclosedend(10))
654  call assert_equal('+--  2 lines: Line2', foldtextresult(2))
655  call assert_equal('+--  2 lines: Line8', 10->foldtextresult())
656
657  set fdm& sw& fdl&
658  enew!
659endfunc
660
661" test for patch 7.3.637
662" Cannot catch the error caused by a foldopen when there is no fold.
663func Test_foldopen_exception()
664  enew!
665  let a = 'No error caught'
666  try
667    foldopen
668  catch
669    let a = matchstr(v:exception,'^[^ ]*')
670  endtry
671  call assert_equal('Vim(foldopen):E490:', a)
672
673  let a = 'No error caught'
674  try
675    foobar
676  catch
677    let a = matchstr(v:exception,'^[^ ]*')
678  endtry
679  call assert_match('E492:', a)
680endfunc
681
682func Test_fold_last_line_with_pagedown()
683  enew!
684  set fdm=manual
685
686  let expect = '+-- 11 lines: 9---'
687  let content = range(1,19)
688  call append(0, content)
689  normal dd9G
690  normal zfG
691  normal zt
692  call assert_equal('9', getline(foldclosed('.')))
693  call assert_equal('19', getline(foldclosedend('.')))
694  call assert_equal(expect, ScreenLines(1, len(expect))[0])
695  call feedkeys("\<C-F>", 'xt')
696  call assert_equal(expect, ScreenLines(1, len(expect))[0])
697  call feedkeys("\<C-F>", 'xt')
698  call assert_equal(expect, ScreenLines(1, len(expect))[0])
699  call feedkeys("\<C-B>\<C-F>\<C-F>", 'xt')
700  call assert_equal(expect, ScreenLines(1, len(expect))[0])
701
702  set fdm&
703  enew!
704endfunc
705
706func Test_folds_with_rnu()
707  CheckScreendump
708
709  call writefile([
710	\ 'set fdm=marker rnu foldcolumn=2',
711	\ 'call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])',
712	\ ], 'Xtest_folds_with_rnu')
713  let buf = RunVimInTerminal('-S Xtest_folds_with_rnu', {})
714
715  call VerifyScreenDump(buf, 'Test_folds_with_rnu_01', {})
716  call term_sendkeys(buf, "j")
717  call VerifyScreenDump(buf, 'Test_folds_with_rnu_02', {})
718
719  " clean up
720  call StopVimInTerminal(buf)
721  call delete('Xtest_folds_with_rnu')
722endfunc
723
724func Test_folds_marker_in_comment2()
725  new
726  call setline(1, ['Lorem ipsum dolor sit', 'Lorem ipsum dolor sit', 'Lorem ipsum dolor sit'])
727  setl fen fdm=marker
728  setl commentstring=<!--%s-->
729  setl comments=s:<!--,m:\ \ \ \ ,e:-->
730  norm! zf2j
731  setl nofen
732  :1y
733  call assert_equal(['Lorem ipsum dolor sit<!--{{{-->'], getreg(0,1,1))
734  :+2y
735  call assert_equal(['Lorem ipsum dolor sit<!--}}}-->'], getreg(0,1,1))
736
737  set foldmethod&
738  bwipe!
739endfunc
740
741func Test_fold_delete_with_marker()
742  new
743  call setline(1, ['func Func() {{{1', 'endfunc'])
744  1,2yank
745  new
746  set fdm=marker
747  call setline(1, 'x')
748  normal! Vp
749  normal! zd
750  call assert_equal(['func Func() ', 'endfunc'], getline(1, '$'))
751
752  set fdm&
753  bwipe!
754  bwipe!
755endfunc
756
757func Test_fold_delete_with_marker_and_whichwrap()
758  new
759  let content1 = ['']
760  let content2 = ['folded line 1 "{{{1', '  test', '  test2', '  test3', '', 'folded line 2 "{{{1', '  test', '  test2', '  test3']
761  call setline(1, content1 + content2)
762  set fdm=marker ww+=l
763  normal! x
764  call assert_equal(content2, getline(1, '$'))
765  set fdm& ww&
766  bwipe!
767endfunc
768
769func Test_fold_delete_first_line()
770  new
771  call setline(1, [
772	\ '" x {{{1',
773	\ '" a',
774	\ '" aa',
775	\ '" x {{{1',
776	\ '" b',
777	\ '" bb',
778	\ '" x {{{1',
779	\ '" c',
780	\ '" cc',
781	\ ])
782  set foldmethod=marker
783  1
784  normal dj
785  call assert_equal([
786	\ '" x {{{1',
787	\ '" c',
788	\ '" cc',
789	\ ], getline(1,'$'))
790  bwipe!
791  set foldmethod&
792endfunc
793
794" Test for errors in 'foldexpr'
795func Test_fold_expr_error()
796  new
797  call setline(1, ['one', 'two', 'three'])
798
799  " Return a list from the expression
800  set foldexpr=[]
801  set foldmethod=expr
802  for i in range(3)
803    call assert_equal(0, foldlevel(i))
804  endfor
805
806  " expression error
807  set foldexpr=[{]
808  set foldmethod=expr
809  for i in range(3)
810    call assert_equal(0, foldlevel(i))
811  endfor
812
813  set foldmethod& foldexpr&
814  close!
815endfunc
816
817func Test_undo_fold_deletion()
818  new
819  set fdm=marker
820  let lines =<< trim END
821      " {{{
822      " }}}1
823      " {{{
824  END
825  call setline(1, lines)
826  3d
827  g/"/d
828  undo
829  redo
830  eval getline(1, '$')->assert_equal([''])
831
832  set fdm&vim
833  bwipe!
834endfunc
835
836" this was crashing
837func Test_move_no_folds()
838  new
839  fold
840  setlocal fdm=expr
841  normal zj
842  bwipe!
843endfunc
844
845" this was crashing
846func Test_fold_create_delete_create()
847  new
848  fold
849  fold
850  normal zd
851  fold
852  bwipe!
853endfunc
854
855" this was crashing
856func Test_fold_create_delete()
857  new
858  norm zFzFzdzj
859  bwipe!
860endfunc
861
862func Test_fold_relative_move()
863  enew!
864  set fdm=indent sw=2 wrap tw=80
865
866  let content = [ '  foo', '  bar', '  baz',
867              \   repeat('x', &columns + 1),
868              \   '  foo', '  bar', '  baz'
869              \ ]
870  call append(0, content)
871
872  normal zM
873
874  call cursor(3, 1)
875  call assert_true(foldclosed(line('.')))
876  normal gj
877  call assert_equal(2, winline())
878
879  call cursor(2, 1)
880  call assert_true(foldclosed(line('.')))
881  normal 2gj
882  call assert_equal(3, winline())
883
884  call cursor(5, 1)
885  call assert_true(foldclosed(line('.')))
886  normal gk
887  call assert_equal(3, winline())
888
889  call cursor(6, 1)
890  call assert_true(foldclosed(line('.')))
891  normal 2gk
892  call assert_equal(2, winline())
893
894  set fdm& sw& wrap& tw&
895endfunc
896
897" Test for using multibyte characters as 'foldopen', 'foldclose' and
898" 'foldsetp' items in 'fillchars'
899func s:mbyte_fillchar_tests(fo, fc, fs)
900  setlocal foldcolumn=3
901
902  normal zE
903  1,2fold
904  call assert_equal([a:fc .. '  +--  2 ', '   three  '],
905        \ ScreenLines([1, 2], 10))
906  1,2foldopen
907  call assert_equal([a:fo .. '  one ', a:fs .. '  two '],
908        \ ScreenLines([1, 2], 7))
909  1,2foldclose
910  redraw!
911  call assert_equal([a:fc .. '  +--  2 ', '   three  '],
912        \  ScreenLines([1, 2], 10))
913
914  " Two level fold
915  normal zE
916  2,3fold
917  1,4fold
918  call assert_equal([a:fc .. '  +--  4 ', '   five   '],
919        \ ScreenLines([1, 2], 10))
920  1,4foldopen
921  call assert_equal([a:fo .. '  one    ', a:fs .. a:fc .. ' +---  2'],
922        \ ScreenLines([1, 2], 10))
923  1,4foldopen
924  call assert_equal([a:fo .. '  one    ', a:fs .. a:fo .. ' two    ',
925        \ a:fs .. a:fs .. ' three  '], ScreenLines([1, 3], 10))
926  2,3foldclose
927  call assert_equal([a:fo .. '  one    ', a:fs .. a:fc .. ' +---  2'],
928        \ ScreenLines([1, 2], 10))
929  1,4foldclose
930  call assert_equal([a:fc .. '  +--  4 ', '   five   '],
931        \ ScreenLines([1, 2], 10))
932
933  " Three level fold
934  normal zE
935  3,4fold
936  2,5fold
937  1,6fold
938  call assert_equal([a:fc .. '  +--  6 '], ScreenLines(1, 10))
939  " open all the folds
940  normal zR
941  call assert_equal([
942        \ a:fo .. '  one    ',
943        \ a:fs .. a:fo .. ' two    ',
944        \ '2' .. a:fo .. ' three  ',
945        \ '23 four   ',
946        \ a:fs .. a:fs .. ' five   ',
947        \ a:fs .. '  six    ',
948        \ ], ScreenLines([1, 6], 10))
949  " close the innermost fold
950  3,4foldclose
951  call assert_equal([
952        \ a:fo .. '  one    ',
953        \ a:fs .. a:fo .. ' two    ',
954        \ a:fs .. a:fs .. a:fc .. '+----  ',
955        \ a:fs .. a:fs .. ' five   ',
956        \ a:fs .. '  six    ',
957        \ ], ScreenLines([1, 5], 10))
958  " close the next fold
959  2,5foldclose
960  call assert_equal([
961        \ a:fo .. '  one    ',
962        \ a:fs .. a:fc .. ' +---  4',
963        \ a:fs .. '  six    ',
964        \ ], ScreenLines([1, 3], 10))
965
966  " set the fold column size to 2
967  setlocal fdc=2
968  normal zR
969  call assert_equal([
970        \ a:fo .. ' one  ',
971        \ a:fo .. ' two  ',
972        \ a:fo .. ' three',
973        \ '3 four ',
974        \ '2 five ',
975        \ a:fs .. ' six  ',
976        \ ], ScreenLines([1, 6], 7))
977
978  " set the fold column size to 1
979  setlocal fdc=1
980  normal zR
981  call assert_equal([
982        \ a:fo .. 'one   ',
983        \ a:fo .. 'two   ',
984        \ a:fo .. 'three ',
985        \ '3four  ',
986        \ '2five  ',
987        \ a:fs .. 'six   ',
988        \ ], ScreenLines([1, 6], 7))
989
990  " Enable number and sign columns and place some signs
991  setlocal fdc=3
992  setlocal number
993  setlocal signcolumn=auto
994  sign define S1 text=->
995  sign place 10 line=3 name=S1
996  call assert_equal([
997        \ a:fo .. '      1 one  ',
998        \ a:fs .. a:fo .. '     2 two  ',
999        \ '2' .. a:fo .. ' ->  3 three',
1000        \ '23     4 four ',
1001        \ a:fs .. a:fs .. '     5 five ',
1002        \ a:fs .. '      6 six  '
1003        \ ], ScreenLines([1, 6], 14))
1004
1005  " Test with 'rightleft'
1006  if has('rightleft')
1007    setlocal rightleft
1008    let lines = ScreenLines([1, 6], winwidth(0))
1009    call assert_equal('o 1      ' .. a:fo,
1010          \  strcharpart(lines[0], strchars(lines[0]) - 10, 10))
1011    call assert_equal('t 2     ' .. a:fo .. a:fs,
1012          \  strcharpart(lines[1], strchars(lines[1]) - 10, 10))
1013    call assert_equal('t 3  >- ' .. a:fo .. '2',
1014          \  strcharpart(lines[2], strchars(lines[2]) - 10, 10))
1015    call assert_equal('f 4     32',
1016          \  strcharpart(lines[3], strchars(lines[3]) - 10, 10))
1017    call assert_equal('f 5     ' .. a:fs .. a:fs,
1018          \  strcharpart(lines[4], strchars(lines[4]) - 10, 10))
1019    call assert_equal('s 6      ' .. a:fs,
1020          \  strcharpart(lines[5], strchars(lines[5]) - 10, 10))
1021    setlocal norightleft
1022  endif
1023
1024  sign unplace *
1025  sign undefine S1
1026  setlocal number& signcolumn&
1027
1028  " Add a test with more than 9 folds (and then delete some folds)
1029  normal zE
1030  for i in range(1, 10)
1031    normal zfGzo
1032  endfor
1033  normal zR
1034  call assert_equal([
1035        \ a:fo .. a:fo .. ' one ',
1036        \ '9> two '
1037        \ ], ScreenLines([1, 2], 7))
1038  normal 1Gzd
1039  call assert_equal([
1040        \ a:fo .. a:fo .. ' one ',
1041        \ '89 two '
1042        \ ], ScreenLines([1, 2], 7))
1043  normal 1Gzdzdzdzdzdzdzd
1044  call assert_equal([
1045        \ a:fo .. a:fo .. ' one ',
1046        \ a:fs .. a:fs .. ' two '
1047        \ ], ScreenLines([1, 2], 7))
1048
1049  setlocal foldcolumn& number& signcolumn&
1050endfunc
1051
1052func Test_foldcolumn_multibyte_char()
1053  new
1054  call setline(1, ['one', 'two', 'three', 'four', 'five', 'six'])
1055  setlocal foldenable foldmethod=manual
1056
1057  " First test with the default setting
1058  call s:mbyte_fillchar_tests('-', '+', '|')
1059
1060  " Use multi-byte characters
1061  set fillchars+=foldopen:▾,foldsep:│,foldclose:▸
1062  call s:mbyte_fillchar_tests('▾', '▸', '│')
1063
1064  " Use a mix of multi-byte and single-byte characters
1065  set fillchars+=foldopen:¬,foldsep:\|,foldclose:+
1066  call s:mbyte_fillchar_tests('¬', '+', '|')
1067  set fillchars+=foldopen:+,foldsep:\|,foldclose:¬
1068  call s:mbyte_fillchar_tests('+', '¬', '|')
1069
1070  bw!
1071  set foldenable& fdc& fdm& fillchars&
1072endfunc
1073
1074" vim: shiftwidth=2 sts=2 expandtab
1075