# HG changeset patch # User Bram Moolenaar # Date 1651834803 -7200 # Node ID 5eea8a249f86a26b0be1139b7046d59522533645 # Parent f608d3f98e0e144e6e568ac878eb3fea3538d4a8 patch 8.2.4881: "P" in Visual mode still changes some registers Commit: https://github.com/vim/vim/commit/509142ab7a9db32114b6d0949722b9133c9c22f2 Author: Shougo Matsushita Date: Fri May 6 11:45:09 2022 +0100 patch 8.2.4881: "P" in Visual mode still changes some registers Problem: "P" in Visual mode still changes some registers. Solution: Make "P" in Visual mode not change any register. (Shougo Matsushita, closes #10349) diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1177,14 +1177,15 @@ register. With blockwise selection it a and whether the corners are on an existing character. (Implementation detail: it actually works by first putting the register after the selection and then deleting the selection.) -With 'p' the previously selected text is put in the unnamed register. This is -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 -replace and use "0p . You can repeat this as many times as you like, and the -unnamed register will be changed each time. +With |p| the previously selected text is put in the unnamed register (and +possibly the selection and/or clipboard). This is 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 (and neither the selection or +clipboard), 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 replace and use "0p . You can +repeat this as many times as you like, and the unnamed register will be +changed each time. When you use a blockwise Visual mode command and yank only a single line into a register, a paste on a visual selected area will paste that single line on diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -939,7 +939,7 @@ tag command note action in Visual |v_K| K run 'keywordprg' on the highlighted area |v_O| O move horizontally to other corner of area |v_P| P replace highlighted area with register - contents; unnamed register is unchanged + contents; registers are unchanged Q does not start Ex mode |v_R| R 2 delete the highlighted lines and start insert diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt --- a/runtime/doc/visual.txt +++ b/runtime/doc/visual.txt @@ -265,7 +265,7 @@ Additionally the following commands can X delete (2) |v_X| Y yank (2) |v_Y| p put |v_p| - P put without unnamed register overwrite |v_P| + P put without overwriting registers |v_P| J join (1) |v_J| U make uppercase |v_U| u make lowercase |v_u| diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -7236,8 +7236,7 @@ nv_put_opt(cmdarg_T *cap, int fix_indent int was_visual = FALSE; int dir; int flags = 0; - int save_unnamed = FALSE; - yankreg_T *old_y_current, *old_y_previous; + int keep_registers = FALSE; if (cap->oap->op_type != OP_NOP) { @@ -7284,7 +7283,7 @@ nv_put_opt(cmdarg_T *cap, int fix_indent // overwrites if the old contents is being put. was_visual = TRUE; regname = cap->oap->regname; - save_unnamed = cap->cmdchar == 'P'; + keep_registers = cap->cmdchar == 'P'; #ifdef FEAT_CLIPBOARD adjust_clip_reg(®name); #endif @@ -7302,26 +7301,15 @@ nv_put_opt(cmdarg_T *cap, int fix_indent } // Now delete the selected text. Avoid messages here. - if (save_unnamed) - { - old_y_current = get_y_current(); - old_y_previous = get_y_previous(); - } cap->cmdchar = 'd'; cap->nchar = NUL; - cap->oap->regname = NUL; + cap->oap->regname = keep_registers ? '_' : NUL; ++msg_silent; nv_operator(cap); do_pending_operator(cap, 0, FALSE); empty = (curbuf->b_ml.ml_flags & ML_EMPTY); --msg_silent; - if (save_unnamed) - { - set_y_current(old_y_current); - set_y_previous(old_y_previous); - } - // delete PUT_LINE_BACKWARD; cap->oap->regname = regname; diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim --- a/src/testdir/test_visual.vim +++ b/src/testdir/test_visual.vim @@ -1390,34 +1390,74 @@ func Test_visual_paste() call assert_equal('x', @-) call assert_equal('bazooxxf', getline(1)) - if has('clipboard') - " v_P does not overwrite unnamed register. + bwipe! +endfunc + +func Test_visual_paste_clipboard() + CheckFeature clipboard_working + + if has('gui') + " auto select feature breaks tests + set guioptions-=a + endif + + " 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('bar', @-) + call assert_equal('fooxxx', getline(1)) + normal $vP + call assert_equal('foo', @") + call assert_equal('bar', @-) + 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('bar', @-) + call assert_equal('bazooxxfoo', getline(1)) + normal $vP + call assert_equal('baz', @") + call assert_equal('bar', @-) + call assert_equal('bazooxxfobaz', getline(1)) + + " Test for unnamed clipboard + set clipboard=unnamed + call setline(1, ['xxxx']) + call setreg('"', 'foo') + call setreg('-', 'bar') + call setreg('*', 'baz') + normal gg0vP + call assert_equal('foo', @") + call assert_equal('bar', @-) + call assert_equal('baz', @*) + call assert_equal('bazxxx', getline(1)) + + " Test for unnamedplus clipboard + if has('unnamedplus') + set clipboard=unnamedplus call setline(1, ['xxxx']) call setreg('"', 'foo') call setreg('-', 'bar') + call setreg('+', 'baz') 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)) + call assert_equal('bar', @-) + call assert_equal('baz', @+) + call assert_equal('bazxxx', getline(1)) endif + set clipboard& + if has('gui') + set guioptions& + endif bwipe! 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 @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4881, +/**/ 4880, /**/ 4879,