blob: 52185dca4359e492a9e05a00494f7969b3d97f1a [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
140 call writefile(["a", "", "\<Tab>a"], 'Xfile')
141 foldopen
142 2read Xfile
143 %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&
153 call delete('Xfile')
154endfunc
155
156func Test_combining_folds_indent()
157 new
158 let one = "\<Tab>a"
159 let zero = 'a'
160 call setline(1, [one, one, zero, zero, zero, one, one, one])
161 set foldmethod=indent
162 3,5d
163 %foldclose
164 call assert_equal(5, foldclosedend(1))
165
166 set foldmethod&
167 bwipe!
168endfunc
169
170func Test_combining_folds_marker()
171 new
172 call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
173 set foldmethod=marker
174 3,5d
175 %foldclose
176 call assert_equal(2, foldclosedend(1))
177
178 set foldmethod&
179 bwipe!
180endfunc
181
Bram Moolenaar025a6b72017-03-12 20:37:21 +0100182func Test_folds_marker_in_comment()
183 new
184 call setline(1, ['" foo', 'bar', 'baz'])
185 setl fen fdm=marker
186 setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
187 norm! zf2j
188 setl nofen
189 :1y
190 call assert_equal(['" foo{{{'], getreg(0,1,1))
191 :+2y
192 call assert_equal(['baz"}}}'], getreg(0,1,1))
193
194 set foldmethod&
195 bwipe!
196endfunc
197
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100198func s:TestFoldExpr(lnum)
199 let thisline = getline(a:lnum)
200 if thisline == 'a'
201 return 1
202 elseif thisline == 'b'
203 return 0
204 elseif thisline == 'c'
205 return '<1'
206 elseif thisline == 'd'
207 return '>1'
208 endif
209 return 0
210endfunction
211
212func Test_update_folds_expr_read()
213 new
214 call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
215 set foldmethod=expr
216 set foldexpr=s:TestFoldExpr(v:lnum)
217 2
218 foldopen
219 call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile')
220 read Xfile
221 %foldclose
222 call assert_equal(2, foldclosedend(1))
223 call assert_equal(0, foldlevel(3))
Bram Moolenaara4208962019-08-24 20:50:19 +0200224 call assert_equal(0, 4->foldlevel())
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100225 call assert_equal(6, foldclosedend(5))
226 call assert_equal(10, foldclosedend(7))
227 call assert_equal(14, foldclosedend(11))
228
229 call delete('Xfile')
230 bwipe!
231 set foldmethod& foldexpr&
232endfunc
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100233
Bram Moolenaar94be6192017-04-22 22:40:11 +0200234func Check_foldlevels(expected)
235 call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)'))
236endfunc
237
238func Test_move_folds_around_manual()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100239 new
240 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
241 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
242 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
243 " all folds closed
244 set foldenable foldlevel=0 fdm=indent
245 " needs a forced redraw
246 redraw!
247 set fdm=manual
248 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
249 call assert_equal(input, getline(1, '$'))
250 7,12m0
251 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
252 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
253 10,12m0
254 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
255 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)'))
256 " moving should not close the folds
257 %d
258 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
259 set fdm=indent
260 redraw!
261 set fdm=manual
262 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100263 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100264 7,12m0
265 let folds=repeat([-1], 18)
266 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
267 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
268 norm! zM
269 " folds are not corrupted and all have been closed
270 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)'))
271 %d
272 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
273 set fdm=indent
274 redraw!
275 set fdm=manual
276 %foldopen
277 3m4
278 %foldclose
279 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
280 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
281 %d
282 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
283 set fdm=indent foldlevel=0
284 set fdm=manual
285 %foldopen
286 3m1
287 %foldclose
288 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
289 call assert_equal(0, foldlevel(2))
290 call assert_equal(5, foldclosedend(3))
291 call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
292 2,6m$
293 %foldclose
294 call assert_equal(5, foldclosedend(2))
295 call assert_equal(0, foldlevel(6))
296 call assert_equal(9, foldclosedend(7))
297 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 +0200298
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100299 %d
300 " Ensure moving around the edges still works.
301 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
302 set fdm=indent foldlevel=0
303 set fdm=manual
304 %foldopen
305 6m$
306 " The first fold has been truncated to the 5'th line.
307 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200308 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])
309
310 %delete
311 set fdm=indent foldlevel=0
312 call setline(1, [
313 \ "a",
314 \ "\ta",
315 \ "\t\ta",
316 \ "\t\ta",
317 \ "\t\ta",
318 \ "a",
319 \ "a"])
320 set fdm=manual
321 %foldopen!
322 4,5m6
323 call Check_foldlevels([0, 1, 2, 0, 0, 0, 0])
324
325 %delete
326 set fdm=indent
327 call setline(1, [
328 \ "\ta",
329 \ "\t\ta",
330 \ "\t\ta",
331 \ "\t\ta",
332 \ "\ta",
333 \ "\t\ta",
334 \ "\t\ta",
335 \ "\t\ta",
336 \ "\ta",
337 \ "\t\ta",
338 \ "\t\ta",
339 \ "\t\ta",
340 \ "\t\ta",
341 \ "\ta",
342 \ "a"])
343 set fdm=manual
344 %foldopen!
345 13m7
346 call Check_foldlevels([1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0])
347
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100348 bw!
349endfunc
350
Bram Moolenaar94be6192017-04-22 22:40:11 +0200351func Test_move_folds_around_indent()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100352 new
353 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
354 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
355 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
356 " all folds closed
357 set fdm=indent
358 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
359 call assert_equal(input, getline(1, '$'))
360 7,12m0
361 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
362 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
363 10,12m0
364 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
365 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)'))
366 " moving should not close the folds
367 %d
368 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
369 set fdm=indent
370 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100371 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100372 7,12m0
373 let folds=repeat([-1], 18)
374 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
375 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
376 norm! zM
377 " folds are not corrupted and all have been closed
378 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)'))
379 %d
380 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
381 set fdm=indent
382 %foldopen
383 3m4
384 %foldclose
385 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
386 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
387 %d
388 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
389 set fdm=indent foldlevel=0
390 %foldopen
391 3m1
392 %foldclose
393 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
394 call assert_equal(1, foldlevel(2))
395 call assert_equal(5, foldclosedend(3))
396 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
397 2,6m$
398 %foldclose
399 call assert_equal(9, foldclosedend(2))
400 call assert_equal(1, foldlevel(6))
401 call assert_equal(9, foldclosedend(7))
402 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 +0100403 " Ensure moving around the edges still works.
404 %d
405 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
406 set fdm=indent foldlevel=0
407 %foldopen
408 6m$
409 " The first fold has been truncated to the 5'th line.
410 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200411 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100412 bw!
413endfunc
Bram Moolenaar518c9b12017-03-21 11:48:39 +0100414
415func Test_folddoopen_folddoclosed()
416 new
417 call setline(1, range(1, 9))
418 set foldmethod=manual
419 1,3 fold
420 6,8 fold
421
422 " Test without range.
423 folddoopen s/$/o/
424 folddoclosed s/$/c/
425 call assert_equal(['1c', '2c', '3c',
426 \ '4o', '5o',
427 \ '6c', '7c', '8c',
428 \ '9o'], getline(1, '$'))
429
430 " Test with range.
431 call setline(1, range(1, 9))
432 1,8 folddoopen s/$/o/
433 4,$ folddoclosed s/$/c/
434 call assert_equal(['1', '2', '3',
435 \ '4o', '5o',
436 \ '6c', '7c', '8c',
437 \ '9'], getline(1, '$'))
438
439 set foldmethod&
440 bw!
441endfunc
442
443func Test_fold_error()
444 new
445 call setline(1, [1, 2])
446
447 for fm in ['indent', 'expr', 'syntax', 'diff']
448 exe 'set foldmethod=' . fm
449 call assert_fails('norm zf', 'E350:')
450 call assert_fails('norm zd', 'E351:')
451 call assert_fails('norm zE', 'E352:')
452 endfor
453
454 set foldmethod=manual
455 call assert_fails('norm zd', 'E490:')
456 call assert_fails('norm zo', 'E490:')
457 call assert_fails('3fold', 'E16:')
458
459 set foldmethod=marker
460 set nomodifiable
461 call assert_fails('1,2fold', 'E21:')
462
463 set modifiable&
464 set foldmethod&
465 bw!
466endfunc
Bram Moolenaar495b7dd2017-09-16 17:19:22 +0200467
468func Test_foldtext_recursive()
469 new
470 call setline(1, ['{{{', 'some text', '}}}'])
471 setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
472 " This was crashing because of endless recursion.
473 2foldclose
474 redraw
475 call assert_equal(1, foldlevel(2))
476 call assert_equal(1, foldclosed(2))
477 call assert_equal(3, foldclosedend(2))
478 bwipe!
479endfunc
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100480
481" Various fold related tests
482
483" Basic test if a fold can be created, opened, moving to the end and closed
484func Test_fold_manual()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200485 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100486 set fdm=manual
487
488 let content = ['1 aa', '2 bb', '3 cc']
489 call append(0, content)
490 call cursor(1, 1)
491 normal zf2j
492 call assert_equal('1 aa', getline(foldclosed('.')))
493 normal zo
494 call assert_equal(-1, foldclosed('.'))
495 normal ]z
496 call assert_equal('3 cc', getline('.'))
497 normal zc
498 call assert_equal('1 aa', getline(foldclosed('.')))
499
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200500 " Create a fold inside a closed fold after setting 'foldlevel'
501 %d _
502 call setline(1, range(1, 5))
503 1,5fold
504 normal zR
505 2,4fold
506 set foldlevel=1
507 3fold
508 call assert_equal([1, 3, 3, 3, 1], map(range(1, 5), {->foldlevel(v:val)}))
509 set foldlevel&
510
511 " Create overlapping folds (at the start and at the end)
512 normal zE
513 2,3fold
514 normal zR
515 3,4fold
516 call assert_equal([0, 2, 2, 1, 0], map(range(1, 5), {->foldlevel(v:val)}))
517 normal zE
518 3,4fold
519 normal zR
520 2,3fold
521 call assert_equal([0, 1, 2, 2, 0], map(range(1, 5), {->foldlevel(v:val)}))
522
523 " Create a nested fold across two non-adjoining folds
524 %d _
525 call setline(1, range(1, 7))
526 1,2fold
527 normal zR
528 4,5fold
529 normal zR
530 6,7fold
531 normal zR
532 1,5fold
533 call assert_equal([2, 2, 1, 2, 2, 1, 1],
534 \ map(range(1, 7), {->foldlevel(v:val)}))
535
536 " A newly created nested fold should be closed
537 %d _
538 call setline(1, range(1, 6))
539 1,6fold
540 normal zR
541 3,4fold
542 normal zR
543 2,5fold
544 call assert_equal([1, 2, 3, 3, 2, 1], map(range(1, 6), {->foldlevel(v:val)}))
545 call assert_equal(2, foldclosed(4))
546 call assert_equal(5, foldclosedend(4))
547
548 " Test zO, zC and zA on a line with no folds.
549 normal zE
550 call assert_fails('normal zO', 'E490:')
551 call assert_fails('normal zC', 'E490:')
552 call assert_fails('normal zA', 'E490:')
553
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100554 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200555 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100556endfunc
557
558" test folding with markers.
559func Test_fold_marker()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200560 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100561 set fdm=marker fdl=1 fdc=3
562
563 let content = ['4 dd {{{', '5 ee {{{ }}}', '6 ff }}}']
564 call append(0, content)
565 call cursor(2, 1)
566 call assert_equal(2, foldlevel('.'))
567 normal [z
568 call assert_equal(1, foldlevel('.'))
569 exe "normal jo{{ \<Esc>r{jj"
570 call assert_equal(1, foldlevel('.'))
571 normal kYpj
572 call assert_equal(0, foldlevel('.'))
573
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200574 " Use only closing fold marker (without and with a count)
575 set fdl&
576 %d _
577 call setline(1, ['one }}}', 'two'])
578 call assert_equal([0, 0], [foldlevel(1), foldlevel(2)])
579 %d _
580 call setline(1, ['one }}}4', 'two'])
581 call assert_equal([4, 3], [foldlevel(1), foldlevel(2)])
582
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100583 set fdm& fdl& fdc&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200584 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100585endfunc
586
Bram Moolenaar4af72592018-12-09 15:00:52 +0100587" test create fold markers with C filetype
588func Test_fold_create_marker_in_C()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200589 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100590 set fdm=marker fdl=9
591 set filetype=c
592
Bram Moolenaarc79745a2019-05-20 22:12:34 +0200593 let content =<< trim [CODE]
594 /*
595 * comment
596 *
597 *
598 */
599 int f(int* p) {
600 *p = 3;
601 return 0;
602 }
603 [CODE]
604
Bram Moolenaar4af72592018-12-09 15:00:52 +0100605 for c in range(len(content) - 1)
606 bw!
607 call append(0, content)
608 call cursor(c + 1, 1)
609 norm! zfG
610 call assert_equal(content[c] . (c < 4 ? '{{{' : '/*{{{*/'), getline(c + 1))
611 endfor
612
613 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200614 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100615endfunc
616
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100617" test folding with indent
618func Test_fold_indent()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200619 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100620 set fdm=indent sw=2
621
622 let content = ['1 aa', '2 bb', '3 cc']
623 call append(0, content)
624 call cursor(2, 1)
625 exe "normal i \<Esc>jI "
626 call assert_equal(2, foldlevel('.'))
627 normal k
628 call assert_equal(1, foldlevel('.'))
629
630 set fdm& sw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200631 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100632endfunc
633
634" test syntax folding
635func Test_fold_syntax()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200636 CheckFeature syntax
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100637
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200638 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100639 set fdm=syntax fdl=0
640
641 syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3
642 syn region Fd1 start="ee" end="ff" fold contained
643 syn region Fd2 start="gg" end="hh" fold contained
644 syn region Fd3 start="commentstart" end="commentend" fold contained
645 let content = ['3 cc', '4 dd {{{', '5 ee {{{ }}}', '{{{{', '6 ff }}}',
646 \ '6 ff }}}', '7 gg', '8 hh', '9 ii']
647 call append(0, content)
648 normal Gzk
649 call assert_equal('9 ii', getline('.'))
650 normal k
651 call assert_equal('3 cc', getline('.'))
652 exe "normal jAcommentstart \<Esc>Acommentend"
653 set fdl=1
654 normal 3j
655 call assert_equal('7 gg', getline('.'))
656 set fdl=0
657 exe "normal zO\<C-L>j"
658 call assert_equal('8 hh', getline('.'))
659 syn clear Fd1 Fd2 Fd3 Hup
660
661 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200662 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100663endfunc
664
665func Flvl()
666 let l = getline(v:lnum)
667 if l =~ "bb$"
668 return 2
669 elseif l =~ "gg$"
670 return "s1"
671 elseif l =~ "ii$"
672 return ">2"
673 elseif l =~ "kk$"
674 return "0"
675 endif
676 return "="
677endfun
678
679" test expression folding
680func Test_fold_expr()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200681 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100682 set fdm=expr fde=Flvl()
683
684 let content = ['1 aa',
685 \ '2 bb',
686 \ '3 cc',
687 \ '4 dd {{{commentstart commentend',
688 \ '5 ee {{{ }}}',
689 \ '{{{',
690 \ '6 ff }}}',
691 \ '6 ff }}}',
692 \ ' 7 gg',
693 \ ' 8 hh',
694 \ '9 ii',
695 \ 'a jj',
696 \ 'b kk']
697 call append(0, content)
698 call cursor(1, 1)
699 exe "normal /bb$\<CR>"
700 call assert_equal(2, foldlevel('.'))
701 exe "normal /hh$\<CR>"
702 call assert_equal(1, foldlevel('.'))
703 exe "normal /ii$\<CR>"
704 call assert_equal(2, foldlevel('.'))
705 exe "normal /kk$\<CR>"
706 call assert_equal(0, foldlevel('.'))
707
708 set fdm& fde&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200709 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100710endfunc
711
712" Bug with fdm=indent and moving folds
713" Moving a fold a few times, messes up the folds below the moved fold.
714" Fixed by 7.4.700
715func Test_fold_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200716 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100717 set fdm=indent sw=2 fdl=0
718
719 let content = ['', '', 'Line1', ' Line2', ' Line3',
720 \ 'Line4', ' Line5', ' Line6',
721 \ 'Line7', ' Line8', ' Line9']
722 call append(0, content)
723 normal zM
724 call cursor(4, 1)
725 move 2
726 move 1
727 call assert_equal(7, foldclosed(7))
728 call assert_equal(8, foldclosedend(7))
729 call assert_equal(0, foldlevel(9))
730 call assert_equal(10, foldclosed(10))
731 call assert_equal(11, foldclosedend(10))
732 call assert_equal('+-- 2 lines: Line2', foldtextresult(2))
Bram Moolenaara4208962019-08-24 20:50:19 +0200733 call assert_equal('+-- 2 lines: Line8', 10->foldtextresult())
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100734
735 set fdm& sw& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200736 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100737endfunc
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100738
739" test for patch 7.3.637
740" Cannot catch the error caused by a foldopen when there is no fold.
741func Test_foldopen_exception()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200742 new
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100743 let a = 'No error caught'
744 try
745 foldopen
746 catch
747 let a = matchstr(v:exception,'^[^ ]*')
748 endtry
749 call assert_equal('Vim(foldopen):E490:', a)
750
751 let a = 'No error caught'
752 try
753 foobar
754 catch
755 let a = matchstr(v:exception,'^[^ ]*')
756 endtry
757 call assert_match('E492:', a)
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200758 bw!
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100759endfunc
Bram Moolenaar907dad72018-07-10 15:07:15 +0200760
761func Test_fold_last_line_with_pagedown()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200762 new
Bram Moolenaar907dad72018-07-10 15:07:15 +0200763 set fdm=manual
764
765 let expect = '+-- 11 lines: 9---'
766 let content = range(1,19)
767 call append(0, content)
768 normal dd9G
769 normal zfG
770 normal zt
771 call assert_equal('9', getline(foldclosed('.')))
772 call assert_equal('19', getline(foldclosedend('.')))
773 call assert_equal(expect, ScreenLines(1, len(expect))[0])
774 call feedkeys("\<C-F>", 'xt')
775 call assert_equal(expect, ScreenLines(1, len(expect))[0])
776 call feedkeys("\<C-F>", 'xt')
777 call assert_equal(expect, ScreenLines(1, len(expect))[0])
778 call feedkeys("\<C-B>\<C-F>\<C-F>", 'xt')
779 call assert_equal(expect, ScreenLines(1, len(expect))[0])
780
781 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200782 bw!
Bram Moolenaar907dad72018-07-10 15:07:15 +0200783endfunc
Bram Moolenaar7701f302018-10-02 21:20:32 +0200784
785func Test_folds_with_rnu()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200786 CheckScreendump
Bram Moolenaar7701f302018-10-02 21:20:32 +0200787
788 call writefile([
789 \ 'set fdm=marker rnu foldcolumn=2',
790 \ 'call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])',
791 \ ], 'Xtest_folds_with_rnu')
792 let buf = RunVimInTerminal('-S Xtest_folds_with_rnu', {})
793
794 call VerifyScreenDump(buf, 'Test_folds_with_rnu_01', {})
795 call term_sendkeys(buf, "j")
796 call VerifyScreenDump(buf, 'Test_folds_with_rnu_02', {})
797
798 " clean up
799 call StopVimInTerminal(buf)
800 call delete('Xtest_folds_with_rnu')
801endfunc
Bram Moolenaar53932812018-12-07 21:08:49 +0100802
803func Test_folds_marker_in_comment2()
804 new
805 call setline(1, ['Lorem ipsum dolor sit', 'Lorem ipsum dolor sit', 'Lorem ipsum dolor sit'])
806 setl fen fdm=marker
807 setl commentstring=<!--%s-->
808 setl comments=s:<!--,m:\ \ \ \ ,e:-->
809 norm! zf2j
810 setl nofen
811 :1y
812 call assert_equal(['Lorem ipsum dolor sit<!--{{{-->'], getreg(0,1,1))
813 :+2y
814 call assert_equal(['Lorem ipsum dolor sit<!--}}}-->'], getreg(0,1,1))
815
816 set foldmethod&
817 bwipe!
818endfunc
Bram Moolenaar9a4a8c42019-08-19 22:48:30 +0200819
820func Test_fold_delete_with_marker()
821 new
822 call setline(1, ['func Func() {{{1', 'endfunc'])
823 1,2yank
824 new
825 set fdm=marker
826 call setline(1, 'x')
827 normal! Vp
828 normal! zd
829 call assert_equal(['func Func() ', 'endfunc'], getline(1, '$'))
830
831 set fdm&
832 bwipe!
833 bwipe!
834endfunc
Bram Moolenaar7a9bd7c2019-09-17 22:42:55 +0200835
836func Test_fold_delete_with_marker_and_whichwrap()
837 new
838 let content1 = ['']
839 let content2 = ['folded line 1 "{{{1', ' test', ' test2', ' test3', '', 'folded line 2 "{{{1', ' test', ' test2', ' test3']
840 call setline(1, content1 + content2)
841 set fdm=marker ww+=l
842 normal! x
843 call assert_equal(content2, getline(1, '$'))
844 set fdm& ww&
845 bwipe!
846endfunc
Bram Moolenaar3b681232019-12-13 19:35:55 +0100847
848func Test_fold_delete_first_line()
849 new
850 call setline(1, [
851 \ '" x {{{1',
852 \ '" a',
853 \ '" aa',
854 \ '" x {{{1',
855 \ '" b',
856 \ '" bb',
857 \ '" x {{{1',
858 \ '" c',
859 \ '" cc',
860 \ ])
861 set foldmethod=marker
862 1
863 normal dj
864 call assert_equal([
865 \ '" x {{{1',
866 \ '" c',
867 \ '" cc',
868 \ ], getline(1,'$'))
869 bwipe!
870 set foldmethod&
871endfunc
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200872
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200873" Add a test for deleting the outer fold of a nested fold and promoting the
874" inner folds to one level up with already a fold at that level following the
875" nested fold.
876func Test_fold_delete_recursive_fold()
877 new
878 call setline(1, range(1, 7))
879 2,3fold
880 normal zR
881 4,5fold
882 normal zR
883 1,5fold
884 normal zR
885 6,7fold
886 normal zR
887 normal 1Gzd
888 normal 1Gzj
889 call assert_equal(2, line('.'))
890 normal zj
891 call assert_equal(4, line('.'))
892 normal zj
893 call assert_equal(6, line('.'))
894 bw!
895endfunc
896
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200897" Test for errors in 'foldexpr'
898func Test_fold_expr_error()
899 new
900 call setline(1, ['one', 'two', 'three'])
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200901 " In a window with no folds, foldlevel() should return 0
902 call assert_equal(0, foldlevel(1))
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200903
904 " Return a list from the expression
905 set foldexpr=[]
906 set foldmethod=expr
907 for i in range(3)
908 call assert_equal(0, foldlevel(i))
909 endfor
910
911 " expression error
912 set foldexpr=[{]
913 set foldmethod=expr
914 for i in range(3)
915 call assert_equal(0, foldlevel(i))
916 endfor
917
918 set foldmethod& foldexpr&
919 close!
920endfunc
921
Bram Moolenaarda697642020-09-17 19:36:04 +0200922func Test_undo_fold_deletion()
923 new
924 set fdm=marker
925 let lines =<< trim END
926 " {{{
927 " }}}1
928 " {{{
929 END
930 call setline(1, lines)
931 3d
932 g/"/d
933 undo
934 redo
935 eval getline(1, '$')->assert_equal([''])
936
937 set fdm&vim
938 bwipe!
939endfunc
940
Bram Moolenaarc136a352020-11-03 20:05:40 +0100941" this was crashing
942func Test_move_no_folds()
943 new
944 fold
945 setlocal fdm=expr
946 normal zj
947 bwipe!
948endfunc
949
Bram Moolenaar5e1f22f2020-11-10 18:23:52 +0100950" this was crashing
951func Test_fold_create_delete_create()
952 new
953 fold
954 fold
955 normal zd
956 fold
957 bwipe!
958endfunc
959
Bram Moolenaar6a78f322020-12-21 14:01:41 +0100960" this was crashing
961func Test_fold_create_delete()
962 new
963 norm zFzFzdzj
964 bwipe!
965endfunc
966
Bram Moolenaare71996b2021-01-21 17:03:07 +0100967func Test_fold_relative_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200968 new
Bram Moolenaare71996b2021-01-21 17:03:07 +0100969 set fdm=indent sw=2 wrap tw=80
970
Bram Moolenaar3c49e742021-04-04 21:26:04 +0200971 let longtext = repeat('x', &columns + 1)
972 let content = [ ' foo', ' ' .. longtext, ' baz',
973 \ longtext,
974 \ ' foo', ' ' .. longtext, ' baz'
Bram Moolenaare71996b2021-01-21 17:03:07 +0100975 \ ]
976 call append(0, content)
977
978 normal zM
979
Bram Moolenaar3c49e742021-04-04 21:26:04 +0200980 for lnum in range(1, 3)
981 call cursor(lnum, 1)
982 call assert_true(foldclosed(line('.')))
983 normal gj
984 call assert_equal(2, winline())
985 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +0100986
987 call cursor(2, 1)
988 call assert_true(foldclosed(line('.')))
989 normal 2gj
990 call assert_equal(3, winline())
991
Bram Moolenaar3c49e742021-04-04 21:26:04 +0200992 for lnum in range(5, 7)
993 call cursor(lnum, 1)
994 call assert_true(foldclosed(line('.')))
995 normal gk
996 call assert_equal(3, winline())
997 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +0100998
999 call cursor(6, 1)
1000 call assert_true(foldclosed(line('.')))
1001 normal 2gk
1002 call assert_equal(2, winline())
1003
1004 set fdm& sw& wrap& tw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001005 bw!
Bram Moolenaare71996b2021-01-21 17:03:07 +01001006endfunc
1007
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001008" Test for using multibyte characters as 'foldopen', 'foldclose' and
1009" 'foldsetp' items in 'fillchars'
1010func s:mbyte_fillchar_tests(fo, fc, fs)
1011 setlocal foldcolumn=3
1012
1013 normal zE
1014 1,2fold
1015 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1016 \ ScreenLines([1, 2], 10))
1017 1,2foldopen
1018 call assert_equal([a:fo .. ' one ', a:fs .. ' two '],
1019 \ ScreenLines([1, 2], 7))
1020 1,2foldclose
1021 redraw!
1022 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1023 \ ScreenLines([1, 2], 10))
1024
1025 " Two level fold
1026 normal zE
1027 2,3fold
1028 1,4fold
1029 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1030 \ ScreenLines([1, 2], 10))
1031 1,4foldopen
1032 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1033 \ ScreenLines([1, 2], 10))
1034 1,4foldopen
1035 call assert_equal([a:fo .. ' one ', a:fs .. a:fo .. ' two ',
1036 \ a:fs .. a:fs .. ' three '], ScreenLines([1, 3], 10))
1037 2,3foldclose
1038 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1039 \ ScreenLines([1, 2], 10))
1040 1,4foldclose
1041 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1042 \ ScreenLines([1, 2], 10))
1043
1044 " Three level fold
1045 normal zE
1046 3,4fold
1047 2,5fold
1048 1,6fold
1049 call assert_equal([a:fc .. ' +-- 6 '], ScreenLines(1, 10))
1050 " open all the folds
1051 normal zR
1052 call assert_equal([
1053 \ a:fo .. ' one ',
1054 \ a:fs .. a:fo .. ' two ',
1055 \ '2' .. a:fo .. ' three ',
1056 \ '23 four ',
1057 \ a:fs .. a:fs .. ' five ',
1058 \ a:fs .. ' six ',
1059 \ ], ScreenLines([1, 6], 10))
1060 " close the innermost fold
1061 3,4foldclose
1062 call assert_equal([
1063 \ a:fo .. ' one ',
1064 \ a:fs .. a:fo .. ' two ',
1065 \ a:fs .. a:fs .. a:fc .. '+---- ',
1066 \ a:fs .. a:fs .. ' five ',
1067 \ a:fs .. ' six ',
1068 \ ], ScreenLines([1, 5], 10))
1069 " close the next fold
1070 2,5foldclose
1071 call assert_equal([
1072 \ a:fo .. ' one ',
1073 \ a:fs .. a:fc .. ' +--- 4',
1074 \ a:fs .. ' six ',
1075 \ ], ScreenLines([1, 3], 10))
1076
1077 " set the fold column size to 2
1078 setlocal fdc=2
1079 normal zR
1080 call assert_equal([
1081 \ a:fo .. ' one ',
1082 \ a:fo .. ' two ',
1083 \ a:fo .. ' three',
1084 \ '3 four ',
1085 \ '2 five ',
1086 \ a:fs .. ' six ',
1087 \ ], ScreenLines([1, 6], 7))
1088
1089 " set the fold column size to 1
1090 setlocal fdc=1
1091 normal zR
1092 call assert_equal([
1093 \ a:fo .. 'one ',
1094 \ a:fo .. 'two ',
1095 \ a:fo .. 'three ',
1096 \ '3four ',
1097 \ '2five ',
1098 \ a:fs .. 'six ',
1099 \ ], ScreenLines([1, 6], 7))
1100
Bram Moolenaar008bff92021-03-04 21:55:58 +01001101 " Enable number and sign columns and place some signs
1102 setlocal fdc=3
1103 setlocal number
1104 setlocal signcolumn=auto
1105 sign define S1 text=->
1106 sign place 10 line=3 name=S1
1107 call assert_equal([
1108 \ a:fo .. ' 1 one ',
1109 \ a:fs .. a:fo .. ' 2 two ',
1110 \ '2' .. a:fo .. ' -> 3 three',
1111 \ '23 4 four ',
1112 \ a:fs .. a:fs .. ' 5 five ',
1113 \ a:fs .. ' 6 six '
1114 \ ], ScreenLines([1, 6], 14))
1115
1116 " Test with 'rightleft'
1117 if has('rightleft')
1118 setlocal rightleft
1119 let lines = ScreenLines([1, 6], winwidth(0))
1120 call assert_equal('o 1 ' .. a:fo,
1121 \ strcharpart(lines[0], strchars(lines[0]) - 10, 10))
1122 call assert_equal('t 2 ' .. a:fo .. a:fs,
1123 \ strcharpart(lines[1], strchars(lines[1]) - 10, 10))
1124 call assert_equal('t 3 >- ' .. a:fo .. '2',
1125 \ strcharpart(lines[2], strchars(lines[2]) - 10, 10))
1126 call assert_equal('f 4 32',
1127 \ strcharpart(lines[3], strchars(lines[3]) - 10, 10))
1128 call assert_equal('f 5 ' .. a:fs .. a:fs,
1129 \ strcharpart(lines[4], strchars(lines[4]) - 10, 10))
1130 call assert_equal('s 6 ' .. a:fs,
1131 \ strcharpart(lines[5], strchars(lines[5]) - 10, 10))
1132 setlocal norightleft
1133 endif
1134
1135 sign unplace *
1136 sign undefine S1
1137 setlocal number& signcolumn&
1138
1139 " Add a test with more than 9 folds (and then delete some folds)
1140 normal zE
1141 for i in range(1, 10)
1142 normal zfGzo
1143 endfor
1144 normal zR
1145 call assert_equal([
1146 \ a:fo .. a:fo .. ' one ',
1147 \ '9> two '
1148 \ ], ScreenLines([1, 2], 7))
1149 normal 1Gzd
1150 call assert_equal([
1151 \ a:fo .. a:fo .. ' one ',
1152 \ '89 two '
1153 \ ], ScreenLines([1, 2], 7))
1154 normal 1Gzdzdzdzdzdzdzd
1155 call assert_equal([
1156 \ a:fo .. a:fo .. ' one ',
1157 \ a:fs .. a:fs .. ' two '
1158 \ ], ScreenLines([1, 2], 7))
1159
1160 setlocal foldcolumn& number& signcolumn&
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001161endfunc
1162
1163func Test_foldcolumn_multibyte_char()
1164 new
1165 call setline(1, ['one', 'two', 'three', 'four', 'five', 'six'])
1166 setlocal foldenable foldmethod=manual
1167
1168 " First test with the default setting
1169 call s:mbyte_fillchar_tests('-', '+', '|')
1170
1171 " Use multi-byte characters
1172 set fillchars+=foldopen:▾,foldsep:│,foldclose:▸
1173 call s:mbyte_fillchar_tests('▾', '▸', '│')
1174
Bram Moolenaar196a1f72021-03-21 14:39:19 +01001175 " Use a mix of multi-byte and single-byte characters
1176 set fillchars+=foldopen:¬,foldsep:\|,foldclose:+
1177 call s:mbyte_fillchar_tests('¬', '+', '|')
1178 set fillchars+=foldopen:+,foldsep:\|,foldclose:¬
1179 call s:mbyte_fillchar_tests('+', '¬', '|')
1180
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001181 bw!
1182 set foldenable& fdc& fdm& fillchars&
1183endfunc
1184
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001185" Test for calling foldlevel() from a fold expression
1186let g:FoldLevels = []
1187func FoldExpr1(lnum)
1188 let f = [a:lnum]
1189 for i in range(1, line('$'))
1190 call add(f, foldlevel(i))
1191 endfor
1192 call add(g:FoldLevels, f)
1193 return getline(a:lnum)[0] == "\t"
1194endfunc
1195
1196func Test_foldexpr_foldlevel()
1197 new
1198 call setline(1, ['one', "\ttwo", "\tthree"])
1199 setlocal foldmethod=expr
1200 setlocal foldexpr=FoldExpr1(v:lnum)
1201 setlocal foldenable
1202 setlocal foldcolumn=3
1203 redraw!
1204 call assert_equal([[1, -1, -1, -1], [2, -1, -1, -1], [3, 0, 1, -1]],
1205 \ g:FoldLevels)
1206 set foldmethod& foldexpr& foldenable& foldcolumn&
1207 bw!
1208endfunc
1209
1210" Test for returning different values from a fold expression
1211func FoldExpr2(lnum)
1212 if a:lnum == 1 || a:lnum == 4
1213 return -2
1214 elseif a:lnum == 2
1215 return 'a1'
1216 elseif a:lnum == 3
1217 return 's4'
1218 endif
1219 return '='
1220endfunc
1221
1222func Test_foldexpr_2()
1223 new
1224 call setline(1, ['one', 'two', 'three', 'four'])
1225 setlocal foldexpr=FoldExpr2(v:lnum)
1226 setlocal foldmethod=expr
1227 call assert_equal([0, 1, 1, 0], [foldlevel(1), foldlevel(2), foldlevel(3),
1228 \ foldlevel(4)])
1229 bw!
1230endfunc
1231
1232" Test for the 'foldclose' option
1233func Test_foldclose_opt()
1234 CheckScreendump
1235
1236 let lines =<< trim END
1237 set foldmethod=manual foldclose=all foldopen=all
1238 call setline(1, ['one', 'two', 'three', 'four'])
1239 2,3fold
1240 func XsaveFoldLevels()
1241 redraw!
1242 call writefile([json_encode([foldclosed(1), foldclosed(2), foldclosed(3),
1243 \ foldclosed(4)])], 'Xoutput', 'a')
1244 endfunc
1245 END
1246 call writefile(lines, 'Xscript')
1247 let rows = 10
1248 let buf = RunVimInTerminal('-S Xscript', {'rows': rows})
1249 call term_wait(buf)
1250 call term_sendkeys(buf, ":set noruler\n")
1251 call term_wait(buf)
1252 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1253 call term_sendkeys(buf, "2G")
1254 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1255 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1256 call term_sendkeys(buf, "4G")
1257 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1258 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1259 call term_sendkeys(buf, "3G")
1260 call WaitForAssert({-> assert_equal('three', term_getline(buf, 3))})
1261 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1262 call term_sendkeys(buf, "1G")
1263 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1264 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001265 call term_sendkeys(buf, "2G")
1266 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1267 call term_sendkeys(buf, "k")
1268 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001269
1270 " clean up
1271 call StopVimInTerminal(buf)
1272
1273 call assert_equal(['[-1,2,2,-1]', '[-1,-1,-1,-1]', '[-1,2,2,-1]',
1274 \ '[-1,-1,-1,-1]', '[-1,2,2,-1]'], readfile('Xoutput'))
1275 call delete('Xscript')
1276 call delete('Xoutput')
1277endfunc
1278
1279" Test for foldtextresult()
1280func Test_foldtextresult()
1281 new
1282 call assert_equal('', foldtextresult(-1))
1283 call assert_equal('', foldtextresult(0))
1284 call assert_equal('', foldtextresult(1))
1285 call setline(1, ['one', 'two', 'three', 'four'])
1286 2,3fold
1287 call assert_equal('', foldtextresult(1))
1288 call assert_equal('+-- 2 lines: two', foldtextresult(2))
1289 setlocal foldtext=
1290 call assert_equal('+-- 2 lines folded ', foldtextresult(2))
1291
1292 " Fold text for a C comment fold
1293 %d _
1294 setlocal foldtext&
1295 call setline(1, ['', '/*', ' * Comment', ' */', ''])
1296 2,4fold
1297 call assert_equal('+-- 3 lines: Comment', foldtextresult(2))
1298
1299 bw!
1300endfunc
1301
1302" Test for merging two recursive folds when an intermediate line with no fold
1303" is removed
1304func Test_fold_merge_recrusive()
1305 new
1306 call setline(1, [' one', ' two', 'xxxx', ' three',
1307 \ ' four', "\tfive"])
1308 setlocal foldmethod=indent shiftwidth=2
1309 3d_
1310 %foldclose
1311 call assert_equal([1, 5], [foldclosed(5), foldclosedend(1)])
1312 bw!
1313endfunc
1314
1315" Test for moving a line which is the start of a fold from a recursive fold to
1316" outside. The fold length should reduce.
1317func Test_fold_move_foldlevel()
1318 new
1319 call setline(1, ['a{{{', 'b{{{', 'c{{{', 'd}}}', 'e}}}', 'f}}}', 'g'])
1320 setlocal foldmethod=marker
1321 normal zR
1322 call assert_equal([3, 2, 1], [foldlevel(4), foldlevel(5), foldlevel(6)])
1323 3move 7
1324 call assert_equal([2, 1, 0], [foldlevel(3), foldlevel(4), foldlevel(5)])
1325 call assert_equal(1, foldlevel(7))
1326
1327 " Move a line from outside a fold to inside the fold.
1328 %d _
1329 call setline(1, ['a', 'b{{{', 'c}}}'])
1330 normal zR
1331 1move 2
1332 call assert_equal([1, 1, 1], [foldlevel(1), foldlevel(2), foldlevel(3)])
1333
1334 " Move the start of one fold to inside another fold
1335 %d _
1336 call setline(1, ['a', 'b{{{', 'c}}}', 'd{{{', 'e}}}'])
1337 normal zR
1338 call assert_equal([0, 1, 1, 1, 1], [foldlevel(1), foldlevel(2),
1339 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1340 1,2move 4
1341 call assert_equal([0, 1, 1, 2, 2], [foldlevel(1), foldlevel(2),
1342 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1343
1344 bw!
1345endfunc
1346
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001347" Test for using zj and zk to move downwards and upwards to the start and end
1348" of the next fold.
1349" Test for using [z and ]z in a closed fold to jump to the beginning and end
1350" of the fold.
1351func Test_fold_jump()
1352 new
1353 call setline(1, ["\t1", "\t2", "\t\t3", "\t\t4", "\t\t\t5", "\t\t\t6", "\t\t7", "\t\t8", "\t9", "\t10"])
1354 setlocal foldmethod=indent
1355 normal zR
1356 normal zj
1357 call assert_equal(3, line('.'))
1358 normal zj
1359 call assert_equal(5, line('.'))
1360 call assert_beeps('normal zj')
1361 call assert_equal(5, line('.'))
1362 call assert_beeps('normal 9Gzj')
1363 call assert_equal(9, line('.'))
1364 normal Gzk
1365 call assert_equal(8, line('.'))
1366 normal zk
1367 call assert_equal(6, line('.'))
1368 call assert_beeps('normal zk')
1369 call assert_equal(6, line('.'))
1370 call assert_beeps('normal 2Gzk')
1371 call assert_equal(2, line('.'))
1372
1373 " Using [z or ]z in a closed fold should not move the cursor
1374 %d _
1375 call setline(1, ["1", "\t2", "\t3", "\t4", "\t5", "\t6", "7"])
1376 normal zR4Gzc
1377 call assert_equal(4, line('.'))
1378 call assert_beeps('normal [z')
1379 call assert_equal(4, line('.'))
1380 call assert_beeps('normal ]z')
1381 call assert_equal(4, line('.'))
1382 bw!
1383endfunc
1384
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001385" Test for using a script-local function for 'foldexpr'
1386func Test_foldexpr_scriptlocal_func()
1387 func! s:FoldFunc()
1388 let g:FoldLnum = v:lnum
1389 endfunc
1390 new | only
1391 call setline(1, 'abc')
1392 let g:FoldLnum = 0
1393 set foldmethod=expr foldexpr=s:FoldFunc()
1394 redraw!
1395 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1396 call assert_equal(1, g:FoldLnum)
1397 set foldmethod& foldexpr=
1398 bw!
1399 new | only
1400 call setline(1, 'abc')
1401 let g:FoldLnum = 0
1402 set foldmethod=expr foldexpr=<SID>FoldFunc()
1403 redraw!
1404 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1405 call assert_equal(1, g:FoldLnum)
1406 set foldmethod& foldexpr=
1407 delfunc s:FoldFunc
1408 bw!
1409endfunc
1410
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001411" Test for using a script-local function for 'foldtext'
1412func Test_foldtext_scriptlocal_func()
1413 func! s:FoldText()
1414 let g:FoldTextArgs = [v:foldstart, v:foldend]
1415 return foldtext()
1416 endfunc
1417 new | only
1418 call setline(1, range(50))
1419 let g:FoldTextArgs = []
1420 set foldmethod=manual
1421 set foldtext=s:FoldText()
1422 norm! 4Gzf4j
1423 redraw!
1424 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1425 call assert_equal([4, 8], g:FoldTextArgs)
1426 set foldtext&
1427 bw!
1428 new | only
1429 call setline(1, range(50))
1430 let g:FoldTextArgs = []
1431 set foldmethod=manual
1432 set foldtext=<SID>FoldText()
1433 norm! 8Gzf4j
1434 redraw!
1435 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1436 call assert_equal([8, 12], g:FoldTextArgs)
1437 set foldtext&
1438 bw!
1439 delfunc s:FoldText
1440endfunc
1441
Brandon Simmons2c407072022-04-23 13:50:17 +01001442" Make sure a fold containing a nested fold is split correctly when using
1443" foldmethod=indent
1444func Test_fold_split()
1445 new
1446 let lines =<< trim END
1447 line 1
1448 line 2
1449 line 3
1450 line 4
1451 line 5
1452 END
1453 call setline(1, lines)
1454 setlocal sw=2
1455 setlocal foldmethod=indent foldenable
1456 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
1457 call append(2, 'line 2.5')
1458 call assert_equal([0, 1, 0, 1, 2, 2], range(1, 6)->map('foldlevel(v:val)'))
1459 bw!
1460endfunc
1461
Brandon Simmonsd98e75e2022-05-10 19:13:23 +01001462" Make sure that when you append under a blank line that is under a fold with
1463" the same indent level as your appended line, the fold expands across the
1464" blank line
1465func Test_indent_append_under_blank_line()
1466 new
1467 let lines =<< trim END
1468 line 1
1469 line 2
1470 line 3
1471 END
1472 call setline(1, lines)
1473 setlocal sw=2
1474 setlocal foldmethod=indent foldenable
1475 call assert_equal([0, 1, 1], range(1, 3)->map('foldlevel(v:val)'))
1476 call append(3, '')
1477 call append(4, ' line 5')
1478 call assert_equal([0, 1, 1, 1, 1], range(1, 5)->map('foldlevel(v:val)'))
1479 bw!
1480endfunc
1481
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001482" vim: shiftwidth=2 sts=2 expandtab