blob: 3bdd99fc0ede073f47999a5c7c3e3d0f91dc7c80 [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
zeertzjq93c15732022-05-21 16:34:38 +0100234" Test for what patch 8.1.0535 fixes.
235func Test_foldexpr_no_interrupt_addsub()
236 new
237 func! FoldFunc()
238 call setpos('.', getcurpos())
239 return '='
240 endfunc
241
242 set foldmethod=expr
243 set foldexpr=FoldFunc()
244 call setline(1, '1.2')
245
246 exe "norm! $\<C-A>"
247 call assert_equal('1.3', getline(1))
248
249 bwipe!
250 delfunc FoldFunc
251 set foldmethod& foldexpr&
252endfunc
253
Bram Moolenaar94be6192017-04-22 22:40:11 +0200254func Check_foldlevels(expected)
255 call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)'))
256endfunc
257
258func Test_move_folds_around_manual()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100259 new
260 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
261 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
262 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
263 " all folds closed
264 set foldenable foldlevel=0 fdm=indent
265 " needs a forced redraw
266 redraw!
267 set fdm=manual
268 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
269 call assert_equal(input, getline(1, '$'))
270 7,12m0
271 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
272 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
273 10,12m0
274 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
275 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)'))
276 " moving should not close the folds
277 %d
278 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
279 set fdm=indent
280 redraw!
281 set fdm=manual
282 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100283 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100284 7,12m0
285 let folds=repeat([-1], 18)
286 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
287 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
288 norm! zM
289 " folds are not corrupted and all have been closed
290 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)'))
291 %d
292 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
293 set fdm=indent
294 redraw!
295 set fdm=manual
296 %foldopen
297 3m4
298 %foldclose
299 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
300 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
301 %d
302 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
303 set fdm=indent foldlevel=0
304 set fdm=manual
305 %foldopen
306 3m1
307 %foldclose
308 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
309 call assert_equal(0, foldlevel(2))
310 call assert_equal(5, foldclosedend(3))
311 call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
312 2,6m$
313 %foldclose
314 call assert_equal(5, foldclosedend(2))
315 call assert_equal(0, foldlevel(6))
316 call assert_equal(9, foldclosedend(7))
317 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 +0200318
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100319 %d
320 " Ensure moving around the edges still works.
321 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
322 set fdm=indent foldlevel=0
323 set fdm=manual
324 %foldopen
325 6m$
326 " The first fold has been truncated to the 5'th line.
327 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200328 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])
329
330 %delete
331 set fdm=indent foldlevel=0
332 call setline(1, [
333 \ "a",
334 \ "\ta",
335 \ "\t\ta",
336 \ "\t\ta",
337 \ "\t\ta",
338 \ "a",
339 \ "a"])
340 set fdm=manual
341 %foldopen!
342 4,5m6
343 call Check_foldlevels([0, 1, 2, 0, 0, 0, 0])
344
345 %delete
346 set fdm=indent
347 call setline(1, [
348 \ "\ta",
349 \ "\t\ta",
350 \ "\t\ta",
351 \ "\t\ta",
352 \ "\ta",
353 \ "\t\ta",
354 \ "\t\ta",
355 \ "\t\ta",
356 \ "\ta",
357 \ "\t\ta",
358 \ "\t\ta",
359 \ "\t\ta",
360 \ "\t\ta",
361 \ "\ta",
362 \ "a"])
363 set fdm=manual
364 %foldopen!
365 13m7
366 call Check_foldlevels([1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0])
367
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100368 bw!
369endfunc
370
Bram Moolenaar94be6192017-04-22 22:40:11 +0200371func Test_move_folds_around_indent()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100372 new
373 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
374 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
375 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
376 " all folds closed
377 set fdm=indent
378 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
379 call assert_equal(input, getline(1, '$'))
380 7,12m0
381 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
382 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
383 10,12m0
384 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
385 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)'))
386 " moving should not close the folds
387 %d
388 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
389 set fdm=indent
390 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100391 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100392 7,12m0
393 let folds=repeat([-1], 18)
394 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
395 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
396 norm! zM
397 " folds are not corrupted and all have been closed
398 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)'))
399 %d
400 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
401 set fdm=indent
402 %foldopen
403 3m4
404 %foldclose
405 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
406 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
407 %d
408 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
409 set fdm=indent foldlevel=0
410 %foldopen
411 3m1
412 %foldclose
413 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
414 call assert_equal(1, foldlevel(2))
415 call assert_equal(5, foldclosedend(3))
416 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
417 2,6m$
418 %foldclose
419 call assert_equal(9, foldclosedend(2))
420 call assert_equal(1, foldlevel(6))
421 call assert_equal(9, foldclosedend(7))
422 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 +0100423 " Ensure moving around the edges still works.
424 %d
425 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
426 set fdm=indent foldlevel=0
427 %foldopen
428 6m$
429 " The first fold has been truncated to the 5'th line.
430 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200431 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100432 bw!
433endfunc
Bram Moolenaar518c9b12017-03-21 11:48:39 +0100434
435func Test_folddoopen_folddoclosed()
436 new
437 call setline(1, range(1, 9))
438 set foldmethod=manual
439 1,3 fold
440 6,8 fold
441
442 " Test without range.
443 folddoopen s/$/o/
444 folddoclosed s/$/c/
445 call assert_equal(['1c', '2c', '3c',
446 \ '4o', '5o',
447 \ '6c', '7c', '8c',
448 \ '9o'], getline(1, '$'))
449
450 " Test with range.
451 call setline(1, range(1, 9))
452 1,8 folddoopen s/$/o/
453 4,$ folddoclosed s/$/c/
454 call assert_equal(['1', '2', '3',
455 \ '4o', '5o',
456 \ '6c', '7c', '8c',
457 \ '9'], getline(1, '$'))
458
459 set foldmethod&
460 bw!
461endfunc
462
463func Test_fold_error()
464 new
465 call setline(1, [1, 2])
466
467 for fm in ['indent', 'expr', 'syntax', 'diff']
468 exe 'set foldmethod=' . fm
469 call assert_fails('norm zf', 'E350:')
470 call assert_fails('norm zd', 'E351:')
471 call assert_fails('norm zE', 'E352:')
472 endfor
473
474 set foldmethod=manual
475 call assert_fails('norm zd', 'E490:')
476 call assert_fails('norm zo', 'E490:')
477 call assert_fails('3fold', 'E16:')
478
479 set foldmethod=marker
480 set nomodifiable
481 call assert_fails('1,2fold', 'E21:')
482
483 set modifiable&
484 set foldmethod&
485 bw!
486endfunc
Bram Moolenaar495b7dd2017-09-16 17:19:22 +0200487
488func Test_foldtext_recursive()
489 new
490 call setline(1, ['{{{', 'some text', '}}}'])
491 setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
492 " This was crashing because of endless recursion.
493 2foldclose
494 redraw
495 call assert_equal(1, foldlevel(2))
496 call assert_equal(1, foldclosed(2))
497 call assert_equal(3, foldclosedend(2))
498 bwipe!
499endfunc
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100500
501" Various fold related tests
502
503" Basic test if a fold can be created, opened, moving to the end and closed
504func Test_fold_manual()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200505 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100506 set fdm=manual
507
508 let content = ['1 aa', '2 bb', '3 cc']
509 call append(0, content)
510 call cursor(1, 1)
511 normal zf2j
512 call assert_equal('1 aa', getline(foldclosed('.')))
513 normal zo
514 call assert_equal(-1, foldclosed('.'))
515 normal ]z
516 call assert_equal('3 cc', getline('.'))
517 normal zc
518 call assert_equal('1 aa', getline(foldclosed('.')))
519
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200520 " Create a fold inside a closed fold after setting 'foldlevel'
521 %d _
522 call setline(1, range(1, 5))
523 1,5fold
524 normal zR
525 2,4fold
526 set foldlevel=1
527 3fold
528 call assert_equal([1, 3, 3, 3, 1], map(range(1, 5), {->foldlevel(v:val)}))
529 set foldlevel&
530
531 " Create overlapping folds (at the start and at the end)
532 normal zE
533 2,3fold
534 normal zR
535 3,4fold
536 call assert_equal([0, 2, 2, 1, 0], map(range(1, 5), {->foldlevel(v:val)}))
537 normal zE
538 3,4fold
539 normal zR
540 2,3fold
541 call assert_equal([0, 1, 2, 2, 0], map(range(1, 5), {->foldlevel(v:val)}))
542
543 " Create a nested fold across two non-adjoining folds
544 %d _
545 call setline(1, range(1, 7))
546 1,2fold
547 normal zR
548 4,5fold
549 normal zR
550 6,7fold
551 normal zR
552 1,5fold
553 call assert_equal([2, 2, 1, 2, 2, 1, 1],
554 \ map(range(1, 7), {->foldlevel(v:val)}))
555
556 " A newly created nested fold should be closed
557 %d _
558 call setline(1, range(1, 6))
559 1,6fold
560 normal zR
561 3,4fold
562 normal zR
563 2,5fold
564 call assert_equal([1, 2, 3, 3, 2, 1], map(range(1, 6), {->foldlevel(v:val)}))
565 call assert_equal(2, foldclosed(4))
566 call assert_equal(5, foldclosedend(4))
567
568 " Test zO, zC and zA on a line with no folds.
569 normal zE
570 call assert_fails('normal zO', 'E490:')
571 call assert_fails('normal zC', 'E490:')
572 call assert_fails('normal zA', 'E490:')
573
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100574 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200575 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100576endfunc
577
578" test folding with markers.
579func Test_fold_marker()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200580 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100581 set fdm=marker fdl=1 fdc=3
582
583 let content = ['4 dd {{{', '5 ee {{{ }}}', '6 ff }}}']
584 call append(0, content)
585 call cursor(2, 1)
586 call assert_equal(2, foldlevel('.'))
587 normal [z
588 call assert_equal(1, foldlevel('.'))
589 exe "normal jo{{ \<Esc>r{jj"
590 call assert_equal(1, foldlevel('.'))
591 normal kYpj
592 call assert_equal(0, foldlevel('.'))
593
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200594 " Use only closing fold marker (without and with a count)
595 set fdl&
596 %d _
597 call setline(1, ['one }}}', 'two'])
598 call assert_equal([0, 0], [foldlevel(1), foldlevel(2)])
599 %d _
600 call setline(1, ['one }}}4', 'two'])
601 call assert_equal([4, 3], [foldlevel(1), foldlevel(2)])
602
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100603 set fdm& fdl& fdc&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200604 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100605endfunc
606
Bram Moolenaar4af72592018-12-09 15:00:52 +0100607" test create fold markers with C filetype
608func Test_fold_create_marker_in_C()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200609 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100610 set fdm=marker fdl=9
611 set filetype=c
612
Bram Moolenaarc79745a2019-05-20 22:12:34 +0200613 let content =<< trim [CODE]
614 /*
615 * comment
616 *
617 *
618 */
619 int f(int* p) {
620 *p = 3;
621 return 0;
622 }
623 [CODE]
624
Bram Moolenaar4af72592018-12-09 15:00:52 +0100625 for c in range(len(content) - 1)
626 bw!
627 call append(0, content)
628 call cursor(c + 1, 1)
629 norm! zfG
630 call assert_equal(content[c] . (c < 4 ? '{{{' : '/*{{{*/'), getline(c + 1))
631 endfor
632
633 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200634 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100635endfunc
636
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100637" test folding with indent
638func Test_fold_indent()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200639 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100640 set fdm=indent sw=2
641
642 let content = ['1 aa', '2 bb', '3 cc']
643 call append(0, content)
644 call cursor(2, 1)
645 exe "normal i \<Esc>jI "
646 call assert_equal(2, foldlevel('.'))
647 normal k
648 call assert_equal(1, foldlevel('.'))
649
650 set fdm& sw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200651 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100652endfunc
653
654" test syntax folding
655func Test_fold_syntax()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200656 CheckFeature syntax
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100657
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200658 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100659 set fdm=syntax fdl=0
660
661 syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3
662 syn region Fd1 start="ee" end="ff" fold contained
663 syn region Fd2 start="gg" end="hh" fold contained
664 syn region Fd3 start="commentstart" end="commentend" fold contained
665 let content = ['3 cc', '4 dd {{{', '5 ee {{{ }}}', '{{{{', '6 ff }}}',
666 \ '6 ff }}}', '7 gg', '8 hh', '9 ii']
667 call append(0, content)
668 normal Gzk
669 call assert_equal('9 ii', getline('.'))
670 normal k
671 call assert_equal('3 cc', getline('.'))
672 exe "normal jAcommentstart \<Esc>Acommentend"
673 set fdl=1
674 normal 3j
675 call assert_equal('7 gg', getline('.'))
676 set fdl=0
677 exe "normal zO\<C-L>j"
678 call assert_equal('8 hh', getline('.'))
679 syn clear Fd1 Fd2 Fd3 Hup
680
681 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200682 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100683endfunc
684
685func Flvl()
686 let l = getline(v:lnum)
687 if l =~ "bb$"
688 return 2
689 elseif l =~ "gg$"
690 return "s1"
691 elseif l =~ "ii$"
692 return ">2"
693 elseif l =~ "kk$"
694 return "0"
695 endif
696 return "="
697endfun
698
699" test expression folding
700func Test_fold_expr()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200701 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100702 set fdm=expr fde=Flvl()
703
704 let content = ['1 aa',
705 \ '2 bb',
706 \ '3 cc',
707 \ '4 dd {{{commentstart commentend',
708 \ '5 ee {{{ }}}',
709 \ '{{{',
710 \ '6 ff }}}',
711 \ '6 ff }}}',
712 \ ' 7 gg',
713 \ ' 8 hh',
714 \ '9 ii',
715 \ 'a jj',
716 \ 'b kk']
717 call append(0, content)
718 call cursor(1, 1)
719 exe "normal /bb$\<CR>"
720 call assert_equal(2, foldlevel('.'))
721 exe "normal /hh$\<CR>"
722 call assert_equal(1, foldlevel('.'))
723 exe "normal /ii$\<CR>"
724 call assert_equal(2, foldlevel('.'))
725 exe "normal /kk$\<CR>"
726 call assert_equal(0, foldlevel('.'))
727
728 set fdm& fde&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200729 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100730endfunc
731
732" Bug with fdm=indent and moving folds
733" Moving a fold a few times, messes up the folds below the moved fold.
734" Fixed by 7.4.700
735func Test_fold_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200736 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100737 set fdm=indent sw=2 fdl=0
738
739 let content = ['', '', 'Line1', ' Line2', ' Line3',
740 \ 'Line4', ' Line5', ' Line6',
741 \ 'Line7', ' Line8', ' Line9']
742 call append(0, content)
743 normal zM
744 call cursor(4, 1)
745 move 2
746 move 1
747 call assert_equal(7, foldclosed(7))
748 call assert_equal(8, foldclosedend(7))
749 call assert_equal(0, foldlevel(9))
750 call assert_equal(10, foldclosed(10))
751 call assert_equal(11, foldclosedend(10))
752 call assert_equal('+-- 2 lines: Line2', foldtextresult(2))
Bram Moolenaara4208962019-08-24 20:50:19 +0200753 call assert_equal('+-- 2 lines: Line8', 10->foldtextresult())
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100754
755 set fdm& sw& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200756 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100757endfunc
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100758
759" test for patch 7.3.637
760" Cannot catch the error caused by a foldopen when there is no fold.
761func Test_foldopen_exception()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200762 new
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100763 let a = 'No error caught'
764 try
765 foldopen
766 catch
767 let a = matchstr(v:exception,'^[^ ]*')
768 endtry
769 call assert_equal('Vim(foldopen):E490:', a)
770
771 let a = 'No error caught'
772 try
773 foobar
774 catch
775 let a = matchstr(v:exception,'^[^ ]*')
776 endtry
777 call assert_match('E492:', a)
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200778 bw!
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100779endfunc
Bram Moolenaar907dad72018-07-10 15:07:15 +0200780
781func Test_fold_last_line_with_pagedown()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200782 new
Bram Moolenaar907dad72018-07-10 15:07:15 +0200783 set fdm=manual
784
785 let expect = '+-- 11 lines: 9---'
786 let content = range(1,19)
787 call append(0, content)
788 normal dd9G
789 normal zfG
790 normal zt
791 call assert_equal('9', getline(foldclosed('.')))
792 call assert_equal('19', getline(foldclosedend('.')))
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-F>", 'xt')
797 call assert_equal(expect, ScreenLines(1, len(expect))[0])
798 call feedkeys("\<C-B>\<C-F>\<C-F>", 'xt')
799 call assert_equal(expect, ScreenLines(1, len(expect))[0])
800
801 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200802 bw!
Bram Moolenaar907dad72018-07-10 15:07:15 +0200803endfunc
Bram Moolenaar7701f302018-10-02 21:20:32 +0200804
805func Test_folds_with_rnu()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200806 CheckScreendump
Bram Moolenaar7701f302018-10-02 21:20:32 +0200807
808 call writefile([
809 \ 'set fdm=marker rnu foldcolumn=2',
810 \ 'call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])',
811 \ ], 'Xtest_folds_with_rnu')
812 let buf = RunVimInTerminal('-S Xtest_folds_with_rnu', {})
813
814 call VerifyScreenDump(buf, 'Test_folds_with_rnu_01', {})
815 call term_sendkeys(buf, "j")
816 call VerifyScreenDump(buf, 'Test_folds_with_rnu_02', {})
817
818 " clean up
819 call StopVimInTerminal(buf)
820 call delete('Xtest_folds_with_rnu')
821endfunc
Bram Moolenaar53932812018-12-07 21:08:49 +0100822
823func Test_folds_marker_in_comment2()
824 new
825 call setline(1, ['Lorem ipsum dolor sit', 'Lorem ipsum dolor sit', 'Lorem ipsum dolor sit'])
826 setl fen fdm=marker
827 setl commentstring=<!--%s-->
828 setl comments=s:<!--,m:\ \ \ \ ,e:-->
829 norm! zf2j
830 setl nofen
831 :1y
832 call assert_equal(['Lorem ipsum dolor sit<!--{{{-->'], getreg(0,1,1))
833 :+2y
834 call assert_equal(['Lorem ipsum dolor sit<!--}}}-->'], getreg(0,1,1))
835
836 set foldmethod&
837 bwipe!
838endfunc
Bram Moolenaar9a4a8c42019-08-19 22:48:30 +0200839
840func Test_fold_delete_with_marker()
841 new
842 call setline(1, ['func Func() {{{1', 'endfunc'])
843 1,2yank
844 new
845 set fdm=marker
846 call setline(1, 'x')
847 normal! Vp
848 normal! zd
849 call assert_equal(['func Func() ', 'endfunc'], getline(1, '$'))
850
851 set fdm&
852 bwipe!
853 bwipe!
854endfunc
Bram Moolenaar7a9bd7c2019-09-17 22:42:55 +0200855
856func Test_fold_delete_with_marker_and_whichwrap()
857 new
858 let content1 = ['']
859 let content2 = ['folded line 1 "{{{1', ' test', ' test2', ' test3', '', 'folded line 2 "{{{1', ' test', ' test2', ' test3']
860 call setline(1, content1 + content2)
861 set fdm=marker ww+=l
862 normal! x
863 call assert_equal(content2, getline(1, '$'))
864 set fdm& ww&
865 bwipe!
866endfunc
Bram Moolenaar3b681232019-12-13 19:35:55 +0100867
868func Test_fold_delete_first_line()
869 new
870 call setline(1, [
871 \ '" x {{{1',
872 \ '" a',
873 \ '" aa',
874 \ '" x {{{1',
875 \ '" b',
876 \ '" bb',
877 \ '" x {{{1',
878 \ '" c',
879 \ '" cc',
880 \ ])
881 set foldmethod=marker
882 1
883 normal dj
884 call assert_equal([
885 \ '" x {{{1',
886 \ '" c',
887 \ '" cc',
888 \ ], getline(1,'$'))
889 bwipe!
890 set foldmethod&
891endfunc
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200892
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200893" Add a test for deleting the outer fold of a nested fold and promoting the
894" inner folds to one level up with already a fold at that level following the
895" nested fold.
896func Test_fold_delete_recursive_fold()
897 new
898 call setline(1, range(1, 7))
899 2,3fold
900 normal zR
901 4,5fold
902 normal zR
903 1,5fold
904 normal zR
905 6,7fold
906 normal zR
907 normal 1Gzd
908 normal 1Gzj
909 call assert_equal(2, line('.'))
910 normal zj
911 call assert_equal(4, line('.'))
912 normal zj
913 call assert_equal(6, line('.'))
914 bw!
915endfunc
916
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200917" Test for errors in 'foldexpr'
918func Test_fold_expr_error()
919 new
920 call setline(1, ['one', 'two', 'three'])
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200921 " In a window with no folds, foldlevel() should return 0
922 call assert_equal(0, foldlevel(1))
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200923
924 " Return a list from the expression
925 set foldexpr=[]
926 set foldmethod=expr
927 for i in range(3)
928 call assert_equal(0, foldlevel(i))
929 endfor
930
931 " expression error
932 set foldexpr=[{]
933 set foldmethod=expr
934 for i in range(3)
935 call assert_equal(0, foldlevel(i))
936 endfor
937
938 set foldmethod& foldexpr&
939 close!
940endfunc
941
Bram Moolenaarda697642020-09-17 19:36:04 +0200942func Test_undo_fold_deletion()
943 new
944 set fdm=marker
945 let lines =<< trim END
946 " {{{
947 " }}}1
948 " {{{
949 END
950 call setline(1, lines)
951 3d
952 g/"/d
953 undo
954 redo
955 eval getline(1, '$')->assert_equal([''])
956
957 set fdm&vim
958 bwipe!
959endfunc
960
Bram Moolenaarc136a352020-11-03 20:05:40 +0100961" this was crashing
962func Test_move_no_folds()
963 new
964 fold
965 setlocal fdm=expr
966 normal zj
967 bwipe!
968endfunc
969
Bram Moolenaar5e1f22f2020-11-10 18:23:52 +0100970" this was crashing
971func Test_fold_create_delete_create()
972 new
973 fold
974 fold
975 normal zd
976 fold
977 bwipe!
978endfunc
979
Bram Moolenaar6a78f322020-12-21 14:01:41 +0100980" this was crashing
981func Test_fold_create_delete()
982 new
983 norm zFzFzdzj
984 bwipe!
985endfunc
986
Bram Moolenaare71996b2021-01-21 17:03:07 +0100987func Test_fold_relative_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200988 new
Bram Moolenaare71996b2021-01-21 17:03:07 +0100989 set fdm=indent sw=2 wrap tw=80
990
Bram Moolenaar3c49e742021-04-04 21:26:04 +0200991 let longtext = repeat('x', &columns + 1)
992 let content = [ ' foo', ' ' .. longtext, ' baz',
993 \ longtext,
994 \ ' foo', ' ' .. longtext, ' baz'
Bram Moolenaare71996b2021-01-21 17:03:07 +0100995 \ ]
996 call append(0, content)
997
998 normal zM
999
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001000 for lnum in range(1, 3)
1001 call cursor(lnum, 1)
1002 call assert_true(foldclosed(line('.')))
1003 normal gj
1004 call assert_equal(2, winline())
1005 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001006
1007 call cursor(2, 1)
1008 call assert_true(foldclosed(line('.')))
1009 normal 2gj
1010 call assert_equal(3, winline())
1011
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001012 for lnum in range(5, 7)
1013 call cursor(lnum, 1)
1014 call assert_true(foldclosed(line('.')))
1015 normal gk
1016 call assert_equal(3, winline())
1017 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001018
1019 call cursor(6, 1)
1020 call assert_true(foldclosed(line('.')))
1021 normal 2gk
1022 call assert_equal(2, winline())
1023
1024 set fdm& sw& wrap& tw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001025 bw!
Bram Moolenaare71996b2021-01-21 17:03:07 +01001026endfunc
1027
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001028" Test for using multibyte characters as 'foldopen', 'foldclose' and
1029" 'foldsetp' items in 'fillchars'
1030func s:mbyte_fillchar_tests(fo, fc, fs)
1031 setlocal foldcolumn=3
1032
1033 normal zE
1034 1,2fold
1035 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1036 \ ScreenLines([1, 2], 10))
1037 1,2foldopen
1038 call assert_equal([a:fo .. ' one ', a:fs .. ' two '],
1039 \ ScreenLines([1, 2], 7))
1040 1,2foldclose
1041 redraw!
1042 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1043 \ ScreenLines([1, 2], 10))
1044
1045 " Two level fold
1046 normal zE
1047 2,3fold
1048 1,4fold
1049 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1050 \ ScreenLines([1, 2], 10))
1051 1,4foldopen
1052 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1053 \ ScreenLines([1, 2], 10))
1054 1,4foldopen
1055 call assert_equal([a:fo .. ' one ', a:fs .. a:fo .. ' two ',
1056 \ a:fs .. a:fs .. ' three '], ScreenLines([1, 3], 10))
1057 2,3foldclose
1058 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1059 \ ScreenLines([1, 2], 10))
1060 1,4foldclose
1061 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1062 \ ScreenLines([1, 2], 10))
1063
1064 " Three level fold
1065 normal zE
1066 3,4fold
1067 2,5fold
1068 1,6fold
1069 call assert_equal([a:fc .. ' +-- 6 '], ScreenLines(1, 10))
1070 " open all the folds
1071 normal zR
1072 call assert_equal([
1073 \ a:fo .. ' one ',
1074 \ a:fs .. a:fo .. ' two ',
1075 \ '2' .. a:fo .. ' three ',
1076 \ '23 four ',
1077 \ a:fs .. a:fs .. ' five ',
1078 \ a:fs .. ' six ',
1079 \ ], ScreenLines([1, 6], 10))
1080 " close the innermost fold
1081 3,4foldclose
1082 call assert_equal([
1083 \ a:fo .. ' one ',
1084 \ a:fs .. a:fo .. ' two ',
1085 \ a:fs .. a:fs .. a:fc .. '+---- ',
1086 \ a:fs .. a:fs .. ' five ',
1087 \ a:fs .. ' six ',
1088 \ ], ScreenLines([1, 5], 10))
1089 " close the next fold
1090 2,5foldclose
1091 call assert_equal([
1092 \ a:fo .. ' one ',
1093 \ a:fs .. a:fc .. ' +--- 4',
1094 \ a:fs .. ' six ',
1095 \ ], ScreenLines([1, 3], 10))
1096
1097 " set the fold column size to 2
1098 setlocal fdc=2
1099 normal zR
1100 call assert_equal([
1101 \ a:fo .. ' one ',
1102 \ a:fo .. ' two ',
1103 \ a:fo .. ' three',
1104 \ '3 four ',
1105 \ '2 five ',
1106 \ a:fs .. ' six ',
1107 \ ], ScreenLines([1, 6], 7))
1108
1109 " set the fold column size to 1
1110 setlocal fdc=1
1111 normal zR
1112 call assert_equal([
1113 \ a:fo .. 'one ',
1114 \ a:fo .. 'two ',
1115 \ a:fo .. 'three ',
1116 \ '3four ',
1117 \ '2five ',
1118 \ a:fs .. 'six ',
1119 \ ], ScreenLines([1, 6], 7))
1120
Bram Moolenaar008bff92021-03-04 21:55:58 +01001121 " Enable number and sign columns and place some signs
1122 setlocal fdc=3
1123 setlocal number
1124 setlocal signcolumn=auto
1125 sign define S1 text=->
1126 sign place 10 line=3 name=S1
1127 call assert_equal([
1128 \ a:fo .. ' 1 one ',
1129 \ a:fs .. a:fo .. ' 2 two ',
1130 \ '2' .. a:fo .. ' -> 3 three',
1131 \ '23 4 four ',
1132 \ a:fs .. a:fs .. ' 5 five ',
1133 \ a:fs .. ' 6 six '
1134 \ ], ScreenLines([1, 6], 14))
1135
1136 " Test with 'rightleft'
1137 if has('rightleft')
1138 setlocal rightleft
1139 let lines = ScreenLines([1, 6], winwidth(0))
1140 call assert_equal('o 1 ' .. a:fo,
1141 \ strcharpart(lines[0], strchars(lines[0]) - 10, 10))
1142 call assert_equal('t 2 ' .. a:fo .. a:fs,
1143 \ strcharpart(lines[1], strchars(lines[1]) - 10, 10))
1144 call assert_equal('t 3 >- ' .. a:fo .. '2',
1145 \ strcharpart(lines[2], strchars(lines[2]) - 10, 10))
1146 call assert_equal('f 4 32',
1147 \ strcharpart(lines[3], strchars(lines[3]) - 10, 10))
1148 call assert_equal('f 5 ' .. a:fs .. a:fs,
1149 \ strcharpart(lines[4], strchars(lines[4]) - 10, 10))
1150 call assert_equal('s 6 ' .. a:fs,
1151 \ strcharpart(lines[5], strchars(lines[5]) - 10, 10))
1152 setlocal norightleft
1153 endif
1154
1155 sign unplace *
1156 sign undefine S1
1157 setlocal number& signcolumn&
1158
1159 " Add a test with more than 9 folds (and then delete some folds)
1160 normal zE
1161 for i in range(1, 10)
1162 normal zfGzo
1163 endfor
1164 normal zR
1165 call assert_equal([
1166 \ a:fo .. a:fo .. ' one ',
1167 \ '9> two '
1168 \ ], ScreenLines([1, 2], 7))
1169 normal 1Gzd
1170 call assert_equal([
1171 \ a:fo .. a:fo .. ' one ',
1172 \ '89 two '
1173 \ ], ScreenLines([1, 2], 7))
1174 normal 1Gzdzdzdzdzdzdzd
1175 call assert_equal([
1176 \ a:fo .. a:fo .. ' one ',
1177 \ a:fs .. a:fs .. ' two '
1178 \ ], ScreenLines([1, 2], 7))
1179
1180 setlocal foldcolumn& number& signcolumn&
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001181endfunc
1182
1183func Test_foldcolumn_multibyte_char()
1184 new
1185 call setline(1, ['one', 'two', 'three', 'four', 'five', 'six'])
1186 setlocal foldenable foldmethod=manual
1187
1188 " First test with the default setting
1189 call s:mbyte_fillchar_tests('-', '+', '|')
1190
1191 " Use multi-byte characters
1192 set fillchars+=foldopen:▾,foldsep:│,foldclose:▸
1193 call s:mbyte_fillchar_tests('▾', '▸', '│')
1194
Bram Moolenaar196a1f72021-03-21 14:39:19 +01001195 " Use a mix of multi-byte and single-byte characters
1196 set fillchars+=foldopen:¬,foldsep:\|,foldclose:+
1197 call s:mbyte_fillchar_tests('¬', '+', '|')
1198 set fillchars+=foldopen:+,foldsep:\|,foldclose:¬
1199 call s:mbyte_fillchar_tests('+', '¬', '|')
1200
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001201 bw!
1202 set foldenable& fdc& fdm& fillchars&
1203endfunc
1204
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001205" Test for calling foldlevel() from a fold expression
1206let g:FoldLevels = []
1207func FoldExpr1(lnum)
1208 let f = [a:lnum]
1209 for i in range(1, line('$'))
1210 call add(f, foldlevel(i))
1211 endfor
1212 call add(g:FoldLevels, f)
1213 return getline(a:lnum)[0] == "\t"
1214endfunc
1215
1216func Test_foldexpr_foldlevel()
1217 new
1218 call setline(1, ['one', "\ttwo", "\tthree"])
1219 setlocal foldmethod=expr
1220 setlocal foldexpr=FoldExpr1(v:lnum)
1221 setlocal foldenable
1222 setlocal foldcolumn=3
1223 redraw!
1224 call assert_equal([[1, -1, -1, -1], [2, -1, -1, -1], [3, 0, 1, -1]],
1225 \ g:FoldLevels)
1226 set foldmethod& foldexpr& foldenable& foldcolumn&
1227 bw!
1228endfunc
1229
1230" Test for returning different values from a fold expression
1231func FoldExpr2(lnum)
1232 if a:lnum == 1 || a:lnum == 4
1233 return -2
1234 elseif a:lnum == 2
1235 return 'a1'
1236 elseif a:lnum == 3
1237 return 's4'
1238 endif
1239 return '='
1240endfunc
1241
1242func Test_foldexpr_2()
1243 new
1244 call setline(1, ['one', 'two', 'three', 'four'])
1245 setlocal foldexpr=FoldExpr2(v:lnum)
1246 setlocal foldmethod=expr
1247 call assert_equal([0, 1, 1, 0], [foldlevel(1), foldlevel(2), foldlevel(3),
1248 \ foldlevel(4)])
1249 bw!
1250endfunc
1251
1252" Test for the 'foldclose' option
1253func Test_foldclose_opt()
1254 CheckScreendump
1255
1256 let lines =<< trim END
1257 set foldmethod=manual foldclose=all foldopen=all
1258 call setline(1, ['one', 'two', 'three', 'four'])
1259 2,3fold
1260 func XsaveFoldLevels()
1261 redraw!
1262 call writefile([json_encode([foldclosed(1), foldclosed(2), foldclosed(3),
1263 \ foldclosed(4)])], 'Xoutput', 'a')
1264 endfunc
1265 END
1266 call writefile(lines, 'Xscript')
1267 let rows = 10
1268 let buf = RunVimInTerminal('-S Xscript', {'rows': rows})
1269 call term_wait(buf)
1270 call term_sendkeys(buf, ":set noruler\n")
1271 call term_wait(buf)
1272 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1273 call term_sendkeys(buf, "2G")
1274 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1275 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1276 call term_sendkeys(buf, "4G")
1277 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1278 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1279 call term_sendkeys(buf, "3G")
1280 call WaitForAssert({-> assert_equal('three', term_getline(buf, 3))})
1281 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1282 call term_sendkeys(buf, "1G")
1283 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1284 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001285 call term_sendkeys(buf, "2G")
1286 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1287 call term_sendkeys(buf, "k")
1288 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001289
1290 " clean up
1291 call StopVimInTerminal(buf)
1292
1293 call assert_equal(['[-1,2,2,-1]', '[-1,-1,-1,-1]', '[-1,2,2,-1]',
1294 \ '[-1,-1,-1,-1]', '[-1,2,2,-1]'], readfile('Xoutput'))
1295 call delete('Xscript')
1296 call delete('Xoutput')
1297endfunc
1298
1299" Test for foldtextresult()
1300func Test_foldtextresult()
1301 new
1302 call assert_equal('', foldtextresult(-1))
1303 call assert_equal('', foldtextresult(0))
1304 call assert_equal('', foldtextresult(1))
1305 call setline(1, ['one', 'two', 'three', 'four'])
1306 2,3fold
1307 call assert_equal('', foldtextresult(1))
1308 call assert_equal('+-- 2 lines: two', foldtextresult(2))
1309 setlocal foldtext=
1310 call assert_equal('+-- 2 lines folded ', foldtextresult(2))
1311
1312 " Fold text for a C comment fold
1313 %d _
1314 setlocal foldtext&
1315 call setline(1, ['', '/*', ' * Comment', ' */', ''])
1316 2,4fold
1317 call assert_equal('+-- 3 lines: Comment', foldtextresult(2))
1318
1319 bw!
1320endfunc
1321
1322" Test for merging two recursive folds when an intermediate line with no fold
1323" is removed
1324func Test_fold_merge_recrusive()
1325 new
1326 call setline(1, [' one', ' two', 'xxxx', ' three',
1327 \ ' four', "\tfive"])
1328 setlocal foldmethod=indent shiftwidth=2
1329 3d_
1330 %foldclose
1331 call assert_equal([1, 5], [foldclosed(5), foldclosedend(1)])
1332 bw!
1333endfunc
1334
1335" Test for moving a line which is the start of a fold from a recursive fold to
1336" outside. The fold length should reduce.
1337func Test_fold_move_foldlevel()
1338 new
1339 call setline(1, ['a{{{', 'b{{{', 'c{{{', 'd}}}', 'e}}}', 'f}}}', 'g'])
1340 setlocal foldmethod=marker
1341 normal zR
1342 call assert_equal([3, 2, 1], [foldlevel(4), foldlevel(5), foldlevel(6)])
1343 3move 7
1344 call assert_equal([2, 1, 0], [foldlevel(3), foldlevel(4), foldlevel(5)])
1345 call assert_equal(1, foldlevel(7))
1346
1347 " Move a line from outside a fold to inside the fold.
1348 %d _
1349 call setline(1, ['a', 'b{{{', 'c}}}'])
1350 normal zR
1351 1move 2
1352 call assert_equal([1, 1, 1], [foldlevel(1), foldlevel(2), foldlevel(3)])
1353
1354 " Move the start of one fold to inside another fold
1355 %d _
1356 call setline(1, ['a', 'b{{{', 'c}}}', 'd{{{', 'e}}}'])
1357 normal zR
1358 call assert_equal([0, 1, 1, 1, 1], [foldlevel(1), foldlevel(2),
1359 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1360 1,2move 4
1361 call assert_equal([0, 1, 1, 2, 2], [foldlevel(1), foldlevel(2),
1362 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1363
1364 bw!
1365endfunc
1366
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001367" Test for using zj and zk to move downwards and upwards to the start and end
1368" of the next fold.
1369" Test for using [z and ]z in a closed fold to jump to the beginning and end
1370" of the fold.
1371func Test_fold_jump()
1372 new
1373 call setline(1, ["\t1", "\t2", "\t\t3", "\t\t4", "\t\t\t5", "\t\t\t6", "\t\t7", "\t\t8", "\t9", "\t10"])
1374 setlocal foldmethod=indent
1375 normal zR
1376 normal zj
1377 call assert_equal(3, line('.'))
1378 normal zj
1379 call assert_equal(5, line('.'))
1380 call assert_beeps('normal zj')
1381 call assert_equal(5, line('.'))
1382 call assert_beeps('normal 9Gzj')
1383 call assert_equal(9, line('.'))
1384 normal Gzk
1385 call assert_equal(8, line('.'))
1386 normal zk
1387 call assert_equal(6, line('.'))
1388 call assert_beeps('normal zk')
1389 call assert_equal(6, line('.'))
1390 call assert_beeps('normal 2Gzk')
1391 call assert_equal(2, line('.'))
1392
1393 " Using [z or ]z in a closed fold should not move the cursor
1394 %d _
1395 call setline(1, ["1", "\t2", "\t3", "\t4", "\t5", "\t6", "7"])
1396 normal zR4Gzc
1397 call assert_equal(4, line('.'))
1398 call assert_beeps('normal [z')
1399 call assert_equal(4, line('.'))
1400 call assert_beeps('normal ]z')
1401 call assert_equal(4, line('.'))
1402 bw!
1403endfunc
1404
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001405" Test for using a script-local function for 'foldexpr'
1406func Test_foldexpr_scriptlocal_func()
1407 func! s:FoldFunc()
1408 let g:FoldLnum = v:lnum
1409 endfunc
1410 new | only
1411 call setline(1, 'abc')
1412 let g:FoldLnum = 0
1413 set foldmethod=expr foldexpr=s:FoldFunc()
1414 redraw!
1415 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1416 call assert_equal(1, g:FoldLnum)
1417 set foldmethod& foldexpr=
1418 bw!
1419 new | only
1420 call setline(1, 'abc')
1421 let g:FoldLnum = 0
1422 set foldmethod=expr foldexpr=<SID>FoldFunc()
1423 redraw!
1424 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1425 call assert_equal(1, g:FoldLnum)
1426 set foldmethod& foldexpr=
1427 delfunc s:FoldFunc
1428 bw!
1429endfunc
1430
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001431" Test for using a script-local function for 'foldtext'
1432func Test_foldtext_scriptlocal_func()
1433 func! s:FoldText()
1434 let g:FoldTextArgs = [v:foldstart, v:foldend]
1435 return foldtext()
1436 endfunc
1437 new | only
1438 call setline(1, range(50))
1439 let g:FoldTextArgs = []
1440 set foldmethod=manual
1441 set foldtext=s:FoldText()
1442 norm! 4Gzf4j
1443 redraw!
1444 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1445 call assert_equal([4, 8], g:FoldTextArgs)
1446 set foldtext&
1447 bw!
1448 new | only
1449 call setline(1, range(50))
1450 let g:FoldTextArgs = []
1451 set foldmethod=manual
1452 set foldtext=<SID>FoldText()
1453 norm! 8Gzf4j
1454 redraw!
1455 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1456 call assert_equal([8, 12], g:FoldTextArgs)
1457 set foldtext&
1458 bw!
1459 delfunc s:FoldText
1460endfunc
1461
Brandon Simmons2c407072022-04-23 13:50:17 +01001462" Make sure a fold containing a nested fold is split correctly when using
1463" foldmethod=indent
1464func Test_fold_split()
1465 new
1466 let lines =<< trim END
1467 line 1
1468 line 2
1469 line 3
1470 line 4
1471 line 5
1472 END
1473 call setline(1, lines)
1474 setlocal sw=2
1475 setlocal foldmethod=indent foldenable
1476 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
1477 call append(2, 'line 2.5')
1478 call assert_equal([0, 1, 0, 1, 2, 2], range(1, 6)->map('foldlevel(v:val)'))
1479 bw!
1480endfunc
1481
Brandon Simmonsd98e75e2022-05-10 19:13:23 +01001482" Make sure that when you append under a blank line that is under a fold with
1483" the same indent level as your appended line, the fold expands across the
1484" blank line
1485func Test_indent_append_under_blank_line()
1486 new
1487 let lines =<< trim END
1488 line 1
1489 line 2
1490 line 3
1491 END
1492 call setline(1, lines)
1493 setlocal sw=2
1494 setlocal foldmethod=indent foldenable
1495 call assert_equal([0, 1, 1], range(1, 3)->map('foldlevel(v:val)'))
1496 call append(3, '')
1497 call append(4, ' line 5')
1498 call assert_equal([0, 1, 1, 1, 1], range(1, 5)->map('foldlevel(v:val)'))
1499 bw!
1500endfunc
1501
Brandon Simmons3fcccf92022-05-20 18:25:21 +01001502" Make sure that when you delete 1 line of a fold whose length is 2 lines, the
1503" fold can't be closed since its length (1) is now less than foldminlines.
1504func Test_indent_one_line_fold_close()
1505 let lines =<< trim END
1506 line 1
1507 line 2
1508 line 3
1509 END
1510
1511 new
1512 setlocal sw=2 foldmethod=indent
1513 call setline(1, lines)
1514 " open all folds, delete line, then close all folds
1515 normal zR
1516 3delete
1517 normal zM
1518 call assert_equal(-1, foldclosed(2)) " the fold should not be closed
1519
1520 " Now do the same, but delete line 2 this time; this covers different code.
1521 " (Combining this code with the above code doesn't expose both bugs.)
1522 1,$delete
1523 call setline(1, lines)
1524 normal zR
1525 2delete
1526 normal zM
1527 call assert_equal(-1, foldclosed(2))
1528 bw!
1529endfunc
1530
Brandon Simmonse8c4a642022-05-23 15:33:08 +01001531" Make sure that when appending [an indented line then a blank line] right
1532" before a single indented line, the resulting extended fold can be closed
1533func Test_indent_append_blank_small_fold_close()
1534 new
1535 setlocal sw=2 foldmethod=indent
1536 " at first, the fold at the second line can't be closed since it's smaller
1537 " than foldminlines
1538 let lines =<< trim END
1539 line 1
1540 line 4
1541 END
1542 call setline(1, lines)
1543 call append(1, [' line 2', ''])
1544 " close all folds
1545 normal zM
1546 call assert_notequal(-1, foldclosed(2)) " the fold should be closed now
1547 bw!
1548endfunc
1549
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001550" vim: shiftwidth=2 sts=2 expandtab