mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 03:48:18 +00:00
vim-patch:9.1.1175: inconsistent behaviour with exclusive selection and motion commands (#32745)
Problem: inconsistent behaviour with exclusive selection and motion
commands (aidancz)
Solution: adjust cursor position when selection is exclusive
(Jim Zhou)
fixes: vim/vim#16278
closes: vim/vim#16784
c8cce711dd
Co-authored-by: Jim Zhou <jimzhouzzy@gmail.com>
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
This commit is contained in:
@@ -464,6 +464,8 @@ EXTERN bool VIsual_active INIT( = false);
|
|||||||
EXTERN bool VIsual_select INIT( = false);
|
EXTERN bool VIsual_select INIT( = false);
|
||||||
/// Register name for Select mode
|
/// Register name for Select mode
|
||||||
EXTERN int VIsual_select_reg INIT( = 0);
|
EXTERN int VIsual_select_reg INIT( = 0);
|
||||||
|
/// Whether incremented cursor during exclusive selection
|
||||||
|
EXTERN bool VIsual_select_exclu_adj INIT( = false);
|
||||||
/// Restart Select mode when next cmd finished
|
/// Restart Select mode when next cmd finished
|
||||||
EXTERN int restart_VIsual_select INIT( = 0);
|
EXTERN int restart_VIsual_select INIT( = 0);
|
||||||
/// Whether to restart the selection after a Select-mode mapping or menu.
|
/// Whether to restart the selection after a Select-mode mapping or menu.
|
||||||
|
@@ -1524,6 +1524,7 @@ static void set_vcount_ca(cmdarg_T *cap, bool *set_prevcount)
|
|||||||
/// do_pending_operator().
|
/// do_pending_operator().
|
||||||
void end_visual_mode(void)
|
void end_visual_mode(void)
|
||||||
{
|
{
|
||||||
|
VIsual_select_exclu_adj = false;
|
||||||
VIsual_active = false;
|
VIsual_active = false;
|
||||||
setmouse();
|
setmouse();
|
||||||
mouse_dragging = 0;
|
mouse_dragging = 0;
|
||||||
@@ -4035,17 +4036,24 @@ static int normal_search(cmdarg_T *cap, int dir, char *pat, size_t patlen, int o
|
|||||||
/// cap->nchar is NUL for ',' and ';' (repeat the search)
|
/// cap->nchar is NUL for ',' and ';' (repeat the search)
|
||||||
static void nv_csearch(cmdarg_T *cap)
|
static void nv_csearch(cmdarg_T *cap)
|
||||||
{
|
{
|
||||||
bool t_cmd;
|
bool cursor_dec = false;
|
||||||
|
|
||||||
if (cap->cmdchar == 't' || cap->cmdchar == 'T') {
|
// If adjusted cursor position previously, unadjust it.
|
||||||
t_cmd = true;
|
if (*p_sel == 'e' && VIsual_active && VIsual_mode == 'v'
|
||||||
} else {
|
&& VIsual_select_exclu_adj) {
|
||||||
t_cmd = false;
|
unadjust_for_sel();
|
||||||
|
cursor_dec = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool t_cmd = cap->cmdchar == 't' || cap->cmdchar == 'T';
|
||||||
|
|
||||||
cap->oap->motion_type = kMTCharWise;
|
cap->oap->motion_type = kMTCharWise;
|
||||||
if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == false) {
|
if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == false) {
|
||||||
clearopbeep(cap->oap);
|
clearopbeep(cap->oap);
|
||||||
|
// Revert unadjust when failed.
|
||||||
|
if (cursor_dec) {
|
||||||
|
adjust_for_sel(cap);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5054,6 +5062,8 @@ static void nv_visual(cmdarg_T *cap)
|
|||||||
n_start_visual_mode(cap->cmdchar);
|
n_start_visual_mode(cap->cmdchar);
|
||||||
if (VIsual_mode != 'V' && *p_sel == 'e') {
|
if (VIsual_mode != 'V' && *p_sel == 'e') {
|
||||||
cap->count1++; // include one more char
|
cap->count1++; // include one more char
|
||||||
|
} else {
|
||||||
|
VIsual_select_exclu_adj = false;
|
||||||
}
|
}
|
||||||
if (cap->count0 > 0 && --cap->count1 > 0) {
|
if (cap->count0 > 0 && --cap->count1 > 0) {
|
||||||
// With a count select that many characters or lines.
|
// With a count select that many characters or lines.
|
||||||
@@ -6021,6 +6031,7 @@ static void adjust_for_sel(cmdarg_T *cap)
|
|||||||
&& gchar_cursor() != NUL && lt(VIsual, curwin->w_cursor)) {
|
&& gchar_cursor() != NUL && lt(VIsual, curwin->w_cursor)) {
|
||||||
inc_cursor();
|
inc_cursor();
|
||||||
cap->oap->inclusive = false;
|
cap->oap->inclusive = false;
|
||||||
|
VIsual_select_exclu_adj = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6042,7 +6053,7 @@ bool unadjust_for_sel(void)
|
|||||||
/// @return true when backed up to the previous line.
|
/// @return true when backed up to the previous line.
|
||||||
bool unadjust_for_sel_inner(pos_T *pp)
|
bool unadjust_for_sel_inner(pos_T *pp)
|
||||||
{
|
{
|
||||||
colnr_T cs, ce;
|
VIsual_select_exclu_adj = false;
|
||||||
|
|
||||||
if (pp->coladd > 0) {
|
if (pp->coladd > 0) {
|
||||||
pp->coladd--;
|
pp->coladd--;
|
||||||
@@ -6050,6 +6061,7 @@ bool unadjust_for_sel_inner(pos_T *pp)
|
|||||||
pp->col--;
|
pp->col--;
|
||||||
mark_mb_adjustpos(curbuf, pp);
|
mark_mb_adjustpos(curbuf, pp);
|
||||||
if (virtual_active(curwin)) {
|
if (virtual_active(curwin)) {
|
||||||
|
colnr_T cs, ce;
|
||||||
getvcol(curwin, pp, &cs, NULL, &ce);
|
getvcol(curwin, pp, &cs, NULL, &ce);
|
||||||
pp->coladd = ce - cs;
|
pp->coladd = ce - cs;
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include "nvim/memline.h"
|
#include "nvim/memline.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
|
#include "nvim/normal.h"
|
||||||
#include "nvim/option_vars.h"
|
#include "nvim/option_vars.h"
|
||||||
#include "nvim/pos_defs.h"
|
#include "nvim/pos_defs.h"
|
||||||
#include "nvim/search.h"
|
#include "nvim/search.h"
|
||||||
@@ -427,6 +428,13 @@ int end_word(int count, bool bigword, bool stop, bool empty)
|
|||||||
|
|
||||||
curwin->w_cursor.coladd = 0;
|
curwin->w_cursor.coladd = 0;
|
||||||
cls_bigword = bigword;
|
cls_bigword = bigword;
|
||||||
|
|
||||||
|
// If adjusted cursor position previously, unadjust it.
|
||||||
|
if (*p_sel == 'e' && VIsual_active && VIsual_mode == 'v'
|
||||||
|
&& VIsual_select_exclu_adj) {
|
||||||
|
unadjust_for_sel();
|
||||||
|
}
|
||||||
|
|
||||||
while (--count >= 0) {
|
while (--count >= 0) {
|
||||||
// When inside a range of folded lines, move to the last char of the
|
// When inside a range of folded lines, move to the last char of the
|
||||||
// last line.
|
// last line.
|
||||||
|
@@ -1101,6 +1101,50 @@ func Test_exclusive_selection()
|
|||||||
bw!
|
bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for inclusive motion in visual mode with 'exclusive' selection
|
||||||
|
func Test_inclusive_motion_selection_exclusive()
|
||||||
|
func s:compare_exclu_inclu(line, keys, expected_exclu)
|
||||||
|
let msg = "data: '" . a:line . "' operation: '" . a:keys . "'"
|
||||||
|
call setline(1, a:line)
|
||||||
|
set selection=exclusive
|
||||||
|
call feedkeys(a:keys, 'xt')
|
||||||
|
call assert_equal(a:expected_exclu, getpos('.'), msg)
|
||||||
|
let pos_ex = col('.')
|
||||||
|
set selection=inclusive
|
||||||
|
call feedkeys(a:keys, 'xt')
|
||||||
|
let pos_in = col('.')
|
||||||
|
call assert_equal(1, pos_ex - pos_in, msg)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
new
|
||||||
|
" Test 'e' motion
|
||||||
|
set selection=exclusive
|
||||||
|
call setline(1, 'eins zwei drei')
|
||||||
|
norm! ggvey
|
||||||
|
call assert_equal('eins', @")
|
||||||
|
call setline(1, 'abc(abc)abc')
|
||||||
|
norm! ggveeed
|
||||||
|
call assert_equal(')abc', getline(1))
|
||||||
|
call setline(1, 'abc(abc)abc')
|
||||||
|
norm! gg3lvey
|
||||||
|
call assert_equal('(abc', @")
|
||||||
|
call s:compare_exclu_inclu('abc(abc)abc', 'ggveee', [0, 1, 8, 0])
|
||||||
|
" Test 'f' motion
|
||||||
|
call s:compare_exclu_inclu('geschwindigkeit', 'ggvfefe', [0, 1, 14, 0])
|
||||||
|
call s:compare_exclu_inclu('loooooooooooong', 'ggv2fo2fo2fo', [0, 1, 8, 0])
|
||||||
|
" Test 't' motion
|
||||||
|
call s:compare_exclu_inclu('geschwindigkeit', 'ggv2te', [0, 1, 13, 0])
|
||||||
|
call s:compare_exclu_inclu('loooooooooooong', 'gglv2to2to2to', [0, 1, 6, 0])
|
||||||
|
" Test ';' motion
|
||||||
|
call s:compare_exclu_inclu('geschwindigkeit', 'ggvfi;;', [0, 1, 15, 0])
|
||||||
|
call s:compare_exclu_inclu('geschwindigkeit', 'ggvti;;', [0, 1, 14, 0])
|
||||||
|
call s:compare_exclu_inclu('loooooooooooong', 'ggv2fo;;', [0, 1, 6, 0])
|
||||||
|
call s:compare_exclu_inclu('loooooooooooong', 'ggvl2to;;', [0, 1, 6, 0])
|
||||||
|
" Clean up
|
||||||
|
set selection&
|
||||||
|
bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" Test for starting linewise visual with a count.
|
" Test for starting linewise visual with a count.
|
||||||
" This test needs to be run without any previous visual mode. Otherwise the
|
" This test needs to be run without any previous visual mode. Otherwise the
|
||||||
" count will use the count from the previous visual mode.
|
" count will use the count from the previous visual mode.
|
||||||
|
Reference in New Issue
Block a user