blob: b6ba99c56fc234043d2c5239589df3c9ca02581c [file] [log] [blame]
Bram Moolenaarded27822017-01-02 14:27:34 +01001" Test for folding
2
Bram Moolenaar94be6192017-04-22 22:40:11 +02003func PrepIndent(arg)
Bram Moolenaar88d298a2017-03-14 21:53:58 +01004 return [a:arg] + repeat(["\t".a:arg], 5)
5endfu
6
Bram Moolenaar94be6192017-04-22 22:40:11 +02007func Test_address_fold()
Bram Moolenaarded27822017-01-02 14:27:34 +01008 new
9 call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
10 \ 'after fold 1', 'after fold 2', 'after fold 3'])
11 setl fen fdm=marker
Bram Moolenaar518c9b12017-03-21 11:48:39 +010012 " The next commands should all copy the same part of the buffer,
13 " regardless of the addressing type, since the part to be copied
Bram Moolenaarded27822017-01-02 14:27:34 +010014 " is folded away
15 :1y
16 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
17 :.y
18 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
19 :.+y
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 :sil .1,.y
24 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
25 " use silent to make E493 go away
26 :sil .+,.y
27 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
28 :,y
29 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
30 :,+y
31 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/','after fold 1'], getreg(0,1,1))
32 " using .+3 as second address should copy the whole folded line + the next 3
33 " lines
34 :.,+3y
35 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/',
36 \ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1))
37 :sil .,-2y
38 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
39
40 " now test again with folding disabled
41 set nofoldenable
42 :1y
43 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
44 :.y
45 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
46 :.+y
47 call assert_equal(['1'], getreg(0,1,1))
48 :.,.y
49 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
50 " use silent to make E493 go away
51 :sil .1,.y
52 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
53 " use silent to make E493 go away
54 :sil .+,.y
55 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
56 :,y
57 call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
58 :,+y
59 call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
60 " using .+3 as second address should copy the whole folded line + the next 3
61 " lines
62 :.,+3y
63 call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1))
64 :7
65 :sil .,-2y
66 call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1))
67
68 quit!
Bram Moolenaar1159b162017-02-28 21:53:56 +010069endfunc
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +010070
Bram Moolenaar94be6192017-04-22 22:40:11 +020071func Test_indent_fold()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +010072 new
73 call setline(1, ['', 'a', ' b', ' c'])
74 setl fen fdm=indent
75 2
76 norm! >>
77 let a=map(range(1,4), 'foldclosed(v:val)')
78 call assert_equal([-1,-1,-1,-1], a)
79 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +010080endfunc
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +010081
Bram Moolenaar94be6192017-04-22 22:40:11 +020082func Test_indent_fold2()
Bram Moolenaar54b2bfa2017-01-02 14:57:08 +010083 new
84 call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
85 setl fen fdm=marker
86 2
87 norm! >>
88 let a=map(range(1,5), 'foldclosed(v:val)')
89 call assert_equal([-1,-1,-1,4,4], a)
90 bw!
Bram Moolenaar1159b162017-02-28 21:53:56 +010091endfunc
92
93func Test_manual_fold_with_filter()
94 if !executable('cat')
95 return
96 endif
Bram Moolenaar3f3897e2017-03-04 15:28:53 +010097 for type in ['manual', 'marker']
98 exe 'set foldmethod=' . type
99 new
100 call setline(1, range(1, 20))
101 4,$fold
102 %foldopen
103 10,$fold
104 %foldopen
105 " This filter command should not have an effect
106 1,8! cat
107 call feedkeys('5ggzdzMGdd', 'xt')
108 call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
109
110 bwipe!
111 set foldmethod&
112 endfor
Bram Moolenaar1159b162017-02-28 21:53:56 +0100113endfunc
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100114
Bram Moolenaar94be6192017-04-22 22:40:11 +0200115func Test_indent_fold_with_read()
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100116 new
117 set foldmethod=indent
118 call setline(1, repeat(["\<Tab>a"], 4))
119 for n in range(1, 4)
120 call assert_equal(1, foldlevel(n))
121 endfor
122
123 call writefile(["a", "", "\<Tab>a"], 'Xfile')
124 foldopen
125 2read Xfile
126 %foldclose
127 call assert_equal(1, foldlevel(1))
128 call assert_equal(2, foldclosedend(1))
129 call assert_equal(0, foldlevel(3))
130 call assert_equal(0, foldlevel(4))
131 call assert_equal(1, foldlevel(5))
132 call assert_equal(7, foldclosedend(5))
133
134 bwipe!
135 set foldmethod&
136 call delete('Xfile')
137endfunc
138
139func Test_combining_folds_indent()
140 new
141 let one = "\<Tab>a"
142 let zero = 'a'
143 call setline(1, [one, one, zero, zero, zero, one, one, one])
144 set foldmethod=indent
145 3,5d
146 %foldclose
147 call assert_equal(5, foldclosedend(1))
148
149 set foldmethod&
150 bwipe!
151endfunc
152
153func Test_combining_folds_marker()
154 new
155 call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
156 set foldmethod=marker
157 3,5d
158 %foldclose
159 call assert_equal(2, foldclosedend(1))
160
161 set foldmethod&
162 bwipe!
163endfunc
164
Bram Moolenaar025a6b72017-03-12 20:37:21 +0100165func Test_folds_marker_in_comment()
166 new
167 call setline(1, ['" foo', 'bar', 'baz'])
168 setl fen fdm=marker
169 setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
170 norm! zf2j
171 setl nofen
172 :1y
173 call assert_equal(['" foo{{{'], getreg(0,1,1))
174 :+2y
175 call assert_equal(['baz"}}}'], getreg(0,1,1))
176
177 set foldmethod&
178 bwipe!
179endfunc
180
Bram Moolenaareadbc2b2017-03-04 18:42:39 +0100181func s:TestFoldExpr(lnum)
182 let thisline = getline(a:lnum)
183 if thisline == 'a'
184 return 1
185 elseif thisline == 'b'
186 return 0
187 elseif thisline == 'c'
188 return '<1'
189 elseif thisline == 'd'
190 return '>1'
191 endif
192 return 0
193endfunction
194
195func Test_update_folds_expr_read()
196 new
197 call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
198 set foldmethod=expr
199 set foldexpr=s:TestFoldExpr(v:lnum)
200 2
201 foldopen
202 call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile')
203 read Xfile
204 %foldclose
205 call assert_equal(2, foldclosedend(1))
206 call assert_equal(0, foldlevel(3))
207 call assert_equal(0, foldlevel(4))
208 call assert_equal(6, foldclosedend(5))
209 call assert_equal(10, foldclosedend(7))
210 call assert_equal(14, foldclosedend(11))
211
212 call delete('Xfile')
213 bwipe!
214 set foldmethod& foldexpr&
215endfunc
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100216
Bram Moolenaar94be6192017-04-22 22:40:11 +0200217func Check_foldlevels(expected)
218 call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)'))
219endfunc
220
221func Test_move_folds_around_manual()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100222 new
223 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
224 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
225 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
226 " all folds closed
227 set foldenable foldlevel=0 fdm=indent
228 " needs a forced redraw
229 redraw!
230 set fdm=manual
231 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
232 call assert_equal(input, getline(1, '$'))
233 7,12m0
234 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
235 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
236 10,12m0
237 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
238 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)'))
239 " moving should not close the folds
240 %d
241 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
242 set fdm=indent
243 redraw!
244 set fdm=manual
245 call cursor(2, 1)
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100246 %foldopen
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100247 7,12m0
248 let folds=repeat([-1], 18)
249 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
250 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
251 norm! zM
252 " folds are not corrupted and all have been closed
253 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)'))
254 %d
255 call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
256 set fdm=indent
257 redraw!
258 set fdm=manual
259 %foldopen
260 3m4
261 %foldclose
262 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
263 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
264 %d
265 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
266 set fdm=indent foldlevel=0
267 set fdm=manual
268 %foldopen
269 3m1
270 %foldclose
271 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
272 call assert_equal(0, foldlevel(2))
273 call assert_equal(5, foldclosedend(3))
274 call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
275 2,6m$
276 %foldclose
277 call assert_equal(5, foldclosedend(2))
278 call assert_equal(0, foldlevel(6))
279 call assert_equal(9, foldclosedend(7))
280 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 +0200281
Bram Moolenaar40ebc0a2017-03-16 15:59:14 +0100282 %d
283 " Ensure moving around the edges still works.
284 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
285 set fdm=indent foldlevel=0
286 set fdm=manual
287 %foldopen
288 6m$
289 " The first fold has been truncated to the 5'th line.
290 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200291 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])
292
293 %delete
294 set fdm=indent foldlevel=0
295 call setline(1, [
296 \ "a",
297 \ "\ta",
298 \ "\t\ta",
299 \ "\t\ta",
300 \ "\t\ta",
301 \ "a",
302 \ "a"])
303 set fdm=manual
304 %foldopen!
305 4,5m6
306 call Check_foldlevels([0, 1, 2, 0, 0, 0, 0])
307
308 %delete
309 set fdm=indent
310 call setline(1, [
311 \ "\ta",
312 \ "\t\ta",
313 \ "\t\ta",
314 \ "\t\ta",
315 \ "\ta",
316 \ "\t\ta",
317 \ "\t\ta",
318 \ "\t\ta",
319 \ "\ta",
320 \ "\t\ta",
321 \ "\t\ta",
322 \ "\t\ta",
323 \ "\t\ta",
324 \ "\ta",
325 \ "a"])
326 set fdm=manual
327 %foldopen!
328 13m7
329 call Check_foldlevels([1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0])
330
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100331 bw!
332endfunc
333
Bram Moolenaar94be6192017-04-22 22:40:11 +0200334func Test_move_folds_around_indent()
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100335 new
336 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
337 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
338 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
339 " all folds closed
340 set fdm=indent
341 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
342 call assert_equal(input, getline(1, '$'))
343 7,12m0
344 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
345 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
346 10,12m0
347 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
348 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)'))
349 " moving should not close the folds
350 %d
351 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
352 set fdm=indent
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 %foldopen
366 3m4
367 %foldclose
368 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
369 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
370 %d
371 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
372 set fdm=indent foldlevel=0
373 %foldopen
374 3m1
375 %foldclose
376 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
377 call assert_equal(1, foldlevel(2))
378 call assert_equal(5, foldclosedend(3))
379 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
380 2,6m$
381 %foldclose
382 call assert_equal(9, foldclosedend(2))
383 call assert_equal(1, foldlevel(6))
384 call assert_equal(9, foldclosedend(7))
385 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 +0100386 " Ensure moving around the edges still works.
387 %d
388 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
389 set fdm=indent foldlevel=0
390 %foldopen
391 6m$
392 " The first fold has been truncated to the 5'th line.
393 " Second fold has been moved up because the moved line is now below it.
Bram Moolenaar94be6192017-04-22 22:40:11 +0200394 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
Bram Moolenaar88d298a2017-03-14 21:53:58 +0100395 bw!
396endfunc
Bram Moolenaar518c9b12017-03-21 11:48:39 +0100397
398func Test_folddoopen_folddoclosed()
399 new
400 call setline(1, range(1, 9))
401 set foldmethod=manual
402 1,3 fold
403 6,8 fold
404
405 " Test without range.
406 folddoopen s/$/o/
407 folddoclosed s/$/c/
408 call assert_equal(['1c', '2c', '3c',
409 \ '4o', '5o',
410 \ '6c', '7c', '8c',
411 \ '9o'], getline(1, '$'))
412
413 " Test with range.
414 call setline(1, range(1, 9))
415 1,8 folddoopen s/$/o/
416 4,$ folddoclosed s/$/c/
417 call assert_equal(['1', '2', '3',
418 \ '4o', '5o',
419 \ '6c', '7c', '8c',
420 \ '9'], getline(1, '$'))
421
422 set foldmethod&
423 bw!
424endfunc
425
426func Test_fold_error()
427 new
428 call setline(1, [1, 2])
429
430 for fm in ['indent', 'expr', 'syntax', 'diff']
431 exe 'set foldmethod=' . fm
432 call assert_fails('norm zf', 'E350:')
433 call assert_fails('norm zd', 'E351:')
434 call assert_fails('norm zE', 'E352:')
435 endfor
436
437 set foldmethod=manual
438 call assert_fails('norm zd', 'E490:')
439 call assert_fails('norm zo', 'E490:')
440 call assert_fails('3fold', 'E16:')
441
442 set foldmethod=marker
443 set nomodifiable
444 call assert_fails('1,2fold', 'E21:')
445
446 set modifiable&
447 set foldmethod&
448 bw!
449endfunc
Bram Moolenaar495b7dd2017-09-16 17:19:22 +0200450
451func Test_foldtext_recursive()
452 new
453 call setline(1, ['{{{', 'some text', '}}}'])
454 setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
455 " This was crashing because of endless recursion.
456 2foldclose
457 redraw
458 call assert_equal(1, foldlevel(2))
459 call assert_equal(1, foldclosed(2))
460 call assert_equal(3, foldclosedend(2))
461 bwipe!
462endfunc