Skip to content

Commit 8ea0e72

Browse files
mcauley-penneychrisbra
authored andcommitted
patch 9.1.2017: getregionpos() depends on 'linebreak' setting
Problem: getregionpos() depends on 'linebreak' setting Solution: Reset linebreak setting temporarily (McAuley Penney) When a line is wrapped on word boundaries, getregionpos() may report a different end column for a visual block than the cursor position used to define the selection. Update the blockwise calculation in getregionpos() to use the same wrapping assumptions as visual block mode, so the reported region matches the selection boundaries. Add a regression test that forces wrapping and checks that the end position stays consistent under "setlocal wrap" and "setlocal linebreak". closes: #19006 Signed-off-by: McAuley Penney <jacobmpenney@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 9d661b0 commit 8ea0e72

5 files changed

Lines changed: 84 additions & 2 deletions

File tree

src/evalfunc.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6175,8 +6175,17 @@ getregionpos(
61756175
{
61766176
colnr_T sc1, ec1, sc2, ec2;
61776177

6178+
#ifdef FEAT_LINEBREAK
6179+
int lbr_saved = reset_lbr();
6180+
#endif
6181+
61786182
getvvcol(curwin, p1, &sc1, NULL, &ec1);
61796183
getvvcol(curwin, p2, &sc2, NULL, &ec2);
6184+
6185+
#ifdef FEAT_LINEBREAK
6186+
restore_lbr(lbr_saved);
6187+
#endif
6188+
61806189
oap->motion_type = MBLOCK;
61816190
oap->inclusive = TRUE;
61826191
oap->op_type = OP_NOP;

src/ops.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,7 +2398,7 @@ do_join(
23982398
* Reset 'linebreak' and take care of side effects.
23992399
* Returns the previous value, to be passed to restore_lbr().
24002400
*/
2401-
static int
2401+
int
24022402
reset_lbr(void)
24032403
{
24042404
if (!curwin->w_p_lbr)
@@ -2412,7 +2412,7 @@ reset_lbr(void)
24122412
/*
24132413
* Restore 'linebreak' and take care of side effects.
24142414
*/
2415-
static void
2415+
void
24162416
restore_lbr(int lbr_saved)
24172417
{
24182418
if (curwin->w_p_lbr || !lbr_saved)

src/proto/ops.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ char *did_set_operatorfunc(optset_T *args);
2222
void free_operatorfunc_option(void);
2323
int set_ref_in_opfunc(int copyID);
2424
void do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank);
25+
int reset_lbr(void);
26+
void restore_lbr(int lbr_saved);
2527
/* vim: set ft=c : */

src/testdir/test_visual.vim

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2835,4 +2835,73 @@ func Test_visual_block_pos_update()
28352835
bw!
28362836
endfunc
28372837

2838+
" Test that blockwise end position matches getpos('.')
2839+
" when 'wrap' and 'linebreak' are set
2840+
func Test_getregionpos_block_linebreak_matches_getpos()
2841+
CheckFeature linebreak
2842+
2843+
new
2844+
setlocal buftype=
2845+
setlocal bufhidden=wipe
2846+
setlocal noswapfile
2847+
2848+
setlocal wrap
2849+
setlocal linebreak
2850+
setlocal breakat=\ \t
2851+
setlocal nonumber norelativenumber
2852+
setlocal signcolumn=no
2853+
setlocal foldcolumn=0
2854+
2855+
call setline(1, '1111111111 2222222222 3333333333 4444444444 5555555555 6666666666 7777777777 8888888888')
2856+
2857+
" Force wrapping deterministically by shrinking the screen width.
2858+
let save_columns = &columns
2859+
let moved = 0
2860+
for c in [30, 20, 15, 10]
2861+
execute 'set columns=' .. c
2862+
redraw!
2863+
normal! gg0
2864+
let row0 = winline()
2865+
normal! gj
2866+
let row1 = winline()
2867+
if row1 > row0
2868+
let moved = 1
2869+
break
2870+
endif
2871+
endfor
2872+
call assert_true(moved)
2873+
2874+
" Move a bit right so we are not at column 1, then go back up one screen line.
2875+
normal! 5l
2876+
normal! gk
2877+
let row2 = winline()
2878+
call assert_equal(row0, row2)
2879+
2880+
" Start Visual block and move down one screen line to the previous position.
2881+
execute "normal! \<C-V>"
2882+
normal! gj
2883+
let row3 = winline()
2884+
call assert_equal(row1, row3)
2885+
2886+
let p1 = getpos('v')
2887+
let p2 = getpos('.')
2888+
2889+
" Sanity: block selection is within the same wrapped buffer line.
2890+
call assert_equal(1, p1[1])
2891+
call assert_equal(1, p2[1])
2892+
2893+
" For blockwise region, getregionpos() should not report an end position
2894+
" different from the {pos2} we passed in.
2895+
let segs = getregionpos(p1, p2, #{ type: "\<C-V>", exclusive: v:false })
2896+
2897+
call assert_equal(1, len(segs))
2898+
let endp = segs[0][1]
2899+
2900+
call assert_equal(p2[1], endp[1]) " lnum
2901+
call assert_equal(p2[2], endp[2]) " col
2902+
call assert_equal(p2[3], endp[3]) " off
2903+
2904+
let &columns = save_columns
2905+
bw!
2906+
endfunc
28382907
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ static char *(features[]) =
734734

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
2017,
737739
/**/
738740
2016,
739741
/**/

0 commit comments

Comments
 (0)