Files
neovim/src/nvim/testdir/test_fold.vim
Matthew Malcomson 3a9dd13f9e fold.c: more edge-cases when updating (#6207)
When foldUpdateIEMSRecurse() re-uses an existing fold, it misses the
case where the existing fold spans from before startlnum to after
firstlnum, the new fold does not span this range, and there is no
"forced start" of a fold. We add a case for this in.

Ensure that if there was no forced break in folds, we merge folds that
now touch each other.

Include testing for a tricky foldmethod=expr case that has never been a
bug. This case works at the moment because of some effects that are not
obvious when reading the code.
A test for this could be useful to ensure a regression doesn't happen.

vim-patch:8.0.0408
2017-03-31 01:21:26 +02:00

363 lines
11 KiB
VimL

" Test for folding
func! PrepIndent(arg)
return [a:arg] + repeat(["\t".a:arg], 5)
endfu
func! Test_address_fold()
new
call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
\ 'after fold 1', 'after fold 2', 'after fold 3'])
setl fen fdm=marker
" The next ccommands should all copy the same part of the buffer,
" regardless of the adressing type, since the part to be copied
" is folded away
:1y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
:.y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
:.+y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
:.,.y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
:sil .1,.y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
" use silent to make E493 go away
:sil .+,.y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
:,y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
:,+y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/','after fold 1'], getreg(0,1,1))
" using .+3 as second address should copy the whole folded line + the next 3
" lines
:.,+3y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/',
\ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1))
:sil .,-2y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
" now test again with folding disabled
set nofoldenable
:1y
call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
:.y
call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
:.+y
call assert_equal(['1'], getreg(0,1,1))
:.,.y
call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
" use silent to make E493 go away
:sil .1,.y
call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
" use silent to make E493 go away
:sil .+,.y
call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
:,y
call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
:,+y
call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
" using .+3 as second address should copy the whole folded line + the next 3
" lines
:.,+3y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1))
:7
:sil .,-2y
call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1))
quit!
endfunc
func! Test_indent_fold()
new
call setline(1, ['', 'a', ' b', ' c'])
setl fen fdm=indent
2
norm! >>
let a=map(range(1,4), 'foldclosed(v:val)')
call assert_equal([-1,-1,-1,-1], a)
endfunc
func! Test_indent_fold()
new
call setline(1, ['', 'a', ' b', ' c'])
setl fen fdm=indent
2
norm! >>
let a=map(range(1,4), 'foldclosed(v:val)')
call assert_equal([-1,-1,-1,-1], a)
bw!
endfunc
func! Test_indent_fold2()
new
call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
setl fen fdm=marker
2
norm! >>
let a=map(range(1,5), 'foldclosed(v:val)')
call assert_equal([-1,-1,-1,4,4], a)
bw!
endfunc
func Test_manual_fold_with_filter()
if !executable('cat')
return
endif
for type in ['manual', 'marker']
exe 'set foldmethod=' . type
new
call setline(1, range(1, 20))
4,$fold
%foldopen
10,$fold
%foldopen
" This filter command should not have an effect
1,8! cat
call feedkeys('5ggzdzMGdd', 'xt')
call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
bwipe!
set foldmethod&
endfor
endfunc
func! Test_indent_fold_with_read()
new
set foldmethod=indent
call setline(1, repeat(["\<Tab>a"], 4))
for n in range(1, 4)
call assert_equal(1, foldlevel(n))
endfor
call writefile(["a", "", "\<Tab>a"], 'Xfile')
foldopen
2read Xfile
%foldclose
call assert_equal(1, foldlevel(1))
call assert_equal(2, foldclosedend(1))
call assert_equal(0, foldlevel(3))
call assert_equal(0, foldlevel(4))
call assert_equal(1, foldlevel(5))
call assert_equal(7, foldclosedend(5))
bwipe!
set foldmethod&
call delete('Xfile')
endfunc
func Test_combining_folds_indent()
new
let one = "\<Tab>a"
let zero = 'a'
call setline(1, [one, one, zero, zero, zero, one, one, one])
set foldmethod=indent
3,5d
%foldclose
call assert_equal(5, foldclosedend(1))
set foldmethod&
bwipe!
endfunc
func Test_combining_folds_marker()
new
call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
set foldmethod=marker
3,5d
%foldclose
call assert_equal(2, foldclosedend(1))
set foldmethod&
bwipe!
endfunc
func Test_folds_marker_in_comment()
new
call setline(1, ['" foo', 'bar', 'baz'])
setl fen fdm=marker
setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
norm! zf2j
setl nofen
:1y
call assert_equal(['" foo{{{'], getreg(0,1,1))
:+2y
call assert_equal(['baz"}}}'], getreg(0,1,1))
set foldmethod&
bwipe!
endfunc
func s:TestFoldExpr(lnum)
let thisline = getline(a:lnum)
if thisline == 'a'
return 1
elseif thisline == 'b'
return 0
elseif thisline == 'c'
return '<1'
elseif thisline == 'd'
return '>1'
endif
return 0
endfunction
func Test_update_folds_expr_read()
new
call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
set foldmethod=expr
set foldexpr=s:TestFoldExpr(v:lnum)
2
foldopen
call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile')
read Xfile
%foldclose
call assert_equal(2, foldclosedend(1))
call assert_equal(0, foldlevel(3))
call assert_equal(0, foldlevel(4))
call assert_equal(6, foldclosedend(5))
call assert_equal(10, foldclosedend(7))
call assert_equal(14, foldclosedend(11))
call delete('Xfile')
bwipe!
set foldmethod& foldexpr&
endfunc
func! Test_move_folds_around_manual()
new
let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
" all folds closed
set foldenable foldlevel=0 fdm=indent
" needs a forced redraw
redraw!
set fdm=manual
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
call assert_equal(input, getline(1, '$'))
7,12m0
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
10,12m0
call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
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)'))
" moving should not close the folds
%d
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
set fdm=indent
redraw!
set fdm=manual
call cursor(2, 1)
%foldopen
7,12m0
let folds=repeat([-1], 18)
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
norm! zM
" folds are not corrupted and all have been closed
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)'))
%d
call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
set fdm=indent
redraw!
set fdm=manual
%foldopen
3m4
%foldclose
call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
%d
call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
set fdm=indent foldlevel=0
set fdm=manual
%foldopen
3m1
%foldclose
call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
call assert_equal(0, foldlevel(2))
call assert_equal(5, foldclosedend(3))
call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
2,6m$
%foldclose
call assert_equal(5, foldclosedend(2))
call assert_equal(0, foldlevel(6))
call assert_equal(9, foldclosedend(7))
call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
%d
" Ensure moving around the edges still works.
call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
set fdm=indent foldlevel=0
set fdm=manual
%foldopen
6m$
" The first fold has been truncated to the 5'th line.
" Second fold has been moved up because the moved line is now below it.
call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 0], map(range(1, line('$')), 'foldlevel(v:val)'))
bw!
endfunc
func! Test_move_folds_around_indent()
new
let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
" all folds closed
set fdm=indent
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
call assert_equal(input, getline(1, '$'))
7,12m0
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
10,12m0
call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
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)'))
" moving should not close the folds
%d
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
set fdm=indent
call cursor(2, 1)
%foldopen
7,12m0
let folds=repeat([-1], 18)
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
norm! zM
" folds are not corrupted and all have been closed
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)'))
%d
call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
set fdm=indent
%foldopen
3m4
%foldclose
call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
%d
call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
set fdm=indent foldlevel=0
%foldopen
3m1
%foldclose
call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
call assert_equal(1, foldlevel(2))
call assert_equal(5, foldclosedend(3))
call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
2,6m$
%foldclose
call assert_equal(9, foldclosedend(2))
call assert_equal(1, foldlevel(6))
call assert_equal(9, foldclosedend(7))
call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
" Ensure moving around the edges still works.
%d
call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
set fdm=indent foldlevel=0
%foldopen
6m$
" The first fold has been truncated to the 5'th line.
" Second fold has been moved up because the moved line is now below it.
call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 1], map(range(1, line('$')), 'foldlevel(v:val)'))
bw!
endfunc