changeset 15326:fe428bee74b3 v8.1.0671

patch 8.1.0671: cursor in the wrong column after auto-formatting commit https://github.com/vim/vim/commit/e1e714ef0d1f4bb8b1712795e9106e3b4ff4c7bd Author: Bram Moolenaar <Bram@vim.org> Date: Mon Dec 31 23:58:24 2018 +0100 patch 8.1.0671: cursor in the wrong column after auto-formatting Problem: Cursor in the wrong column after auto-formatting. Solution: Check for deleting more spaces than adding. (closes https://github.com/vim/vim/issues/3748)
author Bram Moolenaar <Bram@vim.org>
date Tue, 01 Jan 2019 00:00:07 +0100
parents 95f2bbb27172
children c77ac37fbc14
files src/mark.c src/misc1.c src/ops.c src/proto/mark.pro src/testdir/test_textformat.vim src/version.c
diffstat 6 files changed, 31 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/mark.c
+++ b/src/mark.c
@@ -1211,6 +1211,8 @@ mark_adjust_internal(
 	    posp->lnum += lnum_amount; \
 	    if (col_amount < 0 && posp->col <= (colnr_T)-col_amount) \
 		posp->col = 0; \
+	    else if (posp->col < spaces_removed) \
+		posp->col = col_amount + spaces_removed; \
 	    else \
 		posp->col += col_amount; \
 	} \
@@ -1220,13 +1222,16 @@ mark_adjust_internal(
  * Adjust marks in line "lnum" at column "mincol" and further: add
  * "lnum_amount" to the line number and add "col_amount" to the column
  * 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)
+    long	col_amount,
+    int		spaces_removed)
 {
     int		i;
     int		fnum = curbuf->b_fnum;
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -1705,7 +1705,7 @@ open_line(
 		if (flags & OPENLINE_MARKFIX)
 		    mark_col_adjust(curwin->w_cursor.lnum,
 					 curwin->w_cursor.col + less_cols_off,
-							1L, (long)-less_cols);
+						      1L, (long)-less_cols, 0);
 	    }
 	    else
 		changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
--- a/src/ops.c
+++ b/src/ops.c
@@ -4707,6 +4707,8 @@ do_join(
      */
     for (t = count - 1; ; --t)
     {
+	int spaces_removed;
+
 	cend -= currsize;
 	mch_memmove(cend, curr, (size_t)currsize);
 	if (spaces[t] > 0)
@@ -4714,8 +4716,13 @@ do_join(
 	    cend -= spaces[t];
 	    vim_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.
+	spaces_removed = (curr - curr_start) - spaces[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)
 	    break;
 	curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1));
@@ -5225,7 +5232,7 @@ format_lines(
 		{
 		    (void)del_bytes((long)next_leader_len, FALSE, FALSE);
 		    mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
-						      (long)-next_leader_len);
+						      (long)-next_leader_len, 0);
 		} else
 #endif
 		    if (second_indent > 0)  /* the "leader" for FO_Q_SECOND */
@@ -5236,7 +5243,7 @@ format_lines(
 		    {
 			(void)del_bytes(indent, FALSE, FALSE);
 			mark_col_adjust(curwin->w_cursor.lnum,
-					       (colnr_T)0, 0L, (long)-indent);
+					       (colnr_T)0, 0L, (long)-indent, 0);
 		    }
 		}
 		curwin->w_cursor.lnum--;
--- a/src/proto/mark.pro
+++ b/src/proto/mark.pro
@@ -21,7 +21,7 @@ void ex_clearjumps(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_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, int spaces_removed);
 void cleanup_jumplist(win_T *wp, int loadfiles);
 void copy_jumplist(win_T *from, win_T *to);
 void free_jumplist(win_T *wp);
--- a/src/testdir/test_textformat.vim
+++ b/src/testdir/test_textformat.vim
@@ -450,5 +450,16 @@ func Test_format_undo()
 	      \ ], getline(1, '$'))
 
   unmap gg
+  set tw&
   enew!
 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
--- a/src/version.c
+++ b/src/version.c
@@ -800,6 +800,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    671,
+/**/
     670,
 /**/
     669,