# HG changeset patch # User Bram Moolenaar # Date 1570889703 -7200 # Node ID 11f68eb58fdae3d57ddd7608c859cc7092a581f5 # Parent b31d3745f179cc144baba95f8eafe853f62dd012 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 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) diff --git a/src/misc2.c b/src/misc2.c --- 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; } diff --git a/src/normal.c b/src/normal.c --- 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()); } } diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim --- 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 diff --git a/src/version.c b/src/version.c --- 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,