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) 79 bw! 80endfunc 81 82func Test_indent_fold2() 83 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! 91endfunc 92 93func Test_manual_fold_with_filter() 94 if !executable('cat') 95 return 96 endif 97 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 113endfunc 114 115func Test_indent_fold_with_read() 116 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 165func 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 181func 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 216 217func Check_foldlevels(expected) 218 call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)')) 219endfunc 220 221func Test_move_folds_around_manual() 222 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) 246 %foldopen 247 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)')) 281 %d 282 " Ensure moving around the edges still works. 283 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"]) 284 set fdm=indent foldlevel=0 285 set fdm=manual 286 %foldopen 287 6m$ 288 " The first fold has been truncated to the 5'th line. 289 " Second fold has been moved up because the moved line is now below it. 290 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0]) 291 292 %delete 293 set fdm=indent foldlevel=0 294 call setline(1, [ 295 \ "a", 296 \ "\ta", 297 \ "\t\ta", 298 \ "\t\ta", 299 \ "\t\ta", 300 \ "a", 301 \ "a"]) 302 set fdm=manual 303 %foldopen! 304 4,5m6 305 call Check_foldlevels([0, 1, 2, 0, 0, 0, 0]) 306 307 %delete 308 set fdm=indent 309 call setline(1, [ 310 \ "\ta", 311 \ "\t\ta", 312 \ "\t\ta", 313 \ "\t\ta", 314 \ "\ta", 315 \ "\t\ta", 316 \ "\t\ta", 317 \ "\t\ta", 318 \ "\ta", 319 \ "\t\ta", 320 \ "\t\ta", 321 \ "\t\ta", 322 \ "\t\ta", 323 \ "\ta", 324 \ "a"]) 325 set fdm=manual 326 %foldopen! 327 13m7 328 call Check_foldlevels([1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0]) 329 330 bw! 331endfunc 332 333func Test_move_folds_around_indent() 334 new 335 let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c") 336 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) 337 let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14] 338 " all folds closed 339 set fdm=indent 340 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) 341 call assert_equal(input, getline(1, '$')) 342 7,12m0 343 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) 344 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) 345 10,12m0 346 call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$')) 347 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)')) 348 " moving should not close the folds 349 %d 350 call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) 351 set fdm=indent 352 call cursor(2, 1) 353 %foldopen 354 7,12m0 355 let folds=repeat([-1], 18) 356 call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) 357 call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) 358 norm! zM 359 " folds are not corrupted and all have been closed 360 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)')) 361 %d 362 call setline(1, ["a", "\tb", "\tc", "\td", "\te"]) 363 set fdm=indent 364 %foldopen 365 3m4 366 %foldclose 367 call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$')) 368 call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)')) 369 %d 370 call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"]) 371 set fdm=indent foldlevel=0 372 %foldopen 373 3m1 374 %foldclose 375 call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$')) 376 call assert_equal(1, foldlevel(2)) 377 call assert_equal(5, foldclosedend(3)) 378 call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)')) 379 2,6m$ 380 %foldclose 381 call assert_equal(9, foldclosedend(2)) 382 call assert_equal(1, foldlevel(6)) 383 call assert_equal(9, foldclosedend(7)) 384 call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)')) 385 " Ensure moving around the edges still works. 386 %d 387 call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"]) 388 set fdm=indent foldlevel=0 389 %foldopen 390 6m$ 391 " The first fold has been truncated to the 5'th line. 392 " Second fold has been moved up because the moved line is now below it. 393 call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1]) 394 bw! 395endfunc 396 397func Test_folddoopen_folddoclosed() 398 new 399 call setline(1, range(1, 9)) 400 set foldmethod=manual 401 1,3 fold 402 6,8 fold 403 404 " Test without range. 405 folddoopen s/$/o/ 406 folddoclosed s/$/c/ 407 call assert_equal(['1c', '2c', '3c', 408 \ '4o', '5o', 409 \ '6c', '7c', '8c', 410 \ '9o'], getline(1, '$')) 411 412 " Test with range. 413 call setline(1, range(1, 9)) 414 1,8 folddoopen s/$/o/ 415 4,$ folddoclosed s/$/c/ 416 call assert_equal(['1', '2', '3', 417 \ '4o', '5o', 418 \ '6c', '7c', '8c', 419 \ '9'], getline(1, '$')) 420 421 set foldmethod& 422 bw! 423endfunc 424 425func Test_fold_error() 426 new 427 call setline(1, [1, 2]) 428 429 for fm in ['indent', 'expr', 'syntax', 'diff'] 430 exe 'set foldmethod=' . fm 431 call assert_fails('norm zf', 'E350:') 432 call assert_fails('norm zd', 'E351:') 433 call assert_fails('norm zE', 'E352:') 434 endfor 435 436 set foldmethod=manual 437 call assert_fails('norm zd', 'E490:') 438 call assert_fails('norm zo', 'E490:') 439 call assert_fails('3fold', 'E16:') 440 441 set foldmethod=marker 442 set nomodifiable 443 call assert_fails('1,2fold', 'E21:') 444 445 set modifiable& 446 set foldmethod& 447 bw! 448endfunc 449