neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

test_fold.vim (53024B)


      1 " Test for folding
      2 
      3 source check.vim
      4 source view_util.vim
      5 source screendump.vim
      6 
      7 func PrepIndent(arg)
      8  return [a:arg] + repeat(["\t".a:arg], 5)
      9 endfu
     10 
     11 func Test_address_fold_new_default_commentstring()
     12  " Test with the new commentstring defaults, that includes padding after v9.1.464
     13  new
     14  call setline(1, ['int FuncName() {/* {{{ */', 1, 2, 3, 4, 5, '}/* }}} */',
     15       \ 'after fold 1', 'after fold 2', 'after fold 3'])
     16  setl fen fdm=marker
     17  " The next commands should all copy the same part of the buffer,
     18  " regardless of the addressing type, since the part to be copied
     19  " is folded away
     20  :1y
     21  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
     22  :.y
     23  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
     24  :.+y
     25  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
     26  :.,.y
     27  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
     28  :sil .1,.y
     29  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
     30  " use silent to make E493 go away
     31  :sil .+,.y
     32  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
     33  :,y
     34  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
     35  :,+y
     36  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */','after fold 1'], getreg(0,1,1))
     37  " using .+3 as second address should c opy  the whole folded line + the next  3
     38  " lines
     39  :.,+3y
     40  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */',
     41       \ 'after fold 1', 'after fold 2' , 'after fold 3'], getreg(0,1,1))
     42  :sil .,-2y
     43  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3', '4', '5', '}/* }}} */'], getreg(0,1,1))
     44 
     45  " now test again with folding disabled
     46  set nofoldenable
     47  :1y
     48  call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
     49  :.y
     50  call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
     51  :.+y
     52  call assert_equal(['1'], getreg(0,1,1) )
     53  :.,.y
     54  call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
     55  " use silent to make E493 go away
     56  :sil .1,.y
     57  call assert_equal(['int FuncName() {/* {{{ */', '1'], getreg(0,1,1))
     58  " use silent to make E493 go away
     59  :sil .+,.y
     60  call assert_equal(['int FuncName() {/* {{{ */', '1'], getreg(0,1,1))
     61  :,y
     62  call assert_equal(['int FuncName() {/* {{{ */'], getreg(0,1,1))
     63  :,+y
     64  call assert_equal(['int FuncName() {/* {{{ */', '1'], getreg(0,1,1))
     65  " using .+3 as second address should c opy  the whole folded line + the next 3
     66  " lines
     67  :.,+3y
     68  call assert_equal(['int FuncName() {/* {{{ */', '1', '2', '3'], getreg(0,1,1))
     69  :7
     70  :sil .,-2y
     71  call assert_equal(['4', '5', '}/* }}} */'], getreg(0,1,1))
     72 
     73  quit!
     74 endfunc
     75 
     76 func Test_address_fold_old_default_commentstring()
     77  " Test with the old commentstring defaults, before v9.1.464
     78  new
     79  call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
     80       \ 'after fold 1', 'after fold 2', 'after fold 3'])
     81  setl fen fdm=marker
     82  " The next commands should all copy the same part of the buffer,
     83  " regardless of the addressing type, since the part to be copied
     84  " is folded away
     85  :1y
     86  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
     87  :.y
     88  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
     89  :.+y
     90  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
     91  :.,.y
     92  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
     93  :sil .1,.y
     94  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
     95  " use silent to make E493 go away
     96  :sil .+,.y
     97  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
     98  :,y
     99  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
    100  :,+y
    101  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/','after fold 1'], getreg(0,1,1))
    102  " using .+3 as second address should copy the whole folded line + the next 3
    103  " lines
    104  :.,+3y
    105  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/',
    106       \ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1))
    107  :sil .,-2y
    108  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
    109 
    110  " now test again with folding disabled
    111  set nofoldenable
    112  :1y
    113  call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
    114  :.y
    115  call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
    116  :.+y
    117  call assert_equal(['1'], getreg(0,1,1))
    118  :.,.y
    119  call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
    120  " use silent to make E493 go away
    121  :sil .1,.y
    122  call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
    123  " use silent to make E493 go away
    124  :sil .+,.y
    125  call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
    126  :,y
    127  call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
    128  :,+y
    129  call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
    130  " using .+3 as second address should copy the whole folded line + the next 3
    131  " lines
    132  :.,+3y
    133  call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1))
    134  :7
    135  :sil .,-2y
    136  call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1))
    137 
    138  quit!
    139 endfunc
    140 
    141 func Test_address_offsets()
    142  " check the help for :range-closed-fold
    143  enew
    144  call setline(1, [
    145        \ '1 one',
    146        \ '2 two',
    147        \ '3 three',
    148        \ '4 four FOLDED',
    149        \ '5 five FOLDED',
    150        \ '6 six',
    151        \ '7 seven',
    152        \ '8 eight',
    153        \])
    154  set foldmethod=manual
    155  normal 4Gvjzf
    156  3,4+2yank
    157  call assert_equal([
    158        \ '3 three',
    159        \ '4 four FOLDED',
    160        \ '5 five FOLDED',
    161        \ '6 six',
    162        \ '7 seven',
    163        \ ], getreg(0,1,1))
    164 
    165  enew!
    166  call setline(1, [
    167        \ '1 one',
    168        \ '2 two',
    169        \ '3 three FOLDED',
    170        \ '4 four FOLDED',
    171        \ '5 five FOLDED',
    172        \ '6 six FOLDED',
    173        \ '7 seven',
    174        \ '8 eight',
    175        \])
    176  normal 3Gv3jzf
    177  2,4-1yank
    178  call assert_equal([
    179        \ '2 two',
    180        \ '3 three FOLDED',
    181        \ '4 four FOLDED',
    182        \ '5 five FOLDED',
    183        \ '6 six FOLDED',
    184        \ ], getreg(0,1,1))
    185 
    186  bwipe!
    187 endfunc
    188 
    189 func Test_indent_fold()
    190    new
    191    call setline(1, ['', 'a', '    b', '    c'])
    192    setl fen fdm=indent
    193    2
    194    norm! >>
    195    let a=map(range(1,4), 'foldclosed(v:val)')
    196    call assert_equal([-1,-1,-1,-1], a)
    197    bw!
    198 endfunc
    199 
    200 func Test_indent_fold2()
    201    new
    202    call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
    203    setl fen fdm=marker
    204    2
    205    norm! >>
    206    let a=map(range(1,5), 'v:val->foldclosed()')
    207    call assert_equal([-1,-1,-1,4,4], a)
    208    bw!
    209 endfunc
    210 
    211 " Test for fold indent with indents greater than 'foldnestmax'
    212 func Test_indent_fold_max()
    213  new
    214  setlocal foldmethod=indent
    215  setlocal shiftwidth=2
    216  " 'foldnestmax' default value is 20
    217  call setline(1, "\t\t\t\t\t\ta")
    218  call assert_equal(20, foldlevel(1))
    219  setlocal foldnestmax=10
    220  call assert_equal(10, foldlevel(1))
    221  setlocal foldnestmax=-1
    222  call assert_equal(0, foldlevel(1))
    223  bw!
    224 endfunc
    225 
    226 func Test_indent_fold_tabstop()
    227  call setline(1, ['0', '    1', '    1', "\t2", "\t2"])
    228  setlocal shiftwidth=4
    229  setlocal foldcolumn=1
    230  setlocal foldlevel=2
    231  setlocal foldmethod=indent
    232  redraw
    233  call assert_equal('2        2', ScreenLines(5, 10)[0])
    234  vsplit
    235  windo diffthis
    236  botright new
    237  " This 'tabstop' value should not be used for folding in other buffers.
    238  setlocal tabstop=4
    239  diffoff!
    240  redraw
    241  call assert_equal('2        2', ScreenLines(5, 10)[0])
    242 
    243  bwipe!
    244  bwipe!
    245 endfunc
    246 
    247 func Test_manual_fold_with_filter()
    248  CheckExecutable cat
    249  for type in ['manual', 'marker']
    250    exe 'set foldmethod=' . type
    251    new
    252    call setline(1, range(1, 20))
    253    4,$fold
    254    %foldopen
    255    10,$fold
    256    %foldopen
    257    " This filter command should not have an effect
    258    1,8! cat
    259    call feedkeys('5ggzdzMGdd', 'xt')
    260    call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
    261 
    262    bwipe!
    263    set foldmethod&
    264  endfor
    265 endfunc
    266 
    267 func Test_indent_fold_with_read()
    268  new
    269  set foldmethod=indent
    270  call setline(1, repeat(["\<Tab>a"], 4))
    271  for n in range(1, 4)
    272    call assert_equal(1, foldlevel(n))
    273  endfor
    274 
    275  call writefile(["a", "", "\<Tab>a"], 'Xfile')
    276  foldopen
    277  2read Xfile
    278  %foldclose
    279  call assert_equal(1, foldlevel(1))
    280  call assert_equal(2, foldclosedend(1))
    281  call assert_equal(0, foldlevel(3))
    282  call assert_equal(0, foldlevel(4))
    283  call assert_equal(1, foldlevel(5))
    284  call assert_equal(7, 5->foldclosedend())
    285 
    286  bwipe!
    287  set foldmethod&
    288  call delete('Xfile')
    289 endfunc
    290 
    291 func Test_combining_folds_indent()
    292  new
    293  let one = "\<Tab>a"
    294  let zero = 'a'
    295  call setline(1, [one, one, zero, zero, zero, one, one, one])
    296  set foldmethod=indent
    297  3,5d
    298  %foldclose
    299  call assert_equal(5, foldclosedend(1))
    300 
    301  set foldmethod&
    302  bwipe!
    303 endfunc
    304 
    305 func Test_combining_folds_marker()
    306  new
    307  call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
    308  set foldmethod=marker
    309  3,5d
    310  %foldclose
    311  call assert_equal(2, foldclosedend(1))
    312 
    313  set foldmethod&
    314  bwipe!
    315 endfunc
    316 
    317 func Test_folds_marker_in_comment()
    318  new
    319  call setline(1, ['" foo', 'bar', 'baz'])
    320  setl fen fdm=marker
    321  setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
    322  norm! zf2j
    323  setl nofen
    324  :1y
    325  call assert_equal(['" foo{{{'], getreg(0,1,1))
    326  :+2y
    327  call assert_equal(['baz"}}}'], getreg(0,1,1))
    328 
    329  set foldmethod&
    330  bwipe!
    331 endfunc
    332 
    333 func s:TestFoldExpr(lnum)
    334  let thisline = getline(a:lnum)
    335  if thisline == 'a'
    336    return 1
    337  elseif thisline == 'b'
    338    return 0
    339  elseif thisline == 'c'
    340    return '<1'
    341  elseif thisline == 'd'
    342    return '>1'
    343  endif
    344  return 0
    345 endfunction
    346 
    347 func Test_update_folds_expr_read()
    348  new
    349  call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
    350  set foldmethod=expr
    351  set foldexpr=s:TestFoldExpr(v:lnum)
    352  2
    353  foldopen
    354  call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile')
    355  read Xfile
    356  %foldclose
    357  call assert_equal(2, foldclosedend(1))
    358  call assert_equal(0, foldlevel(3))
    359  call assert_equal(0, 4->foldlevel())
    360  call assert_equal(6, foldclosedend(5))
    361  call assert_equal(10, foldclosedend(7))
    362  call assert_equal(14, foldclosedend(11))
    363 
    364  call delete('Xfile')
    365  bwipe!
    366  set foldmethod& foldexpr&
    367 endfunc
    368 
    369 " Test for what patch 8.1.0535 fixes.
    370 func Test_foldexpr_no_interrupt_addsub()
    371  new
    372  func! FoldFunc()
    373    call setpos('.', getcurpos())
    374    return '='
    375  endfunc
    376 
    377  set foldmethod=expr
    378  set foldexpr=FoldFunc()
    379  call setline(1, '1.2')
    380 
    381  exe "norm! $\<C-A>"
    382  call assert_equal('1.3', getline(1))
    383 
    384  bwipe!
    385  delfunc FoldFunc
    386  set foldmethod& foldexpr&
    387 endfunc
    388 
    389 " Fold function defined in another script
    390 func Test_foldexpr_compiled()
    391  throw 'Skipped: Vim9 script is N/A'
    392  new
    393  let lines =<< trim END
    394      vim9script
    395      def FoldFunc(): number
    396        return v:lnum
    397      enddef
    398 
    399      set foldmethod=expr
    400      set foldexpr=s:FoldFunc()
    401  END
    402  call writefile(lines, 'XfoldExpr', 'D')
    403  source XfoldExpr
    404 
    405  call setline(1, ['one', 'two', 'three'])
    406  redraw
    407  call assert_equal(1, foldlevel(1))
    408  call assert_equal(2, foldlevel(2))
    409  call assert_equal(3, foldlevel(3))
    410 
    411  bwipe!
    412  set foldmethod& foldexpr&
    413 endfunc
    414 
    415 func Check_foldlevels(expected)
    416  call assert_equal(a:expected, map(range(1, line('$')), 'foldlevel(v:val)'))
    417 endfunc
    418 
    419 func Test_move_folds_around_manual()
    420  new
    421  let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
    422  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
    423  let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
    424  " all folds closed
    425  set foldenable foldlevel=0 fdm=indent
    426  " needs a forced redraw
    427  redraw!
    428  set fdm=manual
    429  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
    430  call assert_equal(input, getline(1, '$'))
    431  7,12m0
    432  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
    433  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
    434  10,12m0
    435  call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] +  PrepIndent("c"), getline(1, '$'))
    436  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)'))
    437  " moving should not close the folds
    438  %d
    439  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
    440  set fdm=indent
    441  redraw!
    442  set fdm=manual
    443  call cursor(2, 1)
    444  %foldopen
    445  7,12m0
    446  let folds=repeat([-1], 18)
    447  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
    448  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
    449  norm! zM
    450  " folds are not corrupted and all have been closed
    451  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)'))
    452  %d
    453  call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
    454  set fdm=indent
    455  redraw!
    456  set fdm=manual
    457  %foldopen
    458  3m4
    459  %foldclose
    460  call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
    461  call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
    462  %d
    463  call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
    464  set fdm=indent foldlevel=0
    465  set fdm=manual
    466  %foldopen
    467  3m1
    468  %foldclose
    469  call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
    470  call assert_equal(0, foldlevel(2))
    471  call assert_equal(5, foldclosedend(3))
    472  call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
    473  2,6m$
    474  %foldclose
    475  call assert_equal(5, foldclosedend(2))
    476  call assert_equal(0, foldlevel(6))
    477  call assert_equal(9, foldclosedend(7))
    478  call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
    479 
    480  %d
    481  " Ensure moving around the edges still works.
    482  call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
    483  set fdm=indent foldlevel=0
    484  set fdm=manual
    485  %foldopen
    486  6m$
    487  " The first fold has been truncated to the 5'th line.
    488  " Second fold has been moved up because the moved line is now below it.
    489  call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])
    490 
    491  %delete
    492  set fdm=indent foldlevel=0
    493  call setline(1, [
    494 \ "a",
    495 \ "\ta",
    496 \ "\t\ta",
    497 \ "\t\ta",
    498 \ "\t\ta",
    499 \ "a",
    500 \ "a"])
    501  set fdm=manual
    502  %foldopen!
    503  4,5m6
    504  call Check_foldlevels([0, 1, 2, 0, 0, 0, 0])
    505 
    506  %delete
    507  set fdm=indent
    508  call setline(1, [
    509 \ "\ta",
    510 \ "\t\ta",
    511 \ "\t\ta",
    512 \ "\t\ta",
    513 \ "\ta",
    514 \ "\t\ta",
    515 \ "\t\ta",
    516 \ "\t\ta",
    517 \ "\ta",
    518 \ "\t\ta",
    519 \ "\t\ta",
    520 \ "\t\ta",
    521 \ "\t\ta",
    522 \ "\ta",
    523 \ "a"])
    524  set fdm=manual
    525  %foldopen!
    526  13m7
    527  call Check_foldlevels([1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0])
    528 
    529  bw!
    530 endfunc
    531 
    532 func Test_move_folds_around_indent()
    533  new
    534  let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
    535  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
    536  let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
    537  " all folds closed
    538  set fdm=indent
    539  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
    540  call assert_equal(input, getline(1, '$'))
    541  7,12m0
    542  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
    543  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
    544  10,12m0
    545  call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] +  PrepIndent("c"), getline(1, '$'))
    546  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)'))
    547  " moving should not close the folds
    548  %d
    549  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
    550  set fdm=indent
    551  call cursor(2, 1)
    552  %foldopen
    553  7,12m0
    554  let folds=repeat([-1], 18)
    555  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
    556  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
    557  norm! zM
    558  " folds are not corrupted and all have been closed
    559  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)'))
    560  %d
    561  call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
    562  set fdm=indent
    563  %foldopen
    564  3m4
    565  %foldclose
    566  call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
    567  call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
    568  %d
    569  call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
    570  set fdm=indent foldlevel=0
    571  %foldopen
    572  3m1
    573  %foldclose
    574  call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
    575  call assert_equal(1, foldlevel(2))
    576  call assert_equal(5, foldclosedend(3))
    577  call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
    578  2,6m$
    579  %foldclose
    580  call assert_equal(9, foldclosedend(2))
    581  call assert_equal(1, foldlevel(6))
    582  call assert_equal(9, foldclosedend(7))
    583  call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
    584  " Ensure moving around the edges still works.
    585  %d
    586  call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
    587  set fdm=indent foldlevel=0
    588  %foldopen
    589  6m$
    590  " The first fold has been truncated to the 5'th line.
    591  " Second fold has been moved up because the moved line is now below it.
    592  call Check_foldlevels([0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
    593  bw!
    594 endfunc
    595 
    596 func Test_folddoopen_folddoclosed()
    597  new
    598  call setline(1, range(1, 9))
    599  set foldmethod=manual
    600  1,3 fold
    601  6,8 fold
    602 
    603  " Test without range.
    604  folddoopen   s/$/o/
    605  folddoclosed s/$/c/
    606  call assert_equal(['1c', '2c', '3c',
    607  \                  '4o', '5o',
    608  \                  '6c', '7c', '8c',
    609  \                  '9o'], getline(1, '$'))
    610 
    611  " Test with range.
    612  call setline(1, range(1, 9))
    613  1,8 folddoopen   s/$/o/
    614  4,$ folddoclosed s/$/c/
    615  call assert_equal(['1',  '2', '3',
    616  \                  '4o', '5o',
    617  \                  '6c', '7c', '8c',
    618  \                  '9'], getline(1, '$'))
    619 
    620  set foldmethod&
    621  bw!
    622 endfunc
    623 
    624 func Test_fold_error()
    625  new
    626  call setline(1, [1, 2])
    627 
    628  for fm in ['indent', 'expr', 'syntax', 'diff']
    629    exe 'set foldmethod=' . fm
    630    call assert_fails('norm zf', 'E350:')
    631    call assert_fails('norm zd', 'E351:')
    632    call assert_fails('norm zE', 'E352:')
    633  endfor
    634 
    635  set foldmethod=manual
    636  call assert_fails('norm zd', 'E490:')
    637  call assert_fails('norm zo', 'E490:')
    638  call assert_fails('3fold',   'E16:')
    639 
    640  set foldmethod=marker
    641  set nomodifiable
    642  call assert_fails('1,2fold', 'E21:')
    643 
    644  set modifiable&
    645  set foldmethod&
    646  bw!
    647 endfunc
    648 
    649 func Test_foldtext_recursive()
    650  new
    651  call setline(1, ['{{{', 'some text', '}}}'])
    652  setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
    653  " This was crashing because of endless recursion.
    654  2foldclose
    655  redraw
    656  call assert_equal(1, foldlevel(2))
    657  call assert_equal(1, foldclosed(2))
    658  call assert_equal(3, foldclosedend(2))
    659  bwipe!
    660 endfunc
    661 
    662 " Various fold related tests
    663 
    664 " Basic test if a fold can be created, opened, moving to the end and closed
    665 func Test_fold_manual()
    666  new
    667  set fdm=manual
    668 
    669  let content = ['1 aa', '2 bb', '3 cc']
    670  call append(0, content)
    671  call cursor(1, 1)
    672  normal zf2j
    673  call assert_equal('1 aa', getline(foldclosed('.')))
    674  normal zo
    675  call assert_equal(-1, foldclosed('.'))
    676  normal ]z
    677  call assert_equal('3 cc', getline('.'))
    678  normal zc
    679  call assert_equal('1 aa', getline(foldclosed('.')))
    680 
    681  " Create a fold inside a closed fold after setting 'foldlevel'
    682  %d _
    683  call setline(1, range(1, 5))
    684  1,5fold
    685  normal zR
    686  2,4fold
    687  set foldlevel=1
    688  3fold
    689  call assert_equal([1, 3, 3, 3, 1], map(range(1, 5), {->foldlevel(v:val)}))
    690  set foldlevel&
    691 
    692  " Create overlapping folds (at the start and at the end)
    693  normal zE
    694  2,3fold
    695  normal zR
    696  3,4fold
    697  call assert_equal([0, 2, 2, 1, 0], map(range(1, 5), {->foldlevel(v:val)}))
    698  normal zE
    699  3,4fold
    700  normal zR
    701  2,3fold
    702  call assert_equal([0, 1, 2, 2, 0], map(range(1, 5), {->foldlevel(v:val)}))
    703 
    704  " Create a nested fold across two non-adjoining folds
    705  %d _
    706  call setline(1, range(1, 7))
    707  1,2fold
    708  normal zR
    709  4,5fold
    710  normal zR
    711  6,7fold
    712  normal zR
    713  1,5fold
    714  call assert_equal([2, 2, 1, 2, 2, 1, 1],
    715        \ map(range(1, 7), {->foldlevel(v:val)}))
    716 
    717  " A newly created nested fold should be closed
    718  %d _
    719  call setline(1, range(1, 6))
    720  1,6fold
    721  normal zR
    722  3,4fold
    723  normal zR
    724  2,5fold
    725  call assert_equal([1, 2, 3, 3, 2, 1], map(range(1, 6), {->foldlevel(v:val)}))
    726  call assert_equal(2, foldclosed(4))
    727  call assert_equal(5, foldclosedend(4))
    728 
    729  " Test zO, zC and zA on a line with no folds.
    730  normal zE
    731  call assert_fails('normal zO', 'E490:')
    732  call assert_fails('normal zC', 'E490:')
    733  call assert_fails('normal zA', 'E490:')
    734 
    735  set fdm&
    736  bw!
    737 endfunc
    738 
    739 " test folding with markers.
    740 func Test_fold_marker()
    741  new
    742  set fdm=marker fdl=1 fdc=3
    743 
    744  let content = ['4 dd {{{', '5 ee {{{ }}}', '6 ff }}}']
    745  call append(0, content)
    746  call cursor(2, 1)
    747  call assert_equal(2, foldlevel('.'))
    748  normal [z
    749  call assert_equal(1, foldlevel('.'))
    750  exe "normal jo{{ \<Esc>r{jj"
    751  call assert_equal(1, foldlevel('.'))
    752  normal kYpj
    753  call assert_equal(0, foldlevel('.'))
    754 
    755  " Use only closing fold marker (without and with a count)
    756  set fdl&
    757  %d _
    758  call setline(1, ['one }}}', 'two'])
    759  call assert_equal([0, 0], [foldlevel(1), foldlevel(2)])
    760  %d _
    761  call setline(1, ['one }}}4', 'two'])
    762  call assert_equal([4, 3], [foldlevel(1), foldlevel(2)])
    763 
    764  set fdm& fdl& fdc&
    765  bw!
    766 endfunc
    767 
    768 " test create fold markers with C filetype
    769 func Test_fold_create_marker_in_C()
    770  bw!
    771  set fdm=marker fdl=9
    772  set filetype=c
    773 
    774  let content =<< trim [CODE]
    775    /*
    776     * comment
    777     *
    778     *
    779     */
    780    int f(int* p) {
    781        *p = 3;
    782        return 0;
    783    }
    784  [CODE]
    785 
    786  for c in range(len(content) - 1)
    787    bw!
    788    call append(0, content)
    789    call cursor(c + 1, 1)
    790    norm! zfG
    791    call assert_equal(content[c] . (c < 4 ? '{{{' : '/* {{{ */'), getline(c + 1))
    792  endfor
    793 
    794  set fdm& fdl&
    795  bw!
    796 endfunc
    797 
    798 " test folding with indent
    799 func Test_fold_indent()
    800  new
    801  set fdm=indent sw=2
    802 
    803  let content = ['1 aa', '2 bb', '3 cc']
    804  call append(0, content)
    805  call cursor(2, 1)
    806  exe "normal i  \<Esc>jI    "
    807  call assert_equal(2, foldlevel('.'))
    808  normal k
    809  call assert_equal(1, foldlevel('.'))
    810 
    811  set fdm& sw&
    812  bw!
    813 endfunc
    814 
    815 " test syntax folding
    816 func Test_fold_syntax()
    817  CheckFeature syntax
    818 
    819  new
    820  set fdm=syntax fdl=0
    821 
    822  syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3
    823  syn region Fd1 start="ee" end="ff" fold contained
    824  syn region Fd2 start="gg" end="hh" fold contained
    825  syn region Fd3 start="commentstart" end="commentend" fold contained
    826  let content = ['3 cc', '4 dd {{{', '5 ee {{{ }}}', '{{{{', '6 ff }}}',
    827       \ '6 ff }}}', '7 gg', '8 hh', '9 ii']
    828  call append(0, content)
    829  normal Gzk
    830  call assert_equal('9 ii', getline('.'))
    831  normal k
    832  call assert_equal('3 cc', getline('.'))
    833  exe "normal jAcommentstart   \<Esc>Acommentend"
    834  set fdl=1
    835  normal 3j
    836  call assert_equal('7 gg', getline('.'))
    837  set fdl=0
    838  exe "normal zO\<C-L>j"
    839  call assert_equal('8 hh', getline('.'))
    840  syn clear Fd1 Fd2 Fd3 Hup
    841 
    842  set fdm& fdl&
    843  bw!
    844 endfunc
    845 
    846 func Flvl()
    847  let l = getline(v:lnum)
    848  if l =~ "bb$"
    849    return 2
    850  elseif l =~ "gg$"
    851    return "s1"
    852  elseif l =~ "ii$"
    853    return ">2"
    854  elseif l =~ "kk$"
    855    return "0"
    856  endif
    857  return "="
    858 endfun
    859 
    860 " test expression folding
    861 func Test_fold_expr()
    862  new
    863  set fdm=expr fde=Flvl()
    864 
    865  let content = ['1 aa',
    866       \ '2 bb',
    867       \ '3 cc',
    868       \ '4 dd {{{commentstart  commentend',
    869       \ '5 ee {{{ }}}',
    870       \ '{{{',
    871       \ '6 ff }}}',
    872       \ '6 ff }}}',
    873       \ '  7 gg',
    874       \ '    8 hh',
    875       \ '9 ii',
    876       \ 'a jj',
    877       \ 'b kk']
    878  call append(0, content)
    879  call cursor(1, 1)
    880  exe "normal /bb$\<CR>"
    881  call assert_equal(2, foldlevel('.'))
    882  exe "normal /hh$\<CR>"
    883  call assert_equal(1, foldlevel('.'))
    884  exe "normal /ii$\<CR>"
    885  call assert_equal(2, foldlevel('.'))
    886  exe "normal /kk$\<CR>"
    887  call assert_equal(0, foldlevel('.'))
    888 
    889  set fdm& fde&
    890  bw!
    891 endfunc
    892 
    893 " Bug with fdm=indent and moving folds
    894 " Moving a fold a few times, messes up the folds below the moved fold.
    895 " Fixed by 7.4.700
    896 func Test_fold_move()
    897  new
    898  set fdm=indent sw=2 fdl=0
    899 
    900  let content = ['', '', 'Line1', '  Line2', '  Line3',
    901       \ 'Line4', '  Line5', '  Line6',
    902       \ 'Line7', '  Line8', '  Line9']
    903  call append(0, content)
    904  normal zM
    905  call cursor(4, 1)
    906  move 2
    907  move 1
    908  call assert_equal(7, foldclosed(7))
    909  call assert_equal(8, foldclosedend(7))
    910  call assert_equal(0, foldlevel(9))
    911  call assert_equal(10, foldclosed(10))
    912  call assert_equal(11, foldclosedend(10))
    913  call assert_equal('+--  2 lines: Line2', foldtextresult(2))
    914  call assert_equal('+--  2 lines: Line8', 10->foldtextresult())
    915 
    916  set fdm& sw& fdl&
    917  bw!
    918 endfunc
    919 
    920 " test for patch 7.3.637
    921 " Cannot catch the error caused by a foldopen when there is no fold.
    922 func Test_foldopen_exception()
    923  new
    924  let a = 'No error caught'
    925  try
    926    foldopen
    927  catch
    928    let a = matchstr(v:exception,'^[^ ]*')
    929  endtry
    930  call assert_equal('Vim(foldopen):E490:', a)
    931 
    932  let a = 'No error caught'
    933  try
    934    foobar
    935  catch
    936    let a = matchstr(v:exception,'^[^ ]*')
    937  endtry
    938  call assert_match('E492:', a)
    939  bw!
    940 endfunc
    941 
    942 func Test_fold_last_line_with_pagedown()
    943  new
    944  set fdm=manual
    945 
    946  let expect = '+-- 11 lines: 9---'
    947  let content = range(1,19)
    948  call append(0, content)
    949  normal dd9G
    950  normal zfG
    951  normal zt
    952  call assert_equal('9', getline(foldclosed('.')))
    953  call assert_equal('19', getline(foldclosedend('.')))
    954  call assert_equal(expect, ScreenLines(1, len(expect))[0])
    955  call feedkeys("\<C-F>", 'xt')
    956  call assert_equal(expect, ScreenLines(1, len(expect))[0])
    957  call feedkeys("\<C-F>", 'xt')
    958  call assert_equal(expect, ScreenLines(1, len(expect))[0])
    959  call feedkeys("\<C-B>\<C-F>\<C-F>", 'xt')
    960  call assert_equal(expect, ScreenLines(1, len(expect))[0])
    961 
    962  set fdm&
    963  bw!
    964 endfunc
    965 
    966 func Test_folds_with_rnu()
    967  CheckScreendump
    968 
    969  call writefile([
    970 \ 'set fdm=marker rnu foldcolumn=2',
    971 \ 'call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])',
    972 \ ], 'Xtest_folds_with_rnu')
    973  let buf = RunVimInTerminal('-S Xtest_folds_with_rnu', {})
    974 
    975  call VerifyScreenDump(buf, 'Test_folds_with_rnu_01', {})
    976  call term_sendkeys(buf, "j")
    977  call VerifyScreenDump(buf, 'Test_folds_with_rnu_02', {})
    978 
    979  " clean up
    980  call StopVimInTerminal(buf)
    981  call delete('Xtest_folds_with_rnu')
    982 endfunc
    983 
    984 func Test_folds_marker_in_comment2()
    985  new
    986  call setline(1, ['Lorem ipsum dolor sit', 'Lorem ipsum dolor sit', 'Lorem ipsum dolor sit'])
    987  setl fen fdm=marker
    988  setl commentstring=<!--%s-->
    989  setl comments=s:<!--,m:\ \ \ \ ,e:-->
    990  norm! zf2j
    991  setl nofen
    992  :1y
    993  call assert_equal(['Lorem ipsum dolor sit<!--{{{-->'], getreg(0,1,1))
    994  :+2y
    995  call assert_equal(['Lorem ipsum dolor sit<!--}}}-->'], getreg(0,1,1))
    996 
    997  set foldmethod&
    998  bwipe!
    999 endfunc
   1000 
   1001 func Test_fold_delete_with_marker()
   1002  new
   1003  call setline(1, ['func Func() {{{1', 'endfunc'])
   1004  1,2yank
   1005  new
   1006  set fdm=marker
   1007  call setline(1, 'x')
   1008  normal! Vp
   1009  normal! zd
   1010  call assert_equal(['func Func() ', 'endfunc'], getline(1, '$'))
   1011 
   1012  set fdm&
   1013  bwipe!
   1014  bwipe!
   1015 endfunc
   1016 
   1017 func Test_fold_delete_with_marker_and_whichwrap()
   1018  new
   1019  let content1 = ['']
   1020  let content2 = ['folded line 1 "{{{1', '  test', '  test2', '  test3', '', 'folded line 2 "{{{1', '  test', '  test2', '  test3']
   1021  call setline(1, content1 + content2)
   1022  set fdm=marker ww+=l
   1023  normal! x
   1024  call assert_equal(content2, getline(1, '$'))
   1025  set fdm& ww&
   1026  bwipe!
   1027 endfunc
   1028 
   1029 func Test_fold_delete_first_line()
   1030  new
   1031  call setline(1, [
   1032 \ '" x {{{1',
   1033 \ '" a',
   1034 \ '" aa',
   1035 \ '" x {{{1',
   1036 \ '" b',
   1037 \ '" bb',
   1038 \ '" x {{{1',
   1039 \ '" c',
   1040 \ '" cc',
   1041 \ ])
   1042  set foldmethod=marker
   1043  1
   1044  normal dj
   1045  call assert_equal([
   1046 \ '" x {{{1',
   1047 \ '" c',
   1048 \ '" cc',
   1049 \ ], getline(1,'$'))
   1050  bwipe!
   1051  set foldmethod&
   1052 endfunc
   1053 
   1054 " Add a test for deleting the outer fold of a nested fold and promoting the
   1055 " inner folds to one level up with already a fold at that level following the
   1056 " nested fold.
   1057 func Test_fold_delete_recursive_fold()
   1058  new
   1059  call setline(1, range(1, 7))
   1060  2,3fold
   1061  normal zR
   1062  4,5fold
   1063  normal zR
   1064  1,5fold
   1065  normal zR
   1066  6,7fold
   1067  normal zR
   1068  normal 1Gzd
   1069  normal 1Gzj
   1070  call assert_equal(2, line('.'))
   1071  normal zj
   1072  call assert_equal(4, line('.'))
   1073  normal zj
   1074  call assert_equal(6, line('.'))
   1075  bw!
   1076 endfunc
   1077 
   1078 " Test for errors in 'foldexpr'
   1079 func Test_fold_expr_error()
   1080  new
   1081  call setline(1, ['one', 'two', 'three'])
   1082  " In a window with no folds, foldlevel() should return 0
   1083  call assert_equal(0, foldlevel(1))
   1084 
   1085  " Return a list from the expression
   1086  set foldexpr=[]
   1087  set foldmethod=expr
   1088  for i in range(3)
   1089    call assert_equal(0, foldlevel(i))
   1090  endfor
   1091 
   1092  " expression error
   1093  set foldexpr=[{]
   1094  set foldmethod=expr
   1095  for i in range(3)
   1096    call assert_equal(0, foldlevel(i))
   1097  endfor
   1098 
   1099  set foldmethod& foldexpr&
   1100  bw!
   1101 endfunc
   1102 
   1103 func Test_undo_fold_deletion()
   1104  new
   1105  set fdm=marker
   1106  let lines =<< trim END
   1107      " {{{
   1108      " }}}1
   1109      " {{{
   1110  END
   1111  call setline(1, lines)
   1112  3d
   1113  g/"/d
   1114  undo
   1115  redo
   1116  eval getline(1, '$')->assert_equal([''])
   1117 
   1118  set fdm&vim
   1119  bwipe!
   1120 endfunc
   1121 
   1122 " this was crashing
   1123 func Test_move_no_folds()
   1124  new
   1125  fold
   1126  setlocal fdm=expr
   1127  normal zj
   1128  bwipe!
   1129 endfunc
   1130 
   1131 " this was crashing
   1132 func Test_fold_create_delete_create()
   1133  new
   1134  fold
   1135  fold
   1136  normal zd
   1137  fold
   1138  bwipe!
   1139 endfunc
   1140 
   1141 " this was crashing
   1142 func Test_fold_create_delete()
   1143  new
   1144  norm zFzFzdzj
   1145  bwipe!
   1146 endfunc
   1147 
   1148 func Test_fold_relative_move()
   1149  new
   1150  set fdm=indent sw=2 wrap tw=80
   1151 
   1152  let longtext = repeat('x', &columns + 1)
   1153  let content = [ '  foo', '  ' .. longtext, '  baz',
   1154              \   longtext,
   1155              \   '  foo', '  ' .. longtext, '  baz'
   1156              \ ]
   1157  call append(0, content)
   1158 
   1159  normal zM
   1160 
   1161  for lnum in range(1, 3)
   1162    call cursor(lnum, 1)
   1163    call assert_true(foldclosed(line('.')))
   1164    normal gj
   1165    call assert_equal(2, winline())
   1166  endfor
   1167 
   1168  call cursor(2, 1)
   1169  call assert_true(foldclosed(line('.')))
   1170  normal 2gj
   1171  call assert_equal(3, winline())
   1172 
   1173  for lnum in range(5, 7)
   1174    call cursor(lnum, 1)
   1175    call assert_true(foldclosed(line('.')))
   1176    normal gk
   1177    call assert_equal(3, winline())
   1178  endfor
   1179 
   1180  call cursor(6, 1)
   1181  call assert_true(foldclosed(line('.')))
   1182  normal 2gk
   1183  call assert_equal(2, winline())
   1184 
   1185  set fdm& sw& wrap& tw&
   1186  bw!
   1187 endfunc
   1188 
   1189 " Test for calling foldlevel() from a fold expression
   1190 let g:FoldLevels = []
   1191 func FoldExpr1(lnum)
   1192  let f = [a:lnum]
   1193  for i in range(1, line('$'))
   1194    call add(f, foldlevel(i))
   1195  endfor
   1196  call add(g:FoldLevels, f)
   1197  return getline(a:lnum)[0] == "\t"
   1198 endfunc
   1199 
   1200 func Test_foldexpr_foldlevel()
   1201  new
   1202  call setline(1, ['one', "\ttwo", "\tthree"])
   1203  setlocal foldmethod=expr
   1204  setlocal foldexpr=FoldExpr1(v:lnum)
   1205  setlocal foldenable
   1206  setlocal foldcolumn=3
   1207  redraw!
   1208  call assert_equal([[1, -1, -1, -1], [2, -1, -1, -1], [3, 0, 1, -1]],
   1209        \ g:FoldLevels)
   1210  set foldmethod& foldexpr& foldenable& foldcolumn&
   1211  bw!
   1212 endfunc
   1213 
   1214 " Test for returning different values from a fold expression
   1215 func FoldExpr2(lnum)
   1216  if a:lnum == 1 || a:lnum == 4
   1217    return -2
   1218  elseif a:lnum == 2
   1219    return 'a1'
   1220  elseif a:lnum == 3
   1221    return 's4'
   1222  endif
   1223  return '='
   1224 endfunc
   1225 
   1226 func Test_foldexpr_2()
   1227  new
   1228  call setline(1, ['one', 'two', 'three', 'four'])
   1229  setlocal foldexpr=FoldExpr2(v:lnum)
   1230  setlocal foldmethod=expr
   1231  call assert_equal([0, 1, 1, 0], [foldlevel(1), foldlevel(2), foldlevel(3),
   1232        \ foldlevel(4)])
   1233  bw!
   1234 endfunc
   1235 
   1236 " Test for the 'foldclose' option
   1237 func Test_foldclose_opt()
   1238  CheckScreendump
   1239 
   1240  let lines =<< trim END
   1241    set foldmethod=manual foldclose=all foldopen=all
   1242    call setline(1, ['one', 'two', 'three', 'four'])
   1243    2,3fold
   1244    func XsaveFoldLevels()
   1245      redraw!
   1246      call writefile([json_encode([foldclosed(1), foldclosed(2), foldclosed(3),
   1247        \ foldclosed(4)])], 'Xoutput', 'a')
   1248    endfunc
   1249  END
   1250  call writefile(lines, 'Xscript')
   1251  let rows = 10
   1252  let buf = RunVimInTerminal('-S Xscript', {'rows': rows})
   1253  call term_wait(buf)
   1254  call term_sendkeys(buf, ":set noruler\n")
   1255  call term_wait(buf)
   1256  call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
   1257  call term_sendkeys(buf, "2G")
   1258  call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
   1259  call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
   1260  call term_sendkeys(buf, "4G")
   1261  call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
   1262  call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
   1263  call term_sendkeys(buf, "3G")
   1264  call WaitForAssert({-> assert_equal('three', term_getline(buf, 3))})
   1265  call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
   1266  call term_sendkeys(buf, "1G")
   1267  call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
   1268  call term_sendkeys(buf, ":call XsaveFoldLevels()\n")
   1269  call term_sendkeys(buf, "2G")
   1270  call WaitForAssert({-> assert_equal('two', term_getline(buf, 2))})
   1271  call term_sendkeys(buf, "k")
   1272  call WaitForAssert({-> assert_equal('four', term_getline(buf, 3))})
   1273 
   1274  " clean up
   1275  call StopVimInTerminal(buf)
   1276 
   1277  call assert_equal(['[-1,2,2,-1]', '[-1,-1,-1,-1]', '[-1,2,2,-1]',
   1278        \ '[-1,-1,-1,-1]', '[-1,2,2,-1]'], readfile('Xoutput'))
   1279  call delete('Xscript')
   1280  call delete('Xoutput')
   1281 endfunc
   1282 
   1283 " Test for foldtextresult()
   1284 func Test_foldtextresult()
   1285  new
   1286  call assert_equal('', foldtextresult(-1))
   1287  call assert_equal('', foldtextresult(0))
   1288  call assert_equal('', foldtextresult(1))
   1289  call setline(1, ['one', 'two', 'three', 'four'])
   1290  2,3fold
   1291  call assert_equal('', foldtextresult(1))
   1292  call assert_equal('+--  2 lines: two', foldtextresult(2))
   1293  setlocal foldtext=
   1294  call assert_equal('+--  2 lines folded ', foldtextresult(2))
   1295 
   1296  " Fold text for a C comment fold
   1297  %d _
   1298  setlocal foldtext&
   1299  call setline(1, ['', '/*', ' * Comment', ' */', ''])
   1300  2,4fold
   1301  call assert_equal('+--  3 lines: Comment', foldtextresult(2))
   1302 
   1303  bw!
   1304 endfunc
   1305 
   1306 " Test for foldtext and fillchars with 'rightleft' enabled
   1307 func Test_foldtext_and_fillchars_rightleft()
   1308  CheckFeature rightleft
   1309  CheckScreendump
   1310  CheckRunVimInTerminal
   1311 
   1312  let script_lines =<< trim END
   1313    let longtext = 'Lorem ipsum dolor sit amet, consectetur adipiscing'
   1314    let g:multibyte = 'Lorem ipsum dolor sit amet'
   1315 
   1316    call setline(1, [longtext, longtext, longtext])
   1317    1,2fold
   1318 
   1319    setlocal rightleft
   1320    set noshowmode noshowcmd
   1321  END
   1322  call writefile(script_lines, 'XTest_foldtext_and_fillchars_rightleft', 'D')
   1323  let buf = RunVimInTerminal('-S XTest_foldtext_and_fillchars_rightleft', {'rows': 5, 'cols': 70})
   1324 
   1325  call VerifyScreenDump(buf, 'Test_foldtext_and_fillchars_rightleft_01', {})
   1326  call term_sendkeys(buf, ":call setline(1, [g:multibyte, g:multibyte, g:multibyte])\<CR>")
   1327  call VerifyScreenDump(buf, 'Test_foldtext_and_fillchars_rightleft_02', {})
   1328 
   1329  " clean up
   1330  call StopVimInTerminal(buf)
   1331 endfunc
   1332 
   1333 " Test for foldtextresult() with 'rightleft' enabled
   1334 func Test_foldtextresult_rightleft()
   1335  CheckFeature rightleft
   1336 
   1337  let save_columns = &columns
   1338  new
   1339  set columns=70
   1340  setlocal rightleft
   1341 
   1342  let longtext = 'Lorem ipsum dolor sit amet, consectetur adipiscing'
   1343  let multibyte = 'Lorem ipsum dolor sit amet'
   1344 
   1345  call setline(1, [longtext, longtext, longtext])
   1346  1,2fold
   1347  call assert_equal('+--  2 lines: ' .. longtext, foldtextresult(1))
   1348 
   1349  call setline(1, [multibyte, multibyte, multibyte])
   1350  call assert_equal('+--  2 lines: ' .. multibyte, foldtextresult(1))
   1351 
   1352  bw!
   1353  let &columns = save_columns
   1354 endfunc
   1355 
   1356 " Test for merging two recursive folds when an intermediate line with no fold
   1357 " is removed
   1358 func Test_fold_merge_recursive()
   1359  new
   1360  call setline(1, ['  one', '    two', 'xxxx', '    three',
   1361        \ '      four', "\tfive"])
   1362  setlocal foldmethod=indent shiftwidth=2
   1363  3d_
   1364  %foldclose
   1365  call assert_equal([1, 5], [foldclosed(5), foldclosedend(1)])
   1366  bw!
   1367 endfunc
   1368 
   1369 " Test for moving a line which is the start of a fold from a recursive fold to
   1370 " outside. The fold length should reduce.
   1371 func Test_fold_move_foldlevel()
   1372  new
   1373  call setline(1, ['a{{{', 'b{{{', 'c{{{', 'd}}}', 'e}}}', 'f}}}', 'g'])
   1374  setlocal foldmethod=marker
   1375  normal zR
   1376  call assert_equal([3, 2, 1], [foldlevel(4), foldlevel(5), foldlevel(6)])
   1377  3move 7
   1378  call assert_equal([2, 1, 0], [foldlevel(3), foldlevel(4), foldlevel(5)])
   1379  call assert_equal(1, foldlevel(7))
   1380 
   1381  " Move a line from outside a fold to inside the fold.
   1382  %d _
   1383  call setline(1, ['a', 'b{{{', 'c}}}'])
   1384  normal zR
   1385  1move 2
   1386  call assert_equal([1, 1, 1], [foldlevel(1), foldlevel(2), foldlevel(3)])
   1387 
   1388  " Move the start of one fold to inside another fold
   1389  %d _
   1390  call setline(1, ['a', 'b{{{', 'c}}}', 'd{{{', 'e}}}'])
   1391  normal zR
   1392  call assert_equal([0, 1, 1, 1, 1], [foldlevel(1), foldlevel(2),
   1393        \ foldlevel(3), foldlevel(4), foldlevel(5)])
   1394  1,2move 4
   1395  call assert_equal([0, 1, 1, 2, 2], [foldlevel(1), foldlevel(2),
   1396        \ foldlevel(3), foldlevel(4), foldlevel(5)])
   1397 
   1398  bw!
   1399 endfunc
   1400 
   1401 " Test for using zj and zk to move downwards and upwards to the start and end
   1402 " of the next fold.
   1403 " Test for using [z and ]z in a closed fold to jump to the beginning and end
   1404 " of the fold.
   1405 func Test_fold_jump()
   1406  new
   1407  call setline(1, ["\t1", "\t2", "\t\t3", "\t\t4", "\t\t\t5", "\t\t\t6", "\t\t7", "\t\t8", "\t9", "\t10"])
   1408  setlocal foldmethod=indent
   1409  normal zR
   1410  normal zj
   1411  call assert_equal(3, line('.'))
   1412  normal zj
   1413  call assert_equal(5, line('.'))
   1414  call assert_beeps('normal zj')
   1415  call assert_equal(5, line('.'))
   1416  call assert_beeps('normal 9Gzj')
   1417  call assert_equal(9, line('.'))
   1418  normal Gzk
   1419  call assert_equal(8, line('.'))
   1420  normal zk
   1421  call assert_equal(6, line('.'))
   1422  call assert_beeps('normal zk')
   1423  call assert_equal(6, line('.'))
   1424  call assert_beeps('normal 2Gzk')
   1425  call assert_equal(2, line('.'))
   1426 
   1427  " Using [z or ]z in a closed fold should not move the cursor
   1428  %d _
   1429  call setline(1, ["1", "\t2", "\t3", "\t4", "\t5", "\t6", "7"])
   1430  normal zR4Gzc
   1431  call assert_equal(4, line('.'))
   1432  call assert_beeps('normal [z')
   1433  call assert_equal(4, line('.'))
   1434  call assert_beeps('normal ]z')
   1435  call assert_equal(4, line('.'))
   1436  bw!
   1437 endfunc
   1438 
   1439 " Test for using a script-local function for 'foldexpr'
   1440 func Test_foldexpr_scriptlocal_func()
   1441  func! s:FoldFunc()
   1442    let g:FoldLnum = v:lnum
   1443  endfunc
   1444  new | only
   1445  call setline(1, 'abc')
   1446  let g:FoldLnum = 0
   1447  set foldmethod=expr foldexpr=s:FoldFunc()
   1448  redraw!
   1449  call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
   1450  call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
   1451  call assert_equal(1, g:FoldLnum)
   1452  set foldmethod& foldexpr=
   1453  bw!
   1454  new | only
   1455  call setline(1, 'abc')
   1456  let g:FoldLnum = 0
   1457  set foldmethod=expr foldexpr=<SID>FoldFunc()
   1458  redraw!
   1459  call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
   1460  call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
   1461  call assert_equal(1, g:FoldLnum)
   1462  bw!
   1463  call setline(1, 'abc')
   1464  setlocal foldmethod& foldexpr&
   1465  setglobal foldmethod=expr foldexpr=s:FoldFunc()
   1466  call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
   1467  call assert_equal('0', &foldexpr)
   1468  enew!
   1469  call setline(1, 'abc')
   1470  redraw!
   1471  call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
   1472  call assert_equal(1, g:FoldLnum)
   1473  bw!
   1474  call setline(1, 'abc')
   1475  setlocal foldmethod& foldexpr&
   1476  setglobal foldmethod=expr foldexpr=<SID>FoldFunc()
   1477  call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
   1478  call assert_equal('0', &foldexpr)
   1479  enew!
   1480  call setline(1, 'abc')
   1481  redraw!
   1482  call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
   1483  call assert_equal(1, g:FoldLnum)
   1484  set foldmethod& foldexpr&
   1485  delfunc s:FoldFunc
   1486  bw!
   1487 endfunc
   1488 
   1489 " Test for using a script-local function for 'foldtext'
   1490 func Test_foldtext_scriptlocal_func()
   1491  func! s:FoldText()
   1492    let g:FoldTextArgs = [v:foldstart, v:foldend]
   1493    return foldtext()
   1494  endfunc
   1495  new | only
   1496  call setline(1, range(50))
   1497  let g:FoldTextArgs = []
   1498  set foldtext=s:FoldText()
   1499  norm! 4Gzf4j
   1500  redraw!
   1501  call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
   1502  call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
   1503  call assert_equal([4, 8], g:FoldTextArgs)
   1504  set foldtext&
   1505  bw!
   1506  new | only
   1507  call setline(1, range(50))
   1508  let g:FoldTextArgs = []
   1509  set foldtext=<SID>FoldText()
   1510  norm! 8Gzf4j
   1511  redraw!
   1512  call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
   1513  call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
   1514  call assert_equal([8, 12], g:FoldTextArgs)
   1515  set foldtext&
   1516  bw!
   1517  call setline(1, range(50))
   1518  let g:FoldTextArgs = []
   1519  setlocal foldtext&
   1520  setglobal foldtext=s:FoldText()
   1521  call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
   1522  call assert_equal('foldtext()', &foldtext)
   1523  enew!
   1524  call setline(1, range(50))
   1525  norm! 12Gzf4j
   1526  redraw!
   1527  call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
   1528  call assert_equal([12, 16], g:FoldTextArgs)
   1529  set foldtext&
   1530  bw!
   1531  call setline(1, range(50))
   1532  let g:FoldTextArgs = []
   1533  setlocal foldtext&
   1534  setglobal foldtext=<SID>FoldText()
   1535  call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
   1536  call assert_equal('foldtext()', &foldtext)
   1537  enew!
   1538  call setline(1, range(50))
   1539  norm! 16Gzf4j
   1540  redraw!
   1541  call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
   1542  call assert_equal([16, 20], g:FoldTextArgs)
   1543  set foldtext&
   1544  bw!
   1545  delfunc s:FoldText
   1546 endfunc
   1547 
   1548 " Test for setting 'foldtext' from the modeline and executing the expression
   1549 " in a sandbox
   1550 func Test_foldtext_in_modeline()
   1551  func ModelineFoldText()
   1552    call writefile(['after'], 'Xmodelinefoldtext_write')
   1553    return "folded text"
   1554  endfunc
   1555  let lines =<< trim END
   1556    func T()
   1557      let i = 1
   1558    endfunc
   1559    " vim: foldenable foldtext=ModelineFoldText()
   1560  END
   1561  call writefile(lines, 'Xmodelinefoldtext', 'D')
   1562 
   1563  func Check_foldtext_in_modeline(set_cmd)
   1564    call writefile(['before'], 'Xmodelinefoldtext_write', 'D')
   1565    split Xmodelinefoldtext
   1566    call cursor(1, 1)
   1567    normal! zf3j
   1568    call assert_equal('folded text', foldtextresult(1))
   1569    call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
   1570 
   1571    split
   1572    call assert_equal('folded text', foldtextresult(1))
   1573    call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
   1574    close
   1575 
   1576    setglobal foldtext=ModelineFoldText()
   1577    call assert_equal('folded text', foldtextresult(1))
   1578    call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
   1579 
   1580    setglobal foldtext&
   1581    call assert_equal('folded text', foldtextresult(1))
   1582    call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
   1583 
   1584    exe a:set_cmd 'foldtext=ModelineFoldText()'
   1585    call assert_equal('folded text', foldtextresult(1))
   1586    call assert_equal(['after'], readfile('Xmodelinefoldtext_write'))
   1587 
   1588    call writefile(['before'], 'Xmodelinefoldtext_write')
   1589    exe 'sandbox' a:set_cmd 'foldtext=ModelineFoldText()'
   1590    call assert_equal('folded text', foldtextresult(1))
   1591    call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
   1592 
   1593    exe a:set_cmd 'foldtext=ModelineFoldText()'
   1594    call assert_equal('folded text', foldtextresult(1))
   1595    call assert_equal(['after'], readfile('Xmodelinefoldtext_write'))
   1596    bw!
   1597  endfunc
   1598 
   1599  set modeline modelineexpr
   1600  call Check_foldtext_in_modeline('setlocal')
   1601  call Check_foldtext_in_modeline('set')
   1602 
   1603  new Xa
   1604  sandbox setglobal foldenable foldtext=ModelineFoldText()
   1605  setlocal bufhidden=wipe
   1606  call writefile(['before'], 'Xmodelinefoldtext_write', 'D')
   1607  edit! Xb
   1608  call setline(1, ['func T()', '  let i = 1', 'endfunc']) | %fold
   1609  call assert_equal('folded text', foldtextresult(1))
   1610  call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
   1611  setglobal foldtext=ModelineFoldText()
   1612  call assert_equal('folded text', foldtextresult(1))
   1613  call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
   1614  setlocal foldtext=ModelineFoldText()
   1615  call assert_equal('folded text', foldtextresult(1))
   1616  call assert_equal(['after'], readfile('Xmodelinefoldtext_write'))
   1617  setlocal bufhidden=wipe
   1618  call writefile(['before'], 'Xmodelinefoldtext_write', 'D')
   1619  edit! Xc
   1620  call setline(1, ['func T()', '  let i = 1', 'endfunc']) | %fold
   1621  call assert_equal('folded text', foldtextresult(1))
   1622  call assert_equal(['after'], readfile('Xmodelinefoldtext_write'))
   1623  bwipe!
   1624 
   1625  set modeline& modelineexpr&
   1626  delfunc ModelineFoldText
   1627  delfunc Check_foldtext_in_modeline
   1628 endfunc
   1629 
   1630 " Test for setting 'foldexpr' from the modeline and executing the expression
   1631 " in a sandbox
   1632 func Test_foldexpr_in_modeline()
   1633  func ModelineFoldExpr()
   1634    call writefile(['after'], 'Xmodelinefoldexpr_write')
   1635    return strlen(matchstr(getline(v:lnum),'^\s*'))
   1636  endfunc
   1637  let lines =<< trim END
   1638    aaa
   1639     bbb
   1640      ccc
   1641      ccc
   1642     bbb
   1643    aaa
   1644    " vim: foldenable foldmethod=expr foldexpr=ModelineFoldExpr()
   1645  END
   1646  call writefile(lines, 'Xmodelinefoldexpr', 'D')
   1647 
   1648  func Check_foldexpr_in_modeline(set_cmd)
   1649    call writefile(['before'], 'Xmodelinefoldexpr_write', 'D')
   1650    split Xmodelinefoldexpr
   1651    call assert_equal(2, foldlevel(3))
   1652    call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
   1653 
   1654    split
   1655    call assert_equal(2, foldlevel(3))
   1656    call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
   1657    close
   1658 
   1659    setglobal foldexpr=ModelineFoldExpr()
   1660    call assert_equal(2, foldlevel(3))
   1661    call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
   1662 
   1663    setglobal foldexpr&
   1664    call assert_equal(2, foldlevel(3))
   1665    call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
   1666 
   1667    exe a:set_cmd 'foldexpr=ModelineFoldExpr()'
   1668    call assert_equal(2, foldlevel(3))
   1669    call assert_equal(['after'], readfile('Xmodelinefoldexpr_write'))
   1670 
   1671    call writefile(['before'], 'Xmodelinefoldexpr_write')
   1672    exe 'sandbox' a:set_cmd 'foldexpr=ModelineFoldExpr()'
   1673    call assert_equal(2, foldlevel(3))
   1674    call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
   1675 
   1676    exe a:set_cmd 'foldexpr=ModelineFoldExpr()'
   1677    call assert_equal(2, foldlevel(3))
   1678    call assert_equal(['after'], readfile('Xmodelinefoldexpr_write'))
   1679    bw!
   1680  endfunc
   1681 
   1682  set modeline modelineexpr
   1683  call Check_foldexpr_in_modeline('setlocal')
   1684  call Check_foldexpr_in_modeline('set')
   1685 
   1686  new Xa
   1687  sandbox setglobal foldenable foldmethod=expr foldexpr=ModelineFoldExpr()
   1688  setlocal bufhidden=wipe
   1689  call writefile(['before'], 'Xmodelinefoldexpr_write', 'D')
   1690  edit! Xb
   1691  call setline(1, lines[0:5])
   1692  call assert_equal(2, foldlevel(3))
   1693  call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
   1694  setglobal foldexpr=ModelineFoldExpr()
   1695  call assert_equal(2, foldlevel(3))
   1696  call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
   1697  setlocal foldexpr=ModelineFoldExpr()
   1698  call assert_equal(2, foldlevel(3))
   1699  call assert_equal(['after'], readfile('Xmodelinefoldexpr_write'))
   1700  setlocal bufhidden=wipe
   1701  call writefile(['before'], 'Xmodelinefoldexpr_write', 'D')
   1702  edit! Xc
   1703  call setline(1, lines[0:5])
   1704  call assert_equal(2, foldlevel(3))
   1705  call assert_equal(['after'], readfile('Xmodelinefoldexpr_write'))
   1706  bwipe!
   1707 
   1708  set modeline& modelineexpr&
   1709  delfunc ModelineFoldExpr
   1710  delfunc Check_foldexpr_in_modeline
   1711 endfunc
   1712 
   1713 " Make sure a fold containing a nested fold is split correctly when using
   1714 " foldmethod=indent
   1715 func Test_fold_split()
   1716  new
   1717  let lines =<< trim END
   1718    line 1
   1719      line 2
   1720      line 3
   1721        line 4
   1722        line 5
   1723  END
   1724  call setline(1, lines)
   1725  setlocal sw=2
   1726  setlocal foldmethod=indent foldenable
   1727  call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
   1728  call append(2, 'line 2.5')
   1729  call assert_equal([0, 1, 0, 1, 2, 2], range(1, 6)->map('foldlevel(v:val)'))
   1730  3d
   1731  call assert_equal([0, 1, 1, 2, 2], range(1, 5)->map('foldlevel(v:val)'))
   1732  bw!
   1733 endfunc
   1734 
   1735 " Make sure that when you append under a blank line that is under a fold with
   1736 " the same indent level as your appended line, the fold expands across the
   1737 " blank line
   1738 func Test_indent_append_under_blank_line()
   1739  new
   1740  let lines =<< trim END
   1741    line 1
   1742      line 2
   1743      line 3
   1744  END
   1745  call setline(1, lines)
   1746  setlocal sw=2
   1747  setlocal foldmethod=indent foldenable
   1748  call assert_equal([0, 1, 1], range(1, 3)->map('foldlevel(v:val)'))
   1749  call append(3, '')
   1750  call append(4, '  line 5')
   1751  call assert_equal([0, 1, 1, 1, 1], range(1, 5)->map('foldlevel(v:val)'))
   1752  bw!
   1753 endfunc
   1754 
   1755 " Make sure that when you delete 1 line of a fold whose length is 2 lines, the
   1756 " fold can't be closed since its length (1) is now less than foldminlines.
   1757 func Test_indent_one_line_fold_close()
   1758  let lines =<< trim END
   1759    line 1
   1760      line 2
   1761      line 3
   1762  END
   1763 
   1764  new
   1765  setlocal sw=2 foldmethod=indent
   1766  call setline(1, lines)
   1767  " open all folds, delete line, then close all folds
   1768  normal zR
   1769  3delete
   1770  normal zM
   1771  call assert_equal(-1, foldclosed(2)) " the fold should not be closed
   1772 
   1773  " Now do the same, but delete line 2 this time; this covers different code.
   1774  " (Combining this code with the above code doesn't expose both bugs.)
   1775  1,$delete
   1776  call setline(1, lines)
   1777  normal zR
   1778  2delete
   1779  normal zM
   1780  call assert_equal(-1, foldclosed(2))
   1781  bw!
   1782 endfunc
   1783 
   1784 " Make sure that when appending [an indented line then a blank line] right
   1785 " before a single indented line, the resulting extended fold can be closed
   1786 func Test_indent_append_blank_small_fold_close()
   1787  new
   1788  setlocal sw=2 foldmethod=indent
   1789  " at first, the fold at the second line can't be closed since it's smaller
   1790  " than foldminlines
   1791  let lines =<< trim END
   1792    line 1
   1793      line 4
   1794  END
   1795  call setline(1, lines)
   1796  call append(1, ['  line 2', ''])
   1797  " close all folds
   1798  normal zM
   1799  call assert_notequal(-1, foldclosed(2)) " the fold should be closed now
   1800  bw!
   1801 endfunc
   1802 
   1803 func Test_sort_closed_fold()
   1804  CheckExecutable sort
   1805 
   1806  call setline(1, [
   1807        \ 'Section 1',
   1808        \ '   how',
   1809        \ '   now',
   1810        \ '   brown',
   1811        \ '   cow',
   1812        \ 'Section 2',
   1813        \ '   how',
   1814        \ '   now',
   1815        \ '   brown',
   1816        \ '   cow',
   1817        \])
   1818  setlocal foldmethod=indent sw=3
   1819  normal 2G
   1820 
   1821  " The "!!" expands to ".,.+3" and must only sort four lines
   1822  call feedkeys("!!sort\<CR>", 'xt')
   1823  call assert_equal([
   1824        \ 'Section 1',
   1825        \ '   brown',
   1826        \ '   cow',
   1827        \ '   how',
   1828        \ '   now',
   1829        \ 'Section 2',
   1830        \ '   how',
   1831        \ '   now',
   1832        \ '   brown',
   1833        \ '   cow',
   1834        \ ], getline(1, 10))
   1835 
   1836  bwipe!
   1837 endfunc
   1838 
   1839 func Test_indent_with_L_command()
   1840  " The "L" command moved the cursor to line zero, causing the text saved for
   1841  " undo to use line number -1, which caused trouble for undo later.
   1842  new
   1843  sil! norm 8RV{zf8=Lu
   1844  bwipe!
   1845 endfunc
   1846 
   1847 " Make sure that when there is a fold at the bottom of the buffer and a newline
   1848 " character is appended to the line, the fold gets expanded (instead of the new
   1849 " line not being part of the fold).
   1850 func Test_expand_fold_at_bottom_of_buffer()
   1851  new
   1852  " create a fold on the only line
   1853  fold
   1854  execute "normal A\<CR>"
   1855  call assert_equal([1, 1], range(1, 2)->map('foldlevel(v:val)'))
   1856 
   1857  bwipe!
   1858 endfunc
   1859 
   1860 func Test_fold_screenrow_motion()
   1861  call setline(1, repeat(['aaaa'], 5))
   1862  1,4fold
   1863  norm Ggkzo
   1864  call assert_equal(1, line('.'))
   1865 endfunc
   1866 
   1867 " This was using freed memory
   1868 func Test_foldcolumn_linebreak_control_char()
   1869  CheckFeature linebreak
   1870 
   1871  5vnew
   1872  setlocal foldcolumn=1 linebreak
   1873  call setline(1, "aaa\<C-A>b")
   1874  redraw
   1875  call assert_equal([' aaa^', ' Ab  '], ScreenLines([1, 2], 5))
   1876  call assert_equal(screenattr(1, 5), screenattr(2, 2))
   1877 
   1878  bwipe!
   1879 endfunc
   1880 
   1881 " This used to cause invalid memory access
   1882 func Test_foldexpr_return_empty_string()
   1883  new
   1884  setlocal foldexpr='' foldmethod=expr
   1885  redraw
   1886 
   1887  bwipe!
   1888 endfunc
   1889 
   1890 " Make sure that when ending a fold that hasn't been started, it does not
   1891 " start a new fold.
   1892 func Test_foldexpr_end_fold()
   1893  new
   1894  setlocal foldmethod=expr
   1895  let &l:foldexpr = 'v:lnum == 2 ? "<2" : "="'
   1896  call setline(1, range(1, 3))
   1897  redraw
   1898  call assert_equal([0, 0, 0], range(1, 3)->map('foldlevel(v:val)'))
   1899 
   1900  bwipe!
   1901 endfunc
   1902 
   1903 " Test moving cursor down to or beyond start of folded end of buffer.
   1904 func Test_cursor_down_fold_eob()
   1905  call setline(1, range(1, 4))
   1906  norm Gzf2kj
   1907  call assert_equal(2, line('.'))
   1908  norm zojzc
   1909  call assert_equal(3, line('.'))
   1910  norm j
   1911  call assert_equal(3, line('.'))
   1912  norm k2j
   1913  call assert_equal(4, line('.'))
   1914  bwipe!
   1915 endfunc
   1916 
   1917 " issue: #15455
   1918 func Test_cursor_fold_marker_undo()
   1919  new
   1920  call setline(1, ['{{{', '', 'This is a Line', '', 'This is a Line', '', '}}}'])
   1921  let &ul=&ul
   1922  setl foldmethod=marker
   1923  call cursor(2, 1)
   1924  norm! zo1vjdu
   1925  call assert_equal(1, foldlevel('.'))
   1926  bwipe!
   1927  new
   1928  call setline(1, ['', '{{{', '', 'This is a Line', '', 'This is a Line', '', '}}}'])
   1929  let &ul=&ul
   1930  setl foldmethod=marker
   1931  call cursor(3, 1)
   1932  norm! zo
   1933  norm! vjdu
   1934  call assert_equal(1, foldlevel('.'))
   1935  bwipe!
   1936 endfunc
   1937 
   1938 " vim: shiftwidth=2 sts=2 expandtab