]> granicus.if.org Git - vim/commitdiff
patch 8.2.4567: bracketed paste doesn't work well in Visual linewise mode v8.2.4567
authorzeertzjq <zeertzjq@outlook.com>
Mon, 14 Mar 2022 20:46:41 +0000 (20:46 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 14 Mar 2022 20:46:41 +0000 (20:46 +0000)
Problem:    Bracketed paste doesn't work well in Visual linewise mode.
Solution:   Handle linewise Visual mode differently. (closes #9947)

src/normal.c
src/testdir/test_paste.vim
src/version.c

index 9376be5ceb1a60ef10765319df259a7749418fdb..e39fb772ae15c5ca7edd7d08b738d13cc1ce6e3a 100644 (file)
@@ -6880,6 +6880,7 @@ nv_edit(cmdarg_T *cap)
     {
        pos_T old_pos = curwin->w_cursor;
        pos_T old_visual = VIsual;
+       int old_visual_mode = VIsual_mode;
 
        // In Visual mode the selected text is deleted.
        if (VIsual_mode == 'V' || curwin->w_cursor.lnum != VIsual.lnum)
@@ -6895,11 +6896,32 @@ nv_edit(cmdarg_T *cap)
        do_pending_operator(cap, 0, FALSE);
        cap->cmdchar = K_PS;
 
-       // When the last char in the line was deleted then append. Detect this
-       // by checking if the cursor moved to before the Visual area.
-       if (*ml_get_cursor() != NUL && LT_POS(curwin->w_cursor, old_pos)
-                                      && LT_POS(curwin->w_cursor, old_visual))
-           inc_cursor();
+       if (*ml_get_cursor() != NUL)
+       {
+           if (old_visual_mode == 'V')
+           {
+               // In linewise Visual mode insert before the beginning of the
+               // next line.
+               // When the last line in the buffer was deleted then create a
+               // new line, otherwise there is not need to move cursor.
+               // Detect this by checking if cursor moved above Visual area.
+               if (curwin->w_cursor.lnum < old_pos.lnum
+                               && curwin->w_cursor.lnum < old_visual.lnum)
+               {
+                   if (u_save_cursor() == OK)
+                   {
+                       ml_append(curwin->w_cursor.lnum, (char_u *)"", 0,
+                                                                       FALSE);
+                       appended_lines(curwin->w_cursor.lnum++, 1L);
+                   }
+               }
+           }
+           // When the last char in the line was deleted then append.
+           // Detect this by checking if cursor moved before Visual area.
+           else if (curwin->w_cursor.col < old_pos.col
+                               && curwin->w_cursor.col < old_visual.col)
+               inc_cursor();
+       }
 
        // Insert to replace the deleted text with the pasted text.
        invoke_edit(cap, FALSE, cap->cmdchar, FALSE);
index 5b8d8a0e3e2dba9642b16e4e6be34c36fa9af6fc..a59e1286916ef7baae079282c785585e6115eaaf 100644 (file)
@@ -109,23 +109,69 @@ func Test_paste_visual_mode()
   call feedkeys("0fsve\<Esc>[200~more\<Esc>[201~", 'xt')
   call assert_equal('here are more words', getline(1))
   call assert_equal('some', getreg('-'))
+  normal! u
+  call assert_equal('here are some words', getline(1))
+  exe "normal! \<C-R>"
+  call assert_equal('here are more words', getline(1))
 
   " include last char in the line
   call feedkeys("0fwve\<Esc>[200~noises\<Esc>[201~", 'xt')
   call assert_equal('here are more noises', getline(1))
   call assert_equal('words', getreg('-'))
+  normal! u
+  call assert_equal('here are more words', getline(1))
+  exe "normal! \<C-R>"
+  call assert_equal('here are more noises', getline(1))
 
   " exclude last char in the line
   call setline(1, 'some words!')
   call feedkeys("0fwve\<Esc>[200~noises\<Esc>[201~", 'xt')
   call assert_equal('some noises!', getline(1))
   call assert_equal('words', getreg('-'))
+  normal! u
+  call assert_equal('some words!', getline(1))
+  exe "normal! \<C-R>"
+  call assert_equal('some noises!', getline(1))
 
   " multi-line selection
   call setline(1, ['some words', 'and more'])
   call feedkeys("0fwvj0fd\<Esc>[200~letters\<Esc>[201~", 'xt')
   call assert_equal('some letters more', getline(1))
   call assert_equal("words\nand", getreg('1'))
+  normal! u
+  call assert_equal(['some words', 'and more'], getline(1, 2))
+  exe "normal! \<C-R>"
+  call assert_equal('some letters more', getline(1))
+
+  " linewise non-last line, cursor at start of line
+  call setline(1, ['some words', 'and more'])
+  call feedkeys("0V\<Esc>[200~letters\<Esc>[201~", 'xt')
+  call assert_equal('lettersand more', getline(1))
+  call assert_equal("some words\n", getreg('1'))
+  normal! u
+  call assert_equal(['some words', 'and more'], getline(1, 2))
+  exe "normal! \<C-R>"
+  call assert_equal('lettersand more', getline(1))
+
+  " linewise non-last line, cursor in the middle of line
+  call setline(1, ['some words', 'and more'])
+  call feedkeys("0fwV\<Esc>[200~letters\<Esc>[201~", 'xt')
+  call assert_equal('lettersand more', getline(1))
+  call assert_equal("some words\n", getreg('1'))
+  normal! u
+  call assert_equal(['some words', 'and more'], getline(1, 2))
+  exe "normal! \<C-R>"
+  call assert_equal('lettersand more', getline(1))
+
+  " linewise last line
+  call setline(1, ['some words', 'and more'])
+  call feedkeys("j0V\<Esc>[200~letters\<Esc>[201~", 'xt')
+  call assert_equal(['some words', 'letters'], getline(1, 2))
+  call assert_equal("and more\n", getreg('1'))
+  normal! u
+  call assert_equal(['some words', 'and more'], getline(1, 2))
+  exe "normal! \<C-R>"
+  call assert_equal(['some words', 'letters'], getline(1, 2))
 
   bwipe!
 endfunc
index 5576f20f9a76425c25964030fb8b81e7621a7dc8..4a4aa75fea09772f5f89782c20af922208d85d72 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4567,
 /**/
     4566,
 /**/