vim-patch:8.1.0671: cursor in wrong column after auto-format #9729

Problem:    Cursor in the wrong column after auto-formatting.
Solution:   Check for deleting more spaces than adding. (closes vim/vim#3748)
e1e714ef0d
This commit is contained in:
Jan Edmund Lazo 2019-03-14 06:23:05 -04:00 committed by Justin M. Keyes
parent 907b480350
commit cbe4377fde
4 changed files with 38 additions and 15 deletions

View File

@ -1069,19 +1069,24 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2,
{ \ { \
posp->lnum += lnum_amount; \ posp->lnum += lnum_amount; \
assert(col_amount > INT_MIN && col_amount <= INT_MAX); \ assert(col_amount > INT_MIN && col_amount <= INT_MAX); \
if (col_amount < 0 && posp->col <= (colnr_T)-col_amount) \ if (col_amount < 0 && posp->col <= (colnr_T)-col_amount) { \
posp->col = 0; \ posp->col = 0; \
else \ } else if (posp->col < spaces_removed) { \
posp->col = (int)col_amount + spaces_removed; \
} else { \
posp->col += (colnr_T)col_amount; \ posp->col += (colnr_T)col_amount; \
} \
} \ } \
} }
/* // Adjust marks in line "lnum" at column "mincol" and further: add
* Adjust marks in line "lnum" at column "mincol" and further: add // "lnum_amount" to the line number and add "col_amount" to the column
* "lnum_amount" to the line number and add "col_amount" to the column // position.
* position. // "spaces_removed" is the number of spaces that were removed, matters when the
*/ // cursor is inside them.
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,
int spaces_removed)
{ {
int i; int i;
int fnum = curbuf->b_fnum; int fnum = curbuf->b_fnum;

View File

@ -848,10 +848,11 @@ open_line (
/* Move marks after the line break to the new line. */ /* Move marks after the line break to the new line. */
if (flags & OPENLINE_MARKFIX) if (flags & OPENLINE_MARKFIX)
mark_col_adjust(curwin->w_cursor.lnum, mark_col_adjust(curwin->w_cursor.lnum,
curwin->w_cursor.col + less_cols_off, curwin->w_cursor.col + less_cols_off,
1L, (long)-less_cols); 1L, (long)-less_cols, 0);
} else } else {
changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
}
} }
/* /*

View File

@ -3707,10 +3707,16 @@ int do_join(size_t count,
cend -= spaces[t]; cend -= spaces[t];
memset(cend, ' ', (size_t)(spaces[t])); memset(cend, ' ', (size_t)(spaces[t]));
} }
// If deleting more spaces than adding, the cursor moves no more than
// what is added if it is inside these spaces.
const int spaces_removed = (int)((curr - curr_start) - spaces[t]);
mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t, mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t,
(long)(cend - newp + spaces[t] - (curr - curr_start))); (long)(cend - newp - spaces_removed), spaces_removed);
if (t == 0) if (t == 0) {
break; break;
}
curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1));
if (remove_comments) if (remove_comments)
curr += comments[t - 1]; curr += comments[t - 1];
@ -4138,14 +4144,14 @@ format_lines (
if (next_leader_len > 0) { if (next_leader_len > 0) {
(void)del_bytes(next_leader_len, false, false); (void)del_bytes(next_leader_len, false, false);
mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L, mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
(long)-next_leader_len); (long)-next_leader_len, 0);
} else if (second_indent > 0) { // the "leader" for FO_Q_SECOND } else if (second_indent > 0) { // the "leader" for FO_Q_SECOND
int indent = (int)getwhitecols_curline(); int indent = (int)getwhitecols_curline();
if (indent > 0) { if (indent > 0) {
(void)del_bytes(indent, FALSE, FALSE); (void)del_bytes(indent, FALSE, FALSE);
mark_col_adjust(curwin->w_cursor.lnum, mark_col_adjust(curwin->w_cursor.lnum,
(colnr_T)0, 0L, (long)-indent); (colnr_T)0, 0L, (long)-indent, 0);
} }
} }
curwin->w_cursor.lnum--; curwin->w_cursor.lnum--;

View File

@ -450,5 +450,16 @@ func Test_format_undo()
\ ], getline(1, '$')) \ ], getline(1, '$'))
unmap gg unmap gg
set tw&
enew! enew!
endfunc endfunc
func Test_format_list_auto()
new
call setline(1, ['1. abc', '2. def', '3. ghi'])
set fo=tan ai bs=2
call feedkeys("3G0lli\<BS>\<BS>x\<Esc>", 'tx')
call assert_equal('2. defx ghi', getline(2))
bwipe!
set fo& ai& bs&
endfunc