changeset 18291:11f68eb58fda v8.1.2140

patch 8.1.2140: "gk" and "gj" do not work correctly in number column Commit: https://github.com/vim/vim/commit/ceba3dd5187788e09f65bd41b07b40f6f9aab953 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Oct 12 16:12:54 2019 +0200 patch 8.1.2140: "gk" and "gj" do not work correctly in number column Problem: "gk" and "gj" do not work correctly in number column. Solution: Allow for a negative "curswant". (Zach Wegner, closes https://github.com/vim/vim/issues/4969)
author Bram Moolenaar <Bram@vim.org>
date Sat, 12 Oct 2019 16:15:03 +0200
parents b31d3745f179
children d10f337d9fd3
files src/misc2.c src/normal.c src/testdir/test_normal.vim src/version.c
diffstat 4 files changed, 46 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -119,10 +119,11 @@ getvpos(pos_T *pos, colnr_T wcol)
     static int
 coladvance2(
     pos_T	*pos,
-    int		addspaces,	/* change the text to achieve our goal? */
-    int		finetune,	/* change char offset for the exact column */
-    colnr_T	wcol)		/* column to move to */
+    int		addspaces,	// change the text to achieve our goal?
+    int		finetune,	// change char offset for the exact column
+    colnr_T	wcol_arg)	// column to move to (can be negative)
 {
+    colnr_T	wcol = wcol_arg;
     int		idx;
     char_u	*ptr;
     char_u	*line;
@@ -136,7 +137,7 @@ coladvance2(
     one_more = (State & INSERT)
 		    || restart_edit != NUL
 		    || (VIsual_active && *p_sel != 'o')
-		    || ((ve_flags & VE_ONEMORE) && wcol < MAXCOL) ;
+		    || ((ve_flags & VE_ONEMORE) && wcol < MAXCOL);
     line = ml_get_buf(curbuf, pos->lnum, FALSE);
 
     if (wcol >= MAXCOL)
@@ -206,6 +207,7 @@ coladvance2(
 
 	if (virtual_active()
 		&& addspaces
+		&& wcol >= 0
 		&& ((col != wcol && col != wcol + 1) || csize > 1))
 	{
 	    /* 'virtualedit' is set: The difference between wcol and col is
@@ -305,7 +307,7 @@ coladvance2(
     if (has_mbyte)
 	mb_adjustpos(curbuf, pos);
 
-    if (col < wcol)
+    if (wcol < 0 || col < wcol)
 	return FAIL;
     return OK;
 }
--- a/src/normal.c
+++ b/src/normal.c
@@ -2499,17 +2499,18 @@ nv_screengo(oparg_T *oap, int dir, long 
 	    n = ((linelen - width1 - 1) / width2 + 1) * width2 + width1;
 	else
 	    n = width1;
-	if (curwin->w_curswant > (colnr_T)n + 1)
-	    curwin->w_curswant -= ((curwin->w_curswant - n) / width2 + 1)
-								     * width2;
+	if (curwin->w_curswant >= (colnr_T)n)
+	    curwin->w_curswant = n - 1;
       }
 
       while (dist--)
       {
 	if (dir == BACKWARD)
 	{
-	    if ((long)curwin->w_curswant > width2)
-		// move back within line
+	    if ((long)curwin->w_curswant >= width1)
+		// Move back within the line. This can give a negative value
+		// for w_curswant if width1 < width2 (with cpoptions+=n),
+		// which will get clipped to column 0.
 		curwin->w_curswant -= width2;
 	    else
 	    {
@@ -2557,6 +2558,12 @@ nv_screengo(oparg_T *oap, int dir, long 
 		}
 		curwin->w_cursor.lnum++;
 		curwin->w_curswant %= width2;
+		// Check if the cursor has moved below the number display
+		// when width1 < width2 (with cpoptions+=n). Subtract width2
+		// to get a negative value for w_curswant, which will get
+		// clipped to column 0.
+		if (curwin->w_curswant >= width1)
+		    curwin->w_curswant -= width2;
 		linelen = linetabsize(ml_get_curline());
 	    }
 	}
--- a/src/testdir/test_normal.vim
+++ b/src/testdir/test_normal.vim
@@ -2654,4 +2654,29 @@ func Test_normal_gk()
   call assert_equal(95, virtcol('.'))
   bw!
   bw!
+
+  " needs 80 column new window
+  new
+  vert 80new
+  set number
+  set numberwidth=10
+  set cpoptions+=n
+  put =[repeat('0',90), repeat('1',90)]
+  norm! 075l
+  call assert_equal(76, col('.'))
+  norm! gk
+  call assert_equal(1, col('.'))
+  norm! gk
+  call assert_equal(76, col('.'))
+  norm! gk
+  call assert_equal(1, col('.'))
+  norm! gj
+  call assert_equal(76, col('.'))
+  norm! gj
+  call assert_equal(1, col('.'))
+  norm! gj
+  call assert_equal(76, col('.'))
+  bw!
+  bw!
+  set cpoptions& number& numberwidth&
 endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -754,6 +754,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2140,
+/**/
     2139,
 /**/
     2138,