# HG changeset patch # User Bram Moolenaar # Date 1603890004 -3600 # Node ID 4c21a3a4770715236ce1f45fc3e5f0035ab0c4a0 # Parent 45c95095984ad938d328c568417e1eb2dfef2dd9 patch 8.2.1914: Vim9: cannot put line break in expression for '=' register Commit: https://github.com/vim/vim/commit/b4bcea474d9006e4db1fa5d6828773e739af14bb Author: Bram Moolenaar Date: Wed Oct 28 13:53:50 2020 +0100 patch 8.2.1914: Vim9: cannot put line break in expression for '=' register Problem: Vim9: cannot put line break in expression for '=' register. Solution: Pass fgetline to set_expr_line(). (closes https://github.com/vim/vim/issues/7209) diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -474,9 +474,10 @@ skip_expr_concatenate( * Return pointer to allocated memory, or NULL for failure. */ char_u * -eval_to_string( +eval_to_string_eap( char_u *arg, - int convert) + int convert, + exarg_T *eap) { typval_T tv; char_u *retval; @@ -484,8 +485,10 @@ eval_to_string( #ifdef FEAT_FLOAT char_u numbuf[NUMBUFLEN]; #endif - - if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) + evalarg_T evalarg; + + fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip); + if (eval0(arg, &tv, NULL, &evalarg) == FAIL) retval = NULL; else { @@ -512,11 +515,19 @@ eval_to_string( retval = vim_strsave(tv_get_string(&tv)); clear_tv(&tv); } - clear_evalarg(&EVALARG_EVALUATE, NULL); + clear_evalarg(&evalarg, NULL); return retval; } + char_u * +eval_to_string( + char_u *arg, + int convert) +{ + return eval_to_string_eap(arg, convert, NULL); +} + /* * Call eval_to_string() without using current local variables and using * textwinlock. When "use_sandbox" is TRUE use the sandbox. diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -1719,6 +1719,7 @@ do_one_cmd( #ifdef FEAT_EVAL int may_have_range; int vim9script = in_vim9script(); + int did_set_expr_line = FALSE; #endif CLEAR_FIELD(ea); @@ -2315,8 +2316,9 @@ do_one_cmd( // for '=' register: accept the rest of the line as an expression if (ea.arg[-1] == '=' && ea.arg[0] != NUL) { - set_expr_line(vim_strsave(ea.arg)); + set_expr_line(vim_strsave(ea.arg), &ea); ea.arg += STRLEN(ea.arg); + did_set_expr_line = TRUE; } #endif ea.arg = skipwhite(ea.arg); @@ -2595,6 +2597,9 @@ doend: do_errthrow(cstack, (ea.cmdidx != CMD_SIZE && !IS_USER_CMDIDX(ea.cmdidx)) ? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL); + + if (did_set_expr_line) + set_expr_line(NULL, NULL); #endif undo_cmdmod(&cmdmod); diff --git a/src/misc2.c b/src/misc2.c --- a/src/misc2.c +++ b/src/misc2.c @@ -1131,7 +1131,7 @@ free_all_mem(void) free_signs(); # endif # ifdef FEAT_EVAL - set_expr_line(NULL); + set_expr_line(NULL, NULL); # endif # ifdef FEAT_DIFF if (curtab != NULL) diff --git a/src/proto/eval.pro b/src/proto/eval.pro --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -11,6 +11,7 @@ int eval_expr_to_bool(typval_T *expr, in char_u *eval_to_string_skip(char_u *arg, exarg_T *eap, int skip); int skip_expr(char_u **pp, evalarg_T *evalarg); int skip_expr_concatenate(char_u **arg, char_u **start, char_u **end, evalarg_T *evalarg); +char_u *eval_to_string_eap(char_u *arg, int convert, exarg_T *eap); char_u *eval_to_string(char_u *arg, int convert); char_u *eval_to_string_safe(char_u *arg, int use_sandbox); varnumber_T eval_to_number(char_u *expr); diff --git a/src/proto/register.pro b/src/proto/register.pro --- a/src/proto/register.pro +++ b/src/proto/register.pro @@ -6,7 +6,7 @@ yankreg_T *get_y_previous(void); void set_y_current(yankreg_T *yreg); void set_y_previous(yankreg_T *yreg); int get_expr_register(void); -void set_expr_line(char_u *new_line); +void set_expr_line(char_u *new_line, exarg_T *eap); char_u *get_expr_line(void); int valid_yank_reg(int regname, int writing); int get_yank_register(int regname, int writing); diff --git a/src/register.c b/src/register.c --- a/src/register.c +++ b/src/register.c @@ -79,6 +79,7 @@ set_y_previous(yankreg_T *yreg) * Keep the last expression line here, for repeating. */ static char_u *expr_line = NULL; +static exarg_T *expr_eap = NULL; /* * Get an expression for the "\"=expr1" or "CTRL-R =expr1" @@ -95,19 +96,22 @@ get_expr_register(void) if (*new_line == NUL) // use previous line vim_free(new_line); else - set_expr_line(new_line); + set_expr_line(new_line, NULL); return '='; } /* * Set the expression for the '=' register. * Argument must be an allocated string. + * "eap" may be used if the next line needs to be checked when evaluating the + * expression. */ void -set_expr_line(char_u *new_line) +set_expr_line(char_u *new_line, exarg_T *eap) { vim_free(expr_line); expr_line = new_line; + expr_eap = eap; } /* @@ -136,7 +140,7 @@ get_expr_line(void) return expr_copy; ++nested; - rv = eval_to_string(expr_copy, TRUE); + rv = eval_to_string_eap(expr_copy, TRUE, expr_eap); --nested; vim_free(expr_copy); return rv; @@ -2774,7 +2778,7 @@ write_reg_contents_ex( vim_free(p); p = s; } - set_expr_line(p); + set_expr_line(p, NULL); return; } diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2859,6 +2859,18 @@ def Test_catch_exception_in_callback() unlet g:caught enddef +def Test_put_with_linebreak() + new + var lines =<< trim END + vim9script + pu=split('abc', '\zs') + ->join() + END + CheckScriptSuccess(lines) + getline(2)->assert_equal('a b c') + bwipe! +enddef + " Keep this last, it messes up highlighting. def Test_substitute_cmd() new diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1914, +/**/ 1913, /**/ 1912,