vim-patch:8.2.2914: cannot paste a block without adding padding

Problem:    Cannot paste a block without adding padding.
Solution:   Add "zp" and "zP" which paste without adding padding. (Christian
            Brabandt, closes vim/vim#8289)
2fa9384ca1

Cherry-pick Test_normal_z_error() from patch v8.2.0369.
This commit is contained in:
Jan Edmund Lazo
2021-05-30 21:58:16 -04:00
parent 73e3669c7a
commit e399731561
7 changed files with 74 additions and 24 deletions

View File

@@ -1091,6 +1091,11 @@ inside of strings can change! Also see 'softtabstop' option. >
Using the mouse only works when 'mouse' contains 'n' Using the mouse only works when 'mouse' contains 'n'
or 'a'. or 'a'.
["x]zp or *zp* *zP*
["x]zP Like "p" and "P", except without adding trailing spaces
when pasting a block. Thus the inserted text will not
always be a rectangle.
You can use these commands to copy text from one place to another. Do this You can use these commands to copy text from one place to another. Do this
by first getting the text into a register with a yank, delete or change by first getting the text into a register with a yank, delete or change
command, then inserting the register contents with a put command. You can command, then inserting the register contents with a put command. You can
@@ -1130,6 +1135,9 @@ a register, a paste on a visual selected area will paste that single line on
each of the selected lines (thus replacing the blockwise selected region by a each of the selected lines (thus replacing the blockwise selected region by a
block of the pasted line). block of the pasted line).
Use |zP|/|zp| to paste a blockwise yanked register without appending trailing
spaces.
*blockwise-register* *blockwise-register*
If you use a blockwise Visual mode command to get the text into the register, If you use a blockwise Visual mode command to get the text into the register,
the block of text will be inserted before ("P") or after ("p") the cursor the block of text will be inserted before ("P") or after ("p") the cursor

View File

@@ -851,6 +851,8 @@ tag char note action in Normal mode ~
|zm| zm subtract one from 'foldlevel' |zm| zm subtract one from 'foldlevel'
|zn| zn reset 'foldenable' |zn| zn reset 'foldenable'
|zo| zo open fold |zo| zo open fold
|zp| zp paste in block-mode without trailing spaces
|zP| zP paste in block-mode without trailing spaces
|zr| zr add one to 'foldlevel' |zr| zr add one to 'foldlevel'
|zs| zs when 'wrap' off scroll horizontally to |zs| zs when 'wrap' off scroll horizontally to
position the cursor at the start (left position the cursor at the start (left

View File

@@ -4384,6 +4384,12 @@ dozet:
} }
break; break;
// "zp", "zP" in block mode put without addind trailing spaces
case 'P':
case 'p':
nv_put(cap);
break;
/* "zF": create fold command */ /* "zF": create fold command */
/* "zf": create fold operator */ /* "zf": create fold operator */
case 'F': case 'F':
@@ -7913,12 +7919,14 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
flags |= PUT_FIXINDENT; flags |= PUT_FIXINDENT;
} else { } else {
dir = (cap->cmdchar == 'P' dir = (cap->cmdchar == 'P'
|| (cap->cmdchar == 'g' && cap->nchar == 'P')) || ((cap->cmdchar == 'g' || cap->cmdchar == 'z')
? BACKWARD : FORWARD; && cap->nchar == 'P')) ? BACKWARD : FORWARD;
} }
prep_redo_cmd(cap); prep_redo_cmd(cap);
if (cap->cmdchar == 'g') { if (cap->cmdchar == 'g') {
flags |= PUT_CURSEND; flags |= PUT_CURSEND;
} else if (cap->cmdchar == 'z') {
flags |= PUT_BLOCK_INNER;
} }
if (VIsual_active) { if (VIsual_active) {

View File

@@ -2788,13 +2788,13 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
recursive = false; recursive = false;
} }
/* // Put contents of register "regname" into the text.
* Put contents of register "regname" into the text. // Caller must check "regname" to be valid!
* Caller must check "regname" to be valid! // "flags": PUT_FIXINDENT make indent look nice
* "flags": PUT_FIXINDENT make indent look nice // PUT_CURSEND leave cursor after end of new text
* PUT_CURSEND leave cursor after end of new text // PUT_LINE force linewise put (":put")
* PUT_LINE force linewise put (":put") // PUT_BLOCK_INNER in block mode, do not add trailing spaces
dir: BACKWARD for 'P', FORWARD for 'p' */ // dir: BACKWARD for 'P', FORWARD for 'p'
void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
{ {
char_u *ptr; char_u *ptr;
@@ -3126,7 +3126,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
curwin->w_cursor.coladd = 0; curwin->w_cursor.coladd = 0;
bd.textcol = 0; bd.textcol = 0;
for (i = 0; i < y_size; i++) { for (i = 0; i < y_size; i++) {
int spaces; int spaces = 0;
char shortline; char shortline;
// can just be 0 or 1, needed for blockwise paste beyond the current // can just be 0 or 1, needed for blockwise paste beyond the current
// buffer end // buffer end
@@ -3177,14 +3177,17 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
yanklen = (int)STRLEN(y_array[i]); yanklen = (int)STRLEN(y_array[i]);
// calculate number of spaces required to fill right side of block if ((flags & PUT_BLOCK_INNER) == 0) {
// calculate number of spaces required to fill right side of
// block
spaces = y_width + 1; spaces = y_width + 1;
for (long j = 0; j < yanklen; j++) { for (int j = 0; j < yanklen; j++) {
spaces -= lbr_chartabsize(NULL, &y_array[i][j], 0); spaces -= lbr_chartabsize(NULL, &y_array[i][j], 0);
} }
if (spaces < 0) { if (spaces < 0) {
spaces = 0; spaces = 0;
} }
}
// insert the new text // insert the new text
totlen = (size_t)(count * (yanklen + spaces) totlen = (size_t)(count * (yanklen + spaces)

View File

@@ -14,13 +14,14 @@
typedef int (*Indenter)(void); typedef int (*Indenter)(void);
/* flags for do_put() */ // flags for do_put()
#define PUT_FIXINDENT 1 /* make indent look nice */ #define PUT_FIXINDENT 1 // make indent look nice
#define PUT_CURSEND 2 /* leave cursor after end of new text */ #define PUT_CURSEND 2 // leave cursor after end of new text
#define PUT_CURSLINE 4 /* leave cursor on last line of new text */ #define PUT_CURSLINE 4 // leave cursor on last line of new text
#define PUT_LINE 8 /* put register as lines */ #define PUT_LINE 8 // put register as lines
#define PUT_LINE_SPLIT 16 /* split line for linewise register */ #define PUT_LINE_SPLIT 16 // split line for linewise register
#define PUT_LINE_FORWARD 32 /* put linewise register below Visual sel. */ #define PUT_LINE_FORWARD 32 // put linewise register below Visual sel.
#define PUT_BLOCK_INNER 64 // in block mode, do not add trailing spaces
/* /*
* Registers: * Registers:

View File

@@ -512,6 +512,12 @@ func Test_normal14_page_eol()
bw! bw!
endfunc endfunc
" Test for errors with z command
func Test_normal_z_error()
call assert_beeps('normal! z2p')
call assert_beeps('normal! zq')
endfunc
func Test_normal15_z_scroll_vert() func Test_normal15_z_scroll_vert()
" basic test for z commands that scroll the window " basic test for z commands that scroll the window
call Setup_NewWindow() call Setup_NewWindow()

View File

@@ -738,4 +738,26 @@ func Test_select_mode_gv()
bwipe! bwipe!
endfunc endfunc
func Test_visual_put_in_block_using_zp()
new
" paste using zP
call setline(1, ['/path;text', '/path;text', '/path;text', '',
\ '/subdir',
\ '/longsubdir',
\ '/longlongsubdir'])
exe "normal! 5G\<c-v>2j$y"
norm! 1Gf;zP
call assert_equal(['/path/subdir;text', '/path/longsubdir;text', '/path/longlongsubdir;text'], getline(1, 3))
%d
" paste using zP
call setline(1, ['/path;text', '/path;text', '/path;text', '',
\ '/subdir',
\ '/longsubdir',
\ '/longlongsubdir'])
exe "normal! 5G\<c-v>2j$y"
norm! 1Gf;hzp
call assert_equal(['/path/subdir;text', '/path/longsubdir;text', '/path/longlongsubdir;text'], getline(1, 3))
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab