# HG changeset patch # User Christian Brabandt # Date 1489676405 -3600 # Node ID 80241603dd5085e1faa212ca90bea51101daba0b # Parent f32a834a52dec598585188ae54fb7ec22ccef9dc patch 8.0.0465: off-by-one error in using :move with folding commit https://github.com/vim/vim/commit/40ebc0afda8d8e478d2090133ed6a3cd3d8da3ec Author: Bram Moolenaar Date: Thu Mar 16 15:59:14 2017 +0100 patch 8.0.0465: off-by-one error in using :move with folding Problem: Off-by-one error in using :move with folding. Solution: Correct off-by-one mistakes and add more tests. (Matthew Malcomson) diff --git a/src/fold.c b/src/fold.c --- a/src/fold.c +++ b/src/fold.c @@ -3021,8 +3021,9 @@ foldReverseOrder(garray_T *gap, linenr_T static void truncate_fold(fold_T *fp, linenr_T end) { + end += 1; foldRemove(&fp->fd_nested, end - fp->fd_top, MAXLNUM); - fp->fd_len = end - fp->fd_top + 1; + fp->fd_len = end - fp->fd_top; } #define fold_end(fp) ((fp)->fd_top + (fp)->fd_len - 1) @@ -3062,7 +3063,7 @@ foldMoveRange(garray_T *gap, linenr_T li } else /* Case 2 truncate fold, folds after this one must be dealt with. */ - truncate_fold(fp, line1); + truncate_fold(fp, line1 - 1); /* Look at the next fold, and treat that one as if it were the first * after "line1" (because now it is). */ @@ -3078,11 +3079,11 @@ foldMoveRange(garray_T *gap, linenr_T li } else if (fp->fd_top > line2) { - for (; valid_fold(fp, gap) && fold_end(fp) < dest; fp++) + for (; valid_fold(fp, gap) && fold_end(fp) <= dest; fp++) /* Case 9. (for all case 9's) -- shift up. */ fp->fd_top -= range_len; - if (valid_fold(fp, gap) && fp->fd_top < dest) + if (valid_fold(fp, gap) && fp->fd_top <= dest) { /* Case 8. -- ensure truncated at dest, shift up */ truncate_fold(fp, dest); diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim --- a/src/testdir/test_fold.vim +++ b/src/testdir/test_fold.vim @@ -249,7 +249,7 @@ func! Test_move_folds_around_manual() redraw! set fdm=manual call cursor(2, 1) - norm! zR + %foldopen 7,12m0 let folds=repeat([-1], 18) call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) @@ -284,6 +284,16 @@ func! Test_move_folds_around_manual() 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 @@ -307,7 +317,7 @@ func! Test_move_folds_around_indent() call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) set fdm=indent call cursor(2, 1) - norm! zR + %foldopen 7,12m0 let folds=repeat([-1], 18) call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) @@ -339,5 +349,14 @@ func! Test_move_folds_around_indent() 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 diff --git a/src/version.c b/src/version.c --- 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 */ /**/ + 465, +/**/ 464, /**/ 463,