mirror of
https://github.com/neovim/neovim
synced 2025-07-16 01:01:49 +00:00
vim-patch:9.1.1224: cannot :put while keeping indent (#33076)
Problem: cannot :put while keeping indent (Peter Aronoff)
Solution: add the :iput ex command (64-bitman)
fixes: vim/vim#16225
closes: vim/vim#16886
e08f10a55c
Cherry-pick test_put.vim changes from patch 8.2.1593.
N/A patches:
vim-patch:9.1.1213: cannot :put while keeping indent
vim-patch:9.1.1215: Patch 9.1.1213 has some issues
Co-authored-by: 64-bitman <60551350+64-bitman@users.noreply.github.com>
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
This commit is contained in:
@ -1105,6 +1105,11 @@ inside of strings can change! Also see 'softtabstop' option. >
|
||||
:[line]pu[t]! [x] Put the text [from register x] before [line] (default
|
||||
current line).
|
||||
|
||||
*:ip* *:iput*
|
||||
:[line]ip[ut] [x] like |:put|, but adjust indent to the current line
|
||||
|
||||
:[line]ip[ut]! [x] like |:put|!, but adjust indent to the current line
|
||||
|
||||
["x]]p or *]p* *]<MiddleMouse>*
|
||||
["x]]<MiddleMouse> Like "p", but adjust the indent to the current line.
|
||||
Using the mouse only works when 'mouse' contains 'n'
|
||||
|
@ -1348,6 +1348,8 @@ tag command action ~
|
||||
|:inoreabbrev| :inorea[bbrev] like ":noreabbrev" but for Insert mode
|
||||
|:inoremenu| :inoreme[nu] like ":noremenu" but for Insert mode
|
||||
|:intro| :int[ro] print the introductory message
|
||||
|:iput| :ip[ut] like |:put|, but adjust the indent to the
|
||||
current line
|
||||
|:isearch| :is[earch] list one line where identifier matches
|
||||
|:isplit| :isp[lit] split window and jump to definition of
|
||||
identifier
|
||||
|
@ -115,7 +115,7 @@ DIAGNOSTICS
|
||||
|
||||
EDITOR
|
||||
|
||||
• todo
|
||||
• |:iput| works like |:put| but adjusts indent.
|
||||
|
||||
EVENTS
|
||||
|
||||
|
@ -504,7 +504,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Arena
|
||||
VALIDATE((regname != '='), "%s", "Cannot use register \"=", {
|
||||
goto end;
|
||||
});
|
||||
VALIDATE(valid_yank_reg(regname, ea.cmdidx != CMD_put && !IS_USER_CMDIDX(ea.cmdidx)),
|
||||
VALIDATE(valid_yank_reg(regname,
|
||||
(!IS_USER_CMDIDX(ea.cmdidx)
|
||||
&& ea.cmdidx != CMD_put && ea.cmdidx != CMD_iput)),
|
||||
"Invalid register: \"%c", regname, {
|
||||
goto end;
|
||||
});
|
||||
|
@ -1218,6 +1218,12 @@ M.cmds = {
|
||||
addr_type = 'ADDR_NONE',
|
||||
func = 'ex_intro',
|
||||
},
|
||||
{
|
||||
command = 'iput',
|
||||
flags = bit.bor(RANGE, WHOLEFOLD, BANG, REGSTR, TRLBAR, ZEROR, CMDWIN, LOCK_OK, MODIFY),
|
||||
addr_type = 'ADDR_LINES',
|
||||
func = 'ex_iput',
|
||||
},
|
||||
{
|
||||
command = 'isearch',
|
||||
flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK),
|
||||
|
@ -1393,8 +1393,9 @@ static void parse_register(exarg_T *eap)
|
||||
// Do not allow register = for user commands
|
||||
&& (!IS_USER_CMDIDX(eap->cmdidx) || *eap->arg != '=')
|
||||
&& !((eap->argt & EX_COUNT) && ascii_isdigit(*eap->arg))) {
|
||||
if (valid_yank_reg(*eap->arg, (eap->cmdidx != CMD_put
|
||||
&& !IS_USER_CMDIDX(eap->cmdidx)))) {
|
||||
if (valid_yank_reg(*eap->arg,
|
||||
(!IS_USER_CMDIDX(eap->cmdidx)
|
||||
&& eap->cmdidx != CMD_put && eap->cmdidx != CMD_iput))) {
|
||||
eap->regname = (uint8_t)(*eap->arg++);
|
||||
// for '=' register: accept the rest of the line as an expression
|
||||
if (eap->arg[-1] == '=' && eap->arg[0] != NUL) {
|
||||
@ -1752,7 +1753,7 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
|
||||
|
||||
if (!MODIFIABLE(curbuf) && (eap->argt & EX_MODIFY)
|
||||
// allow :put in terminals
|
||||
&& !(curbuf->terminal && eap->cmdidx == CMD_put)) {
|
||||
&& !(curbuf->terminal && (eap->cmdidx == CMD_put || eap->cmdidx == CMD_iput))) {
|
||||
errormsg = _(e_modifiable);
|
||||
goto end;
|
||||
}
|
||||
@ -2155,7 +2156,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
|
||||
}
|
||||
if (!MODIFIABLE(curbuf) && (ea.argt & EX_MODIFY)
|
||||
// allow :put in terminals
|
||||
&& (!curbuf->terminal || ea.cmdidx != CMD_put)) {
|
||||
&& !(curbuf->terminal && (ea.cmdidx == CMD_put || ea.cmdidx == CMD_iput))) {
|
||||
// Command not allowed in non-'modifiable' buffer
|
||||
errormsg = _(e_modifiable);
|
||||
goto doend;
|
||||
@ -6306,6 +6307,20 @@ static void ex_put(exarg_T *eap)
|
||||
PUT_LINE|PUT_CURSLINE);
|
||||
}
|
||||
|
||||
/// ":iput".
|
||||
static void ex_iput(exarg_T *eap)
|
||||
{
|
||||
// ":0iput" works like ":1iput!".
|
||||
if (eap->line2 == 0) {
|
||||
eap->line2 = 1;
|
||||
eap->forceit = true;
|
||||
}
|
||||
curwin->w_cursor.lnum = eap->line2;
|
||||
check_cursor_col(curwin);
|
||||
do_put(eap->regname, NULL, eap->forceit ? BACKWARD : FORWARD, 1L,
|
||||
PUT_LINE|PUT_CURSLINE|PUT_FIXINDENT);
|
||||
}
|
||||
|
||||
/// Handle ":copy" and ":move".
|
||||
static void ex_copymove(exarg_T *eap)
|
||||
{
|
||||
|
@ -73,16 +73,18 @@ func Test_put_fails_when_nomodifiable()
|
||||
setlocal nomodifiable
|
||||
|
||||
normal! yy
|
||||
call assert_fails(':put', 'E21')
|
||||
call assert_fails(':put!', 'E21')
|
||||
call assert_fails(':normal! p', 'E21')
|
||||
call assert_fails(':normal! gp', 'E21')
|
||||
call assert_fails(':normal! P', 'E21')
|
||||
call assert_fails(':normal! gP', 'E21')
|
||||
call assert_fails(':put', 'E21:')
|
||||
call assert_fails(':put!', 'E21:')
|
||||
call assert_fails(':iput', 'E21:')
|
||||
call assert_fails(':iput!', 'E21:')
|
||||
call assert_fails(':normal! p', 'E21:')
|
||||
call assert_fails(':normal! gp', 'E21:')
|
||||
call assert_fails(':normal! P', 'E21:')
|
||||
call assert_fails(':normal! gP', 'E21:')
|
||||
|
||||
if has('mouse')
|
||||
set mouse=n
|
||||
call assert_fails('execute "normal! \<MiddleMouse>"', 'E21')
|
||||
call assert_fails('execute "normal! \<MiddleMouse>"', 'E21:')
|
||||
set mouse&
|
||||
endif
|
||||
|
||||
@ -132,7 +134,7 @@ func Test_put_visual_delete_all_lines()
|
||||
let @r = ''
|
||||
normal! VG"rgp
|
||||
call assert_equal(1, line('$'))
|
||||
close!
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_gp_with_count_leaves_cursor_at_end()
|
||||
@ -328,6 +330,82 @@ func Test_put_list()
|
||||
put! =l
|
||||
call assert_equal(['a', 'b', 'c', ''], getline(1, '$'))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_iput_multiline()
|
||||
new
|
||||
setlocal noexpandtab
|
||||
call setline(1, "\<Tab>foo")
|
||||
call setreg('0', "bar\n\<Tab>bar2\nbar3", 'l')
|
||||
iput
|
||||
call assert_equal(["\<Tab>bar", "\<Tab>\<Tab>bar2", "\<Tab>bar3"], getline(2, 4))
|
||||
setlocal expandtab tabstop=8 shiftwidth=8 noshiftround
|
||||
iput
|
||||
call assert_equal([repeat(' ', 8) . "bar",
|
||||
\ repeat(' ', 16) . "bar2",
|
||||
\ repeat(' ', 8) . "bar3"], getline(5, 7))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_iput_beforeafter_tab()
|
||||
new
|
||||
setlocal noexpandtab
|
||||
call setline(1, "\<Tab>foo")
|
||||
call setreg('0', "bar", 'l')
|
||||
iput
|
||||
call assert_equal(["\<Tab>bar"], getline(2, '$'))
|
||||
call feedkeys("k", 'x')
|
||||
iput!
|
||||
call assert_equal("\<Tab>bar", getline(1))
|
||||
call assert_equal("\<Tab>bar", getline(3))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_iput_beforeafter_expandtab()
|
||||
new
|
||||
setlocal expandtab tabstop=8 shiftwidth=8 noshiftround
|
||||
call setline(1, "\<Tab>foo")
|
||||
call setreg('0', "bar", 'l')
|
||||
iput
|
||||
call assert_equal([repeat(' ', 8) . "bar"], getline(2, '$'))
|
||||
:1iput!
|
||||
call assert_equal(repeat(' ', 8) . "bar", getline(1))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_iput_invalidrange()
|
||||
new
|
||||
call setreg('0', "bar", 'l')
|
||||
call assert_fails(':10iput', 'E16:')
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_iput_zero_range()
|
||||
new
|
||||
let _var = [getreg('a'), getregtype('a')]
|
||||
call setreg('a', 'foobar', 'l')
|
||||
call setline(1, range(1, 2))
|
||||
call cursor(1, 1)
|
||||
0iput a
|
||||
call assert_equal(['foobar', '1', '2'], getline(1, '$'))
|
||||
%d
|
||||
call setline(1, range(1, 2))
|
||||
call cursor(1, 1)
|
||||
0iput! a
|
||||
call assert_equal(['foobar', '1', '2'], getline(1, '$'))
|
||||
call setreg('a', _var[0], _var[1])
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_iput_not_put()
|
||||
new
|
||||
call setline(1, "\<Tab>foo")
|
||||
call setreg('0', "bar", 'l')
|
||||
iput
|
||||
call assert_equal("\<Tab>bar", getline(2))
|
||||
put
|
||||
call assert_equal("bar", getline(3))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" Test pasting the '.' register
|
||||
|
Reference in New Issue
Block a user