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 vim/vim#8685)
51ad850f5f
This commit is contained in:
zeertzjq 2022-01-15 19:21:17 +08:00
parent d391940b9a
commit 87e54f123a
8 changed files with 54 additions and 36 deletions

View File

@ -6782,7 +6782,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

@ -1941,7 +1941,6 @@ void free_buf_options(buf_T *buf, int free_p_ff)
clear_string_option(&buf->b_p_lw); clear_string_option(&buf->b_p_lw);
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

@ -204,6 +204,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'
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'
int wo_wfh; int wo_wfh;
@ -772,8 +776,6 @@ struct file_buffer {
long b_p_ul; ///< 'undolevels' local value long b_p_ul; ///< 'undolevels' local value
int b_p_udf; ///< 'undofile' int b_p_udf; ///< 'undofile'
char_u *b_p_lw; ///< 'lispwords' local value char_u *b_p_lw; ///< 'lispwords' local value
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

@ -2197,21 +2197,21 @@ void 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) {
unsigned old_ve_flags = curbuf->b_ve_flags; unsigned 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

@ -2065,7 +2065,6 @@ void check_buf_options(buf_T *buf)
check_string_option(&buf->b_p_menc); check_string_option(&buf->b_p_menc);
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);
check_string_option(&buf->b_p_ve);
} }
/// Free the string allocated for an option. /// Free the string allocated for an option.
@ -3090,8 +3089,8 @@ ambw_end:
unsigned int *flags = &ve_flags; unsigned int *flags = &ve_flags;
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) {
@ -5763,8 +5762,8 @@ void unset_global_local_option(char *name, void *from)
redraw_later((win_T *)from, NOT_VALID); redraw_later((win_T *)from, 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;
} }
} }
@ -5833,7 +5832,7 @@ static char_u *get_varp_scope(vimoption_T *p, int opt_flags)
case PV_LCS: case PV_LCS:
return (char_u *)&(curwin->w_p_lcs); return (char_u *)&(curwin->w_p_lcs);
case PV_VE: case PV_VE:
return (char_u *)&(curbuf->b_p_ve); return (char_u *)&(curwin->w_p_ve);
} }
return NULL; // "cannot happen" return NULL; // "cannot happen"
} }
@ -5928,6 +5927,9 @@ static char_u *get_varp(vimoption_T *p)
case PV_LCS: case PV_LCS:
return *curwin->w_p_lcs != NUL 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;
case PV_ARAB: case PV_ARAB:
return (char_u *)&(curwin->w_p_arab); return (char_u *)&(curwin->w_p_arab);
@ -6126,8 +6128,6 @@ static char_u *get_varp(vimoption_T *p)
return (char_u *)&(curbuf->b_p_vsts); return (char_u *)&(curbuf->b_p_vsts);
case PV_VTS: case PV_VTS:
return (char_u *)&(curbuf->b_p_vts); return (char_u *)&(curbuf->b_p_vts);
case PV_VE:
return *curbuf->b_p_ve != NUL ? (char_u *)&curbuf->b_p_ve : p->var;
case PV_KMAP: case PV_KMAP:
return (char_u *)&(curbuf->b_p_keymap); return (char_u *)&(curbuf->b_p_keymap);
case PV_SCL: case PV_SCL:
@ -6170,6 +6170,8 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_list = from->wo_list; to->wo_list = from->wo_list;
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;
to->wo_nuw = from->wo_nuw; to->wo_nuw = from->wo_nuw;
to->wo_rl = from->wo_rl; to->wo_rl = from->wo_rl;
to->wo_rlc = vim_strsave(from->wo_rlc); to->wo_rlc = vim_strsave(from->wo_rlc);
@ -6246,6 +6248,7 @@ static void check_winopt(winopt_T *wop)
check_string_option(&wop->wo_winhl); check_string_option(&wop->wo_winhl);
check_string_option(&wop->wo_fcs); check_string_option(&wop->wo_fcs);
check_string_option(&wop->wo_lcs); check_string_option(&wop->wo_lcs);
check_string_option(&wop->wo_ve);
} }
/// Free the allocated memory inside a winopt_T. /// Free the allocated memory inside a winopt_T.
@ -6270,6 +6273,7 @@ void clear_winopt(winopt_T *wop)
clear_string_option(&wop->wo_winhl); clear_string_option(&wop->wo_winhl);
clear_string_option(&wop->wo_fcs); clear_string_option(&wop->wo_fcs);
clear_string_option(&wop->wo_lcs); clear_string_option(&wop->wo_lcs);
clear_string_option(&wop->wo_ve);
} }
void didset_window_options(win_T *wp) void didset_window_options(win_T *wp)
@ -6460,8 +6464,6 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_udf = p_udf; buf->b_p_udf = p_udf;
buf->b_p_lw = empty_option; buf->b_p_lw = empty_option;
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,
@ -7842,7 +7844,7 @@ unsigned int get_bkc_value(buf_T *buf)
/// Get the local or global value of the 'virtualedit' flags. /// Get the local or global value of the 'virtualedit' flags.
unsigned int get_ve_flags(void) unsigned int get_ve_flags(void)
{ {
return (curbuf->b_ve_flags ? curbuf->b_ve_flags : ve_flags) & ~(VE_NONE | VE_NONEU); return (curwin->w_ve_flags ? curwin->w_ve_flags : ve_flags) & ~(VE_NONE | VE_NONEU);
} }
/// Get the local or global value of 'showbreak'. /// Get the local or global value of 'showbreak'.

View File

@ -711,8 +711,8 @@ static char *(p_ve_values[]) = { "block", "insert", "all", "onemore", "none", "N
#define VE_INSERT 6U // includes "all" #define VE_INSERT 6U // includes "all"
#define VE_ALL 4U #define VE_ALL 4U
#define VE_ONEMORE 8U #define VE_ONEMORE 8U
#define VE_NONE 16U #define VE_NONE 16U // "none"
#define VE_NONEU 32U // Upper-case NONE #define VE_NONEU 32U // "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

@ -1215,14 +1215,14 @@ static void win_update(win_T *wp, Providers *providers)
*/ */
if (VIsual_mode == Ctrl_V) { if (VIsual_mode == Ctrl_V) {
colnr_T fromc, toc; colnr_T fromc, toc;
unsigned int save_ve_flags = curbuf->b_ve_flags; unsigned 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;
} }
getvcols(wp, &VIsual, &curwin->w_cursor, &fromc, &toc); getvcols(wp, &VIsual, &curwin->w_cursor, &fromc, &toc);
curbuf->b_ve_flags = save_ve_flags; curwin->w_ve_flags = save_ve_flags;
toc++; toc++;
// Highlight to the end of the line, unless 'virtualedit' has // Highlight to the end of the line, unless 'virtualedit' has
// "block". // "block".

View File

@ -263,7 +263,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
@ -271,7 +271,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
@ -291,8 +291,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))
@ -305,17 +305,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))
@ -374,6 +372,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