vim-patch:8.2.2971: cannot yank a block without trailing spaces

Problem:    Cannot yank a block without trailing spaces.
Solution:   Add the "zy" command. (Christian Brabandt, closes vim/vim#8292)
544a38e44d
This commit is contained in:
Jan Edmund Lazo 2021-06-10 22:41:01 -04:00
parent d662dfde36
commit 8ebbeee1d0
No known key found for this signature in database
GPG Key ID: 64915E6E9F735B15
6 changed files with 92 additions and 4 deletions

View File

@ -1007,6 +1007,10 @@ inside of strings can change! Also see 'softtabstop' option. >
cursor to the end of line (which is more logical, cursor to the end of line (which is more logical,
but not Vi-compatible) use ":map Y y$". but not Vi-compatible) use ":map Y y$".
*zy*
["x]zy{motion} Yank {motion} text [into register x]. Only differs
from `y` when selecting a block of text, see |v_zy|.
*v_y* *v_y*
{Visual}["x]y Yank the highlighted text [into register x] (for {Visual}["x]y Yank the highlighted text [into register x] (for
{Visual} see |Visual-mode|). {Visual} see |Visual-mode|).
@ -1015,6 +1019,12 @@ inside of strings can change! Also see 'softtabstop' option. >
{Visual}["x]Y Yank the highlighted lines [into register x] (for {Visual}["x]Y Yank the highlighted lines [into register x] (for
{Visual} see |Visual-mode|). {Visual} see |Visual-mode|).
*v_zy*
{Visual}["x]zy Yank the highlighted text [into register x]. Trailing
whitespace at the end of each line of a selected block
won't be yanked. Especially useful in combination
with `zp`. (for {Visual} see |Visual-mode|)
*:y* *:yank* *E850* *:y* *:yank* *E850*
:[range]y[ank] [x] Yank [range] lines [into register x]. Yanking to the :[range]y[ank] [x] Yank [range] lines [into register x]. Yanking to the
"* or "+ registers is possible only when the "* or "+ registers is possible only when the
@ -1094,7 +1104,8 @@ inside of strings can change! Also see 'softtabstop' option. >
["x]zp or *zp* *zP* ["x]zp or *zp* *zP*
["x]zP Like "p" and "P", except without adding trailing spaces ["x]zP Like "p" and "P", except without adding trailing spaces
when pasting a block. Thus the inserted text will not when pasting a block. Thus the inserted text will not
always be a rectangle. always be a rectangle. Especially useful in
combination with |v_zy|.
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

View File

@ -865,6 +865,7 @@ tag char note action in Normal mode ~
|zv| zv open enough folds to view the cursor line |zv| zv open enough folds to view the cursor line
|zw| zw permanently mark word as incorrectly spelled |zw| zw permanently mark word as incorrectly spelled
|zx| zx re-apply 'foldlevel' and do "zv" |zx| zx re-apply 'foldlevel' and do "zv"
|zy| zy yank without trailing spaces
|zz| zz redraw, cursor line at center of window |zz| zz redraw, cursor line at center of window
|z<Left>| z<Left> same as "zh" |z<Left>| z<Left> same as "zh"
|z<Right>| z<Right> same as "zl" |z<Right>| z<Right> same as "zl"

View File

@ -1870,6 +1870,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
} }
} else { } else {
curwin->w_p_lbr = lbr_saved; curwin->w_p_lbr = lbr_saved;
oap->excl_tr_ws = cap->cmdchar == 'z';
(void)op_yank(oap, !gui_yank, false); (void)op_yank(oap, !gui_yank, false);
} }
check_cursor_col(); check_cursor_col();
@ -4393,6 +4394,9 @@ dozet:
case 'p': case 'p':
nv_put(cap); nv_put(cap);
break; break;
// "zy" Yank without trailing spaces
case 'y': nv_operator(cap);
break;
/* "zF": create fold command */ /* "zF": create fold command */
/* "zf": create fold operator */ /* "zf": create fold operator */

View File

@ -48,6 +48,8 @@ typedef struct oparg_S {
colnr_T end_vcol; // end col for block mode operator colnr_T end_vcol; // end col for block mode operator
long prev_opcount; // ca.opcount saved for K_EVENT long prev_opcount; // ca.opcount saved for K_EVENT
long prev_count0; // ca.count0 saved for K_EVENT long prev_count0; // ca.count0 saved for K_EVENT
bool excl_tr_ws; // exclude trailing whitespace for yank of a
// block
} oparg_T; } oparg_T;
/* /*

View File

@ -156,6 +156,9 @@ int get_op_type(int char1, int char2)
// subtract // subtract
return OP_NR_SUB; return OP_NR_SUB;
} }
if (char1 == 'z' && char2 == 'y') { // OP_YANK
return OP_YANK;
}
for (i = 0;; i++) { for (i = 0;; i++) {
if (opchars[i][0] == char1 && opchars[i][1] == char2) { if (opchars[i][0] == char1 && opchars[i][1] == char2) {
break; break;
@ -2563,7 +2566,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
switch (reg->y_type) { switch (reg->y_type) {
case kMTBlockWise: case kMTBlockWise:
block_prep(oap, &bd, lnum, false); block_prep(oap, &bd, lnum, false);
yank_copy_line(reg, &bd, y_idx); yank_copy_line(reg, &bd, y_idx, oap->excl_tr_ws);
break; break;
case kMTLineWise: case kMTLineWise:
@ -2627,7 +2630,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
bd.textlen = endcol - startcol + oap->inclusive; bd.textlen = endcol - startcol + oap->inclusive;
} }
bd.textstart = p + startcol; bd.textstart = p + startcol;
yank_copy_line(reg, &bd, y_idx); yank_copy_line(reg, &bd, y_idx, false);
break; break;
} }
// NOTREACHED // NOTREACHED
@ -2714,7 +2717,11 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
return; return;
} }
static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx) // Copy a block range into a register.
// If "exclude_trailing_space" is set, do not copy trailing whitespaces.
static void yank_copy_line(yankreg_T *reg, const struct block_def *bd,
size_t y_idx, bool exclude_trailing_space)
FUNC_ATTR_NONNULL_ALL
{ {
int size = bd->startspaces + bd->endspaces + bd->textlen; int size = bd->startspaces + bd->endspaces + bd->textlen;
assert(size >= 0); assert(size >= 0);
@ -2726,6 +2733,14 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx)
pnew += bd->textlen; pnew += bd->textlen;
memset(pnew, ' ', (size_t)bd->endspaces); memset(pnew, ' ', (size_t)bd->endspaces);
pnew += bd->endspaces; pnew += bd->endspaces;
if (exclude_trailing_space) {
int s = bd->textlen + bd->endspaces;
while (ascii_iswhite(*(bd->textstart + s - 1)) && s > 0) {
s = s - utf_head_off(bd->textstart, bd->textstart + s - 1) - 1;
pnew--;
}
}
*pnew = NUL; *pnew = NUL;
} }

View File

@ -1006,4 +1006,59 @@ func Test_visual_put_in_block_using_zp()
bwipe! bwipe!
endfunc endfunc
func Test_visual_put_in_block_using_zy_and_zp()
new
" Test 1) Paste using zp - after the cursor without trailing spaces
call setline(1, ['/path;text', '/path;text', '/path;text', '',
\ 'texttext /subdir columntext',
\ 'texttext /longsubdir columntext',
\ 'texttext /longlongsubdir columntext'])
exe "normal! 5G0f/\<c-v>2jezy"
norm! 1G0f;hzp
call assert_equal(['/path/subdir;text', '/path/longsubdir;text', '/path/longlongsubdir;text'], getline(1, 3))
" Test 2) Paste using zP - in front of the cursor without trailing spaces
%d
call setline(1, ['/path;text', '/path;text', '/path;text', '',
\ 'texttext /subdir columntext',
\ 'texttext /longsubdir columntext',
\ 'texttext /longlongsubdir columntext'])
exe "normal! 5G0f/\<c-v>2jezy"
norm! 1G0f;zP
call assert_equal(['/path/subdir;text', '/path/longsubdir;text', '/path/longlongsubdir;text'], getline(1, 3))
" Test 3) Paste using p - with trailing spaces
%d
call setline(1, ['/path;text', '/path;text', '/path;text', '',
\ 'texttext /subdir columntext',
\ 'texttext /longsubdir columntext',
\ 'texttext /longlongsubdir columntext'])
exe "normal! 5G0f/\<c-v>2jezy"
norm! 1G0f;hp
call assert_equal(['/path/subdir ;text', '/path/longsubdir ;text', '/path/longlongsubdir;text'], getline(1, 3))
" Test 4) Paste using P - with trailing spaces
%d
call setline(1, ['/path;text', '/path;text', '/path;text', '',
\ 'texttext /subdir columntext',
\ 'texttext /longsubdir columntext',
\ 'texttext /longlongsubdir columntext'])
exe "normal! 5G0f/\<c-v>2jezy"
norm! 1G0f;P
call assert_equal(['/path/subdir ;text', '/path/longsubdir ;text', '/path/longlongsubdir;text'], getline(1, 3))
" Test 5) Yank with spaces inside the block
%d
call setline(1, ['/path;text', '/path;text', '/path;text', '',
\ 'texttext /sub dir/ columntext',
\ 'texttext /lon gsubdir/ columntext',
\ 'texttext /lon glongsubdir/ columntext'])
exe "normal! 5G0f/\<c-v>2jf/zy"
norm! 1G0f;zP
call assert_equal(['/path/sub dir/;text', '/path/lon gsubdir/;text', '/path/lon glongsubdir/;text'], getline(1, 3))
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab