vim-patch:8.2.4242: put in Visual mode cannot be repeated

Problem:    Put in Visual mode cannot be repeated.
Solution:   Use "P" to put without yanking the deleted text into the unnamed
            register. (Shougo Matsushita, closes vim/vim#9591)
fb55207ed1

Cherry-pick get_y_previous() and set_y_previous() from patch 8.1.1736.
Nvim has removed y_current, so code related to it is N/A.
This commit is contained in:
zeertzjq 2022-02-09 14:21:04 +08:00
parent 07c97fa02d
commit d9cb3fba92
5 changed files with 56 additions and 9 deletions

View File

@ -255,6 +255,7 @@ Additionally the following commands can be used:
X delete (2) |v_X| X delete (2) |v_X|
Y yank (2) |v_Y| Y yank (2) |v_Y|
p put |v_p| p put |v_p|
P put without unnamed register overwrite |v_P|
J join (1) |v_J| J join (1) |v_J|
U make uppercase |v_U| U make uppercase |v_U|
u make lowercase |v_u| u make lowercase |v_u|

View File

@ -7509,9 +7509,9 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
// overwrites if the old contents is being put. // overwrites if the old contents is being put.
was_visual = true; was_visual = true;
regname = cap->oap->regname; regname = cap->oap->regname;
bool save_unnamed = cap->cmdchar == 'P';
// '+' and '*' could be the same selection // '+' and '*' could be the same selection
bool clipoverwrite = (regname == '+' || regname == '*') bool clipoverwrite = (regname == '+' || regname == '*') && (cb_flags & CB_UNNAMEDMASK);
&& (cb_flags & CB_UNNAMEDMASK);
if (regname == 0 || regname == '"' || clipoverwrite if (regname == 0 || regname == '"' || clipoverwrite
|| ascii_isdigit(regname) || regname == '-') { || ascii_isdigit(regname) || regname == '-') {
// The delete might overwrite the register we want to put, save it first // The delete might overwrite the register we want to put, save it first
@ -7524,6 +7524,10 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
// do_put(), which requires the visual selection to still be active. // do_put(), which requires the visual selection to still be active.
if (!VIsual_active || VIsual_mode == 'V' || regname != '.') { if (!VIsual_active || VIsual_mode == 'V' || regname != '.') {
// Now delete the selected text. Avoid messages here. // Now delete the selected text. Avoid messages here.
yankreg_T *old_y_previous;
if (save_unnamed) {
old_y_previous = get_y_previous();
}
cap->cmdchar = 'd'; cap->cmdchar = 'd';
cap->nchar = NUL; cap->nchar = NUL;
cap->oap->regname = NUL; cap->oap->regname = NUL;
@ -7533,6 +7537,10 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
empty = (curbuf->b_ml.ml_flags & ML_EMPTY); empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
msg_silent--; msg_silent--;
if (save_unnamed) {
set_y_previous(old_y_previous);
}
// delete PUT_LINE_BACKWARD; // delete PUT_LINE_BACKWARD;
cap->oap->regname = regname; cap->oap->regname = regname;
} }

View File

@ -135,10 +135,18 @@ static char opchars[][3] =
{ Ctrl_X, NUL, OPF_CHANGE }, // OP_NR_SUB { Ctrl_X, NUL, OPF_CHANGE }, // OP_NR_SUB
}; };
/* yankreg_T *get_y_previous(void)
* Translate a command name into an operator type. {
* Must only be called with a valid operator name! return y_previous;
*/ }
void set_y_previous(yankreg_T *yreg)
{
y_previous = yreg;
}
/// Translate a command name into an operator type.
/// Must only be called with a valid operator name!
int get_op_type(int char1, int char2) int get_op_type(int char1, int char2)
{ {
int i; int i;

View File

@ -1184,8 +1184,32 @@ func Test_visual_undo_deletes_last_line()
exe "normal ggvjfxO" exe "normal ggvjfxO"
undo undo
normal gNU normal gNU
bwipe! bwipe!
endfunc endfunc
func Test_visual_paste()
new
" v_p overwrites unnamed register.
call setline(1, ['xxxx'])
call setreg('"', 'foo')
call setreg('-', 'bar')
normal 1Gvp
call assert_equal(@", 'x')
call assert_equal(@-, 'x')
if has('clipboard')
" v_P does not overwrite unnamed register.
call setline(1, ['xxxx'])
call setreg('"', 'foo')
call setreg('-', 'bar')
normal 1GvP
call assert_equal(@", 'foo')
call assert_equal(@-, 'x')
endif
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@ -507,7 +507,9 @@ describe('put command', function()
return function(exception_table, after_redo) return function(exception_table, after_redo)
test_expect(exception_table, after_redo) test_expect(exception_table, after_redo)
if selection_string then if selection_string then
eq(selection_string, getreg('"')) if not conversion_table.put_backwards then
eq(selection_string, getreg('"'))
end
else else
eq('test_string"', getreg('"')) eq('test_string"', getreg('"'))
end end
@ -714,7 +716,9 @@ describe('put command', function()
expect_base, conversion_table) expect_base, conversion_table)
return function(exception_table, after_redo) return function(exception_table, after_redo)
test_expect(exception_table, after_redo) test_expect(exception_table, after_redo)
eq('Line of words 1\n', getreg('"')) if not conversion_table.put_backwards then
eq('Line of words 1\n', getreg('"'))
end
end end
end end
local base_expect_string = [[ local base_expect_string = [[
@ -748,7 +752,9 @@ describe('put command', function()
end, expect_base, conversion_table) end, expect_base, conversion_table)
return function(e,c) return function(e,c)
test_expect(e,c) test_expect(e,c)
eq('Lin\nLin', getreg('"')) if not conversion_table.put_backwards then
eq('Lin\nLin', getreg('"'))
end
end end
end end