blob: 7fb004331149bbdbb24e6af30901344030b2f09e [file] [log] [blame]
Bram Moolenaarded27822017-01-02 14:27:34 +01001" Test for folding
2
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02003source check.vim
Bram Moolenaar907dad72018-07-10 15:07:15 +02004source view_util.vim
Bram Moolenaar7701f302018-10-02 21:20:32 +02005source screendump.vim
Bram Moolenaar907dad72018-07-10 15:07:15 +02006
Bram Moolenaar94be6192017-04-22 22:40:11 +02007func PrepIndent(arg)
Bram Moolenaar88d298a2017-03-14 21:53:58 +01008 return [a:arg] + repeat(["\t".a:arg], 5)
9endfu
10
Riley Bruins0a083062024-06-03 20:40:45 +020011func Test_address_fold_new_default_commentstring()
12 " Test with the new commentstring defaults, that includes padding after v9.1.464
13 new
14 call setline(1, ['int FuncName() {/* {{{ */', 1, 2, 3, 4, 5, '}/* }}} */',
15 \ 'after fold 1', 'after fold 2', 'after fold 3'])
16 setl fen fdm=marker
17 " The next commands should all copy the same part of the buffer,
18 " regardless of the addressing type, since the part to be copied
19 " is folded away
20 :1y
21 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
22 :.y
23 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
24 :.+y
25 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
26 :.,.y
27 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
28 :sil .1,.y
29 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
30 " use silent to make E493 go away
31 :sil .+,.y
32 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
33 :,y
34 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
35 :,+y
36 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */','after fold 1'], getreg(0,1,1))
37 " using .+3 as second address should c opy the whole folded line + the next 3
38 " lines
39 :.,+3y
40 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */',
41 \ 'after fold 1', 'after fold 2' , 'after fold 3'], getreg(0,1,1))
42 :sil .,-2y
43 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
44
45 " now test again with folding disabled
46 set nofoldenable
47 :1y
48 call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
49 :.y
50 call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
51 :.+y
52 call assert_equal(['1'], getreg(0,1,1) )
53 :.,.y
54 call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
55 " use silent to make E493 go away
56 :sil .1,.y
57 call assert_equal(['int FuncName() {/* {{{ */', '1'], getreg(0,1,1))
58 " use silent to make E493 go away
59 :sil .+,.y
60 call assert_equal(['int FuncName() {/* {{{ */', '1'], getreg(0,1,1))
61 :,y
62 call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
63 :,+y
64 call assert_equal(['int FuncName() {/* {{{ */', '1'], getreg(0,1,1))
65 " using .+3 as second address should c opy the whole folded line + the next 3
66 " lines
67 :.,+3y
68 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3'], getreg(0,1,1))
69 :7
70 :sil .,-2y
71 call assert_equal(['4', '5', '}/* }}} */'], getreg(0,1,1))
72
73 quit!
74endfunc
75
76func Test_address_fold_old_default_commentstring()
77 " Test with the old commentstring defaults, before v9.1.464
Bram Moolenaarded27822017-01-02 14:27:34 +010078 new
79 call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
80 \ 'after fold 1', 'after fold 2', 'after fold 3'])
81 setl fen fdm=marker
Bram Moolenaar518c9b12017-03-21 11:48:39 +010082 " The next commands should all copy the same part of the buffer,
83 " regardless of the addressing type, since the part to be copied
Bram Moolenaarded27822017-01-02 14:27:34 +010084 " is folded away
85 :1y
86 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
87 :.y
88 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
89 :.+y
90 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
91 :.,.y
92 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
93 :sil .1,.y
94 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
95 " use silent to make E493 go away
96 :sil .+,.y
97 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
98 :,y
99 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
100 :,+y
101 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/','after fold 1'], getreg(0,1,1))
102 " using .+3 as second address should copy the whole folded line + the next 3
103 " lines
104 :.,+3y
105 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/',
106 \ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1))
107 :sil .,-2y
108 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
109
110 " now test again with folding disabled
111 set nofoldenable
112 :1y
113 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
114 :.y
115 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
116 :.+y
117 call assert_equal(['1'], getreg(0,1,1))
118 :.,.y
119 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
120 " use silent to make E493 go away
121 :sil .1,.y
122 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
123 " use silent to make E493 go away
124 :sil .+,.y
125 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
126 :,y
127 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
128 :,+y
129 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
130 " using .+3 as second address should copy the whole folded line + the next 3
131 " lines
132 :.,+3y
133 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1))
134 :7
135 :sil .,-2y
136 call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1))
137
138 quit!
Bram Moolenaar1159b162017-02-28 21:53:56 +0100139endfunc
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100140
Bram Moolenaar9954dc32022-11-11 22:58:36 +0000141func Test_address_offsets()
142 " check the help for :range-closed-fold
143 enew
144 call setline(1, [
145 \ '1 one',
146 \ '2 two',
147 \ '3 three',
148 \ '4 four FOLDED',
149 \ '5 five FOLDED',
150 \ '6 six',
151 \ '7 seven',
152 \ '8 eight',
153 \])
154 set foldmethod=manual
155 normal 4Gvjzf
156 3,4+2yank
157 call assert_equal([
158 \ '3 three',
159 \ '4 four FOLDED',
160 \ '5 five FOLDED',
161 \ '6 six',
162 \ '7 seven',
163 \ ], getreg(0,1,1))
164
165 enew!
166 call setline(1, [
167 \ '1 one',
168 \ '2 two',
169 \ '3 three FOLDED',
170 \ '4 four FOLDED',
171 \ '5 five FOLDED',
172 \ '6 six FOLDED',
173 \ '7 seven',
174 \ '8 eight',
175 \])
176 normal 3Gv3jzf
177 2,4-1yank
178 call assert_equal([
179 \ '2 two',
180 \ '3 three FOLDED',
181 \ '4 four FOLDED',
182 \ '5 five FOLDED',
183 \ '6 six FOLDED',
184 \ ], getreg(0,1,1))
185
186 bwipe!
187endfunc
188
Bram Moolenaar94be6192017-04-22 22:40:11 +0200189func Test_indent_fold()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100190 new
191 call setline(1, ['', 'a', ' b', ' c'])
192 setl fen fdm=indent
193 2
194 norm! >>
195 let a=map(range(1,4), 'foldclosed(v:val)')
196 call assert_equal([-1,-1,-1,-1], a)
197 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +0100198endfunc
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100199
Bram Moolenaar94be6192017-04-22 22:40:11 +0200200func Test_indent_fold2()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100201 new
202 call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
203 setl fen fdm=marker
204 2
205 norm! >>
Bram Moolenaara4208962019-08-24 20:50:19 +0200206 let a=map(range(1,5), 'v:val->foldclosed()')
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100207 call assert_equal([-1,-1,-1,4,4], a)
208 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +0100209endfunc
210
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200211" Test for fold indent with indents greater than 'foldnestmax'
212func Test_indent_fold_max()
213 new
214 setlocal foldmethod=indent
215 setlocal shiftwidth=2
216 " 'foldnestmax' default value is 20
217 call setline(1, "\t\t\t\t\t\ta")
218 call assert_equal(20, foldlevel(1))
219 setlocal foldnestmax=10
220 call assert_equal(10, foldlevel(1))
221 setlocal foldnestmax=-1
222 call assert_equal(0, foldlevel(1))
223 bw!
224endfunc
225
zeertzjq07146ad2022-12-19 15:51:44 +0000226func Test_indent_fold_tabstop()
227 call setline(1, ['0', ' 1', ' 1', "\t2", "\t2"])
228 setlocal shiftwidth=4
229 setlocal foldcolumn=1
230 setlocal foldlevel=2
231 setlocal foldmethod=indent
232 redraw
233 call assert_equal('2 2', ScreenLines(5, 10)[0])
234 vsplit
235 windo diffthis
236 botright new
237 " This 'tabstop' value should not be used for folding in other buffers.
238 setlocal tabstop=4
239 diffoff!
240 redraw
241 call assert_equal('2 2', ScreenLines(5, 10)[0])
242
243 bwipe!
244 bwipe!
245endfunc
246
Bram Moolenaar1159b162017-02-28 21:53:56 +0100247func Test_manual_fold_with_filter()
Bram Moolenaaraeb313f2020-11-27 19:13:28 +0100248 CheckExecutable cat
Bram Moolenaar3f3897e2017-03-04 15:28:53 +0100249 for type in ['manual', 'marker']
250 exe 'set foldmethod=' . type
251 new
252 call setline(1, range(1, 20))
253 4,$fold
254 %foldopen
255 10,$fold
256 %foldopen
257 " This filter command should not have an effect
258 1,8! cat
259 call feedkeys('5ggzdzMGdd', 'xt')
260 call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
261
262 bwipe!
263 set foldmethod&
264 endfor
Bram Moolenaar1159b162017-02-28 21:53:56 +0100265endfunc
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100266
Bram Moolenaar94be6192017-04-22 22:40:11 +0200267func Test_indent_fold_with_read()
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100268 new
269 set foldmethod=indent
270 call setline(1, repeat(["\<Tab>a"], 4))
271 for n in range(1, 4)
272 call assert_equal(1, foldlevel(n))
273 endfor
274
Bram Moolenaar70e67252022-09-27 19:34:35 +0100275 call writefile(["a", "", "\<Tab>a"], 'Xinfofile', 'D')
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100276 foldopen
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100277 2read Xinfofile
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100278 %foldclose
279 call assert_equal(1, foldlevel(1))
280 call assert_equal(2, foldclosedend(1))
281 call assert_equal(0, foldlevel(3))
282 call assert_equal(0, foldlevel(4))
283 call assert_equal(1, foldlevel(5))
Bram Moolenaara4208962019-08-24 20:50:19 +0200284 call assert_equal(7, 5->foldclosedend())
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100285
286 bwipe!
287 set foldmethod&
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100288endfunc
289
290func Test_combining_folds_indent()
291 new
292 let one = "\<Tab>a"
293 let zero = 'a'
294 call setline(1, [one, one, zero, zero, zero, one, one, one])
295 set foldmethod=indent
296 3,5d
297 %foldclose
298 call assert_equal(5, foldclosedend(1))
299
300 set foldmethod&
301 bwipe!
302endfunc
303
304func Test_combining_folds_marker()
305 new
306 call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
307 set foldmethod=marker
308 3,5d
309 %foldclose
310 call assert_equal(2, foldclosedend(1))
311
312 set foldmethod&
313 bwipe!
314endfunc
315
Bram Moolenaar025a6b72017-03-12 20:37:21 +0100316func Test_folds_marker_in_comment()
317 new
318 call setline(1, ['" foo', 'bar', 'baz'])
319 setl fen fdm=marker
320 setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
321 norm! zf2j
322 setl nofen
323 :1y
324 call assert_equal(['" foo{{{'], getreg(0,1,1))
325 :+2y
326 call assert_equal(['baz"}}}'], getreg(0,1,1))
327
328 set foldmethod&
329 bwipe!
330endfunc
331
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100332func s:TestFoldExpr(lnum)
333 let thisline = getline(a:lnum)
334 if thisline == 'a'
335 return 1
336 elseif thisline == 'b'
337 return 0
338 elseif thisline == 'c'
339 return '<1'
340 elseif thisline == 'd'
341 return '>1'
342 endif
343 return 0
344endfunction
345
346func Test_update_folds_expr_read()
347 new
348 call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
349 set foldmethod=expr
350 set foldexpr=s:TestFoldExpr(v:lnum)
351 2
352 foldopen
Bram Moolenaar70e67252022-09-27 19:34:35 +0100353 call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xupfofile', 'D')
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100354 read Xupfofile
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100355 %foldclose
356 call assert_equal(2, foldclosedend(1))
357 call assert_equal(0, foldlevel(3))
Bram Moolenaara4208962019-08-24 20:50:19 +0200358 call assert_equal(0, 4->foldlevel())
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100359 call assert_equal(6, foldclosedend(5))
360 call assert_equal(10, foldclosedend(7))
361 call assert_equal(14, foldclosedend(11))
362
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100363 bwipe!
364 set foldmethod& foldexpr&
365endfunc
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100366
zeertzjq93c15732022-05-21 16:34:38 +0100367" Test for what patch 8.1.0535 fixes.
368func Test_foldexpr_no_interrupt_addsub()
369 new
370 func! FoldFunc()
371 call setpos('.', getcurpos())
372 return '='
373 endfunc
374
375 set foldmethod=expr
376 set foldexpr=FoldFunc()
377 call setline(1, '1.2')
378
379 exe "norm! $\<C-A>"
380 call assert_equal('1.3', getline(1))
381
382 bwipe!
383 delfunc FoldFunc
384 set foldmethod& foldexpr&
385endfunc
386
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +0100387" Fold function defined in another script
388func Test_foldexpr_compiled()
389 new
390 let lines =<< trim END
391 vim9script
392 def FoldFunc(): number
393 return v:lnum
394 enddef
395
396 set foldmethod=expr
397 set foldexpr=s:FoldFunc()
398 END
399 call writefile(lines, 'XfoldExpr', 'D')
400 source XfoldExpr
401
402 call setline(1, ['one', 'two', 'three'])
403 redraw
404 call assert_equal(1, foldlevel(1))
405 call assert_equal(2, foldlevel(2))
406 call assert_equal(3, foldlevel(3))
407
408 bwipe!
409 set foldmethod& foldexpr&
410endfunc
411
Bram Moolenaar94be6192017-04-22 22:40:11 +0200412func Check_foldlevels(expected)
413 call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)'))
414endfunc
415
416func Test_move_folds_around_manual()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100417 new
418 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
419 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
420 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
421 " all folds closed
422 set foldenable foldlevel=0 fdm=indent
423 " needs a forced redraw
424 redraw!
425 set fdm=manual
426 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
427 call assert_equal(input, getline(1, '$'))
428 7,12m0
429 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
430 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
431 10,12m0
432 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
433 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)'))
434 " moving should not close the folds
435 %d
436 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
437 set fdm=indent
438 redraw!
439 set fdm=manual
440 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100441 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100442 7,12m0
443 let folds=repeat([-1], 18)
444 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
445 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
446 norm! zM
447 " folds are not corrupted and all have been closed
448 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)'))
449 %d
450 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
451 set fdm=indent
452 redraw!
453 set fdm=manual
454 %foldopen
455 3m4
456 %foldclose
457 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
458 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
459 %d
460 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
461 set fdm=indent foldlevel=0
462 set fdm=manual
463 %foldopen
464 3m1
465 %foldclose
466 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
467 call assert_equal(0, foldlevel(2))
468 call assert_equal(5, foldclosedend(3))
469 call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
470 2,6m$
471 %foldclose
472 call assert_equal(5, foldclosedend(2))
473 call assert_equal(0, foldlevel(6))
474 call assert_equal(9, foldclosedend(7))
475 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
Bram Moolenaar495b7dd2017-09-16 17:19:22 +0200476
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100477 %d
478 " Ensure moving around the edges still works.
479 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
480 set fdm=indent foldlevel=0
481 set fdm=manual
482 %foldopen
483 6m$
484 " The first fold has been truncated to the 5'th line.
485 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200486 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])
487
488 %delete
489 set fdm=indent foldlevel=0
490 call setline(1, [
491 \ "a",
492 \ "\ta",
493 \ "\t\ta",
494 \ "\t\ta",
495 \ "\t\ta",
496 \ "a",
497 \ "a"])
498 set fdm=manual
499 %foldopen!
500 4,5m6
501 call Check_foldlevels([0, 1, 2, 0, 0, 0, 0])
502
503 %delete
504 set fdm=indent
505 call setline(1, [
506 \ "\ta",
507 \ "\t\ta",
508 \ "\t\ta",
509 \ "\t\ta",
510 \ "\ta",
511 \ "\t\ta",
512 \ "\t\ta",
513 \ "\t\ta",
514 \ "\ta",
515 \ "\t\ta",
516 \ "\t\ta",
517 \ "\t\ta",
518 \ "\t\ta",
519 \ "\ta",
520 \ "a"])
521 set fdm=manual
522 %foldopen!
523 13m7
524 call Check_foldlevels([1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0])
Bram Moolenaar94722c52023-01-28 19:19:03 +0000525
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100526 bw!
527endfunc
528
Bram Moolenaar94be6192017-04-22 22:40:11 +0200529func Test_move_folds_around_indent()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100530 new
531 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
532 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
533 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
534 " all folds closed
535 set fdm=indent
536 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
537 call assert_equal(input, getline(1, '$'))
538 7,12m0
539 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
540 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
541 10,12m0
542 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
543 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)'))
544 " moving should not close the folds
545 %d
546 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
547 set fdm=indent
548 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100549 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100550 7,12m0
551 let folds=repeat([-1], 18)
552 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
553 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
554 norm! zM
555 " folds are not corrupted and all have been closed
556 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)'))
557 %d
558 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
559 set fdm=indent
560 %foldopen
561 3m4
562 %foldclose
563 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
564 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
565 %d
566 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
567 set fdm=indent foldlevel=0
568 %foldopen
569 3m1
570 %foldclose
571 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
572 call assert_equal(1, foldlevel(2))
573 call assert_equal(5, foldclosedend(3))
574 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
575 2,6m$
576 %foldclose
577 call assert_equal(9, foldclosedend(2))
578 call assert_equal(1, foldlevel(6))
579 call assert_equal(9, foldclosedend(7))
580 call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100581 " Ensure moving around the edges still works.
582 %d
583 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
584 set fdm=indent foldlevel=0
585 %foldopen
586 6m$
587 " The first fold has been truncated to the 5'th line.
588 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200589 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100590 bw!
591endfunc
Bram Moolenaar518c9b12017-03-21 11:48:39 +0100592
593func Test_folddoopen_folddoclosed()
594 new
595 call setline(1, range(1, 9))
596 set foldmethod=manual
597 1,3 fold
598 6,8 fold
599
600 " Test without range.
601 folddoopen s/$/o/
602 folddoclosed s/$/c/
603 call assert_equal(['1c', '2c', '3c',
604 \ '4o', '5o',
605 \ '6c', '7c', '8c',
606 \ '9o'], getline(1, '$'))
607
608 " Test with range.
609 call setline(1, range(1, 9))
610 1,8 folddoopen s/$/o/
611 4,$ folddoclosed s/$/c/
612 call assert_equal(['1', '2', '3',
613 \ '4o', '5o',
614 \ '6c', '7c', '8c',
615 \ '9'], getline(1, '$'))
616
617 set foldmethod&
618 bw!
619endfunc
620
621func Test_fold_error()
622 new
623 call setline(1, [1, 2])
624
625 for fm in ['indent', 'expr', 'syntax', 'diff']
626 exe 'set foldmethod=' . fm
627 call assert_fails('norm zf', 'E350:')
628 call assert_fails('norm zd', 'E351:')
629 call assert_fails('norm zE', 'E352:')
630 endfor
631
632 set foldmethod=manual
633 call assert_fails('norm zd', 'E490:')
634 call assert_fails('norm zo', 'E490:')
635 call assert_fails('3fold', 'E16:')
636
637 set foldmethod=marker
638 set nomodifiable
639 call assert_fails('1,2fold', 'E21:')
640
641 set modifiable&
642 set foldmethod&
643 bw!
644endfunc
Bram Moolenaar495b7dd2017-09-16 17:19:22 +0200645
646func Test_foldtext_recursive()
647 new
648 call setline(1, ['{{{', 'some text', '}}}'])
649 setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
650 " This was crashing because of endless recursion.
651 2foldclose
652 redraw
653 call assert_equal(1, foldlevel(2))
654 call assert_equal(1, foldclosed(2))
655 call assert_equal(3, foldclosedend(2))
656 bwipe!
657endfunc
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100658
659" Various fold related tests
660
661" Basic test if a fold can be created, opened, moving to the end and closed
662func Test_fold_manual()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200663 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100664 set fdm=manual
665
666 let content = ['1 aa', '2 bb', '3 cc']
667 call append(0, content)
668 call cursor(1, 1)
669 normal zf2j
670 call assert_equal('1 aa', getline(foldclosed('.')))
671 normal zo
672 call assert_equal(-1, foldclosed('.'))
673 normal ]z
674 call assert_equal('3 cc', getline('.'))
675 normal zc
676 call assert_equal('1 aa', getline(foldclosed('.')))
677
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200678 " Create a fold inside a closed fold after setting 'foldlevel'
679 %d _
680 call setline(1, range(1, 5))
681 1,5fold
682 normal zR
683 2,4fold
684 set foldlevel=1
685 3fold
686 call assert_equal([1, 3, 3, 3, 1], map(range(1, 5), {->foldlevel(v:val)}))
687 set foldlevel&
688
689 " Create overlapping folds (at the start and at the end)
690 normal zE
691 2,3fold
692 normal zR
693 3,4fold
694 call assert_equal([0, 2, 2, 1, 0], map(range(1, 5), {->foldlevel(v:val)}))
695 normal zE
696 3,4fold
697 normal zR
698 2,3fold
699 call assert_equal([0, 1, 2, 2, 0], map(range(1, 5), {->foldlevel(v:val)}))
700
701 " Create a nested fold across two non-adjoining folds
702 %d _
703 call setline(1, range(1, 7))
704 1,2fold
705 normal zR
706 4,5fold
707 normal zR
708 6,7fold
709 normal zR
710 1,5fold
711 call assert_equal([2, 2, 1, 2, 2, 1, 1],
712 \ map(range(1, 7), {->foldlevel(v:val)}))
713
714 " A newly created nested fold should be closed
715 %d _
716 call setline(1, range(1, 6))
717 1,6fold
718 normal zR
719 3,4fold
720 normal zR
721 2,5fold
722 call assert_equal([1, 2, 3, 3, 2, 1], map(range(1, 6), {->foldlevel(v:val)}))
723 call assert_equal(2, foldclosed(4))
724 call assert_equal(5, foldclosedend(4))
725
726 " Test zO, zC and zA on a line with no folds.
727 normal zE
728 call assert_fails('normal zO', 'E490:')
729 call assert_fails('normal zC', 'E490:')
730 call assert_fails('normal zA', 'E490:')
731
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100732 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200733 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100734endfunc
735
736" test folding with markers.
737func Test_fold_marker()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200738 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100739 set fdm=marker fdl=1 fdc=3
740
741 let content = ['4 dd {{{', '5 ee {{{ }}}', '6 ff }}}']
742 call append(0, content)
743 call cursor(2, 1)
744 call assert_equal(2, foldlevel('.'))
745 normal [z
746 call assert_equal(1, foldlevel('.'))
747 exe "normal jo{{ \<Esc>r{jj"
748 call assert_equal(1, foldlevel('.'))
749 normal kYpj
750 call assert_equal(0, foldlevel('.'))
751
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200752 " Use only closing fold marker (without and with a count)
753 set fdl&
754 %d _
755 call setline(1, ['one }}}', 'two'])
756 call assert_equal([0, 0], [foldlevel(1), foldlevel(2)])
757 %d _
758 call setline(1, ['one }}}4', 'two'])
759 call assert_equal([4, 3], [foldlevel(1), foldlevel(2)])
760
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100761 set fdm& fdl& fdc&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200762 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100763endfunc
764
Bram Moolenaar4af72592018-12-09 15:00:52 +0100765" test create fold markers with C filetype
766func Test_fold_create_marker_in_C()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200767 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100768 set fdm=marker fdl=9
769 set filetype=c
770
Bram Moolenaarc79745a2019-05-20 22:12:34 +0200771 let content =<< trim [CODE]
772 /*
773 * comment
Bram Moolenaar94722c52023-01-28 19:19:03 +0000774 *
Bram Moolenaarc79745a2019-05-20 22:12:34 +0200775 *
776 */
777 int f(int* p) {
778 *p = 3;
779 return 0;
780 }
781 [CODE]
782
Bram Moolenaar4af72592018-12-09 15:00:52 +0100783 for c in range(len(content) - 1)
784 bw!
785 call append(0, content)
786 call cursor(c + 1, 1)
787 norm! zfG
Riley Bruins0a083062024-06-03 20:40:45 +0200788 call assert_equal(content[c] . (c < 4 ? '{{{' : '/* {{{ */'), getline(c + 1))
Bram Moolenaar4af72592018-12-09 15:00:52 +0100789 endfor
790
791 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200792 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100793endfunc
794
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100795" test folding with indent
796func Test_fold_indent()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200797 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100798 set fdm=indent sw=2
799
800 let content = ['1 aa', '2 bb', '3 cc']
801 call append(0, content)
802 call cursor(2, 1)
803 exe "normal i \<Esc>jI "
804 call assert_equal(2, foldlevel('.'))
805 normal k
806 call assert_equal(1, foldlevel('.'))
807
808 set fdm& sw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200809 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100810endfunc
811
812" test syntax folding
813func Test_fold_syntax()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200814 CheckFeature syntax
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100815
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200816 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100817 set fdm=syntax fdl=0
818
819 syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3
820 syn region Fd1 start="ee" end="ff" fold contained
821 syn region Fd2 start="gg" end="hh" fold contained
822 syn region Fd3 start="commentstart" end="commentend" fold contained
823 let content = ['3 cc', '4 dd {{{', '5 ee {{{ }}}', '{{{{', '6 ff }}}',
824 \ '6 ff }}}', '7 gg', '8 hh', '9 ii']
825 call append(0, content)
826 normal Gzk
827 call assert_equal('9 ii', getline('.'))
828 normal k
829 call assert_equal('3 cc', getline('.'))
830 exe "normal jAcommentstart \<Esc>Acommentend"
831 set fdl=1
832 normal 3j
833 call assert_equal('7 gg', getline('.'))
834 set fdl=0
835 exe "normal zO\<C-L>j"
836 call assert_equal('8 hh', getline('.'))
837 syn clear Fd1 Fd2 Fd3 Hup
838
839 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200840 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100841endfunc
842
843func Flvl()
844 let l = getline(v:lnum)
845 if l =~ "bb$"
846 return 2
847 elseif l =~ "gg$"
848 return "s1"
849 elseif l =~ "ii$"
850 return ">2"
851 elseif l =~ "kk$"
852 return "0"
853 endif
854 return "="
855endfun
856
857" test expression folding
858func Test_fold_expr()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200859 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100860 set fdm=expr fde=Flvl()
861
862 let content = ['1 aa',
863 \ '2 bb',
864 \ '3 cc',
865 \ '4 dd {{{commentstart commentend',
866 \ '5 ee {{{ }}}',
867 \ '{{{',
868 \ '6 ff }}}',
869 \ '6 ff }}}',
870 \ ' 7 gg',
871 \ ' 8 hh',
872 \ '9 ii',
873 \ 'a jj',
874 \ 'b kk']
875 call append(0, content)
876 call cursor(1, 1)
877 exe "normal /bb$\<CR>"
878 call assert_equal(2, foldlevel('.'))
879 exe "normal /hh$\<CR>"
880 call assert_equal(1, foldlevel('.'))
881 exe "normal /ii$\<CR>"
882 call assert_equal(2, foldlevel('.'))
883 exe "normal /kk$\<CR>"
884 call assert_equal(0, foldlevel('.'))
885
886 set fdm& fde&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200887 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100888endfunc
889
890" Bug with fdm=indent and moving folds
891" Moving a fold a few times, messes up the folds below the moved fold.
892" Fixed by 7.4.700
893func Test_fold_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200894 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100895 set fdm=indent sw=2 fdl=0
896
897 let content = ['', '', 'Line1', ' Line2', ' Line3',
898 \ 'Line4', ' Line5', ' Line6',
899 \ 'Line7', ' Line8', ' Line9']
900 call append(0, content)
901 normal zM
902 call cursor(4, 1)
903 move 2
904 move 1
905 call assert_equal(7, foldclosed(7))
906 call assert_equal(8, foldclosedend(7))
907 call assert_equal(0, foldlevel(9))
908 call assert_equal(10, foldclosed(10))
909 call assert_equal(11, foldclosedend(10))
910 call assert_equal('+-- 2 lines: Line2', foldtextresult(2))
Bram Moolenaara4208962019-08-24 20:50:19 +0200911 call assert_equal('+-- 2 lines: Line8', 10->foldtextresult())
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100912
913 set fdm& sw& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200914 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100915endfunc
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100916
917" test for patch 7.3.637
918" Cannot catch the error caused by a foldopen when there is no fold.
919func Test_foldopen_exception()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200920 new
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100921 let a = 'No error caught'
922 try
923 foldopen
924 catch
925 let a = matchstr(v:exception,'^[^ ]*')
926 endtry
927 call assert_equal('Vim(foldopen):E490:', a)
928
929 let a = 'No error caught'
930 try
931 foobar
932 catch
933 let a = matchstr(v:exception,'^[^ ]*')
934 endtry
935 call assert_match('E492:', a)
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200936 bw!
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100937endfunc
Bram Moolenaar907dad72018-07-10 15:07:15 +0200938
939func Test_fold_last_line_with_pagedown()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200940 new
Bram Moolenaar907dad72018-07-10 15:07:15 +0200941 set fdm=manual
942
943 let expect = '+-- 11 lines: 9---'
944 let content = range(1,19)
945 call append(0, content)
946 normal dd9G
947 normal zfG
948 normal zt
949 call assert_equal('9', getline(foldclosed('.')))
950 call assert_equal('19', getline(foldclosedend('.')))
951 call assert_equal(expect, ScreenLines(1, len(expect))[0])
952 call feedkeys("\<C-F>", 'xt')
953 call assert_equal(expect, ScreenLines(1, len(expect))[0])
954 call feedkeys("\<C-F>", 'xt')
955 call assert_equal(expect, ScreenLines(1, len(expect))[0])
956 call feedkeys("\<C-B>\<C-F>\<C-F>", 'xt')
957 call assert_equal(expect, ScreenLines(1, len(expect))[0])
958
959 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200960 bw!
Bram Moolenaar907dad72018-07-10 15:07:15 +0200961endfunc
Bram Moolenaar7701f302018-10-02 21:20:32 +0200962
963func Test_folds_with_rnu()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200964 CheckScreendump
Bram Moolenaar7701f302018-10-02 21:20:32 +0200965
966 call writefile([
967 \ 'set fdm=marker rnu foldcolumn=2',
968 \ 'call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])',
Bram Moolenaar70e67252022-09-27 19:34:35 +0100969 \ ], 'Xtest_folds_with_rnu', 'D')
Bram Moolenaar7701f302018-10-02 21:20:32 +0200970 let buf = RunVimInTerminal('-S Xtest_folds_with_rnu', {})
971
972 call VerifyScreenDump(buf, 'Test_folds_with_rnu_01', {})
973 call term_sendkeys(buf, "j")
974 call VerifyScreenDump(buf, 'Test_folds_with_rnu_02', {})
975
976 " clean up
977 call StopVimInTerminal(buf)
Bram Moolenaar7701f302018-10-02 21:20:32 +0200978endfunc
Bram Moolenaar53932812018-12-07 21:08:49 +0100979
980func Test_folds_marker_in_comment2()
981 new
982 call setline(1, ['Lorem ipsum dolor sit', 'Lorem ipsum dolor sit', 'Lorem ipsum dolor sit'])
983 setl fen fdm=marker
984 setl commentstring=<!--%s-->
985 setl comments=s:<!--,m:\ \ \ \ ,e:-->
986 norm! zf2j
987 setl nofen
988 :1y
989 call assert_equal(['Lorem ipsum dolor sit<!--{{{-->'], getreg(0,1,1))
990 :+2y
991 call assert_equal(['Lorem ipsum dolor sit<!--}}}-->'], getreg(0,1,1))
992
993 set foldmethod&
994 bwipe!
995endfunc
Bram Moolenaar9a4a8c42019-08-19 22:48:30 +0200996
997func Test_fold_delete_with_marker()
998 new
999 call setline(1, ['func Func() {{{1', 'endfunc'])
1000 1,2yank
1001 new
1002 set fdm=marker
1003 call setline(1, 'x')
1004 normal! Vp
1005 normal! zd
1006 call assert_equal(['func Func() ', 'endfunc'], getline(1, '$'))
1007
1008 set fdm&
1009 bwipe!
1010 bwipe!
1011endfunc
Bram Moolenaar7a9bd7c2019-09-17 22:42:55 +02001012
1013func Test_fold_delete_with_marker_and_whichwrap()
1014 new
1015 let content1 = ['']
1016 let content2 = ['folded line 1 "{{{1', ' test', ' test2', ' test3', '', 'folded line 2 "{{{1', ' test', ' test2', ' test3']
1017 call setline(1, content1 + content2)
1018 set fdm=marker ww+=l
1019 normal! x
1020 call assert_equal(content2, getline(1, '$'))
1021 set fdm& ww&
1022 bwipe!
1023endfunc
Bram Moolenaar3b681232019-12-13 19:35:55 +01001024
1025func Test_fold_delete_first_line()
1026 new
1027 call setline(1, [
1028 \ '" x {{{1',
1029 \ '" a',
1030 \ '" aa',
1031 \ '" x {{{1',
1032 \ '" b',
1033 \ '" bb',
1034 \ '" x {{{1',
1035 \ '" c',
1036 \ '" cc',
1037 \ ])
1038 set foldmethod=marker
1039 1
1040 normal dj
1041 call assert_equal([
1042 \ '" x {{{1',
1043 \ '" c',
1044 \ '" cc',
1045 \ ], getline(1,'$'))
1046 bwipe!
1047 set foldmethod&
1048endfunc
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001049
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001050" Add a test for deleting the outer fold of a nested fold and promoting the
1051" inner folds to one level up with already a fold at that level following the
1052" nested fold.
1053func Test_fold_delete_recursive_fold()
1054 new
1055 call setline(1, range(1, 7))
1056 2,3fold
1057 normal zR
1058 4,5fold
1059 normal zR
1060 1,5fold
1061 normal zR
1062 6,7fold
1063 normal zR
1064 normal 1Gzd
1065 normal 1Gzj
1066 call assert_equal(2, line('.'))
1067 normal zj
1068 call assert_equal(4, line('.'))
1069 normal zj
1070 call assert_equal(6, line('.'))
1071 bw!
1072endfunc
1073
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001074" Test for errors in 'foldexpr'
1075func Test_fold_expr_error()
1076 new
1077 call setline(1, ['one', 'two', 'three'])
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001078 " In a window with no folds, foldlevel() should return 0
1079 call assert_equal(0, foldlevel(1))
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001080
1081 " Return a list from the expression
1082 set foldexpr=[]
1083 set foldmethod=expr
1084 for i in range(3)
1085 call assert_equal(0, foldlevel(i))
1086 endfor
1087
1088 " expression error
1089 set foldexpr=[{]
1090 set foldmethod=expr
1091 for i in range(3)
1092 call assert_equal(0, foldlevel(i))
1093 endfor
1094
1095 set foldmethod& foldexpr&
1096 close!
1097endfunc
1098
Bram Moolenaarda697642020-09-17 19:36:04 +02001099func Test_undo_fold_deletion()
1100 new
1101 set fdm=marker
1102 let lines =<< trim END
1103 " {{{
1104 " }}}1
1105 " {{{
1106 END
1107 call setline(1, lines)
1108 3d
1109 g/"/d
1110 undo
1111 redo
1112 eval getline(1, '$')->assert_equal([''])
1113
1114 set fdm&vim
1115 bwipe!
1116endfunc
1117
Bram Moolenaarc136a352020-11-03 20:05:40 +01001118" this was crashing
1119func Test_move_no_folds()
1120 new
1121 fold
1122 setlocal fdm=expr
1123 normal zj
1124 bwipe!
1125endfunc
1126
Bram Moolenaar5e1f22f2020-11-10 18:23:52 +01001127" this was crashing
1128func Test_fold_create_delete_create()
1129 new
1130 fold
1131 fold
1132 normal zd
1133 fold
1134 bwipe!
1135endfunc
1136
Bram Moolenaar6a78f322020-12-21 14:01:41 +01001137" this was crashing
1138func Test_fold_create_delete()
1139 new
1140 norm zFzFzdzj
1141 bwipe!
1142endfunc
1143
Bram Moolenaare71996b2021-01-21 17:03:07 +01001144func Test_fold_relative_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001145 new
Bram Moolenaare71996b2021-01-21 17:03:07 +01001146 set fdm=indent sw=2 wrap tw=80
1147
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001148 let longtext = repeat('x', &columns + 1)
1149 let content = [ ' foo', ' ' .. longtext, ' baz',
1150 \ longtext,
1151 \ ' foo', ' ' .. longtext, ' baz'
Bram Moolenaare71996b2021-01-21 17:03:07 +01001152 \ ]
1153 call append(0, content)
1154
1155 normal zM
1156
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001157 for lnum in range(1, 3)
1158 call cursor(lnum, 1)
1159 call assert_true(foldclosed(line('.')))
1160 normal gj
1161 call assert_equal(2, winline())
1162 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001163
1164 call cursor(2, 1)
1165 call assert_true(foldclosed(line('.')))
1166 normal 2gj
1167 call assert_equal(3, winline())
1168
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001169 for lnum in range(5, 7)
1170 call cursor(lnum, 1)
1171 call assert_true(foldclosed(line('.')))
1172 normal gk
1173 call assert_equal(3, winline())
1174 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001175
1176 call cursor(6, 1)
1177 call assert_true(foldclosed(line('.')))
1178 normal 2gk
1179 call assert_equal(2, winline())
1180
1181 set fdm& sw& wrap& tw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001182 bw!
Bram Moolenaare71996b2021-01-21 17:03:07 +01001183endfunc
1184
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001185" Test for using multibyte characters as 'foldopen', 'foldclose' and
1186" 'foldsetp' items in 'fillchars'
1187func s:mbyte_fillchar_tests(fo, fc, fs)
1188 setlocal foldcolumn=3
1189
1190 normal zE
1191 1,2fold
1192 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1193 \ ScreenLines([1, 2], 10))
1194 1,2foldopen
1195 call assert_equal([a:fo .. ' one ', a:fs .. ' two '],
1196 \ ScreenLines([1, 2], 7))
1197 1,2foldclose
1198 redraw!
1199 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1200 \ ScreenLines([1, 2], 10))
1201
1202 " Two level fold
1203 normal zE
1204 2,3fold
1205 1,4fold
1206 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1207 \ ScreenLines([1, 2], 10))
1208 1,4foldopen
1209 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1210 \ ScreenLines([1, 2], 10))
1211 1,4foldopen
1212 call assert_equal([a:fo .. ' one ', a:fs .. a:fo .. ' two ',
1213 \ a:fs .. a:fs .. ' three '], ScreenLines([1, 3], 10))
1214 2,3foldclose
1215 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1216 \ ScreenLines([1, 2], 10))
1217 1,4foldclose
1218 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1219 \ ScreenLines([1, 2], 10))
1220
1221 " Three level fold
1222 normal zE
1223 3,4fold
1224 2,5fold
1225 1,6fold
1226 call assert_equal([a:fc .. ' +-- 6 '], ScreenLines(1, 10))
1227 " open all the folds
1228 normal zR
1229 call assert_equal([
1230 \ a:fo .. ' one ',
1231 \ a:fs .. a:fo .. ' two ',
1232 \ '2' .. a:fo .. ' three ',
1233 \ '23 four ',
1234 \ a:fs .. a:fs .. ' five ',
1235 \ a:fs .. ' six ',
1236 \ ], ScreenLines([1, 6], 10))
1237 " close the innermost fold
1238 3,4foldclose
1239 call assert_equal([
1240 \ a:fo .. ' one ',
1241 \ a:fs .. a:fo .. ' two ',
1242 \ a:fs .. a:fs .. a:fc .. '+---- ',
1243 \ a:fs .. a:fs .. ' five ',
1244 \ a:fs .. ' six ',
1245 \ ], ScreenLines([1, 5], 10))
1246 " close the next fold
1247 2,5foldclose
1248 call assert_equal([
1249 \ a:fo .. ' one ',
1250 \ a:fs .. a:fc .. ' +--- 4',
1251 \ a:fs .. ' six ',
1252 \ ], ScreenLines([1, 3], 10))
1253
1254 " set the fold column size to 2
1255 setlocal fdc=2
1256 normal zR
1257 call assert_equal([
1258 \ a:fo .. ' one ',
1259 \ a:fo .. ' two ',
1260 \ a:fo .. ' three',
1261 \ '3 four ',
1262 \ '2 five ',
1263 \ a:fs .. ' six ',
1264 \ ], ScreenLines([1, 6], 7))
1265
1266 " set the fold column size to 1
1267 setlocal fdc=1
1268 normal zR
1269 call assert_equal([
1270 \ a:fo .. 'one ',
1271 \ a:fo .. 'two ',
1272 \ a:fo .. 'three ',
1273 \ '3four ',
1274 \ '2five ',
1275 \ a:fs .. 'six ',
1276 \ ], ScreenLines([1, 6], 7))
1277
Bram Moolenaar008bff92021-03-04 21:55:58 +01001278 " Enable number and sign columns and place some signs
1279 setlocal fdc=3
1280 setlocal number
1281 setlocal signcolumn=auto
1282 sign define S1 text=->
1283 sign place 10 line=3 name=S1
1284 call assert_equal([
1285 \ a:fo .. ' 1 one ',
1286 \ a:fs .. a:fo .. ' 2 two ',
1287 \ '2' .. a:fo .. ' -> 3 three',
1288 \ '23 4 four ',
1289 \ a:fs .. a:fs .. ' 5 five ',
1290 \ a:fs .. ' 6 six '
1291 \ ], ScreenLines([1, 6], 14))
1292
1293 " Test with 'rightleft'
1294 if has('rightleft')
1295 setlocal rightleft
1296 let lines = ScreenLines([1, 6], winwidth(0))
1297 call assert_equal('o 1 ' .. a:fo,
1298 \ strcharpart(lines[0], strchars(lines[0]) - 10, 10))
1299 call assert_equal('t 2 ' .. a:fo .. a:fs,
1300 \ strcharpart(lines[1], strchars(lines[1]) - 10, 10))
1301 call assert_equal('t 3 >- ' .. a:fo .. '2',
1302 \ strcharpart(lines[2], strchars(lines[2]) - 10, 10))
1303 call assert_equal('f 4 32',
1304 \ strcharpart(lines[3], strchars(lines[3]) - 10, 10))
1305 call assert_equal('f 5 ' .. a:fs .. a:fs,
1306 \ strcharpart(lines[4], strchars(lines[4]) - 10, 10))
1307 call assert_equal('s 6 ' .. a:fs,
1308 \ strcharpart(lines[5], strchars(lines[5]) - 10, 10))
1309 setlocal norightleft
1310 endif
1311
1312 sign unplace *
1313 sign undefine S1
1314 setlocal number& signcolumn&
1315
1316 " Add a test with more than 9 folds (and then delete some folds)
1317 normal zE
1318 for i in range(1, 10)
1319 normal zfGzo
1320 endfor
1321 normal zR
1322 call assert_equal([
1323 \ a:fo .. a:fo .. ' one ',
1324 \ '9> two '
1325 \ ], ScreenLines([1, 2], 7))
1326 normal 1Gzd
1327 call assert_equal([
1328 \ a:fo .. a:fo .. ' one ',
1329 \ '89 two '
1330 \ ], ScreenLines([1, 2], 7))
1331 normal 1Gzdzdzdzdzdzdzd
1332 call assert_equal([
1333 \ a:fo .. a:fo .. ' one ',
1334 \ a:fs .. a:fs .. ' two '
1335 \ ], ScreenLines([1, 2], 7))
1336
1337 setlocal foldcolumn& number& signcolumn&
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001338endfunc
1339
1340func Test_foldcolumn_multibyte_char()
1341 new
1342 call setline(1, ['one', 'two', 'three', 'four', 'five', 'six'])
1343 setlocal foldenable foldmethod=manual
1344
1345 " First test with the default setting
1346 call s:mbyte_fillchar_tests('-', '+', '|')
1347
1348 " Use multi-byte characters
1349 set fillchars+=foldopen:▾,foldsep:│,foldclose:▸
1350 call s:mbyte_fillchar_tests('▾', '▸', '│')
1351
Bram Moolenaar196a1f72021-03-21 14:39:19 +01001352 " Use a mix of multi-byte and single-byte characters
1353 set fillchars+=foldopen:¬,foldsep:\|,foldclose:+
1354 call s:mbyte_fillchar_tests('¬', '+', '|')
1355 set fillchars+=foldopen:+,foldsep:\|,foldclose:¬
1356 call s:mbyte_fillchar_tests('+', '¬', '|')
1357
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001358 bw!
1359 set foldenable& fdc& fdm& fillchars&
1360endfunc
1361
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001362" Test for calling foldlevel() from a fold expression
1363let g:FoldLevels = []
1364func FoldExpr1(lnum)
1365 let f = [a:lnum]
1366 for i in range(1, line('$'))
1367 call add(f, foldlevel(i))
1368 endfor
1369 call add(g:FoldLevels, f)
1370 return getline(a:lnum)[0] == "\t"
1371endfunc
1372
1373func Test_foldexpr_foldlevel()
1374 new
1375 call setline(1, ['one', "\ttwo", "\tthree"])
1376 setlocal foldmethod=expr
1377 setlocal foldexpr=FoldExpr1(v:lnum)
1378 setlocal foldenable
1379 setlocal foldcolumn=3
1380 redraw!
1381 call assert_equal([[1, -1, -1, -1], [2, -1, -1, -1], [3, 0, 1, -1]],
1382 \ g:FoldLevels)
1383 set foldmethod& foldexpr& foldenable& foldcolumn&
1384 bw!
1385endfunc
1386
1387" Test for returning different values from a fold expression
1388func FoldExpr2(lnum)
1389 if a:lnum == 1 || a:lnum == 4
1390 return -2
1391 elseif a:lnum == 2
1392 return 'a1'
1393 elseif a:lnum == 3
1394 return 's4'
1395 endif
1396 return '='
1397endfunc
1398
1399func Test_foldexpr_2()
1400 new
1401 call setline(1, ['one', 'two', 'three', 'four'])
1402 setlocal foldexpr=FoldExpr2(v:lnum)
1403 setlocal foldmethod=expr
1404 call assert_equal([0, 1, 1, 0], [foldlevel(1), foldlevel(2), foldlevel(3),
1405 \ foldlevel(4)])
1406 bw!
1407endfunc
1408
1409" Test for the 'foldclose' option
1410func Test_foldclose_opt()
1411 CheckScreendump
1412
1413 let lines =<< trim END
1414 set foldmethod=manual foldclose=all foldopen=all
1415 call setline(1, ['one', 'two', 'three', 'four'])
1416 2,3fold
1417 func XsaveFoldLevels()
1418 redraw!
1419 call writefile([json_encode([foldclosed(1), foldclosed(2), foldclosed(3),
1420 \ foldclosed(4)])], 'Xoutput', 'a')
1421 endfunc
1422 END
Bram Moolenaar70e67252022-09-27 19:34:35 +01001423 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001424 let rows = 10
1425 let buf = RunVimInTerminal('-S Xscript', {'rows': rows})
1426 call term_wait(buf)
1427 call term_sendkeys(buf, ":set noruler\n")
1428 call term_wait(buf)
1429 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1430 call term_sendkeys(buf, "2G")
1431 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1432 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1433 call term_sendkeys(buf, "4G")
1434 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1435 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1436 call term_sendkeys(buf, "3G")
1437 call WaitForAssert({-> assert_equal('three', term_getline(buf, 3))})
1438 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1439 call term_sendkeys(buf, "1G")
1440 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1441 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001442 call term_sendkeys(buf, "2G")
1443 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1444 call term_sendkeys(buf, "k")
1445 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001446
1447 " clean up
1448 call StopVimInTerminal(buf)
1449
1450 call assert_equal(['[-1,2,2,-1]', '[-1,-1,-1,-1]', '[-1,2,2,-1]',
1451 \ '[-1,-1,-1,-1]', '[-1,2,2,-1]'], readfile('Xoutput'))
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001452 call delete('Xoutput')
1453endfunc
1454
1455" Test for foldtextresult()
1456func Test_foldtextresult()
1457 new
1458 call assert_equal('', foldtextresult(-1))
1459 call assert_equal('', foldtextresult(0))
1460 call assert_equal('', foldtextresult(1))
1461 call setline(1, ['one', 'two', 'three', 'four'])
1462 2,3fold
1463 call assert_equal('', foldtextresult(1))
1464 call assert_equal('+-- 2 lines: two', foldtextresult(2))
1465 setlocal foldtext=
1466 call assert_equal('+-- 2 lines folded ', foldtextresult(2))
1467
1468 " Fold text for a C comment fold
1469 %d _
1470 setlocal foldtext&
1471 call setline(1, ['', '/*', ' * Comment', ' */', ''])
1472 2,4fold
1473 call assert_equal('+-- 3 lines: Comment', foldtextresult(2))
1474
1475 bw!
1476endfunc
1477
1478" Test for merging two recursive folds when an intermediate line with no fold
1479" is removed
dundargocc57b5bc2022-11-02 13:30:51 +00001480func Test_fold_merge_recursive()
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001481 new
1482 call setline(1, [' one', ' two', 'xxxx', ' three',
1483 \ ' four', "\tfive"])
1484 setlocal foldmethod=indent shiftwidth=2
1485 3d_
1486 %foldclose
1487 call assert_equal([1, 5], [foldclosed(5), foldclosedend(1)])
1488 bw!
1489endfunc
1490
1491" Test for moving a line which is the start of a fold from a recursive fold to
1492" outside. The fold length should reduce.
1493func Test_fold_move_foldlevel()
1494 new
1495 call setline(1, ['a{{{', 'b{{{', 'c{{{', 'd}}}', 'e}}}', 'f}}}', 'g'])
1496 setlocal foldmethod=marker
1497 normal zR
1498 call assert_equal([3, 2, 1], [foldlevel(4), foldlevel(5), foldlevel(6)])
1499 3move 7
1500 call assert_equal([2, 1, 0], [foldlevel(3), foldlevel(4), foldlevel(5)])
1501 call assert_equal(1, foldlevel(7))
1502
1503 " Move a line from outside a fold to inside the fold.
1504 %d _
1505 call setline(1, ['a', 'b{{{', 'c}}}'])
1506 normal zR
1507 1move 2
1508 call assert_equal([1, 1, 1], [foldlevel(1), foldlevel(2), foldlevel(3)])
1509
1510 " Move the start of one fold to inside another fold
1511 %d _
1512 call setline(1, ['a', 'b{{{', 'c}}}', 'd{{{', 'e}}}'])
1513 normal zR
1514 call assert_equal([0, 1, 1, 1, 1], [foldlevel(1), foldlevel(2),
1515 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1516 1,2move 4
1517 call assert_equal([0, 1, 1, 2, 2], [foldlevel(1), foldlevel(2),
1518 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1519
1520 bw!
1521endfunc
1522
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001523" Test for using zj and zk to move downwards and upwards to the start and end
1524" of the next fold.
1525" Test for using [z and ]z in a closed fold to jump to the beginning and end
1526" of the fold.
1527func Test_fold_jump()
1528 new
1529 call setline(1, ["\t1", "\t2", "\t\t3", "\t\t4", "\t\t\t5", "\t\t\t6", "\t\t7", "\t\t8", "\t9", "\t10"])
1530 setlocal foldmethod=indent
1531 normal zR
1532 normal zj
1533 call assert_equal(3, line('.'))
1534 normal zj
1535 call assert_equal(5, line('.'))
1536 call assert_beeps('normal zj')
1537 call assert_equal(5, line('.'))
1538 call assert_beeps('normal 9Gzj')
1539 call assert_equal(9, line('.'))
1540 normal Gzk
1541 call assert_equal(8, line('.'))
1542 normal zk
1543 call assert_equal(6, line('.'))
1544 call assert_beeps('normal zk')
1545 call assert_equal(6, line('.'))
1546 call assert_beeps('normal 2Gzk')
1547 call assert_equal(2, line('.'))
1548
1549 " Using [z or ]z in a closed fold should not move the cursor
1550 %d _
1551 call setline(1, ["1", "\t2", "\t3", "\t4", "\t5", "\t6", "7"])
1552 normal zR4Gzc
1553 call assert_equal(4, line('.'))
1554 call assert_beeps('normal [z')
1555 call assert_equal(4, line('.'))
1556 call assert_beeps('normal ]z')
1557 call assert_equal(4, line('.'))
1558 bw!
1559endfunc
1560
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001561" Test for using a script-local function for 'foldexpr'
1562func Test_foldexpr_scriptlocal_func()
1563 func! s:FoldFunc()
1564 let g:FoldLnum = v:lnum
1565 endfunc
1566 new | only
1567 call setline(1, 'abc')
1568 let g:FoldLnum = 0
1569 set foldmethod=expr foldexpr=s:FoldFunc()
1570 redraw!
1571 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
zeertzjq01d4efe2023-01-25 15:31:28 +00001572 call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001573 call assert_equal(1, g:FoldLnum)
1574 set foldmethod& foldexpr=
1575 bw!
1576 new | only
1577 call setline(1, 'abc')
1578 let g:FoldLnum = 0
1579 set foldmethod=expr foldexpr=<SID>FoldFunc()
1580 redraw!
1581 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
zeertzjq01d4efe2023-01-25 15:31:28 +00001582 call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001583 call assert_equal(1, g:FoldLnum)
zeertzjq01d4efe2023-01-25 15:31:28 +00001584 bw!
1585 call setline(1, 'abc')
1586 setlocal foldmethod& foldexpr&
1587 setglobal foldmethod=expr foldexpr=s:FoldFunc()
1588 call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
1589 call assert_equal('0', &foldexpr)
1590 enew!
1591 call setline(1, 'abc')
1592 redraw!
1593 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1594 call assert_equal(1, g:FoldLnum)
1595 bw!
1596 call setline(1, 'abc')
1597 setlocal foldmethod& foldexpr&
1598 setglobal foldmethod=expr foldexpr=<SID>FoldFunc()
1599 call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
1600 call assert_equal('0', &foldexpr)
1601 enew!
1602 call setline(1, 'abc')
1603 redraw!
1604 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1605 call assert_equal(1, g:FoldLnum)
1606 set foldmethod& foldexpr&
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001607 delfunc s:FoldFunc
1608 bw!
1609endfunc
1610
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001611" Test for using a script-local function for 'foldtext'
1612func Test_foldtext_scriptlocal_func()
1613 func! s:FoldText()
1614 let g:FoldTextArgs = [v:foldstart, v:foldend]
1615 return foldtext()
1616 endfunc
1617 new | only
1618 call setline(1, range(50))
1619 let g:FoldTextArgs = []
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001620 set foldtext=s:FoldText()
1621 norm! 4Gzf4j
1622 redraw!
1623 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
zeertzjq01d4efe2023-01-25 15:31:28 +00001624 call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001625 call assert_equal([4, 8], g:FoldTextArgs)
1626 set foldtext&
1627 bw!
1628 new | only
1629 call setline(1, range(50))
1630 let g:FoldTextArgs = []
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001631 set foldtext=<SID>FoldText()
1632 norm! 8Gzf4j
1633 redraw!
1634 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
zeertzjq01d4efe2023-01-25 15:31:28 +00001635 call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001636 call assert_equal([8, 12], g:FoldTextArgs)
1637 set foldtext&
1638 bw!
zeertzjq01d4efe2023-01-25 15:31:28 +00001639 call setline(1, range(50))
1640 let g:FoldTextArgs = []
1641 setlocal foldtext&
1642 setglobal foldtext=s:FoldText()
1643 call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
1644 call assert_equal('foldtext()', &foldtext)
1645 enew!
1646 call setline(1, range(50))
1647 norm! 12Gzf4j
1648 redraw!
1649 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1650 call assert_equal([12, 16], g:FoldTextArgs)
1651 set foldtext&
1652 bw!
1653 call setline(1, range(50))
1654 let g:FoldTextArgs = []
1655 setlocal foldtext&
1656 setglobal foldtext=<SID>FoldText()
1657 call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
1658 call assert_equal('foldtext()', &foldtext)
1659 enew!
1660 call setline(1, range(50))
1661 norm! 16Gzf4j
1662 redraw!
1663 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1664 call assert_equal([16, 20], g:FoldTextArgs)
1665 set foldtext&
1666 bw!
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001667 delfunc s:FoldText
1668endfunc
1669
Yegappan Lakshmananfe424d12024-05-17 18:20:43 +02001670" Test for setting 'foldtext' from the modeline and executing the expression
1671" in a sandbox
1672func Test_foldtext_in_modeline()
1673 func ModelineFoldText()
1674 call feedkeys('aFoo', 'xt')
1675 return "folded text"
1676 endfunc
1677 let lines =<< trim END
1678 func T()
1679 let i = 1
1680 endfunc
1681 " vim: foldenable foldtext=ModelineFoldText()
1682 END
1683 call writefile(lines, 'Xmodelinefoldtext', 'D')
1684
1685 set modeline modelineexpr
1686 split Xmodelinefoldtext
1687
1688 call cursor(1, 1)
1689 normal! zf3j
1690 call assert_equal('folded text', foldtextresult(1))
1691 call assert_equal(lines, getbufline('', 1, '$'))
1692
1693 bw!
1694 set modeline& modelineexpr&
1695 delfunc ModelineFoldText
1696endfunc
1697
Yegappan Lakshmanan4776e642024-05-19 09:06:50 +02001698" Test for setting 'foldexpr' from the modeline and executing the expression
1699" in a sandbox
1700func Test_foldexpr_in_modeline()
1701 func ModelineFoldExpr()
1702 call feedkeys('aFoo', 'xt')
1703 return strlen(matchstr(getline(v:lnum),'^\s*'))
1704 endfunc
1705 let lines =<< trim END
1706 aaa
1707 bbb
1708 ccc
1709 ccc
1710 bbb
1711 aaa
1712 " vim: foldenable foldmethod=expr foldexpr=ModelineFoldExpr()
1713 END
1714 call writefile(lines, 'Xmodelinefoldexpr', 'D')
1715
1716 set modeline modelineexpr
1717 split Xmodelinefoldexpr
1718
1719 call assert_equal(2, foldlevel(3))
1720 call assert_equal(lines, getbufline('', 1, '$'))
1721
1722 bw!
1723 set modeline& modelineexpr&
1724 delfunc ModelineFoldExpr
1725endfunc
1726
Brandon Simmons2c407072022-04-23 13:50:17 +01001727" Make sure a fold containing a nested fold is split correctly when using
1728" foldmethod=indent
1729func Test_fold_split()
1730 new
1731 let lines =<< trim END
1732 line 1
1733 line 2
1734 line 3
1735 line 4
1736 line 5
1737 END
1738 call setline(1, lines)
1739 setlocal sw=2
1740 setlocal foldmethod=indent foldenable
1741 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
1742 call append(2, 'line 2.5')
1743 call assert_equal([0, 1, 0, 1, 2, 2], range(1, 6)->map('foldlevel(v:val)'))
Yegappan Lakshmananee47eac2022-06-29 12:55:36 +01001744 3d
1745 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
Brandon Simmons2c407072022-04-23 13:50:17 +01001746 bw!
1747endfunc
1748
Brandon Simmonsd98e75e2022-05-10 19:13:23 +01001749" Make sure that when you append under a blank line that is under a fold with
1750" the same indent level as your appended line, the fold expands across the
1751" blank line
1752func Test_indent_append_under_blank_line()
1753 new
1754 let lines =<< trim END
1755 line 1
1756 line 2
1757 line 3
1758 END
1759 call setline(1, lines)
1760 setlocal sw=2
1761 setlocal foldmethod=indent foldenable
1762 call assert_equal([0, 1, 1], range(1, 3)->map('foldlevel(v:val)'))
1763 call append(3, '')
1764 call append(4, ' line 5')
1765 call assert_equal([0, 1, 1, 1, 1], range(1, 5)->map('foldlevel(v:val)'))
1766 bw!
1767endfunc
1768
Brandon Simmons3fcccf92022-05-20 18:25:21 +01001769" Make sure that when you delete 1 line of a fold whose length is 2 lines, the
1770" fold can't be closed since its length (1) is now less than foldminlines.
1771func Test_indent_one_line_fold_close()
1772 let lines =<< trim END
1773 line 1
1774 line 2
1775 line 3
1776 END
1777
1778 new
1779 setlocal sw=2 foldmethod=indent
1780 call setline(1, lines)
1781 " open all folds, delete line, then close all folds
1782 normal zR
1783 3delete
1784 normal zM
1785 call assert_equal(-1, foldclosed(2)) " the fold should not be closed
1786
1787 " Now do the same, but delete line 2 this time; this covers different code.
1788 " (Combining this code with the above code doesn't expose both bugs.)
1789 1,$delete
1790 call setline(1, lines)
1791 normal zR
1792 2delete
1793 normal zM
1794 call assert_equal(-1, foldclosed(2))
1795 bw!
1796endfunc
1797
Brandon Simmonse8c4a642022-05-23 15:33:08 +01001798" Make sure that when appending [an indented line then a blank line] right
1799" before a single indented line, the resulting extended fold can be closed
1800func Test_indent_append_blank_small_fold_close()
1801 new
1802 setlocal sw=2 foldmethod=indent
1803 " at first, the fold at the second line can't be closed since it's smaller
1804 " than foldminlines
1805 let lines =<< trim END
1806 line 1
1807 line 4
1808 END
1809 call setline(1, lines)
1810 call append(1, [' line 2', ''])
1811 " close all folds
1812 normal zM
1813 call assert_notequal(-1, foldclosed(2)) " the fold should be closed now
1814 bw!
1815endfunc
1816
Bram Moolenaarf00112d2022-11-11 01:20:35 +00001817func Test_sort_closed_fold()
1818 CheckExecutable sort
1819
1820 call setline(1, [
1821 \ 'Section 1',
1822 \ ' how',
1823 \ ' now',
1824 \ ' brown',
1825 \ ' cow',
1826 \ 'Section 2',
1827 \ ' how',
1828 \ ' now',
1829 \ ' brown',
1830 \ ' cow',
1831 \])
1832 setlocal foldmethod=indent sw=3
1833 normal 2G
1834
1835 " The "!!" expands to ".,.+3" and must only sort four lines
1836 call feedkeys("!!sort\<CR>", 'xt')
1837 call assert_equal([
1838 \ 'Section 1',
1839 \ ' brown',
1840 \ ' cow',
1841 \ ' how',
1842 \ ' now',
1843 \ 'Section 2',
1844 \ ' how',
1845 \ ' now',
1846 \ ' brown',
1847 \ ' cow',
1848 \ ], getline(1, 10))
1849
1850 bwipe!
1851endfunc
1852
Bram Moolenaar232bdaa2023-01-13 14:17:58 +00001853func Test_indent_with_L_command()
1854 " The "L" command moved the cursor to line zero, causing the text saved for
1855 " undo to use line number -1, which caused trouble for undo later.
1856 new
1857 sil! norm 8R V{zf8=Lu
1858 bwipe!
1859endfunc
1860
Brandon Simmonsda3dd7d2023-01-17 19:48:07 +00001861" Make sure that when there is a fold at the bottom of the buffer and a newline
1862" character is appended to the line, the fold gets expanded (instead of the new
1863" line not being part of the fold).
1864func Test_expand_fold_at_bottom_of_buffer()
1865 new
1866 " create a fold on the only line
1867 fold
1868 execute "normal A\<CR>"
1869 call assert_equal([1, 1], range(1, 2)->map('foldlevel(v:val)'))
1870
1871 bwipe!
1872endfunc
1873
Luuk van Baal441a7a92023-02-18 20:15:44 +00001874func Test_fold_screenrow_motion()
1875 call setline(1, repeat(['aaaa'], 5))
1876 1,4fold
1877 norm Ggkzo
1878 call assert_equal(1, line('.'))
1879endfunc
1880
zeertzjq58e1e012023-06-04 18:46:28 +01001881" This was using freed memory
1882func Test_foldcolumn_linebreak_control_char()
1883 CheckFeature linebreak
1884
1885 5vnew
1886 setlocal foldcolumn=1 linebreak
1887 call setline(1, "aaa\<C-A>b")
1888 redraw
1889 call assert_equal([' aaa^', ' Ab '], ScreenLines([1, 2], 5))
1890 call assert_equal(screenattr(1, 5), screenattr(2, 2))
1891
1892 bwipe!
1893endfunc
1894
zeertzjqa991ce92023-10-06 19:16:36 +02001895" This used to cause invalid memory access
1896func Test_foldexpr_return_empty_string()
1897 new
1898 setlocal foldexpr='' foldmethod=expr
1899 redraw
1900
1901 bwipe!
1902endfunc
1903
Shota Nozaki0689b872024-01-03 19:18:43 +01001904" Make sure that when ending a fold that hasn't been started, it does not
1905" start a new fold.
1906func Test_foldexpr_end_fold()
1907 new
1908 setlocal foldmethod=expr
1909 let &l:foldexpr = 'v:lnum == 2 ? "<2" : "="'
1910 call setline(1, range(1, 3))
1911 redraw
1912 call assert_equal([0, 0, 0], range(1, 3)->map('foldlevel(v:val)'))
1913
1914 bwipe!
1915endfunc
1916
Luuk van Baaldc373d42024-07-25 21:24:32 +02001917" Test moving cursor down to or beyond start of folded end of buffer.
1918func Test_cursor_down_fold_eob()
1919 call setline(1, range(1, 4))
1920 norm Gzf2kj
1921 call assert_equal(2, line('.'))
1922 norm zojzc
1923 call assert_equal(3, line('.'))
1924 norm j
1925 call assert_equal(3, line('.'))
1926 norm k2j
1927 call assert_equal(4, line('.'))
1928 bwipe!
1929endfunc
1930
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001931" vim: shiftwidth=2 sts=2 expandtab