# HG changeset patch # User Bram Moolenaar # Date 1642692604 -3600 # Node ID 93d4ee1e61136e5bb1b04c17862c027becc38c0a # Parent f2056837b78a1f997f8cb1d74112eea1ea9dcb3e patch 8.2.4160: cannot change the register used for Select mode delete Commit: https://github.com/vim/vim/commit/4ede01f18884961f2e008880b4964e5d61ea5c36 Author: Shougo Matsushita Date: Thu Jan 20 15:26:03 2022 +0000 patch 8.2.4160: cannot change the register used for Select mode delete Problem: Cannot change the register used for Select mode delete. Solution: Make CTRL-R set the register to be used when deleting text for Select mode. (Shougo Matsushita, closes #9531) diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt --- a/runtime/doc/visual.txt +++ b/runtime/doc/visual.txt @@ -488,6 +488,11 @@ Commands in Select mode: - ESC stops Select mode. - CTRL-O switches to Visual mode for the duration of one command. *v_CTRL-O* - CTRL-G switches to Visual mode. +- CTRL-R {register} selects the register to be used for the text that is + deleted when typing text. *v_CTRL-R* + Unless you specify the "_" (black hole) register, the unnamed register is + also overwritten. + Otherwise, typed characters are handled as in Visual mode. diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -875,6 +875,8 @@ EXTERN int VIsual_active INIT(= FALSE); // whether Visual mode is active EXTERN int VIsual_select INIT(= FALSE); // whether Select mode is active +EXTERN int VIsual_select_reg INIT(= 0); + // register name for Select mode EXTERN int restart_VIsual_select INIT(= 0); // restart Select mode when next cmd finished EXTERN int VIsual_reselect; diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -89,7 +89,7 @@ static void nv_window(cmdarg_T *cap); static void nv_suspend(cmdarg_T *cap); static void nv_g_cmd(cmdarg_T *cap); static void nv_dot(cmdarg_T *cap); -static void nv_redo(cmdarg_T *cap); +static void nv_redo_or_register(cmdarg_T *cap); static void nv_Undo(cmdarg_T *cap); static void nv_tilde(cmdarg_T *cap); static void nv_operator(cmdarg_T *cap); @@ -188,7 +188,7 @@ static const struct nv_cmd {Ctrl_O, nv_ctrlo, 0, 0}, {Ctrl_P, nv_up, NV_STS, FALSE}, {Ctrl_Q, nv_visual, 0, FALSE}, - {Ctrl_R, nv_redo, 0, 0}, + {Ctrl_R, nv_redo_or_register, 0, 0}, {Ctrl_S, nv_ignore, 0, 0}, {Ctrl_T, nv_tagpop, NV_NCW, 0}, {Ctrl_U, nv_halfpage, 0, 0}, @@ -1303,6 +1303,7 @@ normal_end: trigger_modechanged(); showmode(); restart_VIsual_select = 0; + VIsual_select_reg = 0; } if (restart_edit != 0 && !VIsual_active && old_mapped_len == 0) (void)edit(restart_edit, FALSE, 1L); @@ -5997,7 +5998,10 @@ nv_g_cmd(cmdarg_T *cap) * start Select mode. */ if (cap->arg) + { VIsual_select = TRUE; + VIsual_select_reg = 0; + } else may_start_select('c'); setmouse(); @@ -6550,11 +6554,30 @@ nv_dot(cmdarg_T *cap) } /* - * CTRL-R: undo undo + * CTRL-R: undo undo or specify register in select mode */ static void -nv_redo(cmdarg_T *cap) -{ +nv_redo_or_register(cmdarg_T *cap) +{ + if (VIsual_select && VIsual_active) + { + int reg; + // Get register name + ++no_mapping; + ++allow_keys; + reg = plain_vgetc(); + LANGMAP_ADJUST(reg, TRUE); + --no_mapping; + --allow_keys; + + if (reg == '"') + // the unnamed register is 0 + reg = 0; + + VIsual_select_reg = valid_yank_reg(reg, TRUE) ? reg : 0; + return; + } + if (!checkclearopq(cap->oap)) { u_redo((int)cap->count1); @@ -6926,7 +6949,10 @@ unadjust_for_sel(void) nv_select(cmdarg_T *cap) { if (VIsual_active) + { VIsual_select = TRUE; + VIsual_select_reg = 0; + } else if (VIsual_reselect) { cap->nchar = 'v'; // fake "gv" command diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -624,6 +624,10 @@ op_delete(oparg_T *oap) return FAIL; } + if (VIsual_select && oap->is_VIsual) + // use register given with CTRL_R, defaults to zero + oap->regname = VIsual_select_reg; + #ifdef FEAT_CLIPBOARD adjust_clip_reg(&oap->regname); #endif diff --git a/src/testdir/test_selectmode.vim b/src/testdir/test_selectmode.vim --- a/src/testdir/test_selectmode.vim +++ b/src/testdir/test_selectmode.vim @@ -258,4 +258,56 @@ func Test_term_mouse_multiple_clicks_to_ bwipe! endfunc +" Test for selecting a register with CTRL-R +func Test_selectmode_register() + new + + " Default behavior: use unnamed register + call setline(1, 'foo') + call setreg('"', 'bar') + call setreg('a', 'baz') + exe ":norm! v\a" + call assert_equal(getline('.'), 'aoo') + call assert_equal('f', getreg('"')) + call assert_equal('baz', getreg('a')) + + " Use the black hole register + call setline(1, 'foo') + call setreg('"', 'bar') + call setreg('a', 'baz') + exe ":norm! v\\_a" + call assert_equal(getline('.'), 'aoo') + call assert_equal('bar', getreg('"')) + call assert_equal('baz', getreg('a')) + + " Invalid register: use unnamed register + call setline(1, 'foo') + call setreg('"', 'bar') + call setreg('a', 'baz') + exe ":norm! v\\?a" + call assert_equal(getline('.'), 'aoo') + call assert_equal('f', getreg('"')) + call assert_equal('baz', getreg('a')) + + " Use unnamed register + call setline(1, 'foo') + call setreg('"', 'bar') + call setreg('a', 'baz') + exe ":norm! v\\\"a" + call assert_equal(getline('.'), 'aoo') + call assert_equal('f', getreg('"')) + call assert_equal('baz', getreg('a')) + + " use specicifed register, unnamed register is also written + call setline(1, 'foo') + call setreg('"', 'bar') + call setreg('a', 'baz') + exe ":norm! v\\aa" + call assert_equal(getline('.'), 'aoo') + call assert_equal('f', getreg('"')) + call assert_equal('f', getreg('a')) + + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4160, +/**/ 4159, /**/ 4158,