summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-03-04 18:42:39 +0100
committerBram Moolenaar <Bram@vim.org>2017-03-04 18:42:39 +0100
commiteadbc2b46176e2aff2cde5f3874b734ae2ae082a (patch)
tree414d4842c93423c098ce04467c8b3aa4b7f7e511 /src
parent3f3897e41f77a7bcd44ffd37acd4d524c0169ed4 (diff)
patch 8.0.0408: updating folds does not always work properlyv8.0.0408
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)
Diffstat (limited to 'src')
-rw-r--r--src/fold.c64
-rw-r--r--src/testdir/test_fold.vim86
-rw-r--r--src/version.c2
3 files changed, 142 insertions, 10 deletions
diff --git a/src/fold.c b/src/fold.c
index cba1375159..d75e937003 100644
--- a/src/fold.c
+++ b/src/fold.c
@@ -2505,7 +2505,11 @@ foldUpdateIEMSRecurse(
* before where we started looking, extend it. If it
* starts at another line, update nested folds to keep
* their position, compensating for the new fd_top. */
- if (fp->fd_top >= startlnum && fp->fd_top != firstlnum)
+ if (fp->fd_top == firstlnum)
+ {
+ /* have found a fold beginning where we want */
+ }
+ else if (fp->fd_top >= startlnum)
{
if (fp->fd_top > firstlnum)
/* like lines are inserted */
@@ -2523,18 +2527,44 @@ foldUpdateIEMSRecurse(
fp->fd_top = firstlnum;
fold_changed = TRUE;
}
- else if (flp->start != 0 && lvl == level
- && fp->fd_top != firstlnum)
+ else if ((flp->start != 0 && lvl == level)
+ || firstlnum != startlnum)
{
- /* Existing fold that includes startlnum must stop
- * if we find the start of a new fold at the same
- * level. Split it. Delete contained folds at
- * this point to split them too. */
- foldRemove(&fp->fd_nested, flp->lnum - fp->fd_top,
- flp->lnum - fp->fd_top);
+ linenr_T breakstart;
+ linenr_T breakend;
+
+ /*
+ * Before there was a fold spanning from above
+ * startlnum to below firstlnum. This fold is valid
+ * above startlnum (because we are not updating
+ * that range), but there should now be a break in
+ * it.
+ * If the break is because we are now forced to
+ * start a new fold at the level "level" at line
+ * fline->lnum, then we need to split the fold at
+ * fline->lnum.
+ * If the break is because the range
+ * [startlnum, firstlnum) is now at a lower indent
+ * than "level", we need to split the fold in this
+ * range.
+ * Any splits have to be done recursively.
+ */
+ if (firstlnum != startlnum)
+ {
+ breakstart = startlnum;
+ breakend = firstlnum;
+ }
+ else
+ {
+ breakstart = flp->lnum;
+ breakend = flp->lnum;
+ }
+ foldRemove(&fp->fd_nested, breakstart - fp->fd_top,
+ breakend - fp->fd_top);
i = (int)(fp - (fold_T *)gap->ga_data);
- foldSplit(gap, i, flp->lnum, flp->lnum - 1);
+ foldSplit(gap, i, breakstart, breakend - 1);
fp = (fold_T *)gap->ga_data + i + 1;
+
/* If using the "marker" or "syntax" method, we
* need to continue until the end of the fold is
* found. */
@@ -2543,6 +2573,20 @@ foldUpdateIEMSRecurse(
|| getlevel == foldlevelSyntax)
finish = TRUE;
}
+
+ if (fp->fd_top == startlnum && concat)
+ {
+ i = (int)(fp - (fold_T *)gap->ga_data);
+ if (i != 0)
+ {
+ fp2 = fp - 1;
+ if (fp2->fd_top + fp2->fd_len == fp->fd_top)
+ {
+ foldMerge(fp2, gap, fp);
+ fp = fp2;
+ }
+ }
+ }
break;
}
if (fp->fd_top >= startlnum)
diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim
index cdf9fd3142..3c27f4f700 100644
--- a/src/testdir/test_fold.vim
+++ b/src/testdir/test_fold.vim
@@ -117,3 +117,89 @@ func Test_manual_fold_with_filter()
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 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
diff --git a/src/version.c b/src/version.c
index 39c6b4e41a..9b350e7243 100644
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 408,
+/**/
407,
/**/
406,