blob: fc63b1572b0f74b4950ee6d1ca11c259c0fa0d4c [file] [log] [blame]
Bram Moolenaarded27822017-01-02 14:27:34 +01001" Test for folding
2
Christian Brabandteb380b92025-07-07 20:53:55 +02003source util/screendump.vim
Bram Moolenaar907dad72018-07-10 15:07:15 +02004
Bram Moolenaar94be6192017-04-22 22:40:11 +02005func PrepIndent(arg)
Bram Moolenaar88d298a2017-03-14 21:53:58 +01006 return [a:arg] + repeat(["\t".a:arg], 5)
7endfu
8
Riley Bruins0a083062024-06-03 20:40:45 +02009func Test_address_fold_new_default_commentstring()
10 " Test with the new commentstring defaults, that includes padding after v9.1.464
11 new
12 call setline(1, ['int FuncName() {/* {{{ */', 1, 2, 3, 4, 5, '}/* }}} */',
13 \ 'after fold 1', 'after fold 2', 'after fold 3'])
14 setl fen fdm=marker
15 " The next commands should all copy the same part of the buffer,
16 " regardless of the addressing type, since the part to be copied
17 " is folded away
18 :1y
19 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
20 :.y
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 :sil .1,.y
27 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
28 " use silent to make E493 go away
29 :sil .+,.y
30 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
31 :,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', '}/* }}} */','after fold 1'], getreg(0,1,1))
35 " using .+3 as second address should c opy the whole folded line + the next 3
36 " lines
37 :.,+3y
38 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */',
39 \ 'after fold 1', 'after fold 2' , 'after fold 3'], getreg(0,1,1))
40 :sil .,-2y
41 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
42
43 " now test again with folding disabled
44 set nofoldenable
45 :1y
46 call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
47 :.y
48 call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
49 :.+y
50 call assert_equal(['1'], getreg(0,1,1) )
51 :.,.y
52 call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
53 " use silent to make E493 go away
54 :sil .1,.y
55 call assert_equal(['int FuncName() {/* {{{ */', '1'], getreg(0,1,1))
56 " use silent to make E493 go away
57 :sil .+,.y
58 call assert_equal(['int FuncName() {/* {{{ */', '1'], getreg(0,1,1))
59 :,y
60 call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
61 :,+y
62 call assert_equal(['int FuncName() {/* {{{ */', '1'], getreg(0,1,1))
63 " using .+3 as second address should c opy the whole folded line + the next 3
64 " lines
65 :.,+3y
66 call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3'], getreg(0,1,1))
67 :7
68 :sil .,-2y
69 call assert_equal(['4', '5', '}/* }}} */'], getreg(0,1,1))
70
71 quit!
72endfunc
73
74func Test_address_fold_old_default_commentstring()
75 " Test with the old commentstring defaults, before v9.1.464
Bram Moolenaarded27822017-01-02 14:27:34 +010076 new
77 call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
78 \ 'after fold 1', 'after fold 2', 'after fold 3'])
79 setl fen fdm=marker
Bram Moolenaar518c9b12017-03-21 11:48:39 +010080 " The next commands should all copy the same part of the buffer,
81 " regardless of the addressing type, since the part to be copied
Bram Moolenaarded27822017-01-02 14:27:34 +010082 " is folded away
83 :1y
84 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
85 :.y
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 :sil .1,.y
92 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
93 " use silent to make E493 go away
94 :sil .+,.y
95 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
96 :,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', '}/*}}}*/','after fold 1'], getreg(0,1,1))
100 " using .+3 as second address should copy the whole folded line + the next 3
101 " lines
102 :.,+3y
103 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/',
104 \ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1))
105 :sil .,-2y
106 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
107
108 " now test again with folding disabled
109 set nofoldenable
110 :1y
111 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
112 :.y
113 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
114 :.+y
115 call assert_equal(['1'], getreg(0,1,1))
116 :.,.y
117 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
118 " use silent to make E493 go away
119 :sil .1,.y
120 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
121 " use silent to make E493 go away
122 :sil .+,.y
123 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
124 :,y
125 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
126 :,+y
127 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
128 " using .+3 as second address should copy the whole folded line + the next 3
129 " lines
130 :.,+3y
131 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1))
132 :7
133 :sil .,-2y
134 call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1))
135
136 quit!
Bram Moolenaar1159b162017-02-28 21:53:56 +0100137endfunc
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100138
Bram Moolenaar9954dc32022-11-11 22:58:36 +0000139func Test_address_offsets()
140 " check the help for :range-closed-fold
141 enew
142 call setline(1, [
143 \ '1 one',
144 \ '2 two',
145 \ '3 three',
146 \ '4 four FOLDED',
147 \ '5 five FOLDED',
148 \ '6 six',
149 \ '7 seven',
150 \ '8 eight',
151 \])
152 set foldmethod=manual
153 normal 4Gvjzf
154 3,4+2yank
155 call assert_equal([
156 \ '3 three',
157 \ '4 four FOLDED',
158 \ '5 five FOLDED',
159 \ '6 six',
160 \ '7 seven',
161 \ ], getreg(0,1,1))
162
163 enew!
164 call setline(1, [
165 \ '1 one',
166 \ '2 two',
167 \ '3 three FOLDED',
168 \ '4 four FOLDED',
169 \ '5 five FOLDED',
170 \ '6 six FOLDED',
171 \ '7 seven',
172 \ '8 eight',
173 \])
174 normal 3Gv3jzf
175 2,4-1yank
176 call assert_equal([
177 \ '2 two',
178 \ '3 three FOLDED',
179 \ '4 four FOLDED',
180 \ '5 five FOLDED',
181 \ '6 six FOLDED',
182 \ ], getreg(0,1,1))
183
184 bwipe!
185endfunc
186
Bram Moolenaar94be6192017-04-22 22:40:11 +0200187func Test_indent_fold()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100188 new
189 call setline(1, ['', 'a', ' b', ' c'])
190 setl fen fdm=indent
191 2
192 norm! >>
193 let a=map(range(1,4), 'foldclosed(v:val)')
194 call assert_equal([-1,-1,-1,-1], a)
195 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +0100196endfunc
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100197
Bram Moolenaar94be6192017-04-22 22:40:11 +0200198func Test_indent_fold2()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100199 new
200 call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
201 setl fen fdm=marker
202 2
203 norm! >>
Bram Moolenaara4208962019-08-24 20:50:19 +0200204 let a=map(range(1,5), 'v:val->foldclosed()')
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100205 call assert_equal([-1,-1,-1,4,4], a)
206 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +0100207endfunc
208
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200209" Test for fold indent with indents greater than 'foldnestmax'
210func Test_indent_fold_max()
211 new
212 setlocal foldmethod=indent
213 setlocal shiftwidth=2
214 " 'foldnestmax' default value is 20
215 call setline(1, "\t\t\t\t\t\ta")
216 call assert_equal(20, foldlevel(1))
217 setlocal foldnestmax=10
218 call assert_equal(10, foldlevel(1))
219 setlocal foldnestmax=-1
220 call assert_equal(0, foldlevel(1))
221 bw!
222endfunc
223
zeertzjq07146ad2022-12-19 15:51:44 +0000224func Test_indent_fold_tabstop()
225 call setline(1, ['0', ' 1', ' 1', "\t2", "\t2"])
226 setlocal shiftwidth=4
227 setlocal foldcolumn=1
228 setlocal foldlevel=2
229 setlocal foldmethod=indent
230 redraw
231 call assert_equal('2 2', ScreenLines(5, 10)[0])
232 vsplit
233 windo diffthis
234 botright new
235 " This 'tabstop' value should not be used for folding in other buffers.
236 setlocal tabstop=4
237 diffoff!
238 redraw
239 call assert_equal('2 2', ScreenLines(5, 10)[0])
240
241 bwipe!
242 bwipe!
243endfunc
244
Bram Moolenaar1159b162017-02-28 21:53:56 +0100245func Test_manual_fold_with_filter()
Bram Moolenaaraeb313f2020-11-27 19:13:28 +0100246 CheckExecutable cat
Bram Moolenaar3f3897e2017-03-04 15:28:53 +0100247 for type in ['manual', 'marker']
248 exe 'set foldmethod=' . type
249 new
250 call setline(1, range(1, 20))
251 4,$fold
252 %foldopen
253 10,$fold
254 %foldopen
255 " This filter command should not have an effect
256 1,8! cat
257 call feedkeys('5ggzdzMGdd', 'xt')
258 call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
259
260 bwipe!
261 set foldmethod&
262 endfor
Bram Moolenaar1159b162017-02-28 21:53:56 +0100263endfunc
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100264
Bram Moolenaar94be6192017-04-22 22:40:11 +0200265func Test_indent_fold_with_read()
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100266 new
267 set foldmethod=indent
268 call setline(1, repeat(["\<Tab>a"], 4))
269 for n in range(1, 4)
270 call assert_equal(1, foldlevel(n))
271 endfor
272
Bram Moolenaar70e67252022-09-27 19:34:35 +0100273 call writefile(["a", "", "\<Tab>a"], 'Xinfofile', 'D')
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100274 foldopen
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100275 2read Xinfofile
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100276 %foldclose
277 call assert_equal(1, foldlevel(1))
278 call assert_equal(2, foldclosedend(1))
279 call assert_equal(0, foldlevel(3))
280 call assert_equal(0, foldlevel(4))
281 call assert_equal(1, foldlevel(5))
Bram Moolenaara4208962019-08-24 20:50:19 +0200282 call assert_equal(7, 5->foldclosedend())
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100283
284 bwipe!
285 set foldmethod&
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100286endfunc
287
288func Test_combining_folds_indent()
289 new
290 let one = "\<Tab>a"
291 let zero = 'a'
292 call setline(1, [one, one, zero, zero, zero, one, one, one])
293 set foldmethod=indent
294 3,5d
295 %foldclose
296 call assert_equal(5, foldclosedend(1))
297
298 set foldmethod&
299 bwipe!
300endfunc
301
302func Test_combining_folds_marker()
303 new
304 call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
305 set foldmethod=marker
306 3,5d
307 %foldclose
308 call assert_equal(2, foldclosedend(1))
309
310 set foldmethod&
311 bwipe!
312endfunc
313
Bram Moolenaar025a6b72017-03-12 20:37:21 +0100314func Test_folds_marker_in_comment()
315 new
316 call setline(1, ['" foo', 'bar', 'baz'])
317 setl fen fdm=marker
318 setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
319 norm! zf2j
320 setl nofen
321 :1y
322 call assert_equal(['" foo{{{'], getreg(0,1,1))
323 :+2y
324 call assert_equal(['baz"}}}'], getreg(0,1,1))
325
326 set foldmethod&
327 bwipe!
328endfunc
329
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100330func s:TestFoldExpr(lnum)
331 let thisline = getline(a:lnum)
332 if thisline == 'a'
333 return 1
334 elseif thisline == 'b'
335 return 0
336 elseif thisline == 'c'
337 return '<1'
338 elseif thisline == 'd'
339 return '>1'
340 endif
341 return 0
342endfunction
343
344func Test_update_folds_expr_read()
345 new
346 call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
347 set foldmethod=expr
348 set foldexpr=s:TestFoldExpr(v:lnum)
349 2
350 foldopen
Bram Moolenaar70e67252022-09-27 19:34:35 +0100351 call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xupfofile', 'D')
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100352 read Xupfofile
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100353 %foldclose
354 call assert_equal(2, foldclosedend(1))
355 call assert_equal(0, foldlevel(3))
Bram Moolenaara4208962019-08-24 20:50:19 +0200356 call assert_equal(0, 4->foldlevel())
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100357 call assert_equal(6, foldclosedend(5))
358 call assert_equal(10, foldclosedend(7))
359 call assert_equal(14, foldclosedend(11))
360
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100361 bwipe!
362 set foldmethod& foldexpr&
363endfunc
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100364
zeertzjq93c15732022-05-21 16:34:38 +0100365" Test for what patch 8.1.0535 fixes.
366func Test_foldexpr_no_interrupt_addsub()
367 new
368 func! FoldFunc()
369 call setpos('.', getcurpos())
370 return '='
371 endfunc
372
373 set foldmethod=expr
374 set foldexpr=FoldFunc()
375 call setline(1, '1.2')
376
377 exe "norm! $\<C-A>"
378 call assert_equal('1.3', getline(1))
379
380 bwipe!
381 delfunc FoldFunc
382 set foldmethod& foldexpr&
383endfunc
384
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +0100385" Fold function defined in another script
386func Test_foldexpr_compiled()
387 new
388 let lines =<< trim END
389 vim9script
390 def FoldFunc(): number
391 return v:lnum
392 enddef
393
394 set foldmethod=expr
395 set foldexpr=s:FoldFunc()
396 END
397 call writefile(lines, 'XfoldExpr', 'D')
398 source XfoldExpr
399
400 call setline(1, ['one', 'two', 'three'])
401 redraw
402 call assert_equal(1, foldlevel(1))
403 call assert_equal(2, foldlevel(2))
404 call assert_equal(3, foldlevel(3))
405
406 bwipe!
407 set foldmethod& foldexpr&
408endfunc
409
Bram Moolenaar94be6192017-04-22 22:40:11 +0200410func Check_foldlevels(expected)
411 call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)'))
412endfunc
413
414func Test_move_folds_around_manual()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100415 new
416 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
417 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
418 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
419 " all folds closed
420 set foldenable foldlevel=0 fdm=indent
421 " needs a forced redraw
422 redraw!
423 set fdm=manual
424 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
425 call assert_equal(input, getline(1, '$'))
426 7,12m0
427 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
428 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
429 10,12m0
430 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
431 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)'))
432 " moving should not close the folds
433 %d
434 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
435 set fdm=indent
436 redraw!
437 set fdm=manual
438 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100439 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100440 7,12m0
441 let folds=repeat([-1], 18)
442 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
443 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
444 norm! zM
445 " folds are not corrupted and all have been closed
446 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)'))
447 %d
448 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
449 set fdm=indent
450 redraw!
451 set fdm=manual
452 %foldopen
453 3m4
454 %foldclose
455 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
456 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
457 %d
458 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
459 set fdm=indent foldlevel=0
460 set fdm=manual
461 %foldopen
462 3m1
463 %foldclose
464 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
465 call assert_equal(0, foldlevel(2))
466 call assert_equal(5, foldclosedend(3))
467 call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
468 2,6m$
469 %foldclose
470 call assert_equal(5, foldclosedend(2))
471 call assert_equal(0, foldlevel(6))
472 call assert_equal(9, foldclosedend(7))
473 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 +0200474
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100475 %d
476 " Ensure moving around the edges still works.
477 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
478 set fdm=indent foldlevel=0
479 set fdm=manual
480 %foldopen
481 6m$
482 " The first fold has been truncated to the 5'th line.
483 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200484 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])
485
486 %delete
487 set fdm=indent foldlevel=0
488 call setline(1, [
489 \ "a",
490 \ "\ta",
491 \ "\t\ta",
492 \ "\t\ta",
493 \ "\t\ta",
494 \ "a",
495 \ "a"])
496 set fdm=manual
497 %foldopen!
498 4,5m6
499 call Check_foldlevels([0, 1, 2, 0, 0, 0, 0])
500
501 %delete
502 set fdm=indent
503 call setline(1, [
504 \ "\ta",
505 \ "\t\ta",
506 \ "\t\ta",
507 \ "\t\ta",
508 \ "\ta",
509 \ "\t\ta",
510 \ "\t\ta",
511 \ "\t\ta",
512 \ "\ta",
513 \ "\t\ta",
514 \ "\t\ta",
515 \ "\t\ta",
516 \ "\t\ta",
517 \ "\ta",
518 \ "a"])
519 set fdm=manual
520 %foldopen!
521 13m7
522 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 +0000523
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100524 bw!
525endfunc
526
Bram Moolenaar94be6192017-04-22 22:40:11 +0200527func Test_move_folds_around_indent()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100528 new
529 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
530 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
531 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
532 " all folds closed
533 set fdm=indent
534 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
535 call assert_equal(input, getline(1, '$'))
536 7,12m0
537 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
538 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
539 10,12m0
540 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
541 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)'))
542 " moving should not close the folds
543 %d
544 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
545 set fdm=indent
546 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100547 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100548 7,12m0
549 let folds=repeat([-1], 18)
550 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
551 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
552 norm! zM
553 " folds are not corrupted and all have been closed
554 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)'))
555 %d
556 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
557 set fdm=indent
558 %foldopen
559 3m4
560 %foldclose
561 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
562 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
563 %d
564 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
565 set fdm=indent foldlevel=0
566 %foldopen
567 3m1
568 %foldclose
569 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
570 call assert_equal(1, foldlevel(2))
571 call assert_equal(5, foldclosedend(3))
572 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
573 2,6m$
574 %foldclose
575 call assert_equal(9, foldclosedend(2))
576 call assert_equal(1, foldlevel(6))
577 call assert_equal(9, foldclosedend(7))
578 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 +0100579 " Ensure moving around the edges still works.
580 %d
581 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
582 set fdm=indent foldlevel=0
583 %foldopen
584 6m$
585 " The first fold has been truncated to the 5'th line.
586 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200587 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100588 bw!
589endfunc
Bram Moolenaar518c9b12017-03-21 11:48:39 +0100590
591func Test_folddoopen_folddoclosed()
592 new
593 call setline(1, range(1, 9))
594 set foldmethod=manual
595 1,3 fold
596 6,8 fold
597
598 " Test without range.
599 folddoopen s/$/o/
600 folddoclosed s/$/c/
601 call assert_equal(['1c', '2c', '3c',
602 \ '4o', '5o',
603 \ '6c', '7c', '8c',
604 \ '9o'], getline(1, '$'))
605
606 " Test with range.
607 call setline(1, range(1, 9))
608 1,8 folddoopen s/$/o/
609 4,$ folddoclosed s/$/c/
610 call assert_equal(['1', '2', '3',
611 \ '4o', '5o',
612 \ '6c', '7c', '8c',
613 \ '9'], getline(1, '$'))
614
615 set foldmethod&
616 bw!
617endfunc
618
619func Test_fold_error()
620 new
621 call setline(1, [1, 2])
622
623 for fm in ['indent', 'expr', 'syntax', 'diff']
624 exe 'set foldmethod=' . fm
625 call assert_fails('norm zf', 'E350:')
626 call assert_fails('norm zd', 'E351:')
627 call assert_fails('norm zE', 'E352:')
628 endfor
629
630 set foldmethod=manual
631 call assert_fails('norm zd', 'E490:')
632 call assert_fails('norm zo', 'E490:')
633 call assert_fails('3fold', 'E16:')
634
635 set foldmethod=marker
636 set nomodifiable
637 call assert_fails('1,2fold', 'E21:')
638
639 set modifiable&
640 set foldmethod&
641 bw!
642endfunc
Bram Moolenaar495b7dd2017-09-16 17:19:22 +0200643
644func Test_foldtext_recursive()
645 new
646 call setline(1, ['{{{', 'some text', '}}}'])
647 setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
648 " This was crashing because of endless recursion.
649 2foldclose
650 redraw
651 call assert_equal(1, foldlevel(2))
652 call assert_equal(1, foldclosed(2))
653 call assert_equal(3, foldclosedend(2))
654 bwipe!
655endfunc
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100656
657" Various fold related tests
658
659" Basic test if a fold can be created, opened, moving to the end and closed
660func Test_fold_manual()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200661 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100662 set fdm=manual
663
664 let content = ['1 aa', '2 bb', '3 cc']
665 call append(0, content)
666 call cursor(1, 1)
667 normal zf2j
668 call assert_equal('1 aa', getline(foldclosed('.')))
669 normal zo
670 call assert_equal(-1, foldclosed('.'))
671 normal ]z
672 call assert_equal('3 cc', getline('.'))
673 normal zc
674 call assert_equal('1 aa', getline(foldclosed('.')))
675
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200676 " Create a fold inside a closed fold after setting 'foldlevel'
677 %d _
678 call setline(1, range(1, 5))
679 1,5fold
680 normal zR
681 2,4fold
682 set foldlevel=1
683 3fold
684 call assert_equal([1, 3, 3, 3, 1], map(range(1, 5), {->foldlevel(v:val)}))
685 set foldlevel&
686
687 " Create overlapping folds (at the start and at the end)
688 normal zE
689 2,3fold
690 normal zR
691 3,4fold
692 call assert_equal([0, 2, 2, 1, 0], map(range(1, 5), {->foldlevel(v:val)}))
693 normal zE
694 3,4fold
695 normal zR
696 2,3fold
697 call assert_equal([0, 1, 2, 2, 0], map(range(1, 5), {->foldlevel(v:val)}))
698
699 " Create a nested fold across two non-adjoining folds
700 %d _
701 call setline(1, range(1, 7))
702 1,2fold
703 normal zR
704 4,5fold
705 normal zR
706 6,7fold
707 normal zR
708 1,5fold
709 call assert_equal([2, 2, 1, 2, 2, 1, 1],
710 \ map(range(1, 7), {->foldlevel(v:val)}))
711
712 " A newly created nested fold should be closed
713 %d _
714 call setline(1, range(1, 6))
715 1,6fold
716 normal zR
717 3,4fold
718 normal zR
719 2,5fold
720 call assert_equal([1, 2, 3, 3, 2, 1], map(range(1, 6), {->foldlevel(v:val)}))
721 call assert_equal(2, foldclosed(4))
722 call assert_equal(5, foldclosedend(4))
723
724 " Test zO, zC and zA on a line with no folds.
725 normal zE
726 call assert_fails('normal zO', 'E490:')
727 call assert_fails('normal zC', 'E490:')
728 call assert_fails('normal zA', 'E490:')
729
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100730 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200731 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100732endfunc
733
734" test folding with markers.
735func Test_fold_marker()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200736 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100737 set fdm=marker fdl=1 fdc=3
738
739 let content = ['4 dd {{{', '5 ee {{{ }}}', '6 ff }}}']
740 call append(0, content)
741 call cursor(2, 1)
742 call assert_equal(2, foldlevel('.'))
743 normal [z
744 call assert_equal(1, foldlevel('.'))
745 exe "normal jo{{ \<Esc>r{jj"
746 call assert_equal(1, foldlevel('.'))
747 normal kYpj
748 call assert_equal(0, foldlevel('.'))
749
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200750 " Use only closing fold marker (without and with a count)
751 set fdl&
752 %d _
753 call setline(1, ['one }}}', 'two'])
754 call assert_equal([0, 0], [foldlevel(1), foldlevel(2)])
755 %d _
756 call setline(1, ['one }}}4', 'two'])
757 call assert_equal([4, 3], [foldlevel(1), foldlevel(2)])
758
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100759 set fdm& fdl& fdc&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200760 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100761endfunc
762
Bram Moolenaar4af72592018-12-09 15:00:52 +0100763" test create fold markers with C filetype
764func Test_fold_create_marker_in_C()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200765 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100766 set fdm=marker fdl=9
767 set filetype=c
768
Bram Moolenaarc79745a2019-05-20 22:12:34 +0200769 let content =<< trim [CODE]
770 /*
771 * comment
Bram Moolenaar94722c52023-01-28 19:19:03 +0000772 *
Bram Moolenaarc79745a2019-05-20 22:12:34 +0200773 *
774 */
775 int f(int* p) {
776 *p = 3;
777 return 0;
778 }
779 [CODE]
780
Bram Moolenaar4af72592018-12-09 15:00:52 +0100781 for c in range(len(content) - 1)
782 bw!
783 call append(0, content)
784 call cursor(c + 1, 1)
785 norm! zfG
Riley Bruins0a083062024-06-03 20:40:45 +0200786 call assert_equal(content[c] . (c < 4 ? '{{{' : '/* {{{ */'), getline(c + 1))
Bram Moolenaar4af72592018-12-09 15:00:52 +0100787 endfor
788
789 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200790 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100791endfunc
792
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100793" test folding with indent
794func Test_fold_indent()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200795 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100796 set fdm=indent sw=2
797
798 let content = ['1 aa', '2 bb', '3 cc']
799 call append(0, content)
800 call cursor(2, 1)
801 exe "normal i \<Esc>jI "
802 call assert_equal(2, foldlevel('.'))
803 normal k
804 call assert_equal(1, foldlevel('.'))
805
806 set fdm& sw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200807 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100808endfunc
809
810" test syntax folding
811func Test_fold_syntax()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200812 CheckFeature syntax
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100813
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200814 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100815 set fdm=syntax fdl=0
816
817 syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3
818 syn region Fd1 start="ee" end="ff" fold contained
819 syn region Fd2 start="gg" end="hh" fold contained
820 syn region Fd3 start="commentstart" end="commentend" fold contained
821 let content = ['3 cc', '4 dd {{{', '5 ee {{{ }}}', '{{{{', '6 ff }}}',
822 \ '6 ff }}}', '7 gg', '8 hh', '9 ii']
823 call append(0, content)
824 normal Gzk
825 call assert_equal('9 ii', getline('.'))
826 normal k
827 call assert_equal('3 cc', getline('.'))
828 exe "normal jAcommentstart \<Esc>Acommentend"
829 set fdl=1
830 normal 3j
831 call assert_equal('7 gg', getline('.'))
832 set fdl=0
833 exe "normal zO\<C-L>j"
834 call assert_equal('8 hh', getline('.'))
835 syn clear Fd1 Fd2 Fd3 Hup
836
837 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200838 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100839endfunc
840
841func Flvl()
842 let l = getline(v:lnum)
843 if l =~ "bb$"
844 return 2
845 elseif l =~ "gg$"
846 return "s1"
847 elseif l =~ "ii$"
848 return ">2"
849 elseif l =~ "kk$"
850 return "0"
851 endif
852 return "="
853endfun
854
855" test expression folding
856func Test_fold_expr()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200857 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100858 set fdm=expr fde=Flvl()
859
860 let content = ['1 aa',
861 \ '2 bb',
862 \ '3 cc',
863 \ '4 dd {{{commentstart commentend',
864 \ '5 ee {{{ }}}',
865 \ '{{{',
866 \ '6 ff }}}',
867 \ '6 ff }}}',
868 \ ' 7 gg',
869 \ ' 8 hh',
870 \ '9 ii',
871 \ 'a jj',
872 \ 'b kk']
873 call append(0, content)
874 call cursor(1, 1)
875 exe "normal /bb$\<CR>"
876 call assert_equal(2, foldlevel('.'))
877 exe "normal /hh$\<CR>"
878 call assert_equal(1, foldlevel('.'))
879 exe "normal /ii$\<CR>"
880 call assert_equal(2, foldlevel('.'))
881 exe "normal /kk$\<CR>"
882 call assert_equal(0, foldlevel('.'))
883
884 set fdm& fde&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200885 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100886endfunc
887
888" Bug with fdm=indent and moving folds
889" Moving a fold a few times, messes up the folds below the moved fold.
890" Fixed by 7.4.700
891func Test_fold_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200892 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100893 set fdm=indent sw=2 fdl=0
894
895 let content = ['', '', 'Line1', ' Line2', ' Line3',
896 \ 'Line4', ' Line5', ' Line6',
897 \ 'Line7', ' Line8', ' Line9']
898 call append(0, content)
899 normal zM
900 call cursor(4, 1)
901 move 2
902 move 1
903 call assert_equal(7, foldclosed(7))
904 call assert_equal(8, foldclosedend(7))
905 call assert_equal(0, foldlevel(9))
906 call assert_equal(10, foldclosed(10))
907 call assert_equal(11, foldclosedend(10))
908 call assert_equal('+-- 2 lines: Line2', foldtextresult(2))
Bram Moolenaara4208962019-08-24 20:50:19 +0200909 call assert_equal('+-- 2 lines: Line8', 10->foldtextresult())
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100910
911 set fdm& sw& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200912 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100913endfunc
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100914
915" test for patch 7.3.637
916" Cannot catch the error caused by a foldopen when there is no fold.
917func Test_foldopen_exception()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200918 new
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100919 let a = 'No error caught'
920 try
921 foldopen
922 catch
923 let a = matchstr(v:exception,'^[^ ]*')
924 endtry
925 call assert_equal('Vim(foldopen):E490:', a)
926
927 let a = 'No error caught'
928 try
929 foobar
930 catch
931 let a = matchstr(v:exception,'^[^ ]*')
932 endtry
933 call assert_match('E492:', a)
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200934 bw!
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100935endfunc
Bram Moolenaar907dad72018-07-10 15:07:15 +0200936
937func Test_fold_last_line_with_pagedown()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200938 new
Bram Moolenaar907dad72018-07-10 15:07:15 +0200939 set fdm=manual
940
941 let expect = '+-- 11 lines: 9---'
942 let content = range(1,19)
943 call append(0, content)
944 normal dd9G
945 normal zfG
946 normal zt
947 call assert_equal('9', getline(foldclosed('.')))
948 call assert_equal('19', getline(foldclosedend('.')))
949 call assert_equal(expect, ScreenLines(1, len(expect))[0])
950 call feedkeys("\<C-F>", 'xt')
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-B>\<C-F>\<C-F>", 'xt')
955 call assert_equal(expect, ScreenLines(1, len(expect))[0])
956
957 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200958 bw!
Bram Moolenaar907dad72018-07-10 15:07:15 +0200959endfunc
Bram Moolenaar7701f302018-10-02 21:20:32 +0200960
961func Test_folds_with_rnu()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200962 CheckScreendump
Bram Moolenaar7701f302018-10-02 21:20:32 +0200963
964 call writefile([
965 \ 'set fdm=marker rnu foldcolumn=2',
966 \ 'call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])',
Bram Moolenaar70e67252022-09-27 19:34:35 +0100967 \ ], 'Xtest_folds_with_rnu', 'D')
Bram Moolenaar7701f302018-10-02 21:20:32 +0200968 let buf = RunVimInTerminal('-S Xtest_folds_with_rnu', {})
969
970 call VerifyScreenDump(buf, 'Test_folds_with_rnu_01', {})
971 call term_sendkeys(buf, "j")
972 call VerifyScreenDump(buf, 'Test_folds_with_rnu_02', {})
973
974 " clean up
975 call StopVimInTerminal(buf)
Bram Moolenaar7701f302018-10-02 21:20:32 +0200976endfunc
Bram Moolenaar53932812018-12-07 21:08:49 +0100977
978func Test_folds_marker_in_comment2()
979 new
980 call setline(1, ['Lorem ipsum dolor sit', 'Lorem ipsum dolor sit', 'Lorem ipsum dolor sit'])
981 setl fen fdm=marker
982 setl commentstring=<!--%s-->
983 setl comments=s:<!--,m:\ \ \ \ ,e:-->
984 norm! zf2j
985 setl nofen
986 :1y
987 call assert_equal(['Lorem ipsum dolor sit<!--{{{-->'], getreg(0,1,1))
988 :+2y
989 call assert_equal(['Lorem ipsum dolor sit<!--}}}-->'], getreg(0,1,1))
990
991 set foldmethod&
992 bwipe!
993endfunc
Bram Moolenaar9a4a8c42019-08-19 22:48:30 +0200994
995func Test_fold_delete_with_marker()
996 new
997 call setline(1, ['func Func() {{{1', 'endfunc'])
998 1,2yank
999 new
1000 set fdm=marker
1001 call setline(1, 'x')
1002 normal! Vp
1003 normal! zd
1004 call assert_equal(['func Func() ', 'endfunc'], getline(1, '$'))
1005
1006 set fdm&
1007 bwipe!
1008 bwipe!
1009endfunc
Bram Moolenaar7a9bd7c2019-09-17 22:42:55 +02001010
1011func Test_fold_delete_with_marker_and_whichwrap()
1012 new
1013 let content1 = ['']
1014 let content2 = ['folded line 1 "{{{1', ' test', ' test2', ' test3', '', 'folded line 2 "{{{1', ' test', ' test2', ' test3']
1015 call setline(1, content1 + content2)
1016 set fdm=marker ww+=l
1017 normal! x
1018 call assert_equal(content2, getline(1, '$'))
1019 set fdm& ww&
1020 bwipe!
1021endfunc
Bram Moolenaar3b681232019-12-13 19:35:55 +01001022
1023func Test_fold_delete_first_line()
1024 new
1025 call setline(1, [
1026 \ '" x {{{1',
1027 \ '" a',
1028 \ '" aa',
1029 \ '" x {{{1',
1030 \ '" b',
1031 \ '" bb',
1032 \ '" x {{{1',
1033 \ '" c',
1034 \ '" cc',
1035 \ ])
1036 set foldmethod=marker
1037 1
1038 normal dj
1039 call assert_equal([
1040 \ '" x {{{1',
1041 \ '" c',
1042 \ '" cc',
1043 \ ], getline(1,'$'))
1044 bwipe!
1045 set foldmethod&
1046endfunc
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001047
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001048" Add a test for deleting the outer fold of a nested fold and promoting the
1049" inner folds to one level up with already a fold at that level following the
1050" nested fold.
1051func Test_fold_delete_recursive_fold()
1052 new
1053 call setline(1, range(1, 7))
1054 2,3fold
1055 normal zR
1056 4,5fold
1057 normal zR
1058 1,5fold
1059 normal zR
1060 6,7fold
1061 normal zR
1062 normal 1Gzd
1063 normal 1Gzj
1064 call assert_equal(2, line('.'))
1065 normal zj
1066 call assert_equal(4, line('.'))
1067 normal zj
1068 call assert_equal(6, line('.'))
1069 bw!
1070endfunc
1071
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001072" Test for errors in 'foldexpr'
1073func Test_fold_expr_error()
1074 new
1075 call setline(1, ['one', 'two', 'three'])
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001076 " In a window with no folds, foldlevel() should return 0
1077 call assert_equal(0, foldlevel(1))
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001078
1079 " Return a list from the expression
1080 set foldexpr=[]
1081 set foldmethod=expr
1082 for i in range(3)
1083 call assert_equal(0, foldlevel(i))
1084 endfor
1085
1086 " expression error
1087 set foldexpr=[{]
1088 set foldmethod=expr
1089 for i in range(3)
1090 call assert_equal(0, foldlevel(i))
1091 endfor
1092
1093 set foldmethod& foldexpr&
1094 close!
1095endfunc
1096
Bram Moolenaarda697642020-09-17 19:36:04 +02001097func Test_undo_fold_deletion()
1098 new
1099 set fdm=marker
1100 let lines =<< trim END
1101 " {{{
1102 " }}}1
1103 " {{{
1104 END
1105 call setline(1, lines)
1106 3d
1107 g/"/d
1108 undo
1109 redo
1110 eval getline(1, '$')->assert_equal([''])
1111
1112 set fdm&vim
1113 bwipe!
1114endfunc
1115
Bram Moolenaarc136a352020-11-03 20:05:40 +01001116" this was crashing
1117func Test_move_no_folds()
1118 new
1119 fold
1120 setlocal fdm=expr
1121 normal zj
1122 bwipe!
1123endfunc
1124
Bram Moolenaar5e1f22f2020-11-10 18:23:52 +01001125" this was crashing
1126func Test_fold_create_delete_create()
1127 new
1128 fold
1129 fold
1130 normal zd
1131 fold
1132 bwipe!
1133endfunc
1134
Bram Moolenaar6a78f322020-12-21 14:01:41 +01001135" this was crashing
1136func Test_fold_create_delete()
1137 new
1138 norm zFzFzdzj
1139 bwipe!
1140endfunc
1141
Bram Moolenaare71996b2021-01-21 17:03:07 +01001142func Test_fold_relative_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001143 new
Bram Moolenaare71996b2021-01-21 17:03:07 +01001144 set fdm=indent sw=2 wrap tw=80
1145
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001146 let longtext = repeat('x', &columns + 1)
1147 let content = [ ' foo', ' ' .. longtext, ' baz',
1148 \ longtext,
1149 \ ' foo', ' ' .. longtext, ' baz'
Bram Moolenaare71996b2021-01-21 17:03:07 +01001150 \ ]
1151 call append(0, content)
1152
1153 normal zM
1154
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001155 for lnum in range(1, 3)
1156 call cursor(lnum, 1)
1157 call assert_true(foldclosed(line('.')))
1158 normal gj
1159 call assert_equal(2, winline())
1160 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001161
1162 call cursor(2, 1)
1163 call assert_true(foldclosed(line('.')))
1164 normal 2gj
1165 call assert_equal(3, winline())
1166
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001167 for lnum in range(5, 7)
1168 call cursor(lnum, 1)
1169 call assert_true(foldclosed(line('.')))
1170 normal gk
1171 call assert_equal(3, winline())
1172 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001173
1174 call cursor(6, 1)
1175 call assert_true(foldclosed(line('.')))
1176 normal 2gk
1177 call assert_equal(2, winline())
1178
1179 set fdm& sw& wrap& tw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001180 bw!
Bram Moolenaare71996b2021-01-21 17:03:07 +01001181endfunc
1182
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001183" Test for using multibyte characters as 'foldopen', 'foldclose' and
1184" 'foldsetp' items in 'fillchars'
1185func s:mbyte_fillchar_tests(fo, fc, fs)
1186 setlocal foldcolumn=3
1187
1188 normal zE
1189 1,2fold
1190 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1191 \ ScreenLines([1, 2], 10))
1192 1,2foldopen
1193 call assert_equal([a:fo .. ' one ', a:fs .. ' two '],
1194 \ ScreenLines([1, 2], 7))
1195 1,2foldclose
1196 redraw!
1197 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1198 \ ScreenLines([1, 2], 10))
1199
1200 " Two level fold
1201 normal zE
1202 2,3fold
1203 1,4fold
1204 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1205 \ ScreenLines([1, 2], 10))
1206 1,4foldopen
1207 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1208 \ ScreenLines([1, 2], 10))
1209 1,4foldopen
1210 call assert_equal([a:fo .. ' one ', a:fs .. a:fo .. ' two ',
1211 \ a:fs .. a:fs .. ' three '], ScreenLines([1, 3], 10))
1212 2,3foldclose
1213 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1214 \ ScreenLines([1, 2], 10))
1215 1,4foldclose
1216 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1217 \ ScreenLines([1, 2], 10))
1218
1219 " Three level fold
1220 normal zE
1221 3,4fold
1222 2,5fold
1223 1,6fold
1224 call assert_equal([a:fc .. ' +-- 6 '], ScreenLines(1, 10))
1225 " open all the folds
1226 normal zR
1227 call assert_equal([
1228 \ a:fo .. ' one ',
1229 \ a:fs .. a:fo .. ' two ',
1230 \ '2' .. a:fo .. ' three ',
1231 \ '23 four ',
1232 \ a:fs .. a:fs .. ' five ',
1233 \ a:fs .. ' six ',
1234 \ ], ScreenLines([1, 6], 10))
1235 " close the innermost fold
1236 3,4foldclose
1237 call assert_equal([
1238 \ a:fo .. ' one ',
1239 \ a:fs .. a:fo .. ' two ',
1240 \ a:fs .. a:fs .. a:fc .. '+---- ',
1241 \ a:fs .. a:fs .. ' five ',
1242 \ a:fs .. ' six ',
1243 \ ], ScreenLines([1, 5], 10))
1244 " close the next fold
1245 2,5foldclose
1246 call assert_equal([
1247 \ a:fo .. ' one ',
1248 \ a:fs .. a:fc .. ' +--- 4',
1249 \ a:fs .. ' six ',
1250 \ ], ScreenLines([1, 3], 10))
1251
1252 " set the fold column size to 2
1253 setlocal fdc=2
1254 normal zR
1255 call assert_equal([
1256 \ a:fo .. ' one ',
1257 \ a:fo .. ' two ',
1258 \ a:fo .. ' three',
1259 \ '3 four ',
1260 \ '2 five ',
1261 \ a:fs .. ' six ',
1262 \ ], ScreenLines([1, 6], 7))
1263
1264 " set the fold column size to 1
1265 setlocal fdc=1
1266 normal zR
1267 call assert_equal([
1268 \ a:fo .. 'one ',
1269 \ a:fo .. 'two ',
1270 \ a:fo .. 'three ',
1271 \ '3four ',
1272 \ '2five ',
1273 \ a:fs .. 'six ',
1274 \ ], ScreenLines([1, 6], 7))
1275
Bram Moolenaar008bff92021-03-04 21:55:58 +01001276 " Enable number and sign columns and place some signs
1277 setlocal fdc=3
1278 setlocal number
1279 setlocal signcolumn=auto
1280 sign define S1 text=->
1281 sign place 10 line=3 name=S1
1282 call assert_equal([
1283 \ a:fo .. ' 1 one ',
1284 \ a:fs .. a:fo .. ' 2 two ',
1285 \ '2' .. a:fo .. ' -> 3 three',
1286 \ '23 4 four ',
1287 \ a:fs .. a:fs .. ' 5 five ',
1288 \ a:fs .. ' 6 six '
1289 \ ], ScreenLines([1, 6], 14))
1290
1291 " Test with 'rightleft'
1292 if has('rightleft')
1293 setlocal rightleft
1294 let lines = ScreenLines([1, 6], winwidth(0))
1295 call assert_equal('o 1 ' .. a:fo,
1296 \ strcharpart(lines[0], strchars(lines[0]) - 10, 10))
1297 call assert_equal('t 2 ' .. a:fo .. a:fs,
1298 \ strcharpart(lines[1], strchars(lines[1]) - 10, 10))
1299 call assert_equal('t 3 >- ' .. a:fo .. '2',
1300 \ strcharpart(lines[2], strchars(lines[2]) - 10, 10))
1301 call assert_equal('f 4 32',
1302 \ strcharpart(lines[3], strchars(lines[3]) - 10, 10))
1303 call assert_equal('f 5 ' .. a:fs .. a:fs,
1304 \ strcharpart(lines[4], strchars(lines[4]) - 10, 10))
1305 call assert_equal('s 6 ' .. a:fs,
1306 \ strcharpart(lines[5], strchars(lines[5]) - 10, 10))
1307 setlocal norightleft
1308 endif
1309
1310 sign unplace *
1311 sign undefine S1
1312 setlocal number& signcolumn&
1313
1314 " Add a test with more than 9 folds (and then delete some folds)
1315 normal zE
1316 for i in range(1, 10)
1317 normal zfGzo
1318 endfor
1319 normal zR
1320 call assert_equal([
1321 \ a:fo .. a:fo .. ' one ',
1322 \ '9> two '
1323 \ ], ScreenLines([1, 2], 7))
1324 normal 1Gzd
1325 call assert_equal([
1326 \ a:fo .. a:fo .. ' one ',
1327 \ '89 two '
1328 \ ], ScreenLines([1, 2], 7))
1329 normal 1Gzdzdzdzdzdzdzd
1330 call assert_equal([
1331 \ a:fo .. a:fo .. ' one ',
1332 \ a:fs .. a:fs .. ' two '
1333 \ ], ScreenLines([1, 2], 7))
1334
1335 setlocal foldcolumn& number& signcolumn&
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001336endfunc
1337
1338func Test_foldcolumn_multibyte_char()
1339 new
1340 call setline(1, ['one', 'two', 'three', 'four', 'five', 'six'])
1341 setlocal foldenable foldmethod=manual
1342
1343 " First test with the default setting
1344 call s:mbyte_fillchar_tests('-', '+', '|')
1345
1346 " Use multi-byte characters
1347 set fillchars+=foldopen:▾,foldsep:│,foldclose:▸
1348 call s:mbyte_fillchar_tests('▾', '▸', '│')
1349
Bram Moolenaar196a1f72021-03-21 14:39:19 +01001350 " Use a mix of multi-byte and single-byte characters
1351 set fillchars+=foldopen:¬,foldsep:\|,foldclose:+
1352 call s:mbyte_fillchar_tests('¬', '+', '|')
1353 set fillchars+=foldopen:+,foldsep:\|,foldclose:¬
1354 call s:mbyte_fillchar_tests('+', '¬', '|')
1355
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001356 bw!
1357 set foldenable& fdc& fdm& fillchars&
1358endfunc
1359
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001360" Test for calling foldlevel() from a fold expression
1361let g:FoldLevels = []
1362func FoldExpr1(lnum)
1363 let f = [a:lnum]
1364 for i in range(1, line('$'))
1365 call add(f, foldlevel(i))
1366 endfor
1367 call add(g:FoldLevels, f)
1368 return getline(a:lnum)[0] == "\t"
1369endfunc
1370
1371func Test_foldexpr_foldlevel()
1372 new
1373 call setline(1, ['one', "\ttwo", "\tthree"])
1374 setlocal foldmethod=expr
1375 setlocal foldexpr=FoldExpr1(v:lnum)
1376 setlocal foldenable
1377 setlocal foldcolumn=3
1378 redraw!
1379 call assert_equal([[1, -1, -1, -1], [2, -1, -1, -1], [3, 0, 1, -1]],
1380 \ g:FoldLevels)
1381 set foldmethod& foldexpr& foldenable& foldcolumn&
1382 bw!
1383endfunc
1384
1385" Test for returning different values from a fold expression
1386func FoldExpr2(lnum)
1387 if a:lnum == 1 || a:lnum == 4
1388 return -2
1389 elseif a:lnum == 2
1390 return 'a1'
1391 elseif a:lnum == 3
1392 return 's4'
1393 endif
1394 return '='
1395endfunc
1396
1397func Test_foldexpr_2()
1398 new
1399 call setline(1, ['one', 'two', 'three', 'four'])
1400 setlocal foldexpr=FoldExpr2(v:lnum)
1401 setlocal foldmethod=expr
1402 call assert_equal([0, 1, 1, 0], [foldlevel(1), foldlevel(2), foldlevel(3),
1403 \ foldlevel(4)])
1404 bw!
1405endfunc
1406
1407" Test for the 'foldclose' option
1408func Test_foldclose_opt()
1409 CheckScreendump
1410
1411 let lines =<< trim END
1412 set foldmethod=manual foldclose=all foldopen=all
1413 call setline(1, ['one', 'two', 'three', 'four'])
1414 2,3fold
1415 func XsaveFoldLevels()
1416 redraw!
1417 call writefile([json_encode([foldclosed(1), foldclosed(2), foldclosed(3),
1418 \ foldclosed(4)])], 'Xoutput', 'a')
1419 endfunc
1420 END
Bram Moolenaar70e67252022-09-27 19:34:35 +01001421 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001422 let rows = 10
1423 let buf = RunVimInTerminal('-S Xscript', {'rows': rows})
1424 call term_wait(buf)
1425 call term_sendkeys(buf, ":set noruler\n")
1426 call term_wait(buf)
1427 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1428 call term_sendkeys(buf, "2G")
1429 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1430 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1431 call term_sendkeys(buf, "4G")
1432 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1433 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1434 call term_sendkeys(buf, "3G")
1435 call WaitForAssert({-> assert_equal('three', term_getline(buf, 3))})
1436 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1437 call term_sendkeys(buf, "1G")
1438 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1439 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001440 call term_sendkeys(buf, "2G")
1441 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1442 call term_sendkeys(buf, "k")
1443 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001444
1445 " clean up
1446 call StopVimInTerminal(buf)
1447
1448 call assert_equal(['[-1,2,2,-1]', '[-1,-1,-1,-1]', '[-1,2,2,-1]',
1449 \ '[-1,-1,-1,-1]', '[-1,2,2,-1]'], readfile('Xoutput'))
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001450 call delete('Xoutput')
1451endfunc
1452
1453" Test for foldtextresult()
1454func Test_foldtextresult()
1455 new
1456 call assert_equal('', foldtextresult(-1))
1457 call assert_equal('', foldtextresult(0))
1458 call assert_equal('', foldtextresult(1))
1459 call setline(1, ['one', 'two', 'three', 'four'])
1460 2,3fold
1461 call assert_equal('', foldtextresult(1))
1462 call assert_equal('+-- 2 lines: two', foldtextresult(2))
1463 setlocal foldtext=
1464 call assert_equal('+-- 2 lines folded ', foldtextresult(2))
1465
1466 " Fold text for a C comment fold
1467 %d _
1468 setlocal foldtext&
1469 call setline(1, ['', '/*', ' * Comment', ' */', ''])
1470 2,4fold
1471 call assert_equal('+-- 3 lines: Comment', foldtextresult(2))
1472
1473 bw!
1474endfunc
1475
1476" Test for merging two recursive folds when an intermediate line with no fold
1477" is removed
dundargocc57b5bc2022-11-02 13:30:51 +00001478func Test_fold_merge_recursive()
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001479 new
1480 call setline(1, [' one', ' two', 'xxxx', ' three',
1481 \ ' four', "\tfive"])
1482 setlocal foldmethod=indent shiftwidth=2
1483 3d_
1484 %foldclose
1485 call assert_equal([1, 5], [foldclosed(5), foldclosedend(1)])
1486 bw!
1487endfunc
1488
1489" Test for moving a line which is the start of a fold from a recursive fold to
1490" outside. The fold length should reduce.
1491func Test_fold_move_foldlevel()
1492 new
1493 call setline(1, ['a{{{', 'b{{{', 'c{{{', 'd}}}', 'e}}}', 'f}}}', 'g'])
1494 setlocal foldmethod=marker
1495 normal zR
1496 call assert_equal([3, 2, 1], [foldlevel(4), foldlevel(5), foldlevel(6)])
1497 3move 7
1498 call assert_equal([2, 1, 0], [foldlevel(3), foldlevel(4), foldlevel(5)])
1499 call assert_equal(1, foldlevel(7))
1500
1501 " Move a line from outside a fold to inside the fold.
1502 %d _
1503 call setline(1, ['a', 'b{{{', 'c}}}'])
1504 normal zR
1505 1move 2
1506 call assert_equal([1, 1, 1], [foldlevel(1), foldlevel(2), foldlevel(3)])
1507
1508 " Move the start of one fold to inside another fold
1509 %d _
1510 call setline(1, ['a', 'b{{{', 'c}}}', 'd{{{', 'e}}}'])
1511 normal zR
1512 call assert_equal([0, 1, 1, 1, 1], [foldlevel(1), foldlevel(2),
1513 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1514 1,2move 4
1515 call assert_equal([0, 1, 1, 2, 2], [foldlevel(1), foldlevel(2),
1516 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1517
1518 bw!
1519endfunc
1520
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001521" Test for using zj and zk to move downwards and upwards to the start and end
1522" of the next fold.
1523" Test for using [z and ]z in a closed fold to jump to the beginning and end
1524" of the fold.
1525func Test_fold_jump()
1526 new
1527 call setline(1, ["\t1", "\t2", "\t\t3", "\t\t4", "\t\t\t5", "\t\t\t6", "\t\t7", "\t\t8", "\t9", "\t10"])
1528 setlocal foldmethod=indent
1529 normal zR
1530 normal zj
1531 call assert_equal(3, line('.'))
1532 normal zj
1533 call assert_equal(5, line('.'))
1534 call assert_beeps('normal zj')
1535 call assert_equal(5, line('.'))
1536 call assert_beeps('normal 9Gzj')
1537 call assert_equal(9, line('.'))
1538 normal Gzk
1539 call assert_equal(8, line('.'))
1540 normal zk
1541 call assert_equal(6, line('.'))
1542 call assert_beeps('normal zk')
1543 call assert_equal(6, line('.'))
1544 call assert_beeps('normal 2Gzk')
1545 call assert_equal(2, line('.'))
1546
1547 " Using [z or ]z in a closed fold should not move the cursor
1548 %d _
1549 call setline(1, ["1", "\t2", "\t3", "\t4", "\t5", "\t6", "7"])
1550 normal zR4Gzc
1551 call assert_equal(4, line('.'))
1552 call assert_beeps('normal [z')
1553 call assert_equal(4, line('.'))
1554 call assert_beeps('normal ]z')
1555 call assert_equal(4, line('.'))
1556 bw!
1557endfunc
1558
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001559" Test for using a script-local function for 'foldexpr'
1560func Test_foldexpr_scriptlocal_func()
1561 func! s:FoldFunc()
1562 let g:FoldLnum = v:lnum
1563 endfunc
1564 new | only
1565 call setline(1, 'abc')
1566 let g:FoldLnum = 0
1567 set foldmethod=expr foldexpr=s:FoldFunc()
1568 redraw!
1569 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
zeertzjq01d4efe2023-01-25 15:31:28 +00001570 call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001571 call assert_equal(1, g:FoldLnum)
1572 set foldmethod& foldexpr=
1573 bw!
1574 new | only
1575 call setline(1, 'abc')
1576 let g:FoldLnum = 0
1577 set foldmethod=expr foldexpr=<SID>FoldFunc()
1578 redraw!
1579 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
zeertzjq01d4efe2023-01-25 15:31:28 +00001580 call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001581 call assert_equal(1, g:FoldLnum)
zeertzjq01d4efe2023-01-25 15:31:28 +00001582 bw!
1583 call setline(1, 'abc')
1584 setlocal foldmethod& foldexpr&
1585 setglobal foldmethod=expr foldexpr=s:FoldFunc()
1586 call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
1587 call assert_equal('0', &foldexpr)
1588 enew!
1589 call setline(1, 'abc')
1590 redraw!
1591 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1592 call assert_equal(1, g:FoldLnum)
1593 bw!
1594 call setline(1, 'abc')
1595 setlocal foldmethod& foldexpr&
1596 setglobal foldmethod=expr foldexpr=<SID>FoldFunc()
1597 call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
1598 call assert_equal('0', &foldexpr)
1599 enew!
1600 call setline(1, 'abc')
1601 redraw!
1602 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1603 call assert_equal(1, g:FoldLnum)
1604 set foldmethod& foldexpr&
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001605 delfunc s:FoldFunc
1606 bw!
1607endfunc
1608
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001609" Test for using a script-local function for 'foldtext'
1610func Test_foldtext_scriptlocal_func()
1611 func! s:FoldText()
1612 let g:FoldTextArgs = [v:foldstart, v:foldend]
1613 return foldtext()
1614 endfunc
1615 new | only
1616 call setline(1, range(50))
1617 let g:FoldTextArgs = []
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001618 set foldtext=s:FoldText()
1619 norm! 4Gzf4j
1620 redraw!
1621 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
zeertzjq01d4efe2023-01-25 15:31:28 +00001622 call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001623 call assert_equal([4, 8], g:FoldTextArgs)
1624 set foldtext&
1625 bw!
1626 new | only
1627 call setline(1, range(50))
1628 let g:FoldTextArgs = []
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001629 set foldtext=<SID>FoldText()
1630 norm! 8Gzf4j
1631 redraw!
1632 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
zeertzjq01d4efe2023-01-25 15:31:28 +00001633 call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001634 call assert_equal([8, 12], g:FoldTextArgs)
1635 set foldtext&
1636 bw!
zeertzjq01d4efe2023-01-25 15:31:28 +00001637 call setline(1, range(50))
1638 let g:FoldTextArgs = []
1639 setlocal foldtext&
1640 setglobal foldtext=s:FoldText()
1641 call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
1642 call assert_equal('foldtext()', &foldtext)
1643 enew!
1644 call setline(1, range(50))
1645 norm! 12Gzf4j
1646 redraw!
1647 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1648 call assert_equal([12, 16], g:FoldTextArgs)
1649 set foldtext&
1650 bw!
1651 call setline(1, range(50))
1652 let g:FoldTextArgs = []
1653 setlocal foldtext&
1654 setglobal foldtext=<SID>FoldText()
1655 call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
1656 call assert_equal('foldtext()', &foldtext)
1657 enew!
1658 call setline(1, range(50))
1659 norm! 16Gzf4j
1660 redraw!
1661 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1662 call assert_equal([16, 20], g:FoldTextArgs)
1663 set foldtext&
1664 bw!
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001665 delfunc s:FoldText
1666endfunc
1667
Yegappan Lakshmananfe424d12024-05-17 18:20:43 +02001668" Test for setting 'foldtext' from the modeline and executing the expression
1669" in a sandbox
1670func Test_foldtext_in_modeline()
1671 func ModelineFoldText()
1672 call feedkeys('aFoo', 'xt')
1673 return "folded text"
1674 endfunc
1675 let lines =<< trim END
1676 func T()
1677 let i = 1
1678 endfunc
1679 " vim: foldenable foldtext=ModelineFoldText()
1680 END
1681 call writefile(lines, 'Xmodelinefoldtext', 'D')
1682
1683 set modeline modelineexpr
1684 split Xmodelinefoldtext
1685
1686 call cursor(1, 1)
1687 normal! zf3j
1688 call assert_equal('folded text', foldtextresult(1))
1689 call assert_equal(lines, getbufline('', 1, '$'))
1690
1691 bw!
1692 set modeline& modelineexpr&
1693 delfunc ModelineFoldText
1694endfunc
1695
Yegappan Lakshmanan4776e642024-05-19 09:06:50 +02001696" Test for setting 'foldexpr' from the modeline and executing the expression
1697" in a sandbox
1698func Test_foldexpr_in_modeline()
1699 func ModelineFoldExpr()
1700 call feedkeys('aFoo', 'xt')
1701 return strlen(matchstr(getline(v:lnum),'^\s*'))
1702 endfunc
1703 let lines =<< trim END
1704 aaa
1705 bbb
1706 ccc
1707 ccc
1708 bbb
1709 aaa
1710 " vim: foldenable foldmethod=expr foldexpr=ModelineFoldExpr()
1711 END
1712 call writefile(lines, 'Xmodelinefoldexpr', 'D')
1713
1714 set modeline modelineexpr
1715 split Xmodelinefoldexpr
1716
1717 call assert_equal(2, foldlevel(3))
1718 call assert_equal(lines, getbufline('', 1, '$'))
1719
1720 bw!
1721 set modeline& modelineexpr&
1722 delfunc ModelineFoldExpr
1723endfunc
1724
Brandon Simmons2c407072022-04-23 13:50:17 +01001725" Make sure a fold containing a nested fold is split correctly when using
1726" foldmethod=indent
1727func Test_fold_split()
1728 new
1729 let lines =<< trim END
1730 line 1
1731 line 2
1732 line 3
1733 line 4
1734 line 5
1735 END
1736 call setline(1, lines)
1737 setlocal sw=2
1738 setlocal foldmethod=indent foldenable
1739 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
1740 call append(2, 'line 2.5')
1741 call assert_equal([0, 1, 0, 1, 2, 2], range(1, 6)->map('foldlevel(v:val)'))
Yegappan Lakshmananee47eac2022-06-29 12:55:36 +01001742 3d
1743 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
Brandon Simmons2c407072022-04-23 13:50:17 +01001744 bw!
1745endfunc
1746
Brandon Simmonsd98e75e2022-05-10 19:13:23 +01001747" Make sure that when you append under a blank line that is under a fold with
1748" the same indent level as your appended line, the fold expands across the
1749" blank line
1750func Test_indent_append_under_blank_line()
1751 new
1752 let lines =<< trim END
1753 line 1
1754 line 2
1755 line 3
1756 END
1757 call setline(1, lines)
1758 setlocal sw=2
1759 setlocal foldmethod=indent foldenable
1760 call assert_equal([0, 1, 1], range(1, 3)->map('foldlevel(v:val)'))
1761 call append(3, '')
1762 call append(4, ' line 5')
1763 call assert_equal([0, 1, 1, 1, 1], range(1, 5)->map('foldlevel(v:val)'))
1764 bw!
1765endfunc
1766
Brandon Simmons3fcccf92022-05-20 18:25:21 +01001767" Make sure that when you delete 1 line of a fold whose length is 2 lines, the
1768" fold can't be closed since its length (1) is now less than foldminlines.
1769func Test_indent_one_line_fold_close()
1770 let lines =<< trim END
1771 line 1
1772 line 2
1773 line 3
1774 END
1775
1776 new
1777 setlocal sw=2 foldmethod=indent
1778 call setline(1, lines)
1779 " open all folds, delete line, then close all folds
1780 normal zR
1781 3delete
1782 normal zM
1783 call assert_equal(-1, foldclosed(2)) " the fold should not be closed
1784
1785 " Now do the same, but delete line 2 this time; this covers different code.
1786 " (Combining this code with the above code doesn't expose both bugs.)
1787 1,$delete
1788 call setline(1, lines)
1789 normal zR
1790 2delete
1791 normal zM
1792 call assert_equal(-1, foldclosed(2))
1793 bw!
1794endfunc
1795
Brandon Simmonse8c4a642022-05-23 15:33:08 +01001796" Make sure that when appending [an indented line then a blank line] right
1797" before a single indented line, the resulting extended fold can be closed
1798func Test_indent_append_blank_small_fold_close()
1799 new
1800 setlocal sw=2 foldmethod=indent
1801 " at first, the fold at the second line can't be closed since it's smaller
1802 " than foldminlines
1803 let lines =<< trim END
1804 line 1
1805 line 4
1806 END
1807 call setline(1, lines)
1808 call append(1, [' line 2', ''])
1809 " close all folds
1810 normal zM
1811 call assert_notequal(-1, foldclosed(2)) " the fold should be closed now
1812 bw!
1813endfunc
1814
Bram Moolenaarf00112d2022-11-11 01:20:35 +00001815func Test_sort_closed_fold()
1816 CheckExecutable sort
1817
1818 call setline(1, [
1819 \ 'Section 1',
1820 \ ' how',
1821 \ ' now',
1822 \ ' brown',
1823 \ ' cow',
1824 \ 'Section 2',
1825 \ ' how',
1826 \ ' now',
1827 \ ' brown',
1828 \ ' cow',
1829 \])
1830 setlocal foldmethod=indent sw=3
1831 normal 2G
1832
1833 " The "!!" expands to ".,.+3" and must only sort four lines
1834 call feedkeys("!!sort\<CR>", 'xt')
1835 call assert_equal([
1836 \ 'Section 1',
1837 \ ' brown',
1838 \ ' cow',
1839 \ ' how',
1840 \ ' now',
1841 \ 'Section 2',
1842 \ ' how',
1843 \ ' now',
1844 \ ' brown',
1845 \ ' cow',
1846 \ ], getline(1, 10))
1847
1848 bwipe!
1849endfunc
1850
Bram Moolenaar232bdaa2023-01-13 14:17:58 +00001851func Test_indent_with_L_command()
1852 " The "L" command moved the cursor to line zero, causing the text saved for
1853 " undo to use line number -1, which caused trouble for undo later.
1854 new
1855 sil! norm 8R V{zf8=Lu
1856 bwipe!
1857endfunc
1858
Brandon Simmonsda3dd7d2023-01-17 19:48:07 +00001859" Make sure that when there is a fold at the bottom of the buffer and a newline
1860" character is appended to the line, the fold gets expanded (instead of the new
1861" line not being part of the fold).
1862func Test_expand_fold_at_bottom_of_buffer()
1863 new
1864 " create a fold on the only line
1865 fold
1866 execute "normal A\<CR>"
1867 call assert_equal([1, 1], range(1, 2)->map('foldlevel(v:val)'))
1868
1869 bwipe!
1870endfunc
1871
Luuk van Baal441a7a92023-02-18 20:15:44 +00001872func Test_fold_screenrow_motion()
1873 call setline(1, repeat(['aaaa'], 5))
1874 1,4fold
1875 norm Ggkzo
1876 call assert_equal(1, line('.'))
1877endfunc
1878
zeertzjq58e1e012023-06-04 18:46:28 +01001879" This was using freed memory
1880func Test_foldcolumn_linebreak_control_char()
1881 CheckFeature linebreak
1882
1883 5vnew
1884 setlocal foldcolumn=1 linebreak
1885 call setline(1, "aaa\<C-A>b")
1886 redraw
1887 call assert_equal([' aaa^', ' Ab '], ScreenLines([1, 2], 5))
1888 call assert_equal(screenattr(1, 5), screenattr(2, 2))
1889
1890 bwipe!
1891endfunc
1892
zeertzjqa991ce92023-10-06 19:16:36 +02001893" This used to cause invalid memory access
1894func Test_foldexpr_return_empty_string()
1895 new
1896 setlocal foldexpr='' foldmethod=expr
1897 redraw
1898
1899 bwipe!
1900endfunc
1901
Shota Nozaki0689b872024-01-03 19:18:43 +01001902" Make sure that when ending a fold that hasn't been started, it does not
1903" start a new fold.
1904func Test_foldexpr_end_fold()
1905 new
1906 setlocal foldmethod=expr
1907 let &l:foldexpr = 'v:lnum == 2 ? "<2" : "="'
1908 call setline(1, range(1, 3))
1909 redraw
1910 call assert_equal([0, 0, 0], range(1, 3)->map('foldlevel(v:val)'))
1911
1912 bwipe!
1913endfunc
1914
Luuk van Baaldc373d42024-07-25 21:24:32 +02001915" Test moving cursor down to or beyond start of folded end of buffer.
1916func Test_cursor_down_fold_eob()
1917 call setline(1, range(1, 4))
1918 norm Gzf2kj
1919 call assert_equal(2, line('.'))
1920 norm zojzc
1921 call assert_equal(3, line('.'))
1922 norm j
1923 call assert_equal(3, line('.'))
1924 norm k2j
1925 call assert_equal(4, line('.'))
1926 bwipe!
1927endfunc
1928
Christian Brabandt8d02e5c2024-08-11 20:12:41 +02001929" issue: #15455
1930func Test_cursor_fold_marker_undo()
1931 new
1932 call setline(1, ['{{{', '', 'This is a Line', '', 'This is a Line', '', '}}}'])
1933 let &ul=&ul
1934 setl foldmethod=marker
1935 call cursor(2, 1)
1936 norm! zo1vjdu
1937 call assert_equal(1, foldlevel('.'))
1938 bwipe!
1939 new
1940 call setline(1, ['', '{{{', '', 'This is a Line', '', 'This is a Line', '', '}}}'])
1941 let &ul=&ul
1942 setl foldmethod=marker
1943 call cursor(3, 1)
1944 norm! zo
1945 norm! vjdu
1946 call assert_equal(1, foldlevel('.'))
1947 bwipe!
1948endfunc
1949
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001950" vim: shiftwidth=2 sts=2 expandtab