mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.1637: Vim9: :put ={expr} does not work inside :def function
Problem: Vim9: :put ={expr} does not work inside :def function. Solution: Add ISN_PUT. (closes #6397)
This commit is contained in:
parent
6defa7bf0a
commit
c3516f7e45
@ -3399,7 +3399,7 @@ ins_reg(void)
|
|||||||
AppendCharToRedobuff(literally);
|
AppendCharToRedobuff(literally);
|
||||||
AppendCharToRedobuff(regname);
|
AppendCharToRedobuff(regname);
|
||||||
|
|
||||||
do_put(regname, BACKWARD, 1L,
|
do_put(regname, NULL, BACKWARD, 1L,
|
||||||
(literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
|
(literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
|
||||||
}
|
}
|
||||||
else if (insert_reg(regname, literally) == FAIL)
|
else if (insert_reg(regname, literally) == FAIL)
|
||||||
@ -4776,7 +4776,7 @@ ins_pagedown(void)
|
|||||||
static void
|
static void
|
||||||
ins_drop(void)
|
ins_drop(void)
|
||||||
{
|
{
|
||||||
do_put('~', BACKWARD, 1L, PUT_CURSEND);
|
do_put('~', NULL, BACKWARD, 1L, PUT_CURSEND);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7321,7 +7321,7 @@ ex_put(exarg_T *eap)
|
|||||||
eap->forceit = TRUE;
|
eap->forceit = TRUE;
|
||||||
}
|
}
|
||||||
curwin->w_cursor.lnum = eap->line2;
|
curwin->w_cursor.lnum = eap->line2;
|
||||||
do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L,
|
do_put(eap->regname, NULL, eap->forceit ? BACKWARD : FORWARD, 1L,
|
||||||
PUT_LINE|PUT_CURSLINE);
|
PUT_LINE|PUT_CURSLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,7 +430,8 @@ do_mouse(
|
|||||||
insert_reg(regname, TRUE);
|
insert_reg(regname, TRUE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
do_put(regname, BACKWARD, 1L, fixindent | PUT_CURSEND);
|
do_put(regname, NULL, BACKWARD, 1L,
|
||||||
|
fixindent | PUT_CURSEND);
|
||||||
|
|
||||||
// Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r
|
// Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r
|
||||||
AppendCharToRedobuff(Ctrl_R);
|
AppendCharToRedobuff(Ctrl_R);
|
||||||
@ -849,7 +850,7 @@ do_mouse(
|
|||||||
// to this position
|
// to this position
|
||||||
if (restart_edit != 0)
|
if (restart_edit != 0)
|
||||||
where_paste_started = curwin->w_cursor;
|
where_paste_started = curwin->w_cursor;
|
||||||
do_put(regname, dir, count, fixindent | PUT_CURSEND);
|
do_put(regname, NULL, dir, count, fixindent | PUT_CURSEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(FEAT_QUICKFIX)
|
#if defined(FEAT_QUICKFIX)
|
||||||
|
@ -7427,7 +7427,7 @@ nv_put_opt(cmdarg_T *cap, int fix_indent)
|
|||||||
// May have been reset in do_put().
|
// May have been reset in do_put().
|
||||||
VIsual_active = TRUE;
|
VIsual_active = TRUE;
|
||||||
}
|
}
|
||||||
do_put(cap->oap->regname, dir, cap->count1, flags);
|
do_put(cap->oap->regname, NULL, dir, cap->count1, flags);
|
||||||
|
|
||||||
// If a register was saved, put it back now.
|
// If a register was saved, put it back now.
|
||||||
if (reg2 != NULL)
|
if (reg2 != NULL)
|
||||||
@ -7500,7 +7500,7 @@ nv_nbcmd(cmdarg_T *cap)
|
|||||||
static void
|
static void
|
||||||
nv_drop(cmdarg_T *cap UNUSED)
|
nv_drop(cmdarg_T *cap UNUSED)
|
||||||
{
|
{
|
||||||
do_put('~', BACKWARD, 1L, PUT_CURSEND);
|
do_put('~', NULL, BACKWARD, 1L, PUT_CURSEND);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ void init_yank(void);
|
|||||||
void clear_registers(void);
|
void clear_registers(void);
|
||||||
void free_yank_all(void);
|
void free_yank_all(void);
|
||||||
int op_yank(oparg_T *oap, int deleting, int mess);
|
int op_yank(oparg_T *oap, int deleting, int mess);
|
||||||
void do_put(int regname, int dir, long count, int flags);
|
void do_put(int regname, char_u *expr_result, int dir, long count, int flags);
|
||||||
int get_register_name(int num);
|
int get_register_name(int num);
|
||||||
int get_unname_register(void);
|
int get_unname_register(void);
|
||||||
void ex_display(exarg_T *eap);
|
void ex_display(exarg_T *eap);
|
||||||
|
@ -1487,6 +1487,7 @@ copy_yank_reg(yankreg_T *reg)
|
|||||||
void
|
void
|
||||||
do_put(
|
do_put(
|
||||||
int regname,
|
int regname,
|
||||||
|
char_u *expr_result, // result for regname "=" when compiled
|
||||||
int dir, // BACKWARD for 'P', FORWARD for 'p'
|
int dir, // BACKWARD for 'P', FORWARD for 'p'
|
||||||
long count,
|
long count,
|
||||||
int flags)
|
int flags)
|
||||||
@ -1551,11 +1552,12 @@ do_put(
|
|||||||
|
|
||||||
// For special registers '%' (file name), '#' (alternate file name) and
|
// For special registers '%' (file name), '#' (alternate file name) and
|
||||||
// ':' (last command line), etc. we have to create a fake yank register.
|
// ':' (last command line), etc. we have to create a fake yank register.
|
||||||
if (get_spec_reg(regname, &insert_string, &allocated, TRUE))
|
// For compiled code "expr_result" holds the expression result.
|
||||||
{
|
if (regname == '=' && expr_result != NULL)
|
||||||
if (insert_string == NULL)
|
insert_string = expr_result;
|
||||||
return;
|
else if (get_spec_reg(regname, &insert_string, &allocated, TRUE)
|
||||||
}
|
&& insert_string == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
// Autocommands may be executed when saving lines for undo. This might
|
// Autocommands may be executed when saving lines for undo. This might
|
||||||
// make "y_array" invalid, so we start undo now to avoid that.
|
// make "y_array" invalid, so we start undo now to avoid that.
|
||||||
|
@ -315,5 +315,21 @@ def Test_normal_command()
|
|||||||
bwipe!
|
bwipe!
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_put_command()
|
||||||
|
new
|
||||||
|
@p = 'ppp'
|
||||||
|
put p
|
||||||
|
assert_equal('ppp', getline(2))
|
||||||
|
|
||||||
|
put ='below'
|
||||||
|
assert_equal('below', getline(3))
|
||||||
|
put! ='above'
|
||||||
|
assert_equal('above', getline(3))
|
||||||
|
assert_equal('below', getline(4))
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
enddef
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||||
|
@ -118,6 +118,21 @@ def Test_disassemble_yank_range()
|
|||||||
res)
|
res)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def s:PutExpr()
|
||||||
|
:3put ="text"
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def Test_disassemble_put_expr()
|
||||||
|
let res = execute('disass s:PutExpr')
|
||||||
|
assert_match('<SNR>\d*_PutExpr.*' ..
|
||||||
|
' :3put ="text"\_s*' ..
|
||||||
|
'\d PUSHS "text"\_s*' ..
|
||||||
|
'\d PUT = 3\_s*' ..
|
||||||
|
'\d PUSHNR 0\_s*' ..
|
||||||
|
'\d RETURN',
|
||||||
|
res)
|
||||||
|
enddef
|
||||||
|
|
||||||
def s:ScriptFuncPush()
|
def s:ScriptFuncPush()
|
||||||
let localbool = true
|
let localbool = true
|
||||||
let localspec = v:none
|
let localspec = v:none
|
||||||
|
@ -754,6 +754,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1637,
|
||||||
/**/
|
/**/
|
||||||
1636,
|
1636,
|
||||||
/**/
|
/**/
|
||||||
|
@ -135,6 +135,8 @@ typedef enum {
|
|||||||
ISN_CHECKTYPE, // check value type is isn_arg.type.tc_type
|
ISN_CHECKTYPE, // check value type is isn_arg.type.tc_type
|
||||||
ISN_CHECKLEN, // check list length is isn_arg.checklen.cl_min_len
|
ISN_CHECKLEN, // check list length is isn_arg.checklen.cl_min_len
|
||||||
|
|
||||||
|
ISN_PUT, // ":put", uses isn_arg.put
|
||||||
|
|
||||||
ISN_SHUFFLE, // move item on stack up or down
|
ISN_SHUFFLE, // move item on stack up or down
|
||||||
ISN_DROP // pop stack and discard value
|
ISN_DROP // pop stack and discard value
|
||||||
} isntype_T;
|
} isntype_T;
|
||||||
@ -261,6 +263,12 @@ typedef struct {
|
|||||||
int shfl_up; // places to move upwards
|
int shfl_up; // places to move upwards
|
||||||
} shuffle_T;
|
} shuffle_T;
|
||||||
|
|
||||||
|
// arguments to ISN_PUT
|
||||||
|
typedef struct {
|
||||||
|
int put_regname; // register, can be NUL
|
||||||
|
linenr_T put_lnum; // line number to put below
|
||||||
|
} put_T;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Instruction
|
* Instruction
|
||||||
*/
|
*/
|
||||||
@ -296,6 +304,7 @@ struct isn_S {
|
|||||||
newfunc_T newfunc;
|
newfunc_T newfunc;
|
||||||
checklen_T checklen;
|
checklen_T checklen;
|
||||||
shuffle_T shuffle;
|
shuffle_T shuffle;
|
||||||
|
put_T put;
|
||||||
} isn_arg;
|
} isn_arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1567,6 +1567,22 @@ generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate an ISN_PUT instruction.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
generate_PUT(cctx_T *cctx, int regname, linenr_T lnum)
|
||||||
|
{
|
||||||
|
isn_T *isn;
|
||||||
|
|
||||||
|
RETURN_OK_IF_SKIP(cctx);
|
||||||
|
if ((isn = generate_instr(cctx, ISN_PUT)) == NULL)
|
||||||
|
return FAIL;
|
||||||
|
isn->isn_arg.put.put_regname = regname;
|
||||||
|
isn->isn_arg.put.put_lnum = lnum;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
generate_EXEC(cctx_T *cctx, char_u *line)
|
generate_EXEC(cctx_T *cctx, char_u *line)
|
||||||
{
|
{
|
||||||
@ -6271,6 +6287,50 @@ compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* :put r
|
||||||
|
* :put ={expr}
|
||||||
|
*/
|
||||||
|
static char_u *
|
||||||
|
compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
|
||||||
|
{
|
||||||
|
char_u *line = arg;
|
||||||
|
linenr_T lnum;
|
||||||
|
char *errormsg;
|
||||||
|
int above = FALSE;
|
||||||
|
|
||||||
|
if (*arg == '!')
|
||||||
|
{
|
||||||
|
above = TRUE;
|
||||||
|
line = skipwhite(arg + 1);
|
||||||
|
}
|
||||||
|
eap->regname = *line;
|
||||||
|
|
||||||
|
if (eap->regname == '=')
|
||||||
|
{
|
||||||
|
char_u *p = line + 1;
|
||||||
|
|
||||||
|
if (compile_expr0(&p, cctx) == FAIL)
|
||||||
|
return NULL;
|
||||||
|
line = p;
|
||||||
|
}
|
||||||
|
else if (eap->regname != NUL)
|
||||||
|
++line;
|
||||||
|
|
||||||
|
// TODO: if the range is something like "$" need to evaluate at runtime
|
||||||
|
if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
|
||||||
|
return NULL;
|
||||||
|
if (eap->addr_count == 0)
|
||||||
|
lnum = -1;
|
||||||
|
else
|
||||||
|
lnum = eap->line2;
|
||||||
|
if (above)
|
||||||
|
--lnum;
|
||||||
|
|
||||||
|
generate_PUT(cctx, eap->regname, lnum);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A command that is not compiled, execute with legacy code.
|
* A command that is not compiled, execute with legacy code.
|
||||||
*/
|
*/
|
||||||
@ -6870,6 +6930,11 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
|||||||
line = compile_mult_expr(p, ea.cmdidx, &cctx);
|
line = compile_mult_expr(p, ea.cmdidx, &cctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CMD_put:
|
||||||
|
ea.cmd = cmd;
|
||||||
|
line = compile_put(p, &ea, &cctx);
|
||||||
|
break;
|
||||||
|
|
||||||
// TODO: any other commands with an expression argument?
|
// TODO: any other commands with an expression argument?
|
||||||
|
|
||||||
case CMD_append:
|
case CMD_append:
|
||||||
@ -7192,6 +7257,7 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_PUSHF:
|
case ISN_PUSHF:
|
||||||
case ISN_PUSHNR:
|
case ISN_PUSHNR:
|
||||||
case ISN_PUSHSPEC:
|
case ISN_PUSHSPEC:
|
||||||
|
case ISN_PUT:
|
||||||
case ISN_RETURN:
|
case ISN_RETURN:
|
||||||
case ISN_SHUFFLE:
|
case ISN_SHUFFLE:
|
||||||
case ISN_SLICE:
|
case ISN_SLICE:
|
||||||
|
@ -2581,6 +2581,36 @@ call_def_function(
|
|||||||
}
|
}
|
||||||
break;
|
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 (regname == '=')
|
||||||
|
{
|
||||||
|
tv = STACK_TV_BOT(-1);
|
||||||
|
if (tv->v_type == VAR_STRING)
|
||||||
|
expr = tv->vval.v_string;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expr = typval_tostring(tv); // allocates value
|
||||||
|
clear_tv(tv);
|
||||||
|
}
|
||||||
|
--ectx.ec_stack.ga_len;
|
||||||
|
}
|
||||||
|
if (lnum == -2)
|
||||||
|
// :put! above cursor
|
||||||
|
dir = BACKWARD;
|
||||||
|
else if (lnum >= 0)
|
||||||
|
curwin->w_cursor.lnum = iptr->isn_arg.put.put_lnum;
|
||||||
|
check_cursor();
|
||||||
|
do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
|
||||||
|
vim_free(expr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ISN_SHUFFLE:
|
case ISN_SHUFFLE:
|
||||||
{
|
{
|
||||||
typval_T tmp_tv;
|
typval_T tmp_tv;
|
||||||
@ -3227,6 +3257,10 @@ ex_disassemble(exarg_T *eap)
|
|||||||
case ISN_2STRING_ANY: smsg("%4d 2STRING_ANY stack[%lld]", current,
|
case ISN_2STRING_ANY: smsg("%4d 2STRING_ANY stack[%lld]", current,
|
||||||
(long long)(iptr->isn_arg.number));
|
(long long)(iptr->isn_arg.number));
|
||||||
break;
|
break;
|
||||||
|
case ISN_PUT:
|
||||||
|
smsg("%4d PUT %c %ld", current, iptr->isn_arg.put.put_regname,
|
||||||
|
(long)iptr->isn_arg.put.put_lnum);
|
||||||
|
break;
|
||||||
|
|
||||||
case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current,
|
case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current,
|
||||||
iptr->isn_arg.shuffle.shfl_item,
|
iptr->isn_arg.shuffle.shfl_item,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user