mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
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)
This commit is contained in:
@@ -3021,8 +3021,9 @@ foldReverseOrder(garray_T *gap, linenr_T start, linenr_T end)
|
|||||||
static void
|
static void
|
||||||
truncate_fold(fold_T *fp, linenr_T end)
|
truncate_fold(fold_T *fp, linenr_T end)
|
||||||
{
|
{
|
||||||
|
end += 1;
|
||||||
foldRemove(&fp->fd_nested, end - fp->fd_top, MAXLNUM);
|
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)
|
#define fold_end(fp) ((fp)->fd_top + (fp)->fd_len - 1)
|
||||||
@@ -3062,7 +3063,7 @@ foldMoveRange(garray_T *gap, linenr_T line1, linenr_T line2, linenr_T dest)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Case 2 truncate fold, folds after this one must be dealt with. */
|
/* 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
|
/* Look at the next fold, and treat that one as if it were the first
|
||||||
* after "line1" (because now it is). */
|
* after "line1" (because now it is). */
|
||||||
@@ -3078,11 +3079,11 @@ foldMoveRange(garray_T *gap, linenr_T line1, linenr_T line2, linenr_T dest)
|
|||||||
}
|
}
|
||||||
else if (fp->fd_top > line2)
|
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. */
|
/* Case 9. (for all case 9's) -- shift up. */
|
||||||
fp->fd_top -= range_len;
|
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 */
|
/* Case 8. -- ensure truncated at dest, shift up */
|
||||||
truncate_fold(fp, dest);
|
truncate_fold(fp, dest);
|
||||||
|
@@ -249,7 +249,7 @@ func! Test_move_folds_around_manual()
|
|||||||
redraw!
|
redraw!
|
||||||
set fdm=manual
|
set fdm=manual
|
||||||
call cursor(2, 1)
|
call cursor(2, 1)
|
||||||
norm! zR
|
%foldopen
|
||||||
7,12m0
|
7,12m0
|
||||||
let folds=repeat([-1], 18)
|
let folds=repeat([-1], 18)
|
||||||
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
|
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(0, foldlevel(6))
|
||||||
call assert_equal(9, foldclosedend(7))
|
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)'))
|
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!
|
bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -307,7 +317,7 @@ func! Test_move_folds_around_indent()
|
|||||||
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
|
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
|
||||||
set fdm=indent
|
set fdm=indent
|
||||||
call cursor(2, 1)
|
call cursor(2, 1)
|
||||||
norm! zR
|
%foldopen
|
||||||
7,12m0
|
7,12m0
|
||||||
let folds=repeat([-1], 18)
|
let folds=repeat([-1], 18)
|
||||||
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
|
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(1, foldlevel(6))
|
||||||
call assert_equal(9, foldclosedend(7))
|
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)'))
|
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!
|
bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
@@ -764,6 +764,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
465,
|
||||||
/**/
|
/**/
|
||||||
464,
|
464,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user