mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.0.0457: using :move messes up manual folds
Problem: Using :move messes up manual folds. Solution: Split adjusting marks and folds. Add foldMoveRange(). (neovim patch #6221)
This commit is contained in:
@@ -800,6 +800,8 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest)
|
|||||||
linenr_T last_line; /* Last line in file after adding new text */
|
linenr_T last_line; /* Last line in file after adding new text */
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
int isFolded;
|
int isFolded;
|
||||||
|
win_T *win;
|
||||||
|
tabpage_T *tp;
|
||||||
|
|
||||||
/* Moving lines seems to corrupt the folds, delete folding info now
|
/* Moving lines seems to corrupt the folds, delete folding info now
|
||||||
* and recreate it when finished. Don't do this for manual folding, it
|
* and recreate it when finished. Don't do this for manual folding, it
|
||||||
@@ -851,24 +853,34 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest)
|
|||||||
* their final destination at the new text position -- webb
|
* their final destination at the new text position -- webb
|
||||||
*/
|
*/
|
||||||
last_line = curbuf->b_ml.ml_line_count;
|
last_line = curbuf->b_ml.ml_line_count;
|
||||||
mark_adjust(line1, line2, last_line - line2, 0L);
|
mark_adjust_nofold(line1, line2, last_line - line2, 0L);
|
||||||
changed_lines(last_line - num_lines + 1, 0, last_line + 1, num_lines);
|
|
||||||
if (dest >= line2)
|
if (dest >= line2)
|
||||||
{
|
{
|
||||||
mark_adjust(line2 + 1, dest, -num_lines, 0L);
|
mark_adjust_nofold(line2 + 1, dest, -num_lines, 0L);
|
||||||
|
#ifdef FEAT_FOLDING
|
||||||
|
FOR_ALL_TAB_WINDOWS(tp, win) {
|
||||||
|
if (win->w_buffer == curbuf)
|
||||||
|
foldMoveRange(&win->w_folds, line1, line2, dest);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
curbuf->b_op_start.lnum = dest - num_lines + 1;
|
curbuf->b_op_start.lnum = dest - num_lines + 1;
|
||||||
curbuf->b_op_end.lnum = dest;
|
curbuf->b_op_end.lnum = dest;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mark_adjust(dest + 1, line1 - 1, num_lines, 0L);
|
mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0L);
|
||||||
|
#ifdef FEAT_FOLDING
|
||||||
|
FOR_ALL_TAB_WINDOWS(tp, win) {
|
||||||
|
if (win->w_buffer == curbuf)
|
||||||
|
foldMoveRange(&win->w_folds, dest + 1, line1 - 1, line2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
curbuf->b_op_start.lnum = dest + 1;
|
curbuf->b_op_start.lnum = dest + 1;
|
||||||
curbuf->b_op_end.lnum = dest + num_lines;
|
curbuf->b_op_end.lnum = dest + num_lines;
|
||||||
}
|
}
|
||||||
curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
|
curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
|
||||||
mark_adjust(last_line - num_lines + 1, last_line,
|
mark_adjust_nofold(last_line - num_lines + 1, last_line,
|
||||||
-(last_line - dest - extra), 0L);
|
-(last_line - dest - extra), 0L);
|
||||||
changed_lines(last_line - num_lines + 1, 0, last_line + 1, -extra);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we delete the original text -- webb
|
* Now we delete the original text -- webb
|
||||||
@@ -907,9 +919,9 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest)
|
|||||||
changed_lines(dest + 1, 0, line1 + num_lines, 0L);
|
changed_lines(dest + 1, 0, line1 + num_lines, 0L);
|
||||||
|
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
/* recreate folds */
|
/* recreate folds */
|
||||||
if (isFolded)
|
if (isFolded)
|
||||||
foldUpdateAll(curwin);
|
foldUpdateAll(curwin);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
183
src/fold.c
183
src/fold.c
@@ -64,6 +64,7 @@ static void deleteFoldMarkers(fold_T *fp, int recursive, linenr_T lnum_off);
|
|||||||
static void foldDelMarker(linenr_T lnum, char_u *marker, int markerlen);
|
static void foldDelMarker(linenr_T lnum, char_u *marker, int markerlen);
|
||||||
static void foldUpdateIEMS(win_T *wp, linenr_T top, linenr_T bot);
|
static void foldUpdateIEMS(win_T *wp, linenr_T top, linenr_T bot);
|
||||||
static void parseMarker(win_T *wp);
|
static void parseMarker(win_T *wp);
|
||||||
|
static void foldMoveRange_int(garray_T *gap, linenr_T line1, linenr_T line2, linenr_T dest);
|
||||||
|
|
||||||
static char *e_nofold = N_("E490: No fold found");
|
static char *e_nofold = N_("E490: No fold found");
|
||||||
|
|
||||||
@@ -1075,6 +1076,12 @@ foldAdjustCursor(void)
|
|||||||
(void)hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL);
|
(void)hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* foldMoveRange() {{{2 */
|
||||||
|
void
|
||||||
|
foldMoveRange(garray_T *gap, linenr_T line1, linenr_T line2, linenr_T dest)
|
||||||
|
{
|
||||||
|
foldMoveRange_int(gap, line1, line2, dest);
|
||||||
|
}
|
||||||
/* Internal functions for "fold_T" {{{1 */
|
/* Internal functions for "fold_T" {{{1 */
|
||||||
/* cloneFoldGrowArray() {{{2 */
|
/* cloneFoldGrowArray() {{{2 */
|
||||||
/*
|
/*
|
||||||
@@ -2968,6 +2975,182 @@ foldRemove(garray_T *gap, linenr_T top, linenr_T bot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* foldReverseOrder() {{{2 */
|
||||||
|
static void
|
||||||
|
foldReverseOrder(garray_T *gap, linenr_T start, linenr_T end)
|
||||||
|
{
|
||||||
|
fold_T *left, *right;
|
||||||
|
fold_T tmp;
|
||||||
|
|
||||||
|
for (; start < end; start++, end--)
|
||||||
|
{
|
||||||
|
left = (fold_T *)gap->ga_data + start;
|
||||||
|
right = (fold_T *)gap->ga_data + end;
|
||||||
|
tmp = *left;
|
||||||
|
*left = *right;
|
||||||
|
*right = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* foldMoveRange_int() {{{2 */
|
||||||
|
/*
|
||||||
|
* Move folds within the inclusive range "line1" to "line2" to after "dest"
|
||||||
|
* requires "line1" <= "line2" <= "dest"
|
||||||
|
*
|
||||||
|
* There are the following situations for the first fold at or below line1 - 1.
|
||||||
|
* 1 2 3 4
|
||||||
|
* 1 2 3 4
|
||||||
|
* line1 2 3 4
|
||||||
|
* 2 3 4 5 6 7
|
||||||
|
* line2 3 4 5 6 7
|
||||||
|
* 3 4 6 7 8 9
|
||||||
|
* dest 4 7 8 9
|
||||||
|
* 4 7 8 10
|
||||||
|
* 4 7 8 10
|
||||||
|
*
|
||||||
|
* In the following descriptions, "moved" means moving in the buffer, *and* in
|
||||||
|
* the fold array.
|
||||||
|
* Meanwhile, "shifted" just means moving in the buffer.
|
||||||
|
* 1. not changed
|
||||||
|
* 2. truncated above line1
|
||||||
|
* 3. length reduced by line2 - line1, folds starting between the end of 3 and
|
||||||
|
* dest are truncated and shifted up
|
||||||
|
* 4. internal folds moved (from [line1, line2] to dest)
|
||||||
|
* 5. moved to dest.
|
||||||
|
* 6. truncated below line2 and moved.
|
||||||
|
* 7. length reduced by line2 - dest, folds starting between line2 and dest are
|
||||||
|
* removed, top is moved down by move_len.
|
||||||
|
* 8. truncated below dest and shifted up.
|
||||||
|
* 9. shifted up
|
||||||
|
* 10. not changed
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
truncate_fold(fold_T *fp, linenr_T end)
|
||||||
|
{
|
||||||
|
foldRemove(&fp->fd_nested, end - fp->fd_top, MAXLNUM);
|
||||||
|
fp->fd_len = end - fp->fd_top + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define fold_end(fp) ((fp)->fd_top + (fp)->fd_len - 1)
|
||||||
|
#define valid_fold(fp, gap) ((fp) < ((fold_T *)(gap)->ga_data + (gap)->ga_len))
|
||||||
|
#define fold_index(fp, gap) ((size_t)(fp - ((fold_T *)(gap)->ga_data)))
|
||||||
|
|
||||||
|
static void
|
||||||
|
foldMoveRange_int(garray_T *gap, linenr_T line1, linenr_T line2, linenr_T dest)
|
||||||
|
{
|
||||||
|
fold_T *fp;
|
||||||
|
linenr_T range_len = line2 - line1 + 1;
|
||||||
|
linenr_T move_len = dest - line2;
|
||||||
|
int at_start = foldFind(gap, line1 - 1, &fp);
|
||||||
|
size_t move_start = 0, move_end = 0, dest_index = 0;
|
||||||
|
|
||||||
|
if (at_start)
|
||||||
|
{
|
||||||
|
if (fold_end(fp) > dest)
|
||||||
|
{
|
||||||
|
/* Case 4
|
||||||
|
* don't have to change this fold, but have to move nested folds.
|
||||||
|
*/
|
||||||
|
foldMoveRange(&fp->fd_nested, line1 - fp->fd_top, line2 -
|
||||||
|
fp->fd_top, dest - fp->fd_top);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (fold_end(fp) > line2)
|
||||||
|
{
|
||||||
|
/* Case 3
|
||||||
|
* Remove nested folds between line1 and line2 & reduce the
|
||||||
|
* length of fold by "range_len".
|
||||||
|
* Folds after this one must be dealt with.
|
||||||
|
*/
|
||||||
|
foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, line2 -
|
||||||
|
fp->fd_top, MAXLNUM, -range_len);
|
||||||
|
fp->fd_len -= range_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Case 2 truncate fold, folds after this one must be dealt with. */
|
||||||
|
truncate_fold(fp, line1);
|
||||||
|
|
||||||
|
/* Look at the next fold, and treat that one as if it were the first
|
||||||
|
* after "line1" (because now it is). */
|
||||||
|
fp = fp + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid_fold(fp, gap) || fp->fd_top > dest)
|
||||||
|
{
|
||||||
|
/* Case 10
|
||||||
|
* No folds after "line1" and before "dest"
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (fp->fd_top > line2)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* Case 8. -- ensure truncated at dest, shift up */
|
||||||
|
truncate_fold(fp, dest);
|
||||||
|
fp->fd_top -= range_len;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (fold_end(fp) > dest)
|
||||||
|
{
|
||||||
|
/* Case 7 -- remove nested folds and shrink */
|
||||||
|
foldMarkAdjustRecurse(&fp->fd_nested, line2 + 1 - fp->fd_top, dest -
|
||||||
|
fp->fd_top, MAXLNUM, -move_len);
|
||||||
|
fp->fd_len -= move_len;
|
||||||
|
fp->fd_top += move_len;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case 5 or 6
|
||||||
|
* changes rely on whether there are folds between the end of
|
||||||
|
* this fold and "dest".
|
||||||
|
*/
|
||||||
|
move_start = fold_index(fp, gap);
|
||||||
|
|
||||||
|
for (; valid_fold(fp, gap) && fp->fd_top <= dest; fp++)
|
||||||
|
{
|
||||||
|
if (fp->fd_top <= line2)
|
||||||
|
{
|
||||||
|
/* 1. 2. or 3. */
|
||||||
|
if (fold_end(fp) > line2)
|
||||||
|
/* 2. or 3., truncate before moving */
|
||||||
|
truncate_fold(fp, line2);
|
||||||
|
|
||||||
|
fp->fd_top += move_len;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record index of the first fold after the moved range. */
|
||||||
|
if (move_end == 0)
|
||||||
|
move_end = fold_index(fp, gap);
|
||||||
|
|
||||||
|
if (fold_end(fp) > dest)
|
||||||
|
truncate_fold(fp, dest);
|
||||||
|
|
||||||
|
fp->fd_top -= range_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest_index = fold_index(fp, gap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All folds are now correct, but they are not necessarily in the correct
|
||||||
|
* order. We have to swap folds in the range [move_end, dest_index) with
|
||||||
|
* those in the range [move_start, move_end).
|
||||||
|
*/
|
||||||
|
foldReverseOrder(gap, move_start, dest_index - 1);
|
||||||
|
foldReverseOrder(gap, move_start, move_start + dest_index - move_end - 1);
|
||||||
|
foldReverseOrder(gap, move_start + dest_index - move_end, dest_index - 1);
|
||||||
|
}
|
||||||
|
#undef fold_end
|
||||||
|
#undef valid_fold
|
||||||
|
#undef fold_index
|
||||||
|
|
||||||
/* foldMerge() {{{2 */
|
/* foldMerge() {{{2 */
|
||||||
/*
|
/*
|
||||||
* Merge two adjacent folds (and the nested ones in them).
|
* Merge two adjacent folds (and the nested ones in them).
|
||||||
|
26
src/mark.c
26
src/mark.c
@@ -37,6 +37,8 @@ static void cleanup_jumplist(void);
|
|||||||
#ifdef FEAT_VIMINFO
|
#ifdef FEAT_VIMINFO
|
||||||
static void write_one_filemark(FILE *fp, xfmark_T *fm, int c1, int c2);
|
static void write_one_filemark(FILE *fp, xfmark_T *fm, int c1, int c2);
|
||||||
#endif
|
#endif
|
||||||
|
static void mark_adjust_internal(linenr_T line1, linenr_T line2, long amount,
|
||||||
|
long amount_after, int adjust_folds);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set named mark "c" at current cursor position.
|
* Set named mark "c" at current cursor position.
|
||||||
@@ -1028,6 +1030,27 @@ mark_adjust(
|
|||||||
linenr_T line2,
|
linenr_T line2,
|
||||||
long amount,
|
long amount,
|
||||||
long amount_after)
|
long amount_after)
|
||||||
|
{
|
||||||
|
mark_adjust_internal(line1, line2, amount, amount_after, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mark_adjust_nofold(
|
||||||
|
linenr_T line1,
|
||||||
|
linenr_T line2,
|
||||||
|
long amount,
|
||||||
|
long amount_after)
|
||||||
|
{
|
||||||
|
mark_adjust_internal(line1, line2, amount, amount_after, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mark_adjust_internal(
|
||||||
|
linenr_T line1,
|
||||||
|
linenr_T line2,
|
||||||
|
long amount,
|
||||||
|
long amount_after,
|
||||||
|
int adjust_folds UNUSED)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int fnum = curbuf->b_fnum;
|
int fnum = curbuf->b_fnum;
|
||||||
@@ -1174,7 +1197,8 @@ mark_adjust(
|
|||||||
|
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
/* adjust folds */
|
/* adjust folds */
|
||||||
foldMarkAdjust(win, line1, line2, amount, amount_after);
|
if (adjust_folds)
|
||||||
|
foldMarkAdjust(win, line1, line2, amount, amount_after);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,7 @@ void foldInitWin(win_T *new_win);
|
|||||||
int find_wl_entry(win_T *win, linenr_T lnum);
|
int find_wl_entry(win_T *win, linenr_T lnum);
|
||||||
void foldAdjustVisual(void);
|
void foldAdjustVisual(void);
|
||||||
void foldAdjustCursor(void);
|
void foldAdjustCursor(void);
|
||||||
|
void foldMoveRange(garray_T *gap, linenr_T line1, linenr_T line2, linenr_T dest);
|
||||||
void cloneFoldGrowArray(garray_T *from, garray_T *to);
|
void cloneFoldGrowArray(garray_T *from, garray_T *to);
|
||||||
void deleteFoldRecurse(garray_T *gap);
|
void deleteFoldRecurse(garray_T *gap);
|
||||||
void foldMarkAdjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long amount_after);
|
void foldMarkAdjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long amount_after);
|
||||||
|
@@ -19,6 +19,7 @@ void ex_jumps(exarg_T *eap);
|
|||||||
void ex_clearjumps(exarg_T *eap);
|
void ex_clearjumps(exarg_T *eap);
|
||||||
void ex_changes(exarg_T *eap);
|
void ex_changes(exarg_T *eap);
|
||||||
void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after);
|
void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after);
|
||||||
|
void mark_adjust_nofold(linenr_T line1, linenr_T line2, long amount, long amount_after);
|
||||||
void mark_col_adjust(linenr_T lnum, colnr_T mincol, long lnum_amount, long col_amount);
|
void mark_col_adjust(linenr_T lnum, colnr_T mincol, long lnum_amount, long col_amount);
|
||||||
void copy_jumplist(win_T *from, win_T *to);
|
void copy_jumplist(win_T *from, win_T *to);
|
||||||
void free_jumplist(win_T *wp);
|
void free_jumplist(win_T *wp);
|
||||||
|
@@ -1,5 +1,9 @@
|
|||||||
" Test for folding
|
" Test for folding
|
||||||
|
|
||||||
|
func! PrepIndent(arg)
|
||||||
|
return [a:arg] + repeat(["\t".a:arg], 5)
|
||||||
|
endfu
|
||||||
|
|
||||||
func! Test_address_fold()
|
func! Test_address_fold()
|
||||||
new
|
new
|
||||||
call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
|
call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
|
||||||
@@ -219,3 +223,121 @@ func Test_update_folds_expr_read()
|
|||||||
bwipe!
|
bwipe!
|
||||||
set foldmethod& foldexpr&
|
set foldmethod& foldexpr&
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func! Test_move_folds_around_manual()
|
||||||
|
new
|
||||||
|
let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
|
||||||
|
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
|
||||||
|
let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
|
||||||
|
" all folds closed
|
||||||
|
set foldenable foldlevel=0 fdm=indent
|
||||||
|
" needs a forced redraw
|
||||||
|
redraw!
|
||||||
|
set fdm=manual
|
||||||
|
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
call assert_equal(input, getline(1, '$'))
|
||||||
|
7,12m0
|
||||||
|
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
|
||||||
|
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
10,12m0
|
||||||
|
call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
|
||||||
|
call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
" moving should not close the folds
|
||||||
|
%d
|
||||||
|
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
|
||||||
|
set fdm=indent
|
||||||
|
redraw!
|
||||||
|
set fdm=manual
|
||||||
|
call cursor(2, 1)
|
||||||
|
norm! zR
|
||||||
|
7,12m0
|
||||||
|
let folds=repeat([-1], 18)
|
||||||
|
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
|
||||||
|
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
norm! zM
|
||||||
|
" folds are not corrupted and all have been closed
|
||||||
|
call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
%d
|
||||||
|
call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
|
||||||
|
set fdm=indent
|
||||||
|
redraw!
|
||||||
|
set fdm=manual
|
||||||
|
%foldopen
|
||||||
|
3m4
|
||||||
|
%foldclose
|
||||||
|
call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
|
||||||
|
call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
|
||||||
|
%d
|
||||||
|
call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
|
||||||
|
set fdm=indent foldlevel=0
|
||||||
|
set fdm=manual
|
||||||
|
%foldopen
|
||||||
|
3m1
|
||||||
|
%foldclose
|
||||||
|
call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
|
||||||
|
call assert_equal(0, foldlevel(2))
|
||||||
|
call assert_equal(5, foldclosedend(3))
|
||||||
|
call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
2,6m$
|
||||||
|
%foldclose
|
||||||
|
call assert_equal(5, foldclosedend(2))
|
||||||
|
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)'))
|
||||||
|
bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_move_folds_around_indent()
|
||||||
|
new
|
||||||
|
let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
|
||||||
|
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
|
||||||
|
let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
|
||||||
|
" all folds closed
|
||||||
|
set fdm=indent
|
||||||
|
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
call assert_equal(input, getline(1, '$'))
|
||||||
|
7,12m0
|
||||||
|
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
|
||||||
|
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
10,12m0
|
||||||
|
call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
|
||||||
|
call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
" moving should not close the folds
|
||||||
|
%d
|
||||||
|
call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
|
||||||
|
set fdm=indent
|
||||||
|
call cursor(2, 1)
|
||||||
|
norm! zR
|
||||||
|
7,12m0
|
||||||
|
let folds=repeat([-1], 18)
|
||||||
|
call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
|
||||||
|
call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
norm! zM
|
||||||
|
" folds are not corrupted and all have been closed
|
||||||
|
call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
%d
|
||||||
|
call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
|
||||||
|
set fdm=indent
|
||||||
|
%foldopen
|
||||||
|
3m4
|
||||||
|
%foldclose
|
||||||
|
call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
|
||||||
|
call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
|
||||||
|
%d
|
||||||
|
call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
|
||||||
|
set fdm=indent foldlevel=0
|
||||||
|
%foldopen
|
||||||
|
3m1
|
||||||
|
%foldclose
|
||||||
|
call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
|
||||||
|
call assert_equal(1, foldlevel(2))
|
||||||
|
call assert_equal(5, foldclosedend(3))
|
||||||
|
call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
|
||||||
|
2,6m$
|
||||||
|
%foldclose
|
||||||
|
call assert_equal(9, foldclosedend(2))
|
||||||
|
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)'))
|
||||||
|
bw!
|
||||||
|
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 */
|
||||||
|
/**/
|
||||||
|
457,
|
||||||
/**/
|
/**/
|
||||||
456,
|
456,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user