Skip to content

Commit eadbc2b

Browse files
committed
patch 8.0.0408: updating folds does not always work properly
Problem: Updating folds does not work properly when inserting a file and a few other situations. Solution: Adjust the way folds are updated. (Matthew Malcomson)
1 parent 3f3897e commit eadbc2b

File tree

3 files changed

+142
-10
lines changed

3 files changed

+142
-10
lines changed

src/fold.c

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2505,7 +2505,11 @@ foldUpdateIEMSRecurse(
25052505
* before where we started looking, extend it. If it
25062506
* starts at another line, update nested folds to keep
25072507
* their position, compensating for the new fd_top. */
2508-
if (fp->fd_top >= startlnum && fp->fd_top != firstlnum)
2508+
if (fp->fd_top == firstlnum)
2509+
{
2510+
/* have found a fold beginning where we want */
2511+
}
2512+
else if (fp->fd_top >= startlnum)
25092513
{
25102514
if (fp->fd_top > firstlnum)
25112515
/* like lines are inserted */
@@ -2523,18 +2527,44 @@ foldUpdateIEMSRecurse(
25232527
fp->fd_top = firstlnum;
25242528
fold_changed = TRUE;
25252529
}
2526-
else if (flp->start != 0 && lvl == level
2527-
&& fp->fd_top != firstlnum)
2530+
else if ((flp->start != 0 && lvl == level)
2531+
|| firstlnum != startlnum)
25282532
{
2529-
/* Existing fold that includes startlnum must stop
2530-
* if we find the start of a new fold at the same
2531-
* level. Split it. Delete contained folds at
2532-
* this point to split them too. */
2533-
foldRemove(&fp->fd_nested, flp->lnum - fp->fd_top,
2534-
flp->lnum - fp->fd_top);
2533+
linenr_T breakstart;
2534+
linenr_T breakend;
2535+
2536+
/*
2537+
* Before there was a fold spanning from above
2538+
* startlnum to below firstlnum. This fold is valid
2539+
* above startlnum (because we are not updating
2540+
* that range), but there should now be a break in
2541+
* it.
2542+
* If the break is because we are now forced to
2543+
* start a new fold at the level "level" at line
2544+
* fline->lnum, then we need to split the fold at
2545+
* fline->lnum.
2546+
* If the break is because the range
2547+
* [startlnum, firstlnum) is now at a lower indent
2548+
* than "level", we need to split the fold in this
2549+
* range.
2550+
* Any splits have to be done recursively.
2551+
*/
2552+
if (firstlnum != startlnum)
2553+
{
2554+
breakstart = startlnum;
2555+
breakend = firstlnum;
2556+
}
2557+
else
2558+
{
2559+
breakstart = flp->lnum;
2560+
breakend = flp->lnum;
2561+
}
2562+
foldRemove(&fp->fd_nested, breakstart - fp->fd_top,
2563+
breakend - fp->fd_top);
25352564
i = (int)(fp - (fold_T *)gap->ga_data);
2536-
foldSplit(gap, i, flp->lnum, flp->lnum - 1);
2565+
foldSplit(gap, i, breakstart, breakend - 1);
25372566
fp = (fold_T *)gap->ga_data + i + 1;
2567+
25382568
/* If using the "marker" or "syntax" method, we
25392569
* need to continue until the end of the fold is
25402570
* found. */
@@ -2543,6 +2573,20 @@ foldUpdateIEMSRecurse(
25432573
|| getlevel == foldlevelSyntax)
25442574
finish = TRUE;
25452575
}
2576+
2577+
if (fp->fd_top == startlnum && concat)
2578+
{
2579+
i = (int)(fp - (fold_T *)gap->ga_data);
2580+
if (i != 0)
2581+
{
2582+
fp2 = fp - 1;
2583+
if (fp2->fd_top + fp2->fd_len == fp->fd_top)
2584+
{
2585+
foldMerge(fp2, gap, fp);
2586+
fp = fp2;
2587+
}
2588+
}
2589+
}
25462590
break;
25472591
}
25482592
if (fp->fd_top >= startlnum)

src/testdir/test_fold.vim

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,89 @@ func Test_manual_fold_with_filter()
117117
set foldmethod&
118118
endfor
119119
endfunc
120+
121+
func! Test_indent_fold_with_read()
122+
new
123+
set foldmethod=indent
124+
call setline(1, repeat(["\<Tab>a"], 4))
125+
for n in range(1, 4)
126+
call assert_equal(1, foldlevel(n))
127+
endfor
128+
129+
call writefile(["a", "", "\<Tab>a"], 'Xfile')
130+
foldopen
131+
2read Xfile
132+
%foldclose
133+
call assert_equal(1, foldlevel(1))
134+
call assert_equal(2, foldclosedend(1))
135+
call assert_equal(0, foldlevel(3))
136+
call assert_equal(0, foldlevel(4))
137+
call assert_equal(1, foldlevel(5))
138+
call assert_equal(7, foldclosedend(5))
139+
140+
bwipe!
141+
set foldmethod&
142+
call delete('Xfile')
143+
endfunc
144+
145+
func Test_combining_folds_indent()
146+
new
147+
let one = "\<Tab>a"
148+
let zero = 'a'
149+
call setline(1, [one, one, zero, zero, zero, one, one, one])
150+
set foldmethod=indent
151+
3,5d
152+
%foldclose
153+
call assert_equal(5, foldclosedend(1))
154+
155+
set foldmethod&
156+
bwipe!
157+
endfunc
158+
159+
func Test_combining_folds_marker()
160+
new
161+
call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
162+
set foldmethod=marker
163+
3,5d
164+
%foldclose
165+
call assert_equal(2, foldclosedend(1))
166+
167+
set foldmethod&
168+
bwipe!
169+
endfunc
170+
171+
func s:TestFoldExpr(lnum)
172+
let thisline = getline(a:lnum)
173+
if thisline == 'a'
174+
return 1
175+
elseif thisline == 'b'
176+
return 0
177+
elseif thisline == 'c'
178+
return '<1'
179+
elseif thisline == 'd'
180+
return '>1'
181+
endif
182+
return 0
183+
endfunction
184+
185+
func Test_update_folds_expr_read()
186+
new
187+
call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
188+
set foldmethod=expr
189+
set foldexpr=s:TestFoldExpr(v:lnum)
190+
2
191+
foldopen
192+
call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile')
193+
read Xfile
194+
%foldclose
195+
call assert_equal(2, foldclosedend(1))
196+
call assert_equal(0, foldlevel(3))
197+
call assert_equal(0, foldlevel(4))
198+
call assert_equal(6, foldclosedend(5))
199+
call assert_equal(10, foldclosedend(7))
200+
call assert_equal(14, foldclosedend(11))
201+
202+
call delete('Xfile')
203+
bwipe!
204+
set foldmethod& foldexpr&
205+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,8 @@ static char *(features[]) =
764764

765765
static int included_patches[] =
766766
{ /* Add new patch number below this line */
767+
/**/
768+
408,
767769
/**/
768770
407,
769771
/**/

0 commit comments

Comments
 (0)