patch 9.1.1224: cannot :put while keeping indent

Problem:  cannot :put while keeping indent (Peter Aronoff)
Solution: add the :iput ex command (64-bitman)

fixes: #16225
closes: #16886

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: 64-bitman <60551350+64-bitman@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
64-bitman
2025-03-18 22:14:34 +01:00
committed by Christian Brabandt
parent 11ab02c819
commit e08f10a55c
19 changed files with 324 additions and 83 deletions

View File

@ -3252,6 +3252,58 @@ var_any_get_oc_member(class_T *current_class, isn_T *iptr, typval_T *tv)
return OK;
}
/*
* do ISN_PUT or ISN_IPUT instruction depending on fixindent parameter
*/
static void
isn_put_do(ectx_T *ectx, isn_T *iptr, typval_T *tv, int fixindent)
{
int regname = iptr->isn_arg.put.put_regname;
linenr_T lnum = iptr->isn_arg.put.put_lnum;
char_u *expr = NULL;
int dir = FORWARD;
if (lnum < -2)
{
// line number was put on the stack by ISN_RANGE
tv = STACK_TV_BOT(-1);
curwin->w_cursor.lnum = tv->vval.v_number;
if (lnum == LNUM_VARIABLE_RANGE_ABOVE)
dir = BACKWARD;
--ectx->ec_stack.ga_len;
}
else if (lnum == -2)
// :put! above cursor
dir = BACKWARD;
else if (lnum >= 0)
{
curwin->w_cursor.lnum = lnum;
if (lnum == 0)
// check_cursor() below will move to line 1
dir = BACKWARD;
}
if (regname == '=')
{
tv = STACK_TV_BOT(-1);
if (tv->v_type == VAR_STRING)
expr = tv->vval.v_string;
else
{
expr = typval2string(tv, TRUE); // allocates value
clear_tv(tv);
}
--ectx->ec_stack.ga_len;
}
check_cursor();
if (fixindent)
do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE|PUT_FIXINDENT);
else
do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
vim_free(expr);
}
/*
* Execute instructions in execution context "ectx".
* Return OK or FAIL;
@ -5948,48 +6000,12 @@ exec_instructions(ectx_T *ectx)
break;
case ISN_PUT:
{
int regname = iptr->isn_arg.put.put_regname;
linenr_T lnum = iptr->isn_arg.put.put_lnum;
char_u *expr = NULL;
int dir = FORWARD;
if (lnum < -2)
{
// line number was put on the stack by ISN_RANGE
tv = STACK_TV_BOT(-1);
curwin->w_cursor.lnum = tv->vval.v_number;
if (lnum == LNUM_VARIABLE_RANGE_ABOVE)
dir = BACKWARD;
--ectx->ec_stack.ga_len;
}
else if (lnum == -2)
// :put! above cursor
dir = BACKWARD;
else if (lnum >= 0)
{
curwin->w_cursor.lnum = lnum;
if (lnum == 0)
// check_cursor() below will move to line 1
dir = BACKWARD;
}
if (regname == '=')
{
tv = STACK_TV_BOT(-1);
if (tv->v_type == VAR_STRING)
expr = tv->vval.v_string;
else
{
expr = typval2string(tv, TRUE); // allocates value
clear_tv(tv);
}
--ectx->ec_stack.ga_len;
}
check_cursor();
do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
vim_free(expr);
}
tv = NULL; // initialize it so we don't get a warning
isn_put_do(ectx, iptr, tv, FALSE);
break;
case ISN_IPUT:
tv = NULL;
isn_put_do(ectx, iptr, tv, TRUE);
break;
case ISN_CMDMOD:
@ -7619,7 +7635,18 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
iptr->isn_arg.put.put_regname,
(long)iptr->isn_arg.put.put_lnum);
break;
case ISN_IPUT:
if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE_ABOVE)
smsg("%s%4d IPUT %c above range",
pfx, current, iptr->isn_arg.put.put_regname);
else if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE)
smsg("%s%4d IPUT %c range",
pfx, current, iptr->isn_arg.put.put_regname);
else
smsg("%s%4d IPUT %c %ld", pfx, current,
iptr->isn_arg.put.put_regname,
(long)iptr->isn_arg.put.put_lnum);
break;
case ISN_CMDMOD:
{
char_u *buf;
@ -7846,5 +7873,4 @@ check_not_string(typval_T *tv)
return OK;
}
#endif // FEAT_EVAL