Merge pull request #17346 from zeertzjq/vim-8.2.4242

vim-patch:8.2.{4242,4315}: put in Visual mode cannot be repeated
This commit is contained in:
zeertzjq 2022-02-09 20:46:30 +08:00 committed by GitHub
commit 60e3940b4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 98 additions and 12 deletions

View File

@ -1118,8 +1118,11 @@ register. With blockwise selection it also depends on the size of the block
and whether the corners are on an existing character. (Implementation detail: and whether the corners are on an existing character. (Implementation detail:
it actually works by first putting the register after the selection and then it actually works by first putting the register after the selection and then
deleting the selection.) deleting the selection.)
The previously selected text is put in the unnamed register. If you want to With 'p' the previously selected text is put in the unnamed register. This is
put the same text into a Visual selection several times you need to use useful if you want to put that text somewhere else. But you cannot repeat the
same change.
With 'P' the unnamed register is not changed, you can repeat the same change.
But the deleted text cannot be used. If you do need it you can use 'p' with
another register. E.g., yank the text to copy, Visually select the text to another register. E.g., yank the text to copy, Visually select the text to
replace and use "0p . You can repeat this as many times as you like, and the replace and use "0p . You can repeat this as many times as you like, and the
unnamed register will be changed each time. unnamed register will be changed each time.

View File

@ -923,7 +923,9 @@ tag command note action in Visual mode ~
before the highlighted area before the highlighted area
|v_J| J 2 join the highlighted lines |v_J| J 2 join the highlighted lines
|v_K| K run 'keywordprg' on the highlighted area |v_K| K run 'keywordprg' on the highlighted area
|v_O| O move horizontally to other corner of area. |v_O| O move horizontally to other corner of area
|v_P| P replace highlighted area with register
contents; unnamed register is unchanged
Q does not start Ex mode Q does not start Ex mode
|v_R| R 2 delete the highlighted lines and start |v_R| R 2 delete the highlighted lines and start
insert insert

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,66 @@ 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 gg0vp
call assert_equal('x', @")
call assert_equal('x', @-)
call assert_equal('fooxxx', getline(1))
normal $vp
call assert_equal('x', @")
call assert_equal('x', @-)
call assert_equal('fooxxx', getline(1))
" Test with a different register as unnamed register.
call setline(2, ['baz'])
normal 2gg0"rD
call assert_equal('baz', @")
normal gg0vp
call assert_equal('f', @")
call assert_equal('f', @-)
call assert_equal('bazooxxx', getline(1))
normal $vp
call assert_equal('x', @")
call assert_equal('x', @-)
call assert_equal('bazooxxf', getline(1))
if has('clipboard')
" v_P does not overwrite unnamed register.
call setline(1, ['xxxx'])
call setreg('"', 'foo')
call setreg('-', 'bar')
normal gg0vP
call assert_equal('foo', @")
call assert_equal('x', @-)
call assert_equal('fooxxx', getline(1))
normal $vP
call assert_equal('foo', @")
call assert_equal('x', @-)
call assert_equal('fooxxfoo', getline(1))
" Test with a different register as unnamed register.
call setline(2, ['baz'])
normal 2gg0"rD
call assert_equal('baz', @")
normal gg0vP
call assert_equal('baz', @")
call assert_equal('f', @-)
call assert_equal('bazooxxfoo', getline(1))
normal $vP
call assert_equal('baz', @")
call assert_equal('o', @-)
call assert_equal('bazooxxfobaz', getline(1))
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