diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-03-04 18:42:39 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-03-04 18:42:39 +0100 |
commit | eadbc2b46176e2aff2cde5f3874b734ae2ae082a (patch) | |
tree | 414d4842c93423c098ce04467c8b3aa4b7f7e511 /src | |
parent | 3f3897e41f77a7bcd44ffd37acd4d524c0169ed4 (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.c | 64 | ||||
-rw-r--r-- | src/testdir/test_fold.vim | 86 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |