blob: d15f607ae090354f92332780e3d2d995b0765ae8 [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
Bram Moolenaar94be6192017-04-22 22:40:11 +020011func Test_address_fold()
Bram Moolenaarded27822017-01-02 14:27:34 +010012 new
13 call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
14 \ 'after fold 1', 'after fold 2', 'after fold 3'])
15 setl fen fdm=marker
Bram Moolenaar518c9b12017-03-21 11:48:39 +010016 " The next commands should all copy the same part of the buffer,
17 " regardless of the addressing type, since the part to be copied
Bram Moolenaarded27822017-01-02 14:27:34 +010018 " is folded away
19 :1y
20 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
21 :.y
22 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
23 :.+y
24 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
25 :.,.y
26 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
27 :sil .1,.y
28 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
29 " use silent to make E493 go away
30 :sil .+,.y
31 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
32 :,y
33 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
34 :,+y
35 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/','after fold 1'], getreg(0,1,1))
36 " using .+3 as second address should copy the whole folded line + the next 3
37 " lines
38 :.,+3y
39 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/',
40 \ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1))
41 :sil .,-2y
42 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
43
44 " now test again with folding disabled
45 set nofoldenable
46 :1y
47 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
48 :.y
49 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
50 :.+y
51 call assert_equal(['1'], getreg(0,1,1))
52 :.,.y
53 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
54 " use silent to make E493 go away
55 :sil .1,.y
56 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
57 " use silent to make E493 go away
58 :sil .+,.y
59 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
60 :,y
61 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
62 :,+y
63 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
64 " using .+3 as second address should copy the whole folded line + the next 3
65 " lines
66 :.,+3y
67 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1))
68 :7
69 :sil .,-2y
70 call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1))
71
72 quit!
Bram Moolenaar1159b162017-02-28 21:53:56 +010073endfunc
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +010074
Bram Moolenaar94be6192017-04-22 22:40:11 +020075func Test_indent_fold()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +010076 new
77 call setline(1, ['', 'a', ' b', ' c'])
78 setl fen fdm=indent
79 2
80 norm! >>
81 let a=map(range(1,4), 'foldclosed(v:val)')
82 call assert_equal([-1,-1,-1,-1], a)
83 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +010084endfunc
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +010085
Bram Moolenaar94be6192017-04-22 22:40:11 +020086func Test_indent_fold2()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +010087 new
88 call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
89 setl fen fdm=marker
90 2
91 norm! >>
Bram Moolenaara4208962019-08-24 20:50:19 +020092 let a=map(range(1,5), 'v:val->foldclosed()')
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +010093 call assert_equal([-1,-1,-1,4,4], a)
94 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +010095endfunc
96
Bram Moolenaar5c504f62021-04-01 13:39:51 +020097" Test for fold indent with indents greater than 'foldnestmax'
98func Test_indent_fold_max()
99 new
100 setlocal foldmethod=indent
101 setlocal shiftwidth=2
102 " 'foldnestmax' default value is 20
103 call setline(1, "\t\t\t\t\t\ta")
104 call assert_equal(20, foldlevel(1))
105 setlocal foldnestmax=10
106 call assert_equal(10, foldlevel(1))
107 setlocal foldnestmax=-1
108 call assert_equal(0, foldlevel(1))
109 bw!
110endfunc
111
Bram Moolenaar1159b162017-02-28 21:53:56 +0100112func Test_manual_fold_with_filter()
Bram Moolenaaraeb313f2020-11-27 19:13:28 +0100113 CheckExecutable cat
Bram Moolenaar3f3897e2017-03-04 15:28:53 +0100114 for type in ['manual', 'marker']
115 exe 'set foldmethod=' . type
116 new
117 call setline(1, range(1, 20))
118 4,$fold
119 %foldopen
120 10,$fold
121 %foldopen
122 " This filter command should not have an effect
123 1,8! cat
124 call feedkeys('5ggzdzMGdd', 'xt')
125 call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
126
127 bwipe!
128 set foldmethod&
129 endfor
Bram Moolenaar1159b162017-02-28 21:53:56 +0100130endfunc
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100131
Bram Moolenaar94be6192017-04-22 22:40:11 +0200132func Test_indent_fold_with_read()
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100133 new
134 set foldmethod=indent
135 call setline(1, repeat(["\<Tab>a"], 4))
136 for n in range(1, 4)
137 call assert_equal(1, foldlevel(n))
138 endfor
139
Bram Moolenaar70e67252022-09-27 19:34:35 +0100140 call writefile(["a", "", "\<Tab>a"], 'Xinfofile', 'D')
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100141 foldopen
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100142 2read Xinfofile
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100143 %foldclose
144 call assert_equal(1, foldlevel(1))
145 call assert_equal(2, foldclosedend(1))
146 call assert_equal(0, foldlevel(3))
147 call assert_equal(0, foldlevel(4))
148 call assert_equal(1, foldlevel(5))
Bram Moolenaara4208962019-08-24 20:50:19 +0200149 call assert_equal(7, 5->foldclosedend())
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100150
151 bwipe!
152 set foldmethod&
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100153endfunc
154
155func Test_combining_folds_indent()
156 new
157 let one = "\<Tab>a"
158 let zero = 'a'
159 call setline(1, [one, one, zero, zero, zero, one, one, one])
160 set foldmethod=indent
161 3,5d
162 %foldclose
163 call assert_equal(5, foldclosedend(1))
164
165 set foldmethod&
166 bwipe!
167endfunc
168
169func Test_combining_folds_marker()
170 new
171 call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
172 set foldmethod=marker
173 3,5d
174 %foldclose
175 call assert_equal(2, foldclosedend(1))
176
177 set foldmethod&
178 bwipe!
179endfunc
180
Bram Moolenaar025a6b72017-03-12 20:37:21 +0100181func Test_folds_marker_in_comment()
182 new
183 call setline(1, ['" foo', 'bar', 'baz'])
184 setl fen fdm=marker
185 setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
186 norm! zf2j
187 setl nofen
188 :1y
189 call assert_equal(['" foo{{{'], getreg(0,1,1))
190 :+2y
191 call assert_equal(['baz"}}}'], getreg(0,1,1))
192
193 set foldmethod&
194 bwipe!
195endfunc
196
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100197func s:TestFoldExpr(lnum)
198 let thisline = getline(a:lnum)
199 if thisline == 'a'
200 return 1
201 elseif thisline == 'b'
202 return 0
203 elseif thisline == 'c'
204 return '<1'
205 elseif thisline == 'd'
206 return '>1'
207 endif
208 return 0
209endfunction
210
211func Test_update_folds_expr_read()
212 new
213 call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
214 set foldmethod=expr
215 set foldexpr=s:TestFoldExpr(v:lnum)
216 2
217 foldopen
Bram Moolenaar70e67252022-09-27 19:34:35 +0100218 call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xupfofile', 'D')
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100219 read Xupfofile
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100220 %foldclose
221 call assert_equal(2, foldclosedend(1))
222 call assert_equal(0, foldlevel(3))
Bram Moolenaara4208962019-08-24 20:50:19 +0200223 call assert_equal(0, 4->foldlevel())
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100224 call assert_equal(6, foldclosedend(5))
225 call assert_equal(10, foldclosedend(7))
226 call assert_equal(14, foldclosedend(11))
227
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100228 bwipe!
229 set foldmethod& foldexpr&
230endfunc
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100231
zeertzjq93c15732022-05-21 16:34:38 +0100232" Test for what patch 8.1.0535 fixes.
233func Test_foldexpr_no_interrupt_addsub()
234 new
235 func! FoldFunc()
236 call setpos('.', getcurpos())
237 return '='
238 endfunc
239
240 set foldmethod=expr
241 set foldexpr=FoldFunc()
242 call setline(1, '1.2')
243
244 exe "norm! $\<C-A>"
245 call assert_equal('1.3', getline(1))
246
247 bwipe!
248 delfunc FoldFunc
249 set foldmethod& foldexpr&
250endfunc
251
Bram Moolenaar94be6192017-04-22 22:40:11 +0200252func Check_foldlevels(expected)
253 call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)'))
254endfunc
255
256func Test_move_folds_around_manual()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100257 new
258 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
259 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
260 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
261 " all folds closed
262 set foldenable foldlevel=0 fdm=indent
263 " needs a forced redraw
264 redraw!
265 set fdm=manual
266 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
267 call assert_equal(input, getline(1, '$'))
268 7,12m0
269 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
270 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
271 10,12m0
272 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
273 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)'))
274 " moving should not close the folds
275 %d
276 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
277 set fdm=indent
278 redraw!
279 set fdm=manual
280 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100281 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100282 7,12m0
283 let folds=repeat([-1], 18)
284 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
285 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
286 norm! zM
287 " folds are not corrupted and all have been closed
288 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)'))
289 %d
290 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
291 set fdm=indent
292 redraw!
293 set fdm=manual
294 %foldopen
295 3m4
296 %foldclose
297 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
298 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
299 %d
300 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
301 set fdm=indent foldlevel=0
302 set fdm=manual
303 %foldopen
304 3m1
305 %foldclose
306 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
307 call assert_equal(0, foldlevel(2))
308 call assert_equal(5, foldclosedend(3))
309 call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
310 2,6m$
311 %foldclose
312 call assert_equal(5, foldclosedend(2))
313 call assert_equal(0, foldlevel(6))
314 call assert_equal(9, foldclosedend(7))
315 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 +0200316
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100317 %d
318 " Ensure moving around the edges still works.
319 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
320 set fdm=indent foldlevel=0
321 set fdm=manual
322 %foldopen
323 6m$
324 " The first fold has been truncated to the 5'th line.
325 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200326 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])
327
328 %delete
329 set fdm=indent foldlevel=0
330 call setline(1, [
331 \ "a",
332 \ "\ta",
333 \ "\t\ta",
334 \ "\t\ta",
335 \ "\t\ta",
336 \ "a",
337 \ "a"])
338 set fdm=manual
339 %foldopen!
340 4,5m6
341 call Check_foldlevels([0, 1, 2, 0, 0, 0, 0])
342
343 %delete
344 set fdm=indent
345 call setline(1, [
346 \ "\ta",
347 \ "\t\ta",
348 \ "\t\ta",
349 \ "\t\ta",
350 \ "\ta",
351 \ "\t\ta",
352 \ "\t\ta",
353 \ "\t\ta",
354 \ "\ta",
355 \ "\t\ta",
356 \ "\t\ta",
357 \ "\t\ta",
358 \ "\t\ta",
359 \ "\ta",
360 \ "a"])
361 set fdm=manual
362 %foldopen!
363 13m7
364 call Check_foldlevels([1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0])
365
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100366 bw!
367endfunc
368
Bram Moolenaar94be6192017-04-22 22:40:11 +0200369func Test_move_folds_around_indent()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100370 new
371 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
372 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
373 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
374 " all folds closed
375 set fdm=indent
376 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
377 call assert_equal(input, getline(1, '$'))
378 7,12m0
379 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
380 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
381 10,12m0
382 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
383 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)'))
384 " moving should not close the folds
385 %d
386 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
387 set fdm=indent
388 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100389 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100390 7,12m0
391 let folds=repeat([-1], 18)
392 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
393 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
394 norm! zM
395 " folds are not corrupted and all have been closed
396 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)'))
397 %d
398 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
399 set fdm=indent
400 %foldopen
401 3m4
402 %foldclose
403 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
404 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
405 %d
406 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
407 set fdm=indent foldlevel=0
408 %foldopen
409 3m1
410 %foldclose
411 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
412 call assert_equal(1, foldlevel(2))
413 call assert_equal(5, foldclosedend(3))
414 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
415 2,6m$
416 %foldclose
417 call assert_equal(9, foldclosedend(2))
418 call assert_equal(1, foldlevel(6))
419 call assert_equal(9, foldclosedend(7))
420 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 +0100421 " Ensure moving around the edges still works.
422 %d
423 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
424 set fdm=indent foldlevel=0
425 %foldopen
426 6m$
427 " The first fold has been truncated to the 5'th line.
428 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200429 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100430 bw!
431endfunc
Bram Moolenaar518c9b12017-03-21 11:48:39 +0100432
433func Test_folddoopen_folddoclosed()
434 new
435 call setline(1, range(1, 9))
436 set foldmethod=manual
437 1,3 fold
438 6,8 fold
439
440 " Test without range.
441 folddoopen s/$/o/
442 folddoclosed s/$/c/
443 call assert_equal(['1c', '2c', '3c',
444 \ '4o', '5o',
445 \ '6c', '7c', '8c',
446 \ '9o'], getline(1, '$'))
447
448 " Test with range.
449 call setline(1, range(1, 9))
450 1,8 folddoopen s/$/o/
451 4,$ folddoclosed s/$/c/
452 call assert_equal(['1', '2', '3',
453 \ '4o', '5o',
454 \ '6c', '7c', '8c',
455 \ '9'], getline(1, '$'))
456
457 set foldmethod&
458 bw!
459endfunc
460
461func Test_fold_error()
462 new
463 call setline(1, [1, 2])
464
465 for fm in ['indent', 'expr', 'syntax', 'diff']
466 exe 'set foldmethod=' . fm
467 call assert_fails('norm zf', 'E350:')
468 call assert_fails('norm zd', 'E351:')
469 call assert_fails('norm zE', 'E352:')
470 endfor
471
472 set foldmethod=manual
473 call assert_fails('norm zd', 'E490:')
474 call assert_fails('norm zo', 'E490:')
475 call assert_fails('3fold', 'E16:')
476
477 set foldmethod=marker
478 set nomodifiable
479 call assert_fails('1,2fold', 'E21:')
480
481 set modifiable&
482 set foldmethod&
483 bw!
484endfunc
Bram Moolenaar495b7dd2017-09-16 17:19:22 +0200485
486func Test_foldtext_recursive()
487 new
488 call setline(1, ['{{{', 'some text', '}}}'])
489 setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
490 " This was crashing because of endless recursion.
491 2foldclose
492 redraw
493 call assert_equal(1, foldlevel(2))
494 call assert_equal(1, foldclosed(2))
495 call assert_equal(3, foldclosedend(2))
496 bwipe!
497endfunc
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100498
499" Various fold related tests
500
501" Basic test if a fold can be created, opened, moving to the end and closed
502func Test_fold_manual()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200503 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100504 set fdm=manual
505
506 let content = ['1 aa', '2 bb', '3 cc']
507 call append(0, content)
508 call cursor(1, 1)
509 normal zf2j
510 call assert_equal('1 aa', getline(foldclosed('.')))
511 normal zo
512 call assert_equal(-1, foldclosed('.'))
513 normal ]z
514 call assert_equal('3 cc', getline('.'))
515 normal zc
516 call assert_equal('1 aa', getline(foldclosed('.')))
517
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200518 " Create a fold inside a closed fold after setting 'foldlevel'
519 %d _
520 call setline(1, range(1, 5))
521 1,5fold
522 normal zR
523 2,4fold
524 set foldlevel=1
525 3fold
526 call assert_equal([1, 3, 3, 3, 1], map(range(1, 5), {->foldlevel(v:val)}))
527 set foldlevel&
528
529 " Create overlapping folds (at the start and at the end)
530 normal zE
531 2,3fold
532 normal zR
533 3,4fold
534 call assert_equal([0, 2, 2, 1, 0], map(range(1, 5), {->foldlevel(v:val)}))
535 normal zE
536 3,4fold
537 normal zR
538 2,3fold
539 call assert_equal([0, 1, 2, 2, 0], map(range(1, 5), {->foldlevel(v:val)}))
540
541 " Create a nested fold across two non-adjoining folds
542 %d _
543 call setline(1, range(1, 7))
544 1,2fold
545 normal zR
546 4,5fold
547 normal zR
548 6,7fold
549 normal zR
550 1,5fold
551 call assert_equal([2, 2, 1, 2, 2, 1, 1],
552 \ map(range(1, 7), {->foldlevel(v:val)}))
553
554 " A newly created nested fold should be closed
555 %d _
556 call setline(1, range(1, 6))
557 1,6fold
558 normal zR
559 3,4fold
560 normal zR
561 2,5fold
562 call assert_equal([1, 2, 3, 3, 2, 1], map(range(1, 6), {->foldlevel(v:val)}))
563 call assert_equal(2, foldclosed(4))
564 call assert_equal(5, foldclosedend(4))
565
566 " Test zO, zC and zA on a line with no folds.
567 normal zE
568 call assert_fails('normal zO', 'E490:')
569 call assert_fails('normal zC', 'E490:')
570 call assert_fails('normal zA', 'E490:')
571
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100572 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200573 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100574endfunc
575
576" test folding with markers.
577func Test_fold_marker()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200578 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100579 set fdm=marker fdl=1 fdc=3
580
581 let content = ['4 dd {{{', '5 ee {{{ }}}', '6 ff }}}']
582 call append(0, content)
583 call cursor(2, 1)
584 call assert_equal(2, foldlevel('.'))
585 normal [z
586 call assert_equal(1, foldlevel('.'))
587 exe "normal jo{{ \<Esc>r{jj"
588 call assert_equal(1, foldlevel('.'))
589 normal kYpj
590 call assert_equal(0, foldlevel('.'))
591
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200592 " Use only closing fold marker (without and with a count)
593 set fdl&
594 %d _
595 call setline(1, ['one }}}', 'two'])
596 call assert_equal([0, 0], [foldlevel(1), foldlevel(2)])
597 %d _
598 call setline(1, ['one }}}4', 'two'])
599 call assert_equal([4, 3], [foldlevel(1), foldlevel(2)])
600
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100601 set fdm& fdl& fdc&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200602 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100603endfunc
604
Bram Moolenaar4af72592018-12-09 15:00:52 +0100605" test create fold markers with C filetype
606func Test_fold_create_marker_in_C()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200607 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100608 set fdm=marker fdl=9
609 set filetype=c
610
Bram Moolenaarc79745a2019-05-20 22:12:34 +0200611 let content =<< trim [CODE]
612 /*
613 * comment
614 *
615 *
616 */
617 int f(int* p) {
618 *p = 3;
619 return 0;
620 }
621 [CODE]
622
Bram Moolenaar4af72592018-12-09 15:00:52 +0100623 for c in range(len(content) - 1)
624 bw!
625 call append(0, content)
626 call cursor(c + 1, 1)
627 norm! zfG
628 call assert_equal(content[c] . (c < 4 ? '{{{' : '/*{{{*/'), getline(c + 1))
629 endfor
630
631 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200632 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100633endfunc
634
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100635" test folding with indent
636func Test_fold_indent()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200637 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100638 set fdm=indent sw=2
639
640 let content = ['1 aa', '2 bb', '3 cc']
641 call append(0, content)
642 call cursor(2, 1)
643 exe "normal i \<Esc>jI "
644 call assert_equal(2, foldlevel('.'))
645 normal k
646 call assert_equal(1, foldlevel('.'))
647
648 set fdm& sw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200649 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100650endfunc
651
652" test syntax folding
653func Test_fold_syntax()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200654 CheckFeature syntax
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100655
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200656 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100657 set fdm=syntax fdl=0
658
659 syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3
660 syn region Fd1 start="ee" end="ff" fold contained
661 syn region Fd2 start="gg" end="hh" fold contained
662 syn region Fd3 start="commentstart" end="commentend" fold contained
663 let content = ['3 cc', '4 dd {{{', '5 ee {{{ }}}', '{{{{', '6 ff }}}',
664 \ '6 ff }}}', '7 gg', '8 hh', '9 ii']
665 call append(0, content)
666 normal Gzk
667 call assert_equal('9 ii', getline('.'))
668 normal k
669 call assert_equal('3 cc', getline('.'))
670 exe "normal jAcommentstart \<Esc>Acommentend"
671 set fdl=1
672 normal 3j
673 call assert_equal('7 gg', getline('.'))
674 set fdl=0
675 exe "normal zO\<C-L>j"
676 call assert_equal('8 hh', getline('.'))
677 syn clear Fd1 Fd2 Fd3 Hup
678
679 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200680 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100681endfunc
682
683func Flvl()
684 let l = getline(v:lnum)
685 if l =~ "bb$"
686 return 2
687 elseif l =~ "gg$"
688 return "s1"
689 elseif l =~ "ii$"
690 return ">2"
691 elseif l =~ "kk$"
692 return "0"
693 endif
694 return "="
695endfun
696
697" test expression folding
698func Test_fold_expr()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200699 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100700 set fdm=expr fde=Flvl()
701
702 let content = ['1 aa',
703 \ '2 bb',
704 \ '3 cc',
705 \ '4 dd {{{commentstart commentend',
706 \ '5 ee {{{ }}}',
707 \ '{{{',
708 \ '6 ff }}}',
709 \ '6 ff }}}',
710 \ ' 7 gg',
711 \ ' 8 hh',
712 \ '9 ii',
713 \ 'a jj',
714 \ 'b kk']
715 call append(0, content)
716 call cursor(1, 1)
717 exe "normal /bb$\<CR>"
718 call assert_equal(2, foldlevel('.'))
719 exe "normal /hh$\<CR>"
720 call assert_equal(1, foldlevel('.'))
721 exe "normal /ii$\<CR>"
722 call assert_equal(2, foldlevel('.'))
723 exe "normal /kk$\<CR>"
724 call assert_equal(0, foldlevel('.'))
725
726 set fdm& fde&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200727 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100728endfunc
729
730" Bug with fdm=indent and moving folds
731" Moving a fold a few times, messes up the folds below the moved fold.
732" Fixed by 7.4.700
733func Test_fold_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200734 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100735 set fdm=indent sw=2 fdl=0
736
737 let content = ['', '', 'Line1', ' Line2', ' Line3',
738 \ 'Line4', ' Line5', ' Line6',
739 \ 'Line7', ' Line8', ' Line9']
740 call append(0, content)
741 normal zM
742 call cursor(4, 1)
743 move 2
744 move 1
745 call assert_equal(7, foldclosed(7))
746 call assert_equal(8, foldclosedend(7))
747 call assert_equal(0, foldlevel(9))
748 call assert_equal(10, foldclosed(10))
749 call assert_equal(11, foldclosedend(10))
750 call assert_equal('+-- 2 lines: Line2', foldtextresult(2))
Bram Moolenaara4208962019-08-24 20:50:19 +0200751 call assert_equal('+-- 2 lines: Line8', 10->foldtextresult())
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100752
753 set fdm& sw& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200754 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100755endfunc
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100756
757" test for patch 7.3.637
758" Cannot catch the error caused by a foldopen when there is no fold.
759func Test_foldopen_exception()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200760 new
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100761 let a = 'No error caught'
762 try
763 foldopen
764 catch
765 let a = matchstr(v:exception,'^[^ ]*')
766 endtry
767 call assert_equal('Vim(foldopen):E490:', a)
768
769 let a = 'No error caught'
770 try
771 foobar
772 catch
773 let a = matchstr(v:exception,'^[^ ]*')
774 endtry
775 call assert_match('E492:', a)
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200776 bw!
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100777endfunc
Bram Moolenaar907dad72018-07-10 15:07:15 +0200778
779func Test_fold_last_line_with_pagedown()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200780 new
Bram Moolenaar907dad72018-07-10 15:07:15 +0200781 set fdm=manual
782
783 let expect = '+-- 11 lines: 9---'
784 let content = range(1,19)
785 call append(0, content)
786 normal dd9G
787 normal zfG
788 normal zt
789 call assert_equal('9', getline(foldclosed('.')))
790 call assert_equal('19', getline(foldclosedend('.')))
791 call assert_equal(expect, ScreenLines(1, len(expect))[0])
792 call feedkeys("\<C-F>", 'xt')
793 call assert_equal(expect, ScreenLines(1, len(expect))[0])
794 call feedkeys("\<C-F>", 'xt')
795 call assert_equal(expect, ScreenLines(1, len(expect))[0])
796 call feedkeys("\<C-B>\<C-F>\<C-F>", 'xt')
797 call assert_equal(expect, ScreenLines(1, len(expect))[0])
798
799 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200800 bw!
Bram Moolenaar907dad72018-07-10 15:07:15 +0200801endfunc
Bram Moolenaar7701f302018-10-02 21:20:32 +0200802
803func Test_folds_with_rnu()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200804 CheckScreendump
Bram Moolenaar7701f302018-10-02 21:20:32 +0200805
806 call writefile([
807 \ 'set fdm=marker rnu foldcolumn=2',
808 \ 'call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])',
Bram Moolenaar70e67252022-09-27 19:34:35 +0100809 \ ], 'Xtest_folds_with_rnu', 'D')
Bram Moolenaar7701f302018-10-02 21:20:32 +0200810 let buf = RunVimInTerminal('-S Xtest_folds_with_rnu', {})
811
812 call VerifyScreenDump(buf, 'Test_folds_with_rnu_01', {})
813 call term_sendkeys(buf, "j")
814 call VerifyScreenDump(buf, 'Test_folds_with_rnu_02', {})
815
816 " clean up
817 call StopVimInTerminal(buf)
Bram Moolenaar7701f302018-10-02 21:20:32 +0200818endfunc
Bram Moolenaar53932812018-12-07 21:08:49 +0100819
820func Test_folds_marker_in_comment2()
821 new
822 call setline(1, ['Lorem ipsum dolor sit', 'Lorem ipsum dolor sit', 'Lorem ipsum dolor sit'])
823 setl fen fdm=marker
824 setl commentstring=<!--%s-->
825 setl comments=s:<!--,m:\ \ \ \ ,e:-->
826 norm! zf2j
827 setl nofen
828 :1y
829 call assert_equal(['Lorem ipsum dolor sit<!--{{{-->'], getreg(0,1,1))
830 :+2y
831 call assert_equal(['Lorem ipsum dolor sit<!--}}}-->'], getreg(0,1,1))
832
833 set foldmethod&
834 bwipe!
835endfunc
Bram Moolenaar9a4a8c42019-08-19 22:48:30 +0200836
837func Test_fold_delete_with_marker()
838 new
839 call setline(1, ['func Func() {{{1', 'endfunc'])
840 1,2yank
841 new
842 set fdm=marker
843 call setline(1, 'x')
844 normal! Vp
845 normal! zd
846 call assert_equal(['func Func() ', 'endfunc'], getline(1, '$'))
847
848 set fdm&
849 bwipe!
850 bwipe!
851endfunc
Bram Moolenaar7a9bd7c2019-09-17 22:42:55 +0200852
853func Test_fold_delete_with_marker_and_whichwrap()
854 new
855 let content1 = ['']
856 let content2 = ['folded line 1 "{{{1', ' test', ' test2', ' test3', '', 'folded line 2 "{{{1', ' test', ' test2', ' test3']
857 call setline(1, content1 + content2)
858 set fdm=marker ww+=l
859 normal! x
860 call assert_equal(content2, getline(1, '$'))
861 set fdm& ww&
862 bwipe!
863endfunc
Bram Moolenaar3b681232019-12-13 19:35:55 +0100864
865func Test_fold_delete_first_line()
866 new
867 call setline(1, [
868 \ '" x {{{1',
869 \ '" a',
870 \ '" aa',
871 \ '" x {{{1',
872 \ '" b',
873 \ '" bb',
874 \ '" x {{{1',
875 \ '" c',
876 \ '" cc',
877 \ ])
878 set foldmethod=marker
879 1
880 normal dj
881 call assert_equal([
882 \ '" x {{{1',
883 \ '" c',
884 \ '" cc',
885 \ ], getline(1,'$'))
886 bwipe!
887 set foldmethod&
888endfunc
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200889
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200890" Add a test for deleting the outer fold of a nested fold and promoting the
891" inner folds to one level up with already a fold at that level following the
892" nested fold.
893func Test_fold_delete_recursive_fold()
894 new
895 call setline(1, range(1, 7))
896 2,3fold
897 normal zR
898 4,5fold
899 normal zR
900 1,5fold
901 normal zR
902 6,7fold
903 normal zR
904 normal 1Gzd
905 normal 1Gzj
906 call assert_equal(2, line('.'))
907 normal zj
908 call assert_equal(4, line('.'))
909 normal zj
910 call assert_equal(6, line('.'))
911 bw!
912endfunc
913
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200914" Test for errors in 'foldexpr'
915func Test_fold_expr_error()
916 new
917 call setline(1, ['one', 'two', 'three'])
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200918 " In a window with no folds, foldlevel() should return 0
919 call assert_equal(0, foldlevel(1))
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200920
921 " Return a list from the expression
922 set foldexpr=[]
923 set foldmethod=expr
924 for i in range(3)
925 call assert_equal(0, foldlevel(i))
926 endfor
927
928 " expression error
929 set foldexpr=[{]
930 set foldmethod=expr
931 for i in range(3)
932 call assert_equal(0, foldlevel(i))
933 endfor
934
935 set foldmethod& foldexpr&
936 close!
937endfunc
938
Bram Moolenaarda697642020-09-17 19:36:04 +0200939func Test_undo_fold_deletion()
940 new
941 set fdm=marker
942 let lines =<< trim END
943 " {{{
944 " }}}1
945 " {{{
946 END
947 call setline(1, lines)
948 3d
949 g/"/d
950 undo
951 redo
952 eval getline(1, '$')->assert_equal([''])
953
954 set fdm&vim
955 bwipe!
956endfunc
957
Bram Moolenaarc136a352020-11-03 20:05:40 +0100958" this was crashing
959func Test_move_no_folds()
960 new
961 fold
962 setlocal fdm=expr
963 normal zj
964 bwipe!
965endfunc
966
Bram Moolenaar5e1f22f2020-11-10 18:23:52 +0100967" this was crashing
968func Test_fold_create_delete_create()
969 new
970 fold
971 fold
972 normal zd
973 fold
974 bwipe!
975endfunc
976
Bram Moolenaar6a78f322020-12-21 14:01:41 +0100977" this was crashing
978func Test_fold_create_delete()
979 new
980 norm zFzFzdzj
981 bwipe!
982endfunc
983
Bram Moolenaare71996b2021-01-21 17:03:07 +0100984func Test_fold_relative_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200985 new
Bram Moolenaare71996b2021-01-21 17:03:07 +0100986 set fdm=indent sw=2 wrap tw=80
987
Bram Moolenaar3c49e742021-04-04 21:26:04 +0200988 let longtext = repeat('x', &columns + 1)
989 let content = [ ' foo', ' ' .. longtext, ' baz',
990 \ longtext,
991 \ ' foo', ' ' .. longtext, ' baz'
Bram Moolenaare71996b2021-01-21 17:03:07 +0100992 \ ]
993 call append(0, content)
994
995 normal zM
996
Bram Moolenaar3c49e742021-04-04 21:26:04 +0200997 for lnum in range(1, 3)
998 call cursor(lnum, 1)
999 call assert_true(foldclosed(line('.')))
1000 normal gj
1001 call assert_equal(2, winline())
1002 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001003
1004 call cursor(2, 1)
1005 call assert_true(foldclosed(line('.')))
1006 normal 2gj
1007 call assert_equal(3, winline())
1008
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001009 for lnum in range(5, 7)
1010 call cursor(lnum, 1)
1011 call assert_true(foldclosed(line('.')))
1012 normal gk
1013 call assert_equal(3, winline())
1014 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001015
1016 call cursor(6, 1)
1017 call assert_true(foldclosed(line('.')))
1018 normal 2gk
1019 call assert_equal(2, winline())
1020
1021 set fdm& sw& wrap& tw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001022 bw!
Bram Moolenaare71996b2021-01-21 17:03:07 +01001023endfunc
1024
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001025" Test for using multibyte characters as 'foldopen', 'foldclose' and
1026" 'foldsetp' items in 'fillchars'
1027func s:mbyte_fillchar_tests(fo, fc, fs)
1028 setlocal foldcolumn=3
1029
1030 normal zE
1031 1,2fold
1032 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1033 \ ScreenLines([1, 2], 10))
1034 1,2foldopen
1035 call assert_equal([a:fo .. ' one ', a:fs .. ' two '],
1036 \ ScreenLines([1, 2], 7))
1037 1,2foldclose
1038 redraw!
1039 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1040 \ ScreenLines([1, 2], 10))
1041
1042 " Two level fold
1043 normal zE
1044 2,3fold
1045 1,4fold
1046 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1047 \ ScreenLines([1, 2], 10))
1048 1,4foldopen
1049 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1050 \ ScreenLines([1, 2], 10))
1051 1,4foldopen
1052 call assert_equal([a:fo .. ' one ', a:fs .. a:fo .. ' two ',
1053 \ a:fs .. a:fs .. ' three '], ScreenLines([1, 3], 10))
1054 2,3foldclose
1055 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1056 \ ScreenLines([1, 2], 10))
1057 1,4foldclose
1058 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1059 \ ScreenLines([1, 2], 10))
1060
1061 " Three level fold
1062 normal zE
1063 3,4fold
1064 2,5fold
1065 1,6fold
1066 call assert_equal([a:fc .. ' +-- 6 '], ScreenLines(1, 10))
1067 " open all the folds
1068 normal zR
1069 call assert_equal([
1070 \ a:fo .. ' one ',
1071 \ a:fs .. a:fo .. ' two ',
1072 \ '2' .. a:fo .. ' three ',
1073 \ '23 four ',
1074 \ a:fs .. a:fs .. ' five ',
1075 \ a:fs .. ' six ',
1076 \ ], ScreenLines([1, 6], 10))
1077 " close the innermost fold
1078 3,4foldclose
1079 call assert_equal([
1080 \ a:fo .. ' one ',
1081 \ a:fs .. a:fo .. ' two ',
1082 \ a:fs .. a:fs .. a:fc .. '+---- ',
1083 \ a:fs .. a:fs .. ' five ',
1084 \ a:fs .. ' six ',
1085 \ ], ScreenLines([1, 5], 10))
1086 " close the next fold
1087 2,5foldclose
1088 call assert_equal([
1089 \ a:fo .. ' one ',
1090 \ a:fs .. a:fc .. ' +--- 4',
1091 \ a:fs .. ' six ',
1092 \ ], ScreenLines([1, 3], 10))
1093
1094 " set the fold column size to 2
1095 setlocal fdc=2
1096 normal zR
1097 call assert_equal([
1098 \ a:fo .. ' one ',
1099 \ a:fo .. ' two ',
1100 \ a:fo .. ' three',
1101 \ '3 four ',
1102 \ '2 five ',
1103 \ a:fs .. ' six ',
1104 \ ], ScreenLines([1, 6], 7))
1105
1106 " set the fold column size to 1
1107 setlocal fdc=1
1108 normal zR
1109 call assert_equal([
1110 \ a:fo .. 'one ',
1111 \ a:fo .. 'two ',
1112 \ a:fo .. 'three ',
1113 \ '3four ',
1114 \ '2five ',
1115 \ a:fs .. 'six ',
1116 \ ], ScreenLines([1, 6], 7))
1117
Bram Moolenaar008bff92021-03-04 21:55:58 +01001118 " Enable number and sign columns and place some signs
1119 setlocal fdc=3
1120 setlocal number
1121 setlocal signcolumn=auto
1122 sign define S1 text=->
1123 sign place 10 line=3 name=S1
1124 call assert_equal([
1125 \ a:fo .. ' 1 one ',
1126 \ a:fs .. a:fo .. ' 2 two ',
1127 \ '2' .. a:fo .. ' -> 3 three',
1128 \ '23 4 four ',
1129 \ a:fs .. a:fs .. ' 5 five ',
1130 \ a:fs .. ' 6 six '
1131 \ ], ScreenLines([1, 6], 14))
1132
1133 " Test with 'rightleft'
1134 if has('rightleft')
1135 setlocal rightleft
1136 let lines = ScreenLines([1, 6], winwidth(0))
1137 call assert_equal('o 1 ' .. a:fo,
1138 \ strcharpart(lines[0], strchars(lines[0]) - 10, 10))
1139 call assert_equal('t 2 ' .. a:fo .. a:fs,
1140 \ strcharpart(lines[1], strchars(lines[1]) - 10, 10))
1141 call assert_equal('t 3 >- ' .. a:fo .. '2',
1142 \ strcharpart(lines[2], strchars(lines[2]) - 10, 10))
1143 call assert_equal('f 4 32',
1144 \ strcharpart(lines[3], strchars(lines[3]) - 10, 10))
1145 call assert_equal('f 5 ' .. a:fs .. a:fs,
1146 \ strcharpart(lines[4], strchars(lines[4]) - 10, 10))
1147 call assert_equal('s 6 ' .. a:fs,
1148 \ strcharpart(lines[5], strchars(lines[5]) - 10, 10))
1149 setlocal norightleft
1150 endif
1151
1152 sign unplace *
1153 sign undefine S1
1154 setlocal number& signcolumn&
1155
1156 " Add a test with more than 9 folds (and then delete some folds)
1157 normal zE
1158 for i in range(1, 10)
1159 normal zfGzo
1160 endfor
1161 normal zR
1162 call assert_equal([
1163 \ a:fo .. a:fo .. ' one ',
1164 \ '9> two '
1165 \ ], ScreenLines([1, 2], 7))
1166 normal 1Gzd
1167 call assert_equal([
1168 \ a:fo .. a:fo .. ' one ',
1169 \ '89 two '
1170 \ ], ScreenLines([1, 2], 7))
1171 normal 1Gzdzdzdzdzdzdzd
1172 call assert_equal([
1173 \ a:fo .. a:fo .. ' one ',
1174 \ a:fs .. a:fs .. ' two '
1175 \ ], ScreenLines([1, 2], 7))
1176
1177 setlocal foldcolumn& number& signcolumn&
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001178endfunc
1179
1180func Test_foldcolumn_multibyte_char()
1181 new
1182 call setline(1, ['one', 'two', 'three', 'four', 'five', 'six'])
1183 setlocal foldenable foldmethod=manual
1184
1185 " First test with the default setting
1186 call s:mbyte_fillchar_tests('-', '+', '|')
1187
1188 " Use multi-byte characters
1189 set fillchars+=foldopen:▾,foldsep:│,foldclose:▸
1190 call s:mbyte_fillchar_tests('▾', '▸', '│')
1191
Bram Moolenaar196a1f72021-03-21 14:39:19 +01001192 " Use a mix of multi-byte and single-byte characters
1193 set fillchars+=foldopen:¬,foldsep:\|,foldclose:+
1194 call s:mbyte_fillchar_tests('¬', '+', '|')
1195 set fillchars+=foldopen:+,foldsep:\|,foldclose:¬
1196 call s:mbyte_fillchar_tests('+', '¬', '|')
1197
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001198 bw!
1199 set foldenable& fdc& fdm& fillchars&
1200endfunc
1201
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001202" Test for calling foldlevel() from a fold expression
1203let g:FoldLevels = []
1204func FoldExpr1(lnum)
1205 let f = [a:lnum]
1206 for i in range(1, line('$'))
1207 call add(f, foldlevel(i))
1208 endfor
1209 call add(g:FoldLevels, f)
1210 return getline(a:lnum)[0] == "\t"
1211endfunc
1212
1213func Test_foldexpr_foldlevel()
1214 new
1215 call setline(1, ['one', "\ttwo", "\tthree"])
1216 setlocal foldmethod=expr
1217 setlocal foldexpr=FoldExpr1(v:lnum)
1218 setlocal foldenable
1219 setlocal foldcolumn=3
1220 redraw!
1221 call assert_equal([[1, -1, -1, -1], [2, -1, -1, -1], [3, 0, 1, -1]],
1222 \ g:FoldLevels)
1223 set foldmethod& foldexpr& foldenable& foldcolumn&
1224 bw!
1225endfunc
1226
1227" Test for returning different values from a fold expression
1228func FoldExpr2(lnum)
1229 if a:lnum == 1 || a:lnum == 4
1230 return -2
1231 elseif a:lnum == 2
1232 return 'a1'
1233 elseif a:lnum == 3
1234 return 's4'
1235 endif
1236 return '='
1237endfunc
1238
1239func Test_foldexpr_2()
1240 new
1241 call setline(1, ['one', 'two', 'three', 'four'])
1242 setlocal foldexpr=FoldExpr2(v:lnum)
1243 setlocal foldmethod=expr
1244 call assert_equal([0, 1, 1, 0], [foldlevel(1), foldlevel(2), foldlevel(3),
1245 \ foldlevel(4)])
1246 bw!
1247endfunc
1248
1249" Test for the 'foldclose' option
1250func Test_foldclose_opt()
1251 CheckScreendump
1252
1253 let lines =<< trim END
1254 set foldmethod=manual foldclose=all foldopen=all
1255 call setline(1, ['one', 'two', 'three', 'four'])
1256 2,3fold
1257 func XsaveFoldLevels()
1258 redraw!
1259 call writefile([json_encode([foldclosed(1), foldclosed(2), foldclosed(3),
1260 \ foldclosed(4)])], 'Xoutput', 'a')
1261 endfunc
1262 END
Bram Moolenaar70e67252022-09-27 19:34:35 +01001263 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001264 let rows = 10
1265 let buf = RunVimInTerminal('-S Xscript', {'rows': rows})
1266 call term_wait(buf)
1267 call term_sendkeys(buf, ":set noruler\n")
1268 call term_wait(buf)
1269 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1270 call term_sendkeys(buf, "2G")
1271 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1272 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1273 call term_sendkeys(buf, "4G")
1274 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1275 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1276 call term_sendkeys(buf, "3G")
1277 call WaitForAssert({-> assert_equal('three', term_getline(buf, 3))})
1278 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1279 call term_sendkeys(buf, "1G")
1280 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1281 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001282 call term_sendkeys(buf, "2G")
1283 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1284 call term_sendkeys(buf, "k")
1285 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001286
1287 " clean up
1288 call StopVimInTerminal(buf)
1289
1290 call assert_equal(['[-1,2,2,-1]', '[-1,-1,-1,-1]', '[-1,2,2,-1]',
1291 \ '[-1,-1,-1,-1]', '[-1,2,2,-1]'], readfile('Xoutput'))
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001292 call delete('Xoutput')
1293endfunc
1294
1295" Test for foldtextresult()
1296func Test_foldtextresult()
1297 new
1298 call assert_equal('', foldtextresult(-1))
1299 call assert_equal('', foldtextresult(0))
1300 call assert_equal('', foldtextresult(1))
1301 call setline(1, ['one', 'two', 'three', 'four'])
1302 2,3fold
1303 call assert_equal('', foldtextresult(1))
1304 call assert_equal('+-- 2 lines: two', foldtextresult(2))
1305 setlocal foldtext=
1306 call assert_equal('+-- 2 lines folded ', foldtextresult(2))
1307
1308 " Fold text for a C comment fold
1309 %d _
1310 setlocal foldtext&
1311 call setline(1, ['', '/*', ' * Comment', ' */', ''])
1312 2,4fold
1313 call assert_equal('+-- 3 lines: Comment', foldtextresult(2))
1314
1315 bw!
1316endfunc
1317
1318" Test for merging two recursive folds when an intermediate line with no fold
1319" is removed
1320func Test_fold_merge_recrusive()
1321 new
1322 call setline(1, [' one', ' two', 'xxxx', ' three',
1323 \ ' four', "\tfive"])
1324 setlocal foldmethod=indent shiftwidth=2
1325 3d_
1326 %foldclose
1327 call assert_equal([1, 5], [foldclosed(5), foldclosedend(1)])
1328 bw!
1329endfunc
1330
1331" Test for moving a line which is the start of a fold from a recursive fold to
1332" outside. The fold length should reduce.
1333func Test_fold_move_foldlevel()
1334 new
1335 call setline(1, ['a{{{', 'b{{{', 'c{{{', 'd}}}', 'e}}}', 'f}}}', 'g'])
1336 setlocal foldmethod=marker
1337 normal zR
1338 call assert_equal([3, 2, 1], [foldlevel(4), foldlevel(5), foldlevel(6)])
1339 3move 7
1340 call assert_equal([2, 1, 0], [foldlevel(3), foldlevel(4), foldlevel(5)])
1341 call assert_equal(1, foldlevel(7))
1342
1343 " Move a line from outside a fold to inside the fold.
1344 %d _
1345 call setline(1, ['a', 'b{{{', 'c}}}'])
1346 normal zR
1347 1move 2
1348 call assert_equal([1, 1, 1], [foldlevel(1), foldlevel(2), foldlevel(3)])
1349
1350 " Move the start of one fold to inside another fold
1351 %d _
1352 call setline(1, ['a', 'b{{{', 'c}}}', 'd{{{', 'e}}}'])
1353 normal zR
1354 call assert_equal([0, 1, 1, 1, 1], [foldlevel(1), foldlevel(2),
1355 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1356 1,2move 4
1357 call assert_equal([0, 1, 1, 2, 2], [foldlevel(1), foldlevel(2),
1358 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1359
1360 bw!
1361endfunc
1362
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001363" Test for using zj and zk to move downwards and upwards to the start and end
1364" of the next fold.
1365" Test for using [z and ]z in a closed fold to jump to the beginning and end
1366" of the fold.
1367func Test_fold_jump()
1368 new
1369 call setline(1, ["\t1", "\t2", "\t\t3", "\t\t4", "\t\t\t5", "\t\t\t6", "\t\t7", "\t\t8", "\t9", "\t10"])
1370 setlocal foldmethod=indent
1371 normal zR
1372 normal zj
1373 call assert_equal(3, line('.'))
1374 normal zj
1375 call assert_equal(5, line('.'))
1376 call assert_beeps('normal zj')
1377 call assert_equal(5, line('.'))
1378 call assert_beeps('normal 9Gzj')
1379 call assert_equal(9, line('.'))
1380 normal Gzk
1381 call assert_equal(8, line('.'))
1382 normal zk
1383 call assert_equal(6, line('.'))
1384 call assert_beeps('normal zk')
1385 call assert_equal(6, line('.'))
1386 call assert_beeps('normal 2Gzk')
1387 call assert_equal(2, line('.'))
1388
1389 " Using [z or ]z in a closed fold should not move the cursor
1390 %d _
1391 call setline(1, ["1", "\t2", "\t3", "\t4", "\t5", "\t6", "7"])
1392 normal zR4Gzc
1393 call assert_equal(4, line('.'))
1394 call assert_beeps('normal [z')
1395 call assert_equal(4, line('.'))
1396 call assert_beeps('normal ]z')
1397 call assert_equal(4, line('.'))
1398 bw!
1399endfunc
1400
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001401" Test for using a script-local function for 'foldexpr'
1402func Test_foldexpr_scriptlocal_func()
1403 func! s:FoldFunc()
1404 let g:FoldLnum = v:lnum
1405 endfunc
1406 new | only
1407 call setline(1, 'abc')
1408 let g:FoldLnum = 0
1409 set foldmethod=expr foldexpr=s:FoldFunc()
1410 redraw!
1411 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1412 call assert_equal(1, g:FoldLnum)
1413 set foldmethod& foldexpr=
1414 bw!
1415 new | only
1416 call setline(1, 'abc')
1417 let g:FoldLnum = 0
1418 set foldmethod=expr foldexpr=<SID>FoldFunc()
1419 redraw!
1420 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1421 call assert_equal(1, g:FoldLnum)
1422 set foldmethod& foldexpr=
1423 delfunc s:FoldFunc
1424 bw!
1425endfunc
1426
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001427" Test for using a script-local function for 'foldtext'
1428func Test_foldtext_scriptlocal_func()
1429 func! s:FoldText()
1430 let g:FoldTextArgs = [v:foldstart, v:foldend]
1431 return foldtext()
1432 endfunc
1433 new | only
1434 call setline(1, range(50))
1435 let g:FoldTextArgs = []
1436 set foldmethod=manual
1437 set foldtext=s:FoldText()
1438 norm! 4Gzf4j
1439 redraw!
1440 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1441 call assert_equal([4, 8], g:FoldTextArgs)
1442 set foldtext&
1443 bw!
1444 new | only
1445 call setline(1, range(50))
1446 let g:FoldTextArgs = []
1447 set foldmethod=manual
1448 set foldtext=<SID>FoldText()
1449 norm! 8Gzf4j
1450 redraw!
1451 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1452 call assert_equal([8, 12], g:FoldTextArgs)
1453 set foldtext&
1454 bw!
1455 delfunc s:FoldText
1456endfunc
1457
Brandon Simmons2c407072022-04-23 13:50:17 +01001458" Make sure a fold containing a nested fold is split correctly when using
1459" foldmethod=indent
1460func Test_fold_split()
1461 new
1462 let lines =<< trim END
1463 line 1
1464 line 2
1465 line 3
1466 line 4
1467 line 5
1468 END
1469 call setline(1, lines)
1470 setlocal sw=2
1471 setlocal foldmethod=indent foldenable
1472 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
1473 call append(2, 'line 2.5')
1474 call assert_equal([0, 1, 0, 1, 2, 2], range(1, 6)->map('foldlevel(v:val)'))
Yegappan Lakshmananee47eac2022-06-29 12:55:36 +01001475 3d
1476 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
Brandon Simmons2c407072022-04-23 13:50:17 +01001477 bw!
1478endfunc
1479
Brandon Simmonsd98e75e2022-05-10 19:13:23 +01001480" Make sure that when you append under a blank line that is under a fold with
1481" the same indent level as your appended line, the fold expands across the
1482" blank line
1483func Test_indent_append_under_blank_line()
1484 new
1485 let lines =<< trim END
1486 line 1
1487 line 2
1488 line 3
1489 END
1490 call setline(1, lines)
1491 setlocal sw=2
1492 setlocal foldmethod=indent foldenable
1493 call assert_equal([0, 1, 1], range(1, 3)->map('foldlevel(v:val)'))
1494 call append(3, '')
1495 call append(4, ' line 5')
1496 call assert_equal([0, 1, 1, 1, 1], range(1, 5)->map('foldlevel(v:val)'))
1497 bw!
1498endfunc
1499
Brandon Simmons3fcccf92022-05-20 18:25:21 +01001500" Make sure that when you delete 1 line of a fold whose length is 2 lines, the
1501" fold can't be closed since its length (1) is now less than foldminlines.
1502func Test_indent_one_line_fold_close()
1503 let lines =<< trim END
1504 line 1
1505 line 2
1506 line 3
1507 END
1508
1509 new
1510 setlocal sw=2 foldmethod=indent
1511 call setline(1, lines)
1512 " open all folds, delete line, then close all folds
1513 normal zR
1514 3delete
1515 normal zM
1516 call assert_equal(-1, foldclosed(2)) " the fold should not be closed
1517
1518 " Now do the same, but delete line 2 this time; this covers different code.
1519 " (Combining this code with the above code doesn't expose both bugs.)
1520 1,$delete
1521 call setline(1, lines)
1522 normal zR
1523 2delete
1524 normal zM
1525 call assert_equal(-1, foldclosed(2))
1526 bw!
1527endfunc
1528
Brandon Simmonse8c4a642022-05-23 15:33:08 +01001529" Make sure that when appending [an indented line then a blank line] right
1530" before a single indented line, the resulting extended fold can be closed
1531func Test_indent_append_blank_small_fold_close()
1532 new
1533 setlocal sw=2 foldmethod=indent
1534 " at first, the fold at the second line can't be closed since it's smaller
1535 " than foldminlines
1536 let lines =<< trim END
1537 line 1
1538 line 4
1539 END
1540 call setline(1, lines)
1541 call append(1, [' line 2', ''])
1542 " close all folds
1543 normal zM
1544 call assert_notequal(-1, foldclosed(2)) " the fold should be closed now
1545 bw!
1546endfunc
1547
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001548" vim: shiftwidth=2 sts=2 expandtab