diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4996dbcf22..eaaa12a4ac 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2281,8 +2281,10 @@ static int getregionpos(typval_T *argvars, typval_T *rettv, pos_T *p1, pos_T *p2 } } else if (*region_type == kMTBlockWise) { colnr_T sc1, ec1, sc2, ec2; + const bool lbr_saved = reset_lbr(); getvvcol(curwin, p1, &sc1, NULL, &ec1); getvvcol(curwin, p2, &sc2, NULL, &ec2); + restore_lbr(lbr_saved); oap->motion_type = kMTBlockWise; oap->inclusive = true; oap->op_type = OP_NOP; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 366dd662bf..567810cd15 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -2077,7 +2077,7 @@ theend: /// Reset 'linebreak' and take care of side effects. /// @return the previous value, to be passed to restore_lbr(). -static bool reset_lbr(void) +bool reset_lbr(void) { if (!curwin->w_p_lbr) { return false; @@ -2089,7 +2089,7 @@ static bool reset_lbr(void) } /// Restore 'linebreak' and take care of side effects. -static void restore_lbr(bool lbr_saved) +void restore_lbr(bool lbr_saved) { if (curwin->w_p_lbr || !lbr_saved) { return; diff --git a/test/old/testdir/test_visual.vim b/test/old/testdir/test_visual.vim index 9ee5bb8250..2d6eec3870 100644 --- a/test/old/testdir/test_visual.vim +++ b/test/old/testdir/test_visual.vim @@ -2839,4 +2839,73 @@ func Test_visual_block_pos_update() bw! endfunc +" Test that blockwise end position matches getpos('.') +" when 'wrap' and 'linebreak' are set +func Test_getregionpos_block_linebreak_matches_getpos() + CheckFeature linebreak + + new + setlocal buftype= + setlocal bufhidden=wipe + setlocal noswapfile + + setlocal wrap + setlocal linebreak + setlocal breakat=\ \t + setlocal nonumber norelativenumber + setlocal signcolumn=no + setlocal foldcolumn=0 + + call setline(1, '1111111111 2222222222 3333333333 4444444444 5555555555 6666666666 7777777777 8888888888') + + " Force wrapping deterministically by shrinking the screen width. + let save_columns = &columns + let moved = 0 + for c in [30, 20, 15, 10] + execute 'set columns=' .. c + redraw! + normal! gg0 + let row0 = winline() + normal! gj + let row1 = winline() + if row1 > row0 + let moved = 1 + break + endif + endfor + call assert_true(moved) + + " Move a bit right so we are not at column 1, then go back up one screen line. + normal! 5l + normal! gk + let row2 = winline() + call assert_equal(row0, row2) + + " Start Visual block and move down one screen line to the previous position. + execute "normal! \" + normal! gj + let row3 = winline() + call assert_equal(row1, row3) + + let p1 = getpos('v') + let p2 = getpos('.') + + " Sanity: block selection is within the same wrapped buffer line. + call assert_equal(1, p1[1]) + call assert_equal(1, p2[1]) + + " For blockwise region, getregionpos() should not report an end position + " different from the {pos2} we passed in. + let segs = getregionpos(p1, p2, #{ type: "\", exclusive: v:false }) + + call assert_equal(1, len(segs)) + let endp = segs[0][1] + + call assert_equal(p2[1], endp[1]) " lnum + call assert_equal(p2[2], endp[2]) " col + call assert_equal(p2[3], endp[3]) " off + + let &columns = save_columns + bw! +endfunc " vim: shiftwidth=2 sts=2 expandtab