1" Test for folding 2 3func! PrepIndent(arg) 4 return [a:arg] + repeat(["\t".a:arg], 5) 5endfu 6 7func! Test_address_fold() 8 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 12 " The next commands should all copy the same part of the buffer, 13 " regardless of the addressing type, since the part to be copied 14 " 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! 69endfunc 70 71func! Test_indent_fold() 72 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) 79endfunc 80 81func! Test_indent_fold() 82 new 83 call setline(1, ['', 'a', ' b', ' c']) 84 setl fen fdm=indent 85 2 86 norm! >> 87 let a=map(range(1,4), 'foldclosed(v:val)') 88 call assert_equal([-1,-1,-1,-1], a) 89 bw! 90endfunc 91 92func! Test_indent_fold2() 93 new 94 call setline(1, ['', '{{{', '}}}', '{{{', '}}}']) 95 setl fen fdm=marker 96 2 97 norm! >> 98 let a=map(range(1,5), 'foldclosed(v:val)') 99 call assert_equal([-1,-1,-1,4,4], a) 100 bw! 101endfunc 102 103func Test_manual_fold_with_filter() 104 if !executable('cat') 105 return 106 endif 107 for type in ['manual', 'marker'] 108 exe 'set foldmethod=' . type 109 new 110 call setline(1, range(1, 20)) 111 4,$fold 112 %foldopen 113 10,$fold 114 %foldopen 115 " This filter command should not have an effect 116 1,8! cat 117 call feedkeys('5ggzdzMGdd', 'xt') 118 call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$')) 119 120 bwipe! 121 set foldmethod& 122 endfor 123endfunc 124 125func! Test_indent_fold_with_read() 126 new 127 set foldmethod=indent 128 call setline(1, repeat(["\<Tab>a"], 4)) 129 for n in range(1, 4) 130 call assert_equal(1, foldlevel(n)) 131 endfor 132 133 call writefile(["a", "", "\<Tab>a"], 'Xfile') 134 foldopen 135 2read Xfile 136 %foldclose 137 call assert_equal(1, foldlevel(1)) 138 call assert_equal(2, foldclosedend(1)) 139 call assert_equal(0, foldlevel(3)) 140 call assert_equal(0, foldlevel(4)) 141 call assert_equal(1, foldlevel(5)) 142 call assert_equal(7, foldclosedend(5)) 143 144 bwipe! 145 set foldmethod& 146 call delete('Xfile') 147endfunc 148 149func Test_combining_folds_indent() 150 new 151 let one = "\<Tab>a" 152 let zero = 'a' 153 call setline(1, [one, one, zero, zero, zero, one, one, one]) 154 set foldmethod=indent 155 3,5d 156 %foldclose 157 call assert_equal(5, foldclosedend(1)) 158 159 set foldmethod& 160 bwipe! 161endfunc 162 163func Test_combining_folds_marker() 164 new 165 call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}']) 166 set foldmethod=marker 167 3,5d 168 %foldclose 169 call assert_equal(2, foldclosedend(1)) 170 171 set foldmethod& 172 bwipe! 173endfunc 174 175func Test_folds_marker_in_comment() 176 new 177 call setline(1, ['" foo', 'bar', 'baz']) 178 setl fen fdm=marker 179 setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s 180 norm! zf2j 181 setl nofen 182 :1y 183 call assert_equal(['" foo{{{'], getreg(0,1,1)) 184 :+2y 185 call assert_equal(['baz"}}}'], getreg(0,1,1)) 186 187 set foldmethod& 188 bwipe! 189endfunc 190 191func s:TestFoldExpr(lnum) 192 let thisline = getline(a:lnum) 193 if thisline == 'a' 194 return 1 195 elseif thisline == 'b' 196 return 0 197 elseif thisline == 'c' 198 return '<1' 199 elseif thisline == 'd' 200 return '>1' 201 endif 202 return 0 203endfunction 204 205func Test_update_folds_expr_read() 206 new 207 call setline(1, ['a', 'a', 'a', 'a', 'a', 'a']) 208 set foldmethod=expr 209 set foldexpr=s:TestFoldExpr(v:lnum) 210 2 211 foldopen 212 call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile') 213 read Xfile 214 %foldclose 215 call assert_equal(2, foldclosedend(1)) 216 call assert_equal(0, foldlevel(3)) 217 call assert_equal(0, foldlevel(4)) 218 call assert_equal(6, foldclosedend(5)) 219 call assert_equal(10, foldclosedend(7)) 220 call assert_equal(14, foldclosedend(11)) 221 222 call delete('Xfile') 223 bwipe! 224 set foldmethod& foldexpr& 225endfunc 226 227func! Test_move_folds_around_manual() 228 new 229 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c") 230 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) 231 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14] 232 " all folds closed 233 set foldenable foldlevel=0 fdm=indent 234 " needs a forced redraw 235 redraw! 236 set fdm=manual 237 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) 238 call assert_equal(input, getline(1, '$')) 239 7,12m0 240 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) 241 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) 242 10,12m0 243 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$')) 244 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)')) 245 " moving should not close the folds 246 %d 247 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) 248 set fdm=indent 249 redraw! 250 set fdm=manual 251 call cursor(2, 1) 252 %foldopen 253 7,12m0 254 let folds=repeat([-1], 18) 255 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) 256 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) 257 norm! zM 258 " folds are not corrupted and all have been closed 259 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)')) 260 %d 261 call setline(1, ["a", "\tb", "\tc", "\td", "\te"]) 262 set fdm=indent 263 redraw! 264 set fdm=manual 265 %foldopen 266 3m4 267 %foldclose 268 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$')) 269 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)')) 270 %d 271 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"]) 272 set fdm=indent foldlevel=0 273 set fdm=manual 274 %foldopen 275 3m1 276 %foldclose 277 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$')) 278 call assert_equal(0, foldlevel(2)) 279 call assert_equal(5, foldclosedend(3)) 280 call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)')) 281 2,6m$ 282 %foldclose 283 call assert_equal(5, foldclosedend(2)) 284 call assert_equal(0, foldlevel(6)) 285 call assert_equal(9, foldclosedend(7)) 286 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)')) 287 %d 288 " Ensure moving around the edges still works. 289 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"]) 290 set fdm=indent foldlevel=0 291 set fdm=manual 292 %foldopen 293 6m$ 294 " The first fold has been truncated to the 5'th line. 295 " Second fold has been moved up because the moved line is now below it. 296 call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 0], map(range(1, line('$')), 'foldlevel(v:val)')) 297 bw! 298endfunc 299 300func! Test_move_folds_around_indent() 301 new 302 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c") 303 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) 304 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14] 305 " all folds closed 306 set fdm=indent 307 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) 308 call assert_equal(input, getline(1, '$')) 309 7,12m0 310 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) 311 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) 312 10,12m0 313 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$')) 314 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)')) 315 " moving should not close the folds 316 %d 317 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) 318 set fdm=indent 319 call cursor(2, 1) 320 %foldopen 321 7,12m0 322 let folds=repeat([-1], 18) 323 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) 324 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) 325 norm! zM 326 " folds are not corrupted and all have been closed 327 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)')) 328 %d 329 call setline(1, ["a", "\tb", "\tc", "\td", "\te"]) 330 set fdm=indent 331 %foldopen 332 3m4 333 %foldclose 334 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$')) 335 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)')) 336 %d 337 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"]) 338 set fdm=indent foldlevel=0 339 %foldopen 340 3m1 341 %foldclose 342 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$')) 343 call assert_equal(1, foldlevel(2)) 344 call assert_equal(5, foldclosedend(3)) 345 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)')) 346 2,6m$ 347 %foldclose 348 call assert_equal(9, foldclosedend(2)) 349 call assert_equal(1, foldlevel(6)) 350 call assert_equal(9, foldclosedend(7)) 351 call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)')) 352 " Ensure moving around the edges still works. 353 %d 354 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"]) 355 set fdm=indent foldlevel=0 356 %foldopen 357 6m$ 358 " The first fold has been truncated to the 5'th line. 359 " Second fold has been moved up because the moved line is now below it. 360 call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 1], map(range(1, line('$')), 'foldlevel(v:val)')) 361 bw! 362endfunc 363 364func Test_folddoopen_folddoclosed() 365 new 366 call setline(1, range(1, 9)) 367 set foldmethod=manual 368 1,3 fold 369 6,8 fold 370 371 " Test without range. 372 folddoopen s/$/o/ 373 folddoclosed s/$/c/ 374 call assert_equal(['1c', '2c', '3c', 375 \ '4o', '5o', 376 \ '6c', '7c', '8c', 377 \ '9o'], getline(1, '$')) 378 379 " Test with range. 380 call setline(1, range(1, 9)) 381 1,8 folddoopen s/$/o/ 382 4,$ folddoclosed s/$/c/ 383 call assert_equal(['1', '2', '3', 384 \ '4o', '5o', 385 \ '6c', '7c', '8c', 386 \ '9'], getline(1, '$')) 387 388 set foldmethod& 389 bw! 390endfunc 391 392func Test_fold_error() 393 new 394 call setline(1, [1, 2]) 395 396 for fm in ['indent', 'expr', 'syntax', 'diff'] 397 exe 'set foldmethod=' . fm 398 call assert_fails('norm zf', 'E350:') 399 call assert_fails('norm zd', 'E351:') 400 call assert_fails('norm zE', 'E352:') 401 endfor 402 403 set foldmethod=manual 404 call assert_fails('norm zd', 'E490:') 405 call assert_fails('norm zo', 'E490:') 406 call assert_fails('3fold', 'E16:') 407 408 set foldmethod=marker 409 set nomodifiable 410 call assert_fails('1,2fold', 'E21:') 411 412 set modifiable& 413 set foldmethod& 414 bw! 415endfunc 416