1
0
forked from aniani/vim

patch 8.2.3280: 'virtualedit' local to buffer is not the best solution

Problem:    'virtualedit' local to buffer is not the best solution.
Solution:   Make it window-local. (Gary Johnson, closes #8685)
This commit is contained in:
Gary Johnson 2021-08-03 18:33:08 +02:00 committed by Bram Moolenaar
parent 2c70711e3f
commit 51ad850f5f
10 changed files with 56 additions and 37 deletions

View File

@ -8643,7 +8643,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'virtualedit'* *'ve'* *'virtualedit'* *'ve'*
'virtualedit' 've' string (default "") 'virtualedit' 've' string (default "")
global or local to buffer |global-local| global or local to window |global-local|
A comma separated list of these words: A comma separated list of these words:
block Allow virtual editing in Visual block mode. block Allow virtual editing in Visual block mode.
insert Allow virtual editing in Insert mode. insert Allow virtual editing in Insert mode.

View File

@ -2388,7 +2388,6 @@ free_buf_options(
#endif #endif
clear_string_option(&buf->b_p_bkc); clear_string_option(&buf->b_p_bkc);
clear_string_option(&buf->b_p_menc); clear_string_option(&buf->b_p_menc);
clear_string_option(&buf->b_p_ve);
} }
/* /*

View File

@ -2006,15 +2006,15 @@ win_update(win_T *wp)
{ {
colnr_T fromc, toc; colnr_T fromc, toc;
#if defined(FEAT_LINEBREAK) #if defined(FEAT_LINEBREAK)
int save_ve_flags = curbuf->b_ve_flags; int save_ve_flags = curwin->w_ve_flags;
if (curwin->w_p_lbr) if (curwin->w_p_lbr)
curbuf->b_ve_flags = VE_ALL; curwin->w_ve_flags = VE_ALL;
#endif #endif
getvcols(wp, &VIsual, &curwin->w_cursor, &fromc, &toc); getvcols(wp, &VIsual, &curwin->w_cursor, &fromc, &toc);
++toc; ++toc;
#if defined(FEAT_LINEBREAK) #if defined(FEAT_LINEBREAK)
curbuf->b_ve_flags = save_ve_flags; curwin->w_ve_flags = save_ve_flags;
#endif #endif
// Highlight to the end of the line, unless 'virtualedit' has // Highlight to the end of the line, unless 'virtualedit' has
// "block". // "block".

View File

@ -1475,21 +1475,21 @@ op_insert(oparg_T *oap, long count1)
// already disabled, but still need it when calling // already disabled, but still need it when calling
// coladvance_force(). // coladvance_force().
// coladvance_force() uses get_ve_flags() to get the 'virtualedit' // coladvance_force() uses get_ve_flags() to get the 'virtualedit'
// state for the current buffer. To override that state, we need to // state for the current window. To override that state, we need to
// set the buffer-local value of ve_flags rather than the global value. // set the window-local value of ve_flags rather than the global value.
if (curwin->w_cursor.coladd > 0) if (curwin->w_cursor.coladd > 0)
{ {
int old_ve_flags = curbuf->b_ve_flags; int old_ve_flags = curwin->w_ve_flags;
if (u_save_cursor() == FAIL) if (u_save_cursor() == FAIL)
return; return;
curbuf->b_ve_flags = VE_ALL; curwin->w_ve_flags = VE_ALL;
coladvance_force(oap->op_type == OP_APPEND coladvance_force(oap->op_type == OP_APPEND
? oap->end_vcol + 1 : getviscol()); ? oap->end_vcol + 1 : getviscol());
if (oap->op_type == OP_APPEND) if (oap->op_type == OP_APPEND)
--curwin->w_cursor.col; --curwin->w_cursor.col;
curbuf->b_ve_flags = old_ve_flags; curwin->w_ve_flags = old_ve_flags;
} }
// Get the info about the block before entering the text // Get the info about the block before entering the text
block_prep(oap, &bd, oap->start.lnum, TRUE); block_prep(oap, &bd, oap->start.lnum, TRUE);

View File

@ -5182,8 +5182,8 @@ unset_global_local_option(char_u *name, void *from)
redraw_later(NOT_VALID); redraw_later(NOT_VALID);
break; break;
case PV_VE: case PV_VE:
clear_string_option(&buf->b_p_ve); clear_string_option(&((win_T *)from)->w_p_ve);
buf->b_ve_flags = 0; ((win_T *)from)->w_ve_flags = 0;
break; break;
} }
} }
@ -5244,7 +5244,7 @@ get_varp_scope(struct vimoption *p, int opt_flags)
case PV_BKC: return (char_u *)&(curbuf->b_p_bkc); case PV_BKC: return (char_u *)&(curbuf->b_p_bkc);
case PV_MENC: return (char_u *)&(curbuf->b_p_menc); case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
case PV_LCS: return (char_u *)&(curwin->w_p_lcs); case PV_LCS: return (char_u *)&(curwin->w_p_lcs);
case PV_VE: return (char_u *)&(curbuf->b_p_ve); case PV_VE: return (char_u *)&(curwin->w_p_ve);
} }
return NULL; // "cannot happen" return NULL; // "cannot happen"
@ -5345,6 +5345,8 @@ get_varp(struct vimoption *p)
case PV_LIST: return (char_u *)&(curwin->w_p_list); case PV_LIST: return (char_u *)&(curwin->w_p_list);
case PV_LCS: return *curwin->w_p_lcs != NUL case PV_LCS: return *curwin->w_p_lcs != NUL
? (char_u *)&(curwin->w_p_lcs) : p->var; ? (char_u *)&(curwin->w_p_lcs) : p->var;
case PV_VE: return *curwin->w_p_ve != NUL
? (char_u *)&(curwin->w_p_ve) : p->var;
#ifdef FEAT_SPELL #ifdef FEAT_SPELL
case PV_SPELL: return (char_u *)&(curwin->w_p_spell); case PV_SPELL: return (char_u *)&(curwin->w_p_spell);
#endif #endif
@ -5512,8 +5514,6 @@ get_varp(struct vimoption *p)
case PV_VSTS: return (char_u *)&(curbuf->b_p_vsts); case PV_VSTS: return (char_u *)&(curbuf->b_p_vsts);
case PV_VTS: return (char_u *)&(curbuf->b_p_vts); case PV_VTS: return (char_u *)&(curbuf->b_p_vts);
#endif #endif
case PV_VE: return *curbuf->b_p_ve != NUL
? (char_u *)&(curbuf->b_p_ve) : p->var;
default: iemsg(_("E356: get_varp ERROR")); default: iemsg(_("E356: get_varp ERROR"));
} }
// always return a valid pointer to avoid a crash! // always return a valid pointer to avoid a crash!
@ -5593,6 +5593,8 @@ copy_winopt(winopt_T *from, winopt_T *to)
to->wo_lcs = vim_strsave(from->wo_lcs); to->wo_lcs = vim_strsave(from->wo_lcs);
to->wo_nu = from->wo_nu; to->wo_nu = from->wo_nu;
to->wo_rnu = from->wo_rnu; to->wo_rnu = from->wo_rnu;
to->wo_ve = vim_strsave(from->wo_ve);
to->wo_ve_flags = from->wo_ve_flags;
#ifdef FEAT_LINEBREAK #ifdef FEAT_LINEBREAK
to->wo_nuw = from->wo_nuw; to->wo_nuw = from->wo_nuw;
#endif #endif
@ -5726,6 +5728,7 @@ check_winopt(winopt_T *wop UNUSED)
#endif #endif
check_string_option(&wop->wo_wcr); check_string_option(&wop->wo_wcr);
check_string_option(&wop->wo_lcs); check_string_option(&wop->wo_lcs);
check_string_option(&wop->wo_ve);
} }
/* /*
@ -5772,6 +5775,7 @@ clear_winopt(winopt_T *wop UNUSED)
clear_string_option(&wop->wo_tws); clear_string_option(&wop->wo_tws);
#endif #endif
clear_string_option(&wop->wo_lcs); clear_string_option(&wop->wo_lcs);
clear_string_option(&wop->wo_ve);
} }
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
@ -6091,8 +6095,6 @@ buf_copy_options(buf_T *buf, int flags)
buf->b_p_lw = empty_option; buf->b_p_lw = empty_option;
#endif #endif
buf->b_p_menc = empty_option; buf->b_p_menc = empty_option;
buf->b_p_ve = empty_option;
buf->b_ve_flags = 0;
/* /*
* Don't copy the options set by ex_help(), use the saved values, * Don't copy the options set by ex_help(), use the saved values,
@ -7041,8 +7043,8 @@ get_bkc_value(buf_T *buf)
unsigned int unsigned int
get_ve_flags(void) get_ve_flags(void)
{ {
return (curbuf->b_ve_flags ? curbuf->b_ve_flags : ve_flags) return (curwin->w_ve_flags ? curwin->w_ve_flags : ve_flags)
& ~(VE_NONE | VE_NONEU); & ~(VE_NONE | VE_NONEU);
} }
#if defined(FEAT_LINEBREAK) || defined(PROTO) #if defined(FEAT_LINEBREAK) || defined(PROTO)

View File

@ -1052,8 +1052,8 @@ EXTERN unsigned ve_flags;
#define VE_INSERT 6 // includes "all" #define VE_INSERT 6 // includes "all"
#define VE_ALL 4 #define VE_ALL 4
#define VE_ONEMORE 8 #define VE_ONEMORE 8
#define VE_NONE 16 #define VE_NONE 16 // "none"
#define VE_NONEU 32 // Upper-case NONE #define VE_NONEU 32 // "NONE"
EXTERN long p_verbose; // 'verbose' EXTERN long p_verbose; // 'verbose'
#ifdef IN_OPTION_C #ifdef IN_OPTION_C
char_u *p_vfile = (char_u *)""; // used before options are initialized char_u *p_vfile = (char_u *)""; // used before options are initialized

View File

@ -298,7 +298,6 @@ check_buf_options(buf_T *buf)
check_string_option(&buf->b_p_vsts); check_string_option(&buf->b_p_vsts);
check_string_option(&buf->b_p_vts); check_string_option(&buf->b_p_vts);
#endif #endif
check_string_option(&buf->b_p_ve);
} }
/* /*
@ -2083,8 +2082,8 @@ ambw_end:
if (opt_flags & OPT_LOCAL) if (opt_flags & OPT_LOCAL)
{ {
ve = curbuf->b_p_ve; ve = curwin->w_p_ve;
flags = &curbuf->b_ve_flags; flags = &curwin->w_ve_flags;
} }
if ((opt_flags & OPT_LOCAL) && *ve == NUL) if ((opt_flags & OPT_LOCAL) && *ve == NUL)

View File

@ -231,6 +231,10 @@ typedef struct
#define w_p_nu w_onebuf_opt.wo_nu // 'number' #define w_p_nu w_onebuf_opt.wo_nu // 'number'
int wo_rnu; int wo_rnu;
#define w_p_rnu w_onebuf_opt.wo_rnu // 'relativenumber' #define w_p_rnu w_onebuf_opt.wo_rnu // 'relativenumber'
char_u *wo_ve;
#define w_p_ve w_onebuf_opt.wo_ve // 'virtualedit'
unsigned wo_ve_flags;
#define w_ve_flags w_onebuf_opt.wo_ve_flags // flags for 'virtualedit'
#ifdef FEAT_LINEBREAK #ifdef FEAT_LINEBREAK
long wo_nuw; long wo_nuw;
# define w_p_nuw w_onebuf_opt.wo_nuw // 'numberwidth' # define w_p_nuw w_onebuf_opt.wo_nuw // 'numberwidth'
@ -2969,8 +2973,6 @@ struct file_buffer
#ifdef FEAT_TERMINAL #ifdef FEAT_TERMINAL
long b_p_twsl; // 'termwinscroll' long b_p_twsl; // 'termwinscroll'
#endif #endif
char_u *b_p_ve; // 'virtualedit' local value
unsigned b_ve_flags; // flags for 'virtualedit'
/* /*
* end of buffer options * end of buffer options

View File

@ -407,7 +407,7 @@ endfunc
let s:result_ve_on = 'a x' let s:result_ve_on = 'a x'
let s:result_ve_off = 'x' let s:result_ve_off = 'x'
" Utility function for Test_global_local() " Utility function for Test_global_local_virtualedit()
func s:TryVirtualeditReplace() func s:TryVirtualeditReplace()
call setline(1, 'a') call setline(1, 'a')
normal gg7l normal gg7l
@ -415,7 +415,7 @@ func s:TryVirtualeditReplace()
endfunc endfunc
" Test for :set and :setlocal " Test for :set and :setlocal
func Test_global_local() func Test_global_local_virtualedit()
new new
" Verify that 'virtualedit' is initialized to empty, can be set globally to " Verify that 'virtualedit' is initialized to empty, can be set globally to
@ -435,8 +435,8 @@ func Test_global_local()
call s:TryVirtualeditReplace() call s:TryVirtualeditReplace()
call assert_equal(s:result_ve_off, getline(1)) call assert_equal(s:result_ve_off, getline(1))
" Verify that :set affects multiple buffers " Verify that :set affects multiple windows.
new split
set ve=all set ve=all
call s:TryVirtualeditReplace() call s:TryVirtualeditReplace()
call assert_equal(s:result_ve_on, getline(1)) call assert_equal(s:result_ve_on, getline(1))
@ -449,17 +449,15 @@ func Test_global_local()
call assert_equal(s:result_ve_off, getline(1)) call assert_equal(s:result_ve_off, getline(1))
bwipe! bwipe!
" Verify that :setlocal affects only the current buffer " Verify that :setlocal affects only the current window.
setlocal ve=all
new new
call s:TryVirtualeditReplace() split
call assert_equal(s:result_ve_off, getline(1))
setlocal ve=all setlocal ve=all
wincmd p
setlocal ve=
wincmd p
call s:TryVirtualeditReplace() call s:TryVirtualeditReplace()
call assert_equal(s:result_ve_on, getline(1)) call assert_equal(s:result_ve_on, getline(1))
wincmd p
call s:TryVirtualeditReplace()
call assert_equal(s:result_ve_off, getline(1))
bwipe! bwipe!
call s:TryVirtualeditReplace() call s:TryVirtualeditReplace()
call assert_equal(s:result_ve_off, getline(1)) call assert_equal(s:result_ve_off, getline(1))
@ -518,6 +516,23 @@ func Test_global_local()
bwipe! bwipe!
" Verify that the 'virtualedit' state is copied to new windows.
new
call s:TryVirtualeditReplace()
call assert_equal(s:result_ve_off, getline(1))
split
setlocal ve=all
call s:TryVirtualeditReplace()
call assert_equal(s:result_ve_on, getline(1))
split
call s:TryVirtualeditReplace()
call assert_equal(s:result_ve_on, getline(1))
setlocal ve=
split
call s:TryVirtualeditReplace()
call assert_equal(s:result_ve_off, getline(1))
bwipe!
setlocal virtualedit& setlocal virtualedit&
set virtualedit& set virtualedit&
endfunc endfunc

View File

@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
3280,
/**/ /**/
3279, 3279,
/**/ /**/