Patch 8.2.1637
Problem: Vim9: :put ={expr} does not work inside :def function.
Solution: Add ISN_PUT. (closes #6397)
Files: src/vim9.h, src/vim9compile.c, src/vim9execute.c, src/register.c,
src/proto/register.pro, src/edit.c, src/ex_docmd.c, src/mouse.c,
src/normal.c, src/testdir/test_vim9_cmd.vim,
src/testdir/test_vim9_disassemble.vim
*** ../vim-8.2.1636/src/vim9.h 2020-08-16 17:33:29.517887810 +0200
--- src/vim9.h 2020-09-07 22:41:01.141689898 +0200
***************
*** 135,140 ****
--- 135,142 ----
ISN_CHECKTYPE, // check value type is isn_arg.type.tc_type
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_DROP // pop stack and discard value
} isntype_T;
***************
*** 261,266 ****
--- 263,274 ----
int shfl_up; // places to move upwards
} 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
*/
***************
*** 296,301 ****
--- 304,310 ----
newfunc_T newfunc;
checklen_T checklen;
shuffle_T shuffle;
+ put_T put;
} isn_arg;
};
*** ../vim-8.2.1636/src/vim9compile.c 2020-09-01 19:56:10.928571016 +0200
--- src/vim9compile.c 2020-09-08 22:34:11.887703034 +0200
***************
*** 1567,1572 ****
--- 1567,1588 ----
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
generate_EXEC(cctx_T *cctx, char_u *line)
{
***************
*** 6272,6277 ****
--- 6288,6337 ----
}
/*
+ * :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.
*/
static char_u *
***************
*** 6870,6875 ****
--- 6930,6940 ----
line = compile_mult_expr(p, ea.cmdidx, &cctx);
break;
+ case CMD_put:
+ ea.cmd = cmd;
+ line = compile_put(p, &ea, &cctx);
+ break;
+
// TODO: any other commands with an expression argument?
case CMD_append:
***************
*** 7192,7197 ****
--- 7257,7263 ----
case ISN_PUSHF:
case ISN_PUSHNR:
case ISN_PUSHSPEC:
+ case ISN_PUT:
case ISN_RETURN:
case ISN_SHUFFLE:
case ISN_SLICE:
*** ../vim-8.2.1636/src/vim9execute.c 2020-08-30 23:24:17.219401371 +0200
--- src/vim9execute.c 2020-09-08 22:36:32.211254084 +0200
***************
*** 2581,2586 ****
--- 2581,2616 ----
}
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:
{
typval_T tmp_tv;
***************
*** 3227,3232 ****
--- 3257,3266 ----
case ISN_2STRING_ANY: smsg("%4d 2STRING_ANY stack[%lld]", current,
(long long)(iptr->isn_arg.number));
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,
iptr->isn_arg.shuffle.shfl_item,
*** ../vim-8.2.1636/src/register.c 2020-08-22 21:08:40.756880896 +0200
--- src/register.c 2020-09-07 23:01:51.011437331 +0200
***************
*** 1487,1492 ****
--- 1487,1493 ----
void
do_put(
int regname,
+ char_u *expr_result, // result for regname "=" when compiled
int dir, // BACKWARD for 'P', FORWARD for 'p'
long count,
int flags)
***************
*** 1551,1561 ****
// For special registers '%' (file name), '#' (alternate file name) and
// ':' (last command line), etc. we have to create a fake yank register.
! if (get_spec_reg(regname, &insert_string, &allocated, TRUE))
! {
! if (insert_string == NULL)
! return;
! }
// Autocommands may be executed when saving lines for undo. This might
// make "y_array" invalid, so we start undo now to avoid that.
--- 1552,1563 ----
// For special registers '%' (file name), '#' (alternate file name) and
// ':' (last command line), etc. we have to create a fake yank register.
! // For compiled code "expr_result" holds the expression result.
! if (regname == '=' && expr_result != NULL)
! insert_string = expr_result;
! 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
// make "y_array" invalid, so we start undo now to avoid that.
*** ../vim-8.2.1636/src/proto/register.pro 2020-06-07 18:16:31.307293302
+0200
--- src/proto/register.pro 2020-09-07 23:01:54.483433547 +0200
***************
*** 27,33 ****
void clear_registers(void);
void free_yank_all(void);
int op_yank(oparg_T *oap, int deleting, int mess);
! void do_put(int regname, int dir, long count, int flags);
int get_register_name(int num);
int get_unname_register(void);
void ex_display(exarg_T *eap);
--- 27,33 ----
void clear_registers(void);
void free_yank_all(void);
int op_yank(oparg_T *oap, int deleting, int mess);
! void do_put(int regname, char_u *expr_result, int dir, long count, int flags);
int get_register_name(int num);
int get_unname_register(void);
void ex_display(exarg_T *eap);
*** ../vim-8.2.1636/src/edit.c 2020-09-05 15:48:32.469546692 +0200
--- src/edit.c 2020-09-07 22:54:59.227542967 +0200
***************
*** 3399,3405 ****
AppendCharToRedobuff(literally);
AppendCharToRedobuff(regname);
! do_put(regname, BACKWARD, 1L,
(literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
}
else if (insert_reg(regname, literally) == FAIL)
--- 3399,3405 ----
AppendCharToRedobuff(literally);
AppendCharToRedobuff(regname);
! do_put(regname, NULL, BACKWARD, 1L,
(literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
}
else if (insert_reg(regname, literally) == FAIL)
***************
*** 4776,4782 ****
static void
ins_drop(void)
{
! do_put('~', BACKWARD, 1L, PUT_CURSEND);
}
#endif
--- 4776,4782 ----
static void
ins_drop(void)
{
! do_put('~', NULL, BACKWARD, 1L, PUT_CURSEND);
}
#endif
*** ../vim-8.2.1636/src/ex_docmd.c 2020-08-23 21:05:59.210438670 +0200
--- src/ex_docmd.c 2020-09-07 22:55:34.319567860 +0200
***************
*** 7321,7327 ****
eap->forceit = TRUE;
}
curwin->w_cursor.lnum = eap->line2;
! do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L,
PUT_LINE|PUT_CURSLINE);
}
--- 7321,7327 ----
eap->forceit = TRUE;
}
curwin->w_cursor.lnum = eap->line2;
! do_put(eap->regname, NULL, eap->forceit ? BACKWARD : FORWARD, 1L,
PUT_LINE|PUT_CURSLINE);
}
*** ../vim-8.2.1636/src/mouse.c 2020-08-11 21:58:12.581968226 +0200
--- src/mouse.c 2020-09-07 22:56:33.747592563 +0200
***************
*** 430,436 ****
insert_reg(regname, TRUE);
else
{
! do_put(regname, BACKWARD, 1L, fixindent | PUT_CURSEND);
// Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r
AppendCharToRedobuff(Ctrl_R);
--- 430,437 ----
insert_reg(regname, TRUE);
else
{
! do_put(regname, NULL, BACKWARD, 1L,
! fixindent | PUT_CURSEND);
// Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r
AppendCharToRedobuff(Ctrl_R);
***************
*** 849,855 ****
// to this position
if (restart_edit != 0)
where_paste_started = curwin->w_cursor;
! do_put(regname, dir, count, fixindent | PUT_CURSEND);
}
#if defined(FEAT_QUICKFIX)
--- 850,856 ----
// to this position
if (restart_edit != 0)
where_paste_started = curwin->w_cursor;
! do_put(regname, NULL, dir, count, fixindent | PUT_CURSEND);
}
#if defined(FEAT_QUICKFIX)
*** ../vim-8.2.1636/src/normal.c 2020-09-05 14:27:19.466565808 +0200
--- src/normal.c 2020-09-07 22:56:58.583596890 +0200
***************
*** 7427,7433 ****
// May have been reset in do_put().
VIsual_active = TRUE;
}
! do_put(cap->oap->regname, dir, cap->count1, flags);
// If a register was saved, put it back now.
if (reg2 != NULL)
--- 7427,7433 ----
// May have been reset in do_put().
VIsual_active = TRUE;
}
! do_put(cap->oap->regname, NULL, dir, cap->count1, flags);
// If a register was saved, put it back now.
if (reg2 != NULL)
***************
*** 7500,7506 ****
static void
nv_drop(cmdarg_T *cap UNUSED)
{
! do_put('~', BACKWARD, 1L, PUT_CURSEND);
}
#endif
--- 7500,7506 ----
static void
nv_drop(cmdarg_T *cap UNUSED)
{
! do_put('~', NULL, BACKWARD, 1L, PUT_CURSEND);
}
#endif
*** ../vim-8.2.1636/src/testdir/test_vim9_cmd.vim 2020-08-23
21:46:29.075938591 +0200
--- src/testdir/test_vim9_cmd.vim 2020-09-08 22:26:37.385116567 +0200
***************
*** 315,319 ****
--- 315,335 ----
bwipe!
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-8.2.1636/src/testdir/test_vim9_disassemble.vim 2020-09-06
15:58:33.383154915 +0200
--- src/testdir/test_vim9_disassemble.vim 2020-09-08 22:22:57.693762215
+0200
***************
*** 118,123 ****
--- 118,138 ----
res)
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()
let localbool = true
let localspec = v:none
*** ../vim-8.2.1636/src/version.c 2020-09-08 22:06:12.829040924 +0200
--- src/version.c 2020-09-08 22:38:20.094906814 +0200
***************
*** 756,757 ****
--- 756,759 ----
{ /* Add new patch number below this line */
+ /**/
+ 1637,
/**/
--
ARTHUR: Go on, Bors, chop its head off.
BORS: Right. Silly little bleeder. One rabbit stew coming up.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202009082056.088Kuhrj152219%40masaka.moolenaar.net.