blob: 2f4aade0133cd61c5c62cf5e4218c55e39cde75b [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 Moolenaar9954dc32022-11-11 22:58:36 +000075func Test_address_offsets()
76 " check the help for :range-closed-fold
77 enew
78 call setline(1, [
79 \ '1 one',
80 \ '2 two',
81 \ '3 three',
82 \ '4 four FOLDED',
83 \ '5 five FOLDED',
84 \ '6 six',
85 \ '7 seven',
86 \ '8 eight',
87 \])
88 set foldmethod=manual
89 normal 4Gvjzf
90 3,4+2yank
91 call assert_equal([
92 \ '3 three',
93 \ '4 four FOLDED',
94 \ '5 five FOLDED',
95 \ '6 six',
96 \ '7 seven',
97 \ ], getreg(0,1,1))
98
99 enew!
100 call setline(1, [
101 \ '1 one',
102 \ '2 two',
103 \ '3 three FOLDED',
104 \ '4 four FOLDED',
105 \ '5 five FOLDED',
106 \ '6 six FOLDED',
107 \ '7 seven',
108 \ '8 eight',
109 \])
110 normal 3Gv3jzf
111 2,4-1yank
112 call assert_equal([
113 \ '2 two',
114 \ '3 three FOLDED',
115 \ '4 four FOLDED',
116 \ '5 five FOLDED',
117 \ '6 six FOLDED',
118 \ ], getreg(0,1,1))
119
120 bwipe!
121endfunc
122
Bram Moolenaar94be6192017-04-22 22:40:11 +0200123func Test_indent_fold()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100124 new
125 call setline(1, ['', 'a', ' b', ' c'])
126 setl fen fdm=indent
127 2
128 norm! >>
129 let a=map(range(1,4), 'foldclosed(v:val)')
130 call assert_equal([-1,-1,-1,-1], a)
131 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +0100132endfunc
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100133
Bram Moolenaar94be6192017-04-22 22:40:11 +0200134func Test_indent_fold2()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100135 new
136 call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
137 setl fen fdm=marker
138 2
139 norm! >>
Bram Moolenaara4208962019-08-24 20:50:19 +0200140 let a=map(range(1,5), 'v:val->foldclosed()')
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +0100141 call assert_equal([-1,-1,-1,4,4], a)
142 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +0100143endfunc
144
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200145" Test for fold indent with indents greater than 'foldnestmax'
146func Test_indent_fold_max()
147 new
148 setlocal foldmethod=indent
149 setlocal shiftwidth=2
150 " 'foldnestmax' default value is 20
151 call setline(1, "\t\t\t\t\t\ta")
152 call assert_equal(20, foldlevel(1))
153 setlocal foldnestmax=10
154 call assert_equal(10, foldlevel(1))
155 setlocal foldnestmax=-1
156 call assert_equal(0, foldlevel(1))
157 bw!
158endfunc
159
Bram Moolenaar1159b162017-02-28 21:53:56 +0100160func Test_manual_fold_with_filter()
Bram Moolenaaraeb313f2020-11-27 19:13:28 +0100161 CheckExecutable cat
Bram Moolenaar3f3897e2017-03-04 15:28:53 +0100162 for type in ['manual', 'marker']
163 exe 'set foldmethod=' . type
164 new
165 call setline(1, range(1, 20))
166 4,$fold
167 %foldopen
168 10,$fold
169 %foldopen
170 " This filter command should not have an effect
171 1,8! cat
172 call feedkeys('5ggzdzMGdd', 'xt')
173 call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
174
175 bwipe!
176 set foldmethod&
177 endfor
Bram Moolenaar1159b162017-02-28 21:53:56 +0100178endfunc
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100179
Bram Moolenaar94be6192017-04-22 22:40:11 +0200180func Test_indent_fold_with_read()
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100181 new
182 set foldmethod=indent
183 call setline(1, repeat(["\<Tab>a"], 4))
184 for n in range(1, 4)
185 call assert_equal(1, foldlevel(n))
186 endfor
187
Bram Moolenaar70e67252022-09-27 19:34:35 +0100188 call writefile(["a", "", "\<Tab>a"], 'Xinfofile', 'D')
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100189 foldopen
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100190 2read Xinfofile
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100191 %foldclose
192 call assert_equal(1, foldlevel(1))
193 call assert_equal(2, foldclosedend(1))
194 call assert_equal(0, foldlevel(3))
195 call assert_equal(0, foldlevel(4))
196 call assert_equal(1, foldlevel(5))
Bram Moolenaara4208962019-08-24 20:50:19 +0200197 call assert_equal(7, 5->foldclosedend())
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100198
199 bwipe!
200 set foldmethod&
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100201endfunc
202
203func Test_combining_folds_indent()
204 new
205 let one = "\<Tab>a"
206 let zero = 'a'
207 call setline(1, [one, one, zero, zero, zero, one, one, one])
208 set foldmethod=indent
209 3,5d
210 %foldclose
211 call assert_equal(5, foldclosedend(1))
212
213 set foldmethod&
214 bwipe!
215endfunc
216
217func Test_combining_folds_marker()
218 new
219 call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
220 set foldmethod=marker
221 3,5d
222 %foldclose
223 call assert_equal(2, foldclosedend(1))
224
225 set foldmethod&
226 bwipe!
227endfunc
228
Bram Moolenaar025a6b72017-03-12 20:37:21 +0100229func Test_folds_marker_in_comment()
230 new
231 call setline(1, ['" foo', 'bar', 'baz'])
232 setl fen fdm=marker
233 setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
234 norm! zf2j
235 setl nofen
236 :1y
237 call assert_equal(['" foo{{{'], getreg(0,1,1))
238 :+2y
239 call assert_equal(['baz"}}}'], getreg(0,1,1))
240
241 set foldmethod&
242 bwipe!
243endfunc
244
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100245func s:TestFoldExpr(lnum)
246 let thisline = getline(a:lnum)
247 if thisline == 'a'
248 return 1
249 elseif thisline == 'b'
250 return 0
251 elseif thisline == 'c'
252 return '<1'
253 elseif thisline == 'd'
254 return '>1'
255 endif
256 return 0
257endfunction
258
259func Test_update_folds_expr_read()
260 new
261 call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
262 set foldmethod=expr
263 set foldexpr=s:TestFoldExpr(v:lnum)
264 2
265 foldopen
Bram Moolenaar70e67252022-09-27 19:34:35 +0100266 call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xupfofile', 'D')
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100267 read Xupfofile
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100268 %foldclose
269 call assert_equal(2, foldclosedend(1))
270 call assert_equal(0, foldlevel(3))
Bram Moolenaara4208962019-08-24 20:50:19 +0200271 call assert_equal(0, 4->foldlevel())
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100272 call assert_equal(6, foldclosedend(5))
273 call assert_equal(10, foldclosedend(7))
274 call assert_equal(14, foldclosedend(11))
275
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100276 bwipe!
277 set foldmethod& foldexpr&
278endfunc
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100279
zeertzjq93c15732022-05-21 16:34:38 +0100280" Test for what patch 8.1.0535 fixes.
281func Test_foldexpr_no_interrupt_addsub()
282 new
283 func! FoldFunc()
284 call setpos('.', getcurpos())
285 return '='
286 endfunc
287
288 set foldmethod=expr
289 set foldexpr=FoldFunc()
290 call setline(1, '1.2')
291
292 exe "norm! $\<C-A>"
293 call assert_equal('1.3', getline(1))
294
295 bwipe!
296 delfunc FoldFunc
297 set foldmethod& foldexpr&
298endfunc
299
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +0100300" Fold function defined in another script
301func Test_foldexpr_compiled()
302 new
303 let lines =<< trim END
304 vim9script
305 def FoldFunc(): number
306 return v:lnum
307 enddef
308
309 set foldmethod=expr
310 set foldexpr=s:FoldFunc()
311 END
312 call writefile(lines, 'XfoldExpr', 'D')
313 source XfoldExpr
314
315 call setline(1, ['one', 'two', 'three'])
316 redraw
317 call assert_equal(1, foldlevel(1))
318 call assert_equal(2, foldlevel(2))
319 call assert_equal(3, foldlevel(3))
320
321 bwipe!
322 set foldmethod& foldexpr&
323endfunc
324
Bram Moolenaar94be6192017-04-22 22:40:11 +0200325func Check_foldlevels(expected)
326 call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)'))
327endfunc
328
329func Test_move_folds_around_manual()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100330 new
331 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
332 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
333 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
334 " all folds closed
335 set foldenable foldlevel=0 fdm=indent
336 " needs a forced redraw
337 redraw!
338 set fdm=manual
339 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
340 call assert_equal(input, getline(1, '$'))
341 7,12m0
342 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
343 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
344 10,12m0
345 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
346 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)'))
347 " moving should not close the folds
348 %d
349 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
350 set fdm=indent
351 redraw!
352 set fdm=manual
353 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100354 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100355 7,12m0
356 let folds=repeat([-1], 18)
357 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
358 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
359 norm! zM
360 " folds are not corrupted and all have been closed
361 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)'))
362 %d
363 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
364 set fdm=indent
365 redraw!
366 set fdm=manual
367 %foldopen
368 3m4
369 %foldclose
370 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
371 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
372 %d
373 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
374 set fdm=indent foldlevel=0
375 set fdm=manual
376 %foldopen
377 3m1
378 %foldclose
379 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
380 call assert_equal(0, foldlevel(2))
381 call assert_equal(5, foldclosedend(3))
382 call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
383 2,6m$
384 %foldclose
385 call assert_equal(5, foldclosedend(2))
386 call assert_equal(0, foldlevel(6))
387 call assert_equal(9, foldclosedend(7))
388 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 +0200389
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100390 %d
391 " Ensure moving around the edges still works.
392 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
393 set fdm=indent foldlevel=0
394 set fdm=manual
395 %foldopen
396 6m$
397 " The first fold has been truncated to the 5'th line.
398 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200399 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])
400
401 %delete
402 set fdm=indent foldlevel=0
403 call setline(1, [
404 \ "a",
405 \ "\ta",
406 \ "\t\ta",
407 \ "\t\ta",
408 \ "\t\ta",
409 \ "a",
410 \ "a"])
411 set fdm=manual
412 %foldopen!
413 4,5m6
414 call Check_foldlevels([0, 1, 2, 0, 0, 0, 0])
415
416 %delete
417 set fdm=indent
418 call setline(1, [
419 \ "\ta",
420 \ "\t\ta",
421 \ "\t\ta",
422 \ "\t\ta",
423 \ "\ta",
424 \ "\t\ta",
425 \ "\t\ta",
426 \ "\t\ta",
427 \ "\ta",
428 \ "\t\ta",
429 \ "\t\ta",
430 \ "\t\ta",
431 \ "\t\ta",
432 \ "\ta",
433 \ "a"])
434 set fdm=manual
435 %foldopen!
436 13m7
437 call Check_foldlevels([1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0])
438
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100439 bw!
440endfunc
441
Bram Moolenaar94be6192017-04-22 22:40:11 +0200442func Test_move_folds_around_indent()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100443 new
444 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
445 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
446 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
447 " all folds closed
448 set fdm=indent
449 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
450 call assert_equal(input, getline(1, '$'))
451 7,12m0
452 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
453 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
454 10,12m0
455 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
456 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)'))
457 " moving should not close the folds
458 %d
459 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
460 set fdm=indent
461 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100462 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100463 7,12m0
464 let folds=repeat([-1], 18)
465 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
466 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
467 norm! zM
468 " folds are not corrupted and all have been closed
469 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)'))
470 %d
471 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
472 set fdm=indent
473 %foldopen
474 3m4
475 %foldclose
476 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
477 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
478 %d
479 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
480 set fdm=indent foldlevel=0
481 %foldopen
482 3m1
483 %foldclose
484 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
485 call assert_equal(1, foldlevel(2))
486 call assert_equal(5, foldclosedend(3))
487 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
488 2,6m$
489 %foldclose
490 call assert_equal(9, foldclosedend(2))
491 call assert_equal(1, foldlevel(6))
492 call assert_equal(9, foldclosedend(7))
493 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 +0100494 " Ensure moving around the edges still works.
495 %d
496 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
497 set fdm=indent foldlevel=0
498 %foldopen
499 6m$
500 " The first fold has been truncated to the 5'th line.
501 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200502 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100503 bw!
504endfunc
Bram Moolenaar518c9b12017-03-21 11:48:39 +0100505
506func Test_folddoopen_folddoclosed()
507 new
508 call setline(1, range(1, 9))
509 set foldmethod=manual
510 1,3 fold
511 6,8 fold
512
513 " Test without range.
514 folddoopen s/$/o/
515 folddoclosed s/$/c/
516 call assert_equal(['1c', '2c', '3c',
517 \ '4o', '5o',
518 \ '6c', '7c', '8c',
519 \ '9o'], getline(1, '$'))
520
521 " Test with range.
522 call setline(1, range(1, 9))
523 1,8 folddoopen s/$/o/
524 4,$ folddoclosed s/$/c/
525 call assert_equal(['1', '2', '3',
526 \ '4o', '5o',
527 \ '6c', '7c', '8c',
528 \ '9'], getline(1, '$'))
529
530 set foldmethod&
531 bw!
532endfunc
533
534func Test_fold_error()
535 new
536 call setline(1, [1, 2])
537
538 for fm in ['indent', 'expr', 'syntax', 'diff']
539 exe 'set foldmethod=' . fm
540 call assert_fails('norm zf', 'E350:')
541 call assert_fails('norm zd', 'E351:')
542 call assert_fails('norm zE', 'E352:')
543 endfor
544
545 set foldmethod=manual
546 call assert_fails('norm zd', 'E490:')
547 call assert_fails('norm zo', 'E490:')
548 call assert_fails('3fold', 'E16:')
549
550 set foldmethod=marker
551 set nomodifiable
552 call assert_fails('1,2fold', 'E21:')
553
554 set modifiable&
555 set foldmethod&
556 bw!
557endfunc
Bram Moolenaar495b7dd2017-09-16 17:19:22 +0200558
559func Test_foldtext_recursive()
560 new
561 call setline(1, ['{{{', 'some text', '}}}'])
562 setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
563 " This was crashing because of endless recursion.
564 2foldclose
565 redraw
566 call assert_equal(1, foldlevel(2))
567 call assert_equal(1, foldclosed(2))
568 call assert_equal(3, foldclosedend(2))
569 bwipe!
570endfunc
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100571
572" Various fold related tests
573
574" Basic test if a fold can be created, opened, moving to the end and closed
575func Test_fold_manual()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200576 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100577 set fdm=manual
578
579 let content = ['1 aa', '2 bb', '3 cc']
580 call append(0, content)
581 call cursor(1, 1)
582 normal zf2j
583 call assert_equal('1 aa', getline(foldclosed('.')))
584 normal zo
585 call assert_equal(-1, foldclosed('.'))
586 normal ]z
587 call assert_equal('3 cc', getline('.'))
588 normal zc
589 call assert_equal('1 aa', getline(foldclosed('.')))
590
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200591 " Create a fold inside a closed fold after setting 'foldlevel'
592 %d _
593 call setline(1, range(1, 5))
594 1,5fold
595 normal zR
596 2,4fold
597 set foldlevel=1
598 3fold
599 call assert_equal([1, 3, 3, 3, 1], map(range(1, 5), {->foldlevel(v:val)}))
600 set foldlevel&
601
602 " Create overlapping folds (at the start and at the end)
603 normal zE
604 2,3fold
605 normal zR
606 3,4fold
607 call assert_equal([0, 2, 2, 1, 0], map(range(1, 5), {->foldlevel(v:val)}))
608 normal zE
609 3,4fold
610 normal zR
611 2,3fold
612 call assert_equal([0, 1, 2, 2, 0], map(range(1, 5), {->foldlevel(v:val)}))
613
614 " Create a nested fold across two non-adjoining folds
615 %d _
616 call setline(1, range(1, 7))
617 1,2fold
618 normal zR
619 4,5fold
620 normal zR
621 6,7fold
622 normal zR
623 1,5fold
624 call assert_equal([2, 2, 1, 2, 2, 1, 1],
625 \ map(range(1, 7), {->foldlevel(v:val)}))
626
627 " A newly created nested fold should be closed
628 %d _
629 call setline(1, range(1, 6))
630 1,6fold
631 normal zR
632 3,4fold
633 normal zR
634 2,5fold
635 call assert_equal([1, 2, 3, 3, 2, 1], map(range(1, 6), {->foldlevel(v:val)}))
636 call assert_equal(2, foldclosed(4))
637 call assert_equal(5, foldclosedend(4))
638
639 " Test zO, zC and zA on a line with no folds.
640 normal zE
641 call assert_fails('normal zO', 'E490:')
642 call assert_fails('normal zC', 'E490:')
643 call assert_fails('normal zA', 'E490:')
644
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100645 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200646 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100647endfunc
648
649" test folding with markers.
650func Test_fold_marker()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200651 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100652 set fdm=marker fdl=1 fdc=3
653
654 let content = ['4 dd {{{', '5 ee {{{ }}}', '6 ff }}}']
655 call append(0, content)
656 call cursor(2, 1)
657 call assert_equal(2, foldlevel('.'))
658 normal [z
659 call assert_equal(1, foldlevel('.'))
660 exe "normal jo{{ \<Esc>r{jj"
661 call assert_equal(1, foldlevel('.'))
662 normal kYpj
663 call assert_equal(0, foldlevel('.'))
664
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200665 " Use only closing fold marker (without and with a count)
666 set fdl&
667 %d _
668 call setline(1, ['one }}}', 'two'])
669 call assert_equal([0, 0], [foldlevel(1), foldlevel(2)])
670 %d _
671 call setline(1, ['one }}}4', 'two'])
672 call assert_equal([4, 3], [foldlevel(1), foldlevel(2)])
673
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100674 set fdm& fdl& fdc&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200675 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100676endfunc
677
Bram Moolenaar4af72592018-12-09 15:00:52 +0100678" test create fold markers with C filetype
679func Test_fold_create_marker_in_C()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200680 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100681 set fdm=marker fdl=9
682 set filetype=c
683
Bram Moolenaarc79745a2019-05-20 22:12:34 +0200684 let content =<< trim [CODE]
685 /*
686 * comment
687 *
688 *
689 */
690 int f(int* p) {
691 *p = 3;
692 return 0;
693 }
694 [CODE]
695
Bram Moolenaar4af72592018-12-09 15:00:52 +0100696 for c in range(len(content) - 1)
697 bw!
698 call append(0, content)
699 call cursor(c + 1, 1)
700 norm! zfG
701 call assert_equal(content[c] . (c < 4 ? '{{{' : '/*{{{*/'), getline(c + 1))
702 endfor
703
704 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200705 bw!
Bram Moolenaar4af72592018-12-09 15:00:52 +0100706endfunc
707
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100708" test folding with indent
709func Test_fold_indent()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200710 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100711 set fdm=indent sw=2
712
713 let content = ['1 aa', '2 bb', '3 cc']
714 call append(0, content)
715 call cursor(2, 1)
716 exe "normal i \<Esc>jI "
717 call assert_equal(2, foldlevel('.'))
718 normal k
719 call assert_equal(1, foldlevel('.'))
720
721 set fdm& sw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200722 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100723endfunc
724
725" test syntax folding
726func Test_fold_syntax()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200727 CheckFeature syntax
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100728
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200729 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100730 set fdm=syntax fdl=0
731
732 syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3
733 syn region Fd1 start="ee" end="ff" fold contained
734 syn region Fd2 start="gg" end="hh" fold contained
735 syn region Fd3 start="commentstart" end="commentend" fold contained
736 let content = ['3 cc', '4 dd {{{', '5 ee {{{ }}}', '{{{{', '6 ff }}}',
737 \ '6 ff }}}', '7 gg', '8 hh', '9 ii']
738 call append(0, content)
739 normal Gzk
740 call assert_equal('9 ii', getline('.'))
741 normal k
742 call assert_equal('3 cc', getline('.'))
743 exe "normal jAcommentstart \<Esc>Acommentend"
744 set fdl=1
745 normal 3j
746 call assert_equal('7 gg', getline('.'))
747 set fdl=0
748 exe "normal zO\<C-L>j"
749 call assert_equal('8 hh', getline('.'))
750 syn clear Fd1 Fd2 Fd3 Hup
751
752 set fdm& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200753 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100754endfunc
755
756func Flvl()
757 let l = getline(v:lnum)
758 if l =~ "bb$"
759 return 2
760 elseif l =~ "gg$"
761 return "s1"
762 elseif l =~ "ii$"
763 return ">2"
764 elseif l =~ "kk$"
765 return "0"
766 endif
767 return "="
768endfun
769
770" test expression folding
771func Test_fold_expr()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200772 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100773 set fdm=expr fde=Flvl()
774
775 let content = ['1 aa',
776 \ '2 bb',
777 \ '3 cc',
778 \ '4 dd {{{commentstart commentend',
779 \ '5 ee {{{ }}}',
780 \ '{{{',
781 \ '6 ff }}}',
782 \ '6 ff }}}',
783 \ ' 7 gg',
784 \ ' 8 hh',
785 \ '9 ii',
786 \ 'a jj',
787 \ 'b kk']
788 call append(0, content)
789 call cursor(1, 1)
790 exe "normal /bb$\<CR>"
791 call assert_equal(2, foldlevel('.'))
792 exe "normal /hh$\<CR>"
793 call assert_equal(1, foldlevel('.'))
794 exe "normal /ii$\<CR>"
795 call assert_equal(2, foldlevel('.'))
796 exe "normal /kk$\<CR>"
797 call assert_equal(0, foldlevel('.'))
798
799 set fdm& fde&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200800 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100801endfunc
802
803" Bug with fdm=indent and moving folds
804" Moving a fold a few times, messes up the folds below the moved fold.
805" Fixed by 7.4.700
806func Test_fold_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200807 new
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100808 set fdm=indent sw=2 fdl=0
809
810 let content = ['', '', 'Line1', ' Line2', ' Line3',
811 \ 'Line4', ' Line5', ' Line6',
812 \ 'Line7', ' Line8', ' Line9']
813 call append(0, content)
814 normal zM
815 call cursor(4, 1)
816 move 2
817 move 1
818 call assert_equal(7, foldclosed(7))
819 call assert_equal(8, foldclosedend(7))
820 call assert_equal(0, foldlevel(9))
821 call assert_equal(10, foldclosed(10))
822 call assert_equal(11, foldclosedend(10))
823 call assert_equal('+-- 2 lines: Line2', foldtextresult(2))
Bram Moolenaara4208962019-08-24 20:50:19 +0200824 call assert_equal('+-- 2 lines: Line8', 10->foldtextresult())
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100825
826 set fdm& sw& fdl&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200827 bw!
Bram Moolenaar430dc5d2017-11-02 21:04:47 +0100828endfunc
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100829
830" test for patch 7.3.637
831" Cannot catch the error caused by a foldopen when there is no fold.
832func Test_foldopen_exception()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200833 new
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100834 let a = 'No error caught'
835 try
836 foldopen
837 catch
838 let a = matchstr(v:exception,'^[^ ]*')
839 endtry
840 call assert_equal('Vim(foldopen):E490:', a)
841
842 let a = 'No error caught'
843 try
844 foobar
845 catch
846 let a = matchstr(v:exception,'^[^ ]*')
847 endtry
848 call assert_match('E492:', a)
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200849 bw!
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100850endfunc
Bram Moolenaar907dad72018-07-10 15:07:15 +0200851
852func Test_fold_last_line_with_pagedown()
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200853 new
Bram Moolenaar907dad72018-07-10 15:07:15 +0200854 set fdm=manual
855
856 let expect = '+-- 11 lines: 9---'
857 let content = range(1,19)
858 call append(0, content)
859 normal dd9G
860 normal zfG
861 normal zt
862 call assert_equal('9', getline(foldclosed('.')))
863 call assert_equal('19', getline(foldclosedend('.')))
864 call assert_equal(expect, ScreenLines(1, len(expect))[0])
865 call feedkeys("\<C-F>", 'xt')
866 call assert_equal(expect, ScreenLines(1, len(expect))[0])
867 call feedkeys("\<C-F>", 'xt')
868 call assert_equal(expect, ScreenLines(1, len(expect))[0])
869 call feedkeys("\<C-B>\<C-F>\<C-F>", 'xt')
870 call assert_equal(expect, ScreenLines(1, len(expect))[0])
871
872 set fdm&
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200873 bw!
Bram Moolenaar907dad72018-07-10 15:07:15 +0200874endfunc
Bram Moolenaar7701f302018-10-02 21:20:32 +0200875
876func Test_folds_with_rnu()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200877 CheckScreendump
Bram Moolenaar7701f302018-10-02 21:20:32 +0200878
879 call writefile([
880 \ 'set fdm=marker rnu foldcolumn=2',
881 \ 'call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])',
Bram Moolenaar70e67252022-09-27 19:34:35 +0100882 \ ], 'Xtest_folds_with_rnu', 'D')
Bram Moolenaar7701f302018-10-02 21:20:32 +0200883 let buf = RunVimInTerminal('-S Xtest_folds_with_rnu', {})
884
885 call VerifyScreenDump(buf, 'Test_folds_with_rnu_01', {})
886 call term_sendkeys(buf, "j")
887 call VerifyScreenDump(buf, 'Test_folds_with_rnu_02', {})
888
889 " clean up
890 call StopVimInTerminal(buf)
Bram Moolenaar7701f302018-10-02 21:20:32 +0200891endfunc
Bram Moolenaar53932812018-12-07 21:08:49 +0100892
893func Test_folds_marker_in_comment2()
894 new
895 call setline(1, ['Lorem ipsum dolor sit', 'Lorem ipsum dolor sit', 'Lorem ipsum dolor sit'])
896 setl fen fdm=marker
897 setl commentstring=<!--%s-->
898 setl comments=s:<!--,m:\ \ \ \ ,e:-->
899 norm! zf2j
900 setl nofen
901 :1y
902 call assert_equal(['Lorem ipsum dolor sit<!--{{{-->'], getreg(0,1,1))
903 :+2y
904 call assert_equal(['Lorem ipsum dolor sit<!--}}}-->'], getreg(0,1,1))
905
906 set foldmethod&
907 bwipe!
908endfunc
Bram Moolenaar9a4a8c42019-08-19 22:48:30 +0200909
910func Test_fold_delete_with_marker()
911 new
912 call setline(1, ['func Func() {{{1', 'endfunc'])
913 1,2yank
914 new
915 set fdm=marker
916 call setline(1, 'x')
917 normal! Vp
918 normal! zd
919 call assert_equal(['func Func() ', 'endfunc'], getline(1, '$'))
920
921 set fdm&
922 bwipe!
923 bwipe!
924endfunc
Bram Moolenaar7a9bd7c2019-09-17 22:42:55 +0200925
926func Test_fold_delete_with_marker_and_whichwrap()
927 new
928 let content1 = ['']
929 let content2 = ['folded line 1 "{{{1', ' test', ' test2', ' test3', '', 'folded line 2 "{{{1', ' test', ' test2', ' test3']
930 call setline(1, content1 + content2)
931 set fdm=marker ww+=l
932 normal! x
933 call assert_equal(content2, getline(1, '$'))
934 set fdm& ww&
935 bwipe!
936endfunc
Bram Moolenaar3b681232019-12-13 19:35:55 +0100937
938func Test_fold_delete_first_line()
939 new
940 call setline(1, [
941 \ '" x {{{1',
942 \ '" a',
943 \ '" aa',
944 \ '" x {{{1',
945 \ '" b',
946 \ '" bb',
947 \ '" x {{{1',
948 \ '" c',
949 \ '" cc',
950 \ ])
951 set foldmethod=marker
952 1
953 normal dj
954 call assert_equal([
955 \ '" x {{{1',
956 \ '" c',
957 \ '" cc',
958 \ ], getline(1,'$'))
959 bwipe!
960 set foldmethod&
961endfunc
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200962
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +0200963" Add a test for deleting the outer fold of a nested fold and promoting the
964" inner folds to one level up with already a fold at that level following the
965" nested fold.
966func Test_fold_delete_recursive_fold()
967 new
968 call setline(1, range(1, 7))
969 2,3fold
970 normal zR
971 4,5fold
972 normal zR
973 1,5fold
974 normal zR
975 6,7fold
976 normal zR
977 normal 1Gzd
978 normal 1Gzj
979 call assert_equal(2, line('.'))
980 normal zj
981 call assert_equal(4, line('.'))
982 normal zj
983 call assert_equal(6, line('.'))
984 bw!
985endfunc
986
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200987" Test for errors in 'foldexpr'
988func Test_fold_expr_error()
989 new
990 call setline(1, ['one', 'two', 'three'])
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200991 " In a window with no folds, foldlevel() should return 0
992 call assert_equal(0, foldlevel(1))
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +0200993
994 " Return a list from the expression
995 set foldexpr=[]
996 set foldmethod=expr
997 for i in range(3)
998 call assert_equal(0, foldlevel(i))
999 endfor
1000
1001 " expression error
1002 set foldexpr=[{]
1003 set foldmethod=expr
1004 for i in range(3)
1005 call assert_equal(0, foldlevel(i))
1006 endfor
1007
1008 set foldmethod& foldexpr&
1009 close!
1010endfunc
1011
Bram Moolenaarda697642020-09-17 19:36:04 +02001012func Test_undo_fold_deletion()
1013 new
1014 set fdm=marker
1015 let lines =<< trim END
1016 " {{{
1017 " }}}1
1018 " {{{
1019 END
1020 call setline(1, lines)
1021 3d
1022 g/"/d
1023 undo
1024 redo
1025 eval getline(1, '$')->assert_equal([''])
1026
1027 set fdm&vim
1028 bwipe!
1029endfunc
1030
Bram Moolenaarc136a352020-11-03 20:05:40 +01001031" this was crashing
1032func Test_move_no_folds()
1033 new
1034 fold
1035 setlocal fdm=expr
1036 normal zj
1037 bwipe!
1038endfunc
1039
Bram Moolenaar5e1f22f2020-11-10 18:23:52 +01001040" this was crashing
1041func Test_fold_create_delete_create()
1042 new
1043 fold
1044 fold
1045 normal zd
1046 fold
1047 bwipe!
1048endfunc
1049
Bram Moolenaar6a78f322020-12-21 14:01:41 +01001050" this was crashing
1051func Test_fold_create_delete()
1052 new
1053 norm zFzFzdzj
1054 bwipe!
1055endfunc
1056
Bram Moolenaare71996b2021-01-21 17:03:07 +01001057func Test_fold_relative_move()
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001058 new
Bram Moolenaare71996b2021-01-21 17:03:07 +01001059 set fdm=indent sw=2 wrap tw=80
1060
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001061 let longtext = repeat('x', &columns + 1)
1062 let content = [ ' foo', ' ' .. longtext, ' baz',
1063 \ longtext,
1064 \ ' foo', ' ' .. longtext, ' baz'
Bram Moolenaare71996b2021-01-21 17:03:07 +01001065 \ ]
1066 call append(0, content)
1067
1068 normal zM
1069
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001070 for lnum in range(1, 3)
1071 call cursor(lnum, 1)
1072 call assert_true(foldclosed(line('.')))
1073 normal gj
1074 call assert_equal(2, winline())
1075 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001076
1077 call cursor(2, 1)
1078 call assert_true(foldclosed(line('.')))
1079 normal 2gj
1080 call assert_equal(3, winline())
1081
Bram Moolenaar3c49e742021-04-04 21:26:04 +02001082 for lnum in range(5, 7)
1083 call cursor(lnum, 1)
1084 call assert_true(foldclosed(line('.')))
1085 normal gk
1086 call assert_equal(3, winline())
1087 endfor
Bram Moolenaare71996b2021-01-21 17:03:07 +01001088
1089 call cursor(6, 1)
1090 call assert_true(foldclosed(line('.')))
1091 normal 2gk
1092 call assert_equal(2, winline())
1093
1094 set fdm& sw& wrap& tw&
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001095 bw!
Bram Moolenaare71996b2021-01-21 17:03:07 +01001096endfunc
1097
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001098" Test for using multibyte characters as 'foldopen', 'foldclose' and
1099" 'foldsetp' items in 'fillchars'
1100func s:mbyte_fillchar_tests(fo, fc, fs)
1101 setlocal foldcolumn=3
1102
1103 normal zE
1104 1,2fold
1105 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1106 \ ScreenLines([1, 2], 10))
1107 1,2foldopen
1108 call assert_equal([a:fo .. ' one ', a:fs .. ' two '],
1109 \ ScreenLines([1, 2], 7))
1110 1,2foldclose
1111 redraw!
1112 call assert_equal([a:fc .. ' +-- 2 ', ' three '],
1113 \ ScreenLines([1, 2], 10))
1114
1115 " Two level fold
1116 normal zE
1117 2,3fold
1118 1,4fold
1119 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1120 \ ScreenLines([1, 2], 10))
1121 1,4foldopen
1122 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1123 \ ScreenLines([1, 2], 10))
1124 1,4foldopen
1125 call assert_equal([a:fo .. ' one ', a:fs .. a:fo .. ' two ',
1126 \ a:fs .. a:fs .. ' three '], ScreenLines([1, 3], 10))
1127 2,3foldclose
1128 call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
1129 \ ScreenLines([1, 2], 10))
1130 1,4foldclose
1131 call assert_equal([a:fc .. ' +-- 4 ', ' five '],
1132 \ ScreenLines([1, 2], 10))
1133
1134 " Three level fold
1135 normal zE
1136 3,4fold
1137 2,5fold
1138 1,6fold
1139 call assert_equal([a:fc .. ' +-- 6 '], ScreenLines(1, 10))
1140 " open all the folds
1141 normal zR
1142 call assert_equal([
1143 \ a:fo .. ' one ',
1144 \ a:fs .. a:fo .. ' two ',
1145 \ '2' .. a:fo .. ' three ',
1146 \ '23 four ',
1147 \ a:fs .. a:fs .. ' five ',
1148 \ a:fs .. ' six ',
1149 \ ], ScreenLines([1, 6], 10))
1150 " close the innermost fold
1151 3,4foldclose
1152 call assert_equal([
1153 \ a:fo .. ' one ',
1154 \ a:fs .. a:fo .. ' two ',
1155 \ a:fs .. a:fs .. a:fc .. '+---- ',
1156 \ a:fs .. a:fs .. ' five ',
1157 \ a:fs .. ' six ',
1158 \ ], ScreenLines([1, 5], 10))
1159 " close the next fold
1160 2,5foldclose
1161 call assert_equal([
1162 \ a:fo .. ' one ',
1163 \ a:fs .. a:fc .. ' +--- 4',
1164 \ a:fs .. ' six ',
1165 \ ], ScreenLines([1, 3], 10))
1166
1167 " set the fold column size to 2
1168 setlocal fdc=2
1169 normal zR
1170 call assert_equal([
1171 \ a:fo .. ' one ',
1172 \ a:fo .. ' two ',
1173 \ a:fo .. ' three',
1174 \ '3 four ',
1175 \ '2 five ',
1176 \ a:fs .. ' six ',
1177 \ ], ScreenLines([1, 6], 7))
1178
1179 " set the fold column size to 1
1180 setlocal fdc=1
1181 normal zR
1182 call assert_equal([
1183 \ a:fo .. 'one ',
1184 \ a:fo .. 'two ',
1185 \ a:fo .. 'three ',
1186 \ '3four ',
1187 \ '2five ',
1188 \ a:fs .. 'six ',
1189 \ ], ScreenLines([1, 6], 7))
1190
Bram Moolenaar008bff92021-03-04 21:55:58 +01001191 " Enable number and sign columns and place some signs
1192 setlocal fdc=3
1193 setlocal number
1194 setlocal signcolumn=auto
1195 sign define S1 text=->
1196 sign place 10 line=3 name=S1
1197 call assert_equal([
1198 \ a:fo .. ' 1 one ',
1199 \ a:fs .. a:fo .. ' 2 two ',
1200 \ '2' .. a:fo .. ' -> 3 three',
1201 \ '23 4 four ',
1202 \ a:fs .. a:fs .. ' 5 five ',
1203 \ a:fs .. ' 6 six '
1204 \ ], ScreenLines([1, 6], 14))
1205
1206 " Test with 'rightleft'
1207 if has('rightleft')
1208 setlocal rightleft
1209 let lines = ScreenLines([1, 6], winwidth(0))
1210 call assert_equal('o 1 ' .. a:fo,
1211 \ strcharpart(lines[0], strchars(lines[0]) - 10, 10))
1212 call assert_equal('t 2 ' .. a:fo .. a:fs,
1213 \ strcharpart(lines[1], strchars(lines[1]) - 10, 10))
1214 call assert_equal('t 3 >- ' .. a:fo .. '2',
1215 \ strcharpart(lines[2], strchars(lines[2]) - 10, 10))
1216 call assert_equal('f 4 32',
1217 \ strcharpart(lines[3], strchars(lines[3]) - 10, 10))
1218 call assert_equal('f 5 ' .. a:fs .. a:fs,
1219 \ strcharpart(lines[4], strchars(lines[4]) - 10, 10))
1220 call assert_equal('s 6 ' .. a:fs,
1221 \ strcharpart(lines[5], strchars(lines[5]) - 10, 10))
1222 setlocal norightleft
1223 endif
1224
1225 sign unplace *
1226 sign undefine S1
1227 setlocal number& signcolumn&
1228
1229 " Add a test with more than 9 folds (and then delete some folds)
1230 normal zE
1231 for i in range(1, 10)
1232 normal zfGzo
1233 endfor
1234 normal zR
1235 call assert_equal([
1236 \ a:fo .. a:fo .. ' one ',
1237 \ '9> two '
1238 \ ], ScreenLines([1, 2], 7))
1239 normal 1Gzd
1240 call assert_equal([
1241 \ a:fo .. a:fo .. ' one ',
1242 \ '89 two '
1243 \ ], ScreenLines([1, 2], 7))
1244 normal 1Gzdzdzdzdzdzdzd
1245 call assert_equal([
1246 \ a:fo .. a:fo .. ' one ',
1247 \ a:fs .. a:fs .. ' two '
1248 \ ], ScreenLines([1, 2], 7))
1249
1250 setlocal foldcolumn& number& signcolumn&
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001251endfunc
1252
1253func Test_foldcolumn_multibyte_char()
1254 new
1255 call setline(1, ['one', 'two', 'three', 'four', 'five', 'six'])
1256 setlocal foldenable foldmethod=manual
1257
1258 " First test with the default setting
1259 call s:mbyte_fillchar_tests('-', '+', '|')
1260
1261 " Use multi-byte characters
1262 set fillchars+=foldopen:▾,foldsep:│,foldclose:▸
1263 call s:mbyte_fillchar_tests('▾', '▸', '│')
1264
Bram Moolenaar196a1f72021-03-21 14:39:19 +01001265 " Use a mix of multi-byte and single-byte characters
1266 set fillchars+=foldopen:¬,foldsep:\|,foldclose:+
1267 call s:mbyte_fillchar_tests('¬', '+', '|')
1268 set fillchars+=foldopen:+,foldsep:\|,foldclose:¬
1269 call s:mbyte_fillchar_tests('+', '¬', '|')
1270
Bram Moolenaar4fa11752021-03-03 13:26:02 +01001271 bw!
1272 set foldenable& fdc& fdm& fillchars&
1273endfunc
1274
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001275" Test for calling foldlevel() from a fold expression
1276let g:FoldLevels = []
1277func FoldExpr1(lnum)
1278 let f = [a:lnum]
1279 for i in range(1, line('$'))
1280 call add(f, foldlevel(i))
1281 endfor
1282 call add(g:FoldLevels, f)
1283 return getline(a:lnum)[0] == "\t"
1284endfunc
1285
1286func Test_foldexpr_foldlevel()
1287 new
1288 call setline(1, ['one', "\ttwo", "\tthree"])
1289 setlocal foldmethod=expr
1290 setlocal foldexpr=FoldExpr1(v:lnum)
1291 setlocal foldenable
1292 setlocal foldcolumn=3
1293 redraw!
1294 call assert_equal([[1, -1, -1, -1], [2, -1, -1, -1], [3, 0, 1, -1]],
1295 \ g:FoldLevels)
1296 set foldmethod& foldexpr& foldenable& foldcolumn&
1297 bw!
1298endfunc
1299
1300" Test for returning different values from a fold expression
1301func FoldExpr2(lnum)
1302 if a:lnum == 1 || a:lnum == 4
1303 return -2
1304 elseif a:lnum == 2
1305 return 'a1'
1306 elseif a:lnum == 3
1307 return 's4'
1308 endif
1309 return '='
1310endfunc
1311
1312func Test_foldexpr_2()
1313 new
1314 call setline(1, ['one', 'two', 'three', 'four'])
1315 setlocal foldexpr=FoldExpr2(v:lnum)
1316 setlocal foldmethod=expr
1317 call assert_equal([0, 1, 1, 0], [foldlevel(1), foldlevel(2), foldlevel(3),
1318 \ foldlevel(4)])
1319 bw!
1320endfunc
1321
1322" Test for the 'foldclose' option
1323func Test_foldclose_opt()
1324 CheckScreendump
1325
1326 let lines =<< trim END
1327 set foldmethod=manual foldclose=all foldopen=all
1328 call setline(1, ['one', 'two', 'three', 'four'])
1329 2,3fold
1330 func XsaveFoldLevels()
1331 redraw!
1332 call writefile([json_encode([foldclosed(1), foldclosed(2), foldclosed(3),
1333 \ foldclosed(4)])], 'Xoutput', 'a')
1334 endfunc
1335 END
Bram Moolenaar70e67252022-09-27 19:34:35 +01001336 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001337 let rows = 10
1338 let buf = RunVimInTerminal('-S Xscript', {'rows': rows})
1339 call term_wait(buf)
1340 call term_sendkeys(buf, ":set noruler\n")
1341 call term_wait(buf)
1342 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1343 call term_sendkeys(buf, "2G")
1344 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1345 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1346 call term_sendkeys(buf, "4G")
1347 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1348 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1349 call term_sendkeys(buf, "3G")
1350 call WaitForAssert({-> assert_equal('three', term_getline(buf, 3))})
1351 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
1352 call term_sendkeys(buf, "1G")
1353 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
1354 call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001355 call term_sendkeys(buf, "2G")
1356 call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
1357 call term_sendkeys(buf, "k")
1358 call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001359
1360 " clean up
1361 call StopVimInTerminal(buf)
1362
1363 call assert_equal(['[-1,2,2,-1]', '[-1,-1,-1,-1]', '[-1,2,2,-1]',
1364 \ '[-1,-1,-1,-1]', '[-1,2,2,-1]'], readfile('Xoutput'))
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001365 call delete('Xoutput')
1366endfunc
1367
1368" Test for foldtextresult()
1369func Test_foldtextresult()
1370 new
1371 call assert_equal('', foldtextresult(-1))
1372 call assert_equal('', foldtextresult(0))
1373 call assert_equal('', foldtextresult(1))
1374 call setline(1, ['one', 'two', 'three', 'four'])
1375 2,3fold
1376 call assert_equal('', foldtextresult(1))
1377 call assert_equal('+-- 2 lines: two', foldtextresult(2))
1378 setlocal foldtext=
1379 call assert_equal('+-- 2 lines folded ', foldtextresult(2))
1380
1381 " Fold text for a C comment fold
1382 %d _
1383 setlocal foldtext&
1384 call setline(1, ['', '/*', ' * Comment', ' */', ''])
1385 2,4fold
1386 call assert_equal('+-- 3 lines: Comment', foldtextresult(2))
1387
1388 bw!
1389endfunc
1390
1391" Test for merging two recursive folds when an intermediate line with no fold
1392" is removed
dundargocc57b5bc2022-11-02 13:30:51 +00001393func Test_fold_merge_recursive()
Bram Moolenaar5c504f62021-04-01 13:39:51 +02001394 new
1395 call setline(1, [' one', ' two', 'xxxx', ' three',
1396 \ ' four', "\tfive"])
1397 setlocal foldmethod=indent shiftwidth=2
1398 3d_
1399 %foldclose
1400 call assert_equal([1, 5], [foldclosed(5), foldclosedend(1)])
1401 bw!
1402endfunc
1403
1404" Test for moving a line which is the start of a fold from a recursive fold to
1405" outside. The fold length should reduce.
1406func Test_fold_move_foldlevel()
1407 new
1408 call setline(1, ['a{{{', 'b{{{', 'c{{{', 'd}}}', 'e}}}', 'f}}}', 'g'])
1409 setlocal foldmethod=marker
1410 normal zR
1411 call assert_equal([3, 2, 1], [foldlevel(4), foldlevel(5), foldlevel(6)])
1412 3move 7
1413 call assert_equal([2, 1, 0], [foldlevel(3), foldlevel(4), foldlevel(5)])
1414 call assert_equal(1, foldlevel(7))
1415
1416 " Move a line from outside a fold to inside the fold.
1417 %d _
1418 call setline(1, ['a', 'b{{{', 'c}}}'])
1419 normal zR
1420 1move 2
1421 call assert_equal([1, 1, 1], [foldlevel(1), foldlevel(2), foldlevel(3)])
1422
1423 " Move the start of one fold to inside another fold
1424 %d _
1425 call setline(1, ['a', 'b{{{', 'c}}}', 'd{{{', 'e}}}'])
1426 normal zR
1427 call assert_equal([0, 1, 1, 1, 1], [foldlevel(1), foldlevel(2),
1428 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1429 1,2move 4
1430 call assert_equal([0, 1, 1, 2, 2], [foldlevel(1), foldlevel(2),
1431 \ foldlevel(3), foldlevel(4), foldlevel(5)])
1432
1433 bw!
1434endfunc
1435
Bram Moolenaar68ffe8c2021-04-05 12:47:25 +02001436" Test for using zj and zk to move downwards and upwards to the start and end
1437" of the next fold.
1438" Test for using [z and ]z in a closed fold to jump to the beginning and end
1439" of the fold.
1440func Test_fold_jump()
1441 new
1442 call setline(1, ["\t1", "\t2", "\t\t3", "\t\t4", "\t\t\t5", "\t\t\t6", "\t\t7", "\t\t8", "\t9", "\t10"])
1443 setlocal foldmethod=indent
1444 normal zR
1445 normal zj
1446 call assert_equal(3, line('.'))
1447 normal zj
1448 call assert_equal(5, line('.'))
1449 call assert_beeps('normal zj')
1450 call assert_equal(5, line('.'))
1451 call assert_beeps('normal 9Gzj')
1452 call assert_equal(9, line('.'))
1453 normal Gzk
1454 call assert_equal(8, line('.'))
1455 normal zk
1456 call assert_equal(6, line('.'))
1457 call assert_beeps('normal zk')
1458 call assert_equal(6, line('.'))
1459 call assert_beeps('normal 2Gzk')
1460 call assert_equal(2, line('.'))
1461
1462 " Using [z or ]z in a closed fold should not move the cursor
1463 %d _
1464 call setline(1, ["1", "\t2", "\t3", "\t4", "\t5", "\t6", "7"])
1465 normal zR4Gzc
1466 call assert_equal(4, line('.'))
1467 call assert_beeps('normal [z')
1468 call assert_equal(4, line('.'))
1469 call assert_beeps('normal ]z')
1470 call assert_equal(4, line('.'))
1471 bw!
1472endfunc
1473
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001474" Test for using a script-local function for 'foldexpr'
1475func Test_foldexpr_scriptlocal_func()
1476 func! s:FoldFunc()
1477 let g:FoldLnum = v:lnum
1478 endfunc
1479 new | only
1480 call setline(1, 'abc')
1481 let g:FoldLnum = 0
1482 set foldmethod=expr foldexpr=s:FoldFunc()
1483 redraw!
1484 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1485 call assert_equal(1, g:FoldLnum)
1486 set foldmethod& foldexpr=
1487 bw!
1488 new | only
1489 call setline(1, 'abc')
1490 let g:FoldLnum = 0
1491 set foldmethod=expr foldexpr=<SID>FoldFunc()
1492 redraw!
1493 call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
1494 call assert_equal(1, g:FoldLnum)
1495 set foldmethod& foldexpr=
1496 delfunc s:FoldFunc
1497 bw!
1498endfunc
1499
Yegappan Lakshmanan27708e62021-12-26 21:54:43 +00001500" Test for using a script-local function for 'foldtext'
1501func Test_foldtext_scriptlocal_func()
1502 func! s:FoldText()
1503 let g:FoldTextArgs = [v:foldstart, v:foldend]
1504 return foldtext()
1505 endfunc
1506 new | only
1507 call setline(1, range(50))
1508 let g:FoldTextArgs = []
1509 set foldmethod=manual
1510 set foldtext=s:FoldText()
1511 norm! 4Gzf4j
1512 redraw!
1513 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1514 call assert_equal([4, 8], g:FoldTextArgs)
1515 set foldtext&
1516 bw!
1517 new | only
1518 call setline(1, range(50))
1519 let g:FoldTextArgs = []
1520 set foldmethod=manual
1521 set foldtext=<SID>FoldText()
1522 norm! 8Gzf4j
1523 redraw!
1524 call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
1525 call assert_equal([8, 12], g:FoldTextArgs)
1526 set foldtext&
1527 bw!
1528 delfunc s:FoldText
1529endfunc
1530
Brandon Simmons2c407072022-04-23 13:50:17 +01001531" Make sure a fold containing a nested fold is split correctly when using
1532" foldmethod=indent
1533func Test_fold_split()
1534 new
1535 let lines =<< trim END
1536 line 1
1537 line 2
1538 line 3
1539 line 4
1540 line 5
1541 END
1542 call setline(1, lines)
1543 setlocal sw=2
1544 setlocal foldmethod=indent foldenable
1545 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
1546 call append(2, 'line 2.5')
1547 call assert_equal([0, 1, 0, 1, 2, 2], range(1, 6)->map('foldlevel(v:val)'))
Yegappan Lakshmananee47eac2022-06-29 12:55:36 +01001548 3d
1549 call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
Brandon Simmons2c407072022-04-23 13:50:17 +01001550 bw!
1551endfunc
1552
Brandon Simmonsd98e75e2022-05-10 19:13:23 +01001553" Make sure that when you append under a blank line that is under a fold with
1554" the same indent level as your appended line, the fold expands across the
1555" blank line
1556func Test_indent_append_under_blank_line()
1557 new
1558 let lines =<< trim END
1559 line 1
1560 line 2
1561 line 3
1562 END
1563 call setline(1, lines)
1564 setlocal sw=2
1565 setlocal foldmethod=indent foldenable
1566 call assert_equal([0, 1, 1], range(1, 3)->map('foldlevel(v:val)'))
1567 call append(3, '')
1568 call append(4, ' line 5')
1569 call assert_equal([0, 1, 1, 1, 1], range(1, 5)->map('foldlevel(v:val)'))
1570 bw!
1571endfunc
1572
Brandon Simmons3fcccf92022-05-20 18:25:21 +01001573" Make sure that when you delete 1 line of a fold whose length is 2 lines, the
1574" fold can't be closed since its length (1) is now less than foldminlines.
1575func Test_indent_one_line_fold_close()
1576 let lines =<< trim END
1577 line 1
1578 line 2
1579 line 3
1580 END
1581
1582 new
1583 setlocal sw=2 foldmethod=indent
1584 call setline(1, lines)
1585 " open all folds, delete line, then close all folds
1586 normal zR
1587 3delete
1588 normal zM
1589 call assert_equal(-1, foldclosed(2)) " the fold should not be closed
1590
1591 " Now do the same, but delete line 2 this time; this covers different code.
1592 " (Combining this code with the above code doesn't expose both bugs.)
1593 1,$delete
1594 call setline(1, lines)
1595 normal zR
1596 2delete
1597 normal zM
1598 call assert_equal(-1, foldclosed(2))
1599 bw!
1600endfunc
1601
Brandon Simmonse8c4a642022-05-23 15:33:08 +01001602" Make sure that when appending [an indented line then a blank line] right
1603" before a single indented line, the resulting extended fold can be closed
1604func Test_indent_append_blank_small_fold_close()
1605 new
1606 setlocal sw=2 foldmethod=indent
1607 " at first, the fold at the second line can't be closed since it's smaller
1608 " than foldminlines
1609 let lines =<< trim END
1610 line 1
1611 line 4
1612 END
1613 call setline(1, lines)
1614 call append(1, [' line 2', ''])
1615 " close all folds
1616 normal zM
1617 call assert_notequal(-1, foldclosed(2)) " the fold should be closed now
1618 bw!
1619endfunc
1620
Bram Moolenaarf00112d2022-11-11 01:20:35 +00001621func Test_sort_closed_fold()
1622 CheckExecutable sort
1623
1624 call setline(1, [
1625 \ 'Section 1',
1626 \ ' how',
1627 \ ' now',
1628 \ ' brown',
1629 \ ' cow',
1630 \ 'Section 2',
1631 \ ' how',
1632 \ ' now',
1633 \ ' brown',
1634 \ ' cow',
1635 \])
1636 setlocal foldmethod=indent sw=3
1637 normal 2G
1638
1639 " The "!!" expands to ".,.+3" and must only sort four lines
1640 call feedkeys("!!sort\<CR>", 'xt')
1641 call assert_equal([
1642 \ 'Section 1',
1643 \ ' brown',
1644 \ ' cow',
1645 \ ' how',
1646 \ ' now',
1647 \ 'Section 2',
1648 \ ' how',
1649 \ ' now',
1650 \ ' brown',
1651 \ ' cow',
1652 \ ], getline(1, 10))
1653
1654 bwipe!
1655endfunc
1656
Bram Moolenaar9d8d0b52020-04-24 22:47:31 +02001657" vim: shiftwidth=2 sts=2 expandtab