# HG changeset patch # User Bram Moolenaar # Date 1561428908 -7200 # Node ID 40c4cb095d538da9590ba4e47fbab0f68a9b2c53 # Parent b58feb1a84f0ec067e1338cdebccdcd16aa7faa7 patch 8.1.1588: in :let-heredoc line continuation is recognized commit https://github.com/vim/vim/commit/e96a2498f9a2d3e93ac07431f6d4afd77f30afdf Author: Bram Moolenaar Date: Tue Jun 25 04:12:16 2019 +0200 patch 8.1.1588: in :let-heredoc line continuation is recognized Problem: In :let-heredoc line continuation is recognized. Solution: Do not consume line continuation. (Ozaki Kiichi, closes https://github.com/vim/vim/issues/4580) diff --git a/src/autocmd.c b/src/autocmd.c --- a/src/autocmd.c +++ b/src/autocmd.c @@ -2329,7 +2329,7 @@ auto_next_pat( * Returns allocated string, or NULL for end of autocommands. */ char_u * -getnextac(int c UNUSED, void *cookie, int indent UNUSED) +getnextac(int c UNUSED, void *cookie, int indent UNUSED, int do_concat UNUSED) { AutoPatCmd *acp = (AutoPatCmd *)cookie; char_u *retval; diff --git a/src/digraph.c b/src/digraph.c --- a/src/digraph.c +++ b/src/digraph.c @@ -2378,7 +2378,7 @@ ex_loadkeymap(exarg_T *eap) */ for (;;) { - line = eap->getline(0, eap->cookie, 0); + line = eap->getline(0, eap->cookie, 0, TRUE); if (line == NULL) break; diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -1307,7 +1307,7 @@ heredoc_get(exarg_T *eap, char_u *cmd) int mi = 0; int ti = 0; - theline = eap->getline(NUL, eap->cookie, 0); + theline = eap->getline(NUL, eap->cookie, 0, FALSE); if (theline == NULL) { semsg(_("E990: Missing end marker '%s'"), marker); diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3234,7 +3234,8 @@ execute_redir_str(char_u *value, int val get_list_line( int c UNUSED, void *cookie, - int indent UNUSED) + int indent UNUSED, + int do_concat UNUSED) { listitem_T **p = (listitem_T **)cookie; listitem_T *item = *p; diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -4540,7 +4540,7 @@ ex_append(exarg_T *eap) #ifdef FEAT_EVAL eap->cstack->cs_looplevel > 0 ? -1 : #endif - NUL, eap->cookie, indent); + NUL, eap->cookie, indent, TRUE); State = save_State; } lines_left = Rows - 1; @@ -5388,7 +5388,7 @@ do_sub(exarg_T *eap) for ( ; i <= (long)ec; ++i) msg_putchar('^'); - resp = getexmodeline('?', NULL, 0); + resp = getexmodeline('?', NULL, 0, TRUE); if (resp != NULL) { typed = *resp; diff --git a/src/ex_cmds.h b/src/ex_cmds.h --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -1837,7 +1837,7 @@ struct exarg int bad_char; /* BAD_KEEP, BAD_DROP or replacement byte */ int useridx; /* user command index */ char *errmsg; /* returned error message */ - char_u *(*getline)(int, void *, int); + char_u *(*getline)(int, void *, int, int); void *cookie; /* argument for getline() */ #ifdef FEAT_EVAL struct condstack *cstack; /* condition stack for ":if" etc. */ diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -371,6 +371,7 @@ check_due_timer(void) int save_trylevel = trylevel; int save_did_throw = did_throw; int save_ex_pressedreturn = get_pressedreturn(); + int save_may_garbage_collect = may_garbage_collect; except_T *save_current_exception = current_exception; vimvars_save_T vvsave; @@ -385,7 +386,9 @@ check_due_timer(void) trylevel = 0; did_throw = FALSE; current_exception = NULL; + may_garbage_collect = FALSE; save_vimvars(&vvsave); + timer->tr_firing = TRUE; timer_callback(timer); timer->tr_firing = FALSE; @@ -407,6 +410,7 @@ check_due_timer(void) must_redraw = must_redraw > save_must_redraw ? must_redraw : save_must_redraw; set_pressedreturn(save_ex_pressedreturn); + may_garbage_collect = save_may_garbage_collect; /* Only fire the timer again if it repeats and stop_timer() wasn't * called while inside the callback (tr_id == -1). */ @@ -3611,7 +3615,7 @@ do_source( cookie.conv.vc_type = CONV_NONE; /* no conversion */ /* Read the first line so we can check for a UTF-8 BOM. */ - firstline = getsourceline(0, (void *)&cookie, 0); + firstline = getsourceline(0, (void *)&cookie, 0, TRUE); if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef && firstline[1] == 0xbb && firstline[2] == 0xbf) { @@ -3794,7 +3798,7 @@ free_scriptnames(void) * Return NULL for end-of-file or some error. */ char_u * -getsourceline(int c UNUSED, void *cookie, int indent UNUSED) +getsourceline(int c UNUSED, void *cookie, int indent UNUSED, int do_concat) { struct source_cookie *sp = (struct source_cookie *)cookie; char_u *line; @@ -3833,7 +3837,7 @@ getsourceline(int c UNUSED, void *cookie /* Only concatenate lines starting with a \ when 'cpoptions' doesn't * contain the 'C' flag. */ - if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL)) + if (line != NULL && do_concat && vim_strchr(p_cpo, CPO_CONCAT) == NULL) { /* compensate for the one line read-ahead */ --sourcing_lnum; @@ -4212,7 +4216,7 @@ do_finish(exarg_T *eap, int reanimate) */ int source_finished( - char_u *(*fgetline)(int, void *, int), + char_u *(*fgetline)(int, void *, int, int), void *cookie) { return (getline_equal(fgetline, cookie, getsourceline) diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -20,9 +20,9 @@ static int ex_pressedreturn = FALSE; #endif #ifdef FEAT_EVAL -static char_u *do_one_cmd(char_u **, int, struct condstack *, char_u *(*fgetline)(int, void *, int), void *cookie); +static char_u *do_one_cmd(char_u **, int, struct condstack *, char_u *(*fgetline)(int, void *, int, int), void *cookie); #else -static char_u *do_one_cmd(char_u **, int, char_u *(*fgetline)(int, void *, int), void *cookie); +static char_u *do_one_cmd(char_u **, int, char_u *(*fgetline)(int, void *, int, int), void *cookie); static int if_level = 0; /* depth in :if */ #endif static void free_cmdmod(void); @@ -431,11 +431,11 @@ struct loop_cookie int current_line; /* last read line from growarray */ int repeating; /* TRUE when looping a second time */ /* When "repeating" is FALSE use "getline" and "cookie" to get lines */ - char_u *(*getline)(int, void *, int); + char_u *(*getline)(int, void *, int, int); void *cookie; }; -static char_u *get_loop_line(int c, void *cookie, int indent); +static char_u *get_loop_line(int c, void *cookie, int indent, int do_concat); static int store_loop_line(garray_T *gap, char_u *line); static void free_cmdlines(garray_T *gap); @@ -619,7 +619,7 @@ do_cmdline_cmd(char_u *cmd) int do_cmdline( char_u *cmdline, - char_u *(*fgetline)(int, void *, int), + char_u *(*fgetline)(int, void *, int, int), void *cookie, /* argument for fgetline() */ int flags) { @@ -644,7 +644,7 @@ do_cmdline( struct msglist *private_msg_list; /* "fgetline" and "cookie" passed to do_one_cmd() */ - char_u *(*cmd_getline)(int, void *, int); + char_u *(*cmd_getline)(int, void *, int, int); void *cmd_cookie; struct loop_cookie cmd_loop_cookie; void *real_cookie; @@ -894,7 +894,7 @@ do_cmdline( #else 0 #endif - )) == NULL) + , TRUE)) == NULL) { /* Don't call wait_return for aborted command line. The NULL * returned for the end of a sourced file or executed function @@ -1424,7 +1424,7 @@ do_cmdline( * Obtain a line when inside a ":while" or ":for" loop. */ static char_u * -get_loop_line(int c, void *cookie, int indent) +get_loop_line(int c, void *cookie, int indent, int do_concat) { struct loop_cookie *cp = (struct loop_cookie *)cookie; wcmd_T *wp; @@ -1437,9 +1437,9 @@ get_loop_line(int c, void *cookie, int i /* First time inside the ":while"/":for": get line normally. */ if (cp->getline == NULL) - line = getcmdline(c, 0L, indent); + line = getcmdline(c, 0L, indent, do_concat); else - line = cp->getline(c, cp->cookie, indent); + line = cp->getline(c, cp->cookie, indent, do_concat); if (line != NULL && store_loop_line(cp->lines_gap, line) == OK) ++cp->current_line; @@ -1487,12 +1487,12 @@ free_cmdlines(garray_T *gap) */ int getline_equal( - char_u *(*fgetline)(int, void *, int), + char_u *(*fgetline)(int, void *, int, int), void *cookie UNUSED, /* argument for fgetline() */ - char_u *(*func)(int, void *, int)) + char_u *(*func)(int, void *, int, int)) { #ifdef FEAT_EVAL - char_u *(*gp)(int, void *, int); + char_u *(*gp)(int, void *, int, int); struct loop_cookie *cp; /* When "fgetline" is "get_loop_line()" use the "cookie" to find the @@ -1517,11 +1517,11 @@ getline_equal( */ void * getline_cookie( - char_u *(*fgetline)(int, void *, int) UNUSED, + char_u *(*fgetline)(int, void *, int, int) UNUSED, void *cookie) /* argument for fgetline() */ { #ifdef FEAT_EVAL - char_u *(*gp)(int, void *, int); + char_u *(*gp)(int, void *, int, int); struct loop_cookie *cp; /* When "fgetline" is "get_loop_line()" use the "cookie" to find the @@ -1654,7 +1654,7 @@ do_one_cmd( #ifdef FEAT_EVAL struct condstack *cstack, #endif - char_u *(*fgetline)(int, void *, int), + char_u *(*fgetline)(int, void *, int, int), void *cookie) /* argument for fgetline() */ { char_u *p; diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -838,7 +838,8 @@ cmdline_init(void) getcmdline( int firstc, long count, // only used for incremental search - int indent) // indent for inside conditionals + int indent, // indent for inside conditionals + int do_concat UNUSED) { return getcmdline_int(firstc, count, indent, TRUE); } @@ -2687,12 +2688,13 @@ correct_cmdspos(int idx, int cells) getexline( int c, /* normally ':', NUL for ":append" */ void *cookie UNUSED, - int indent) /* indent for inside conditionals */ + int indent, /* indent for inside conditionals */ + int do_concat) { /* When executing a register, remove ':' that's in front of each line. */ if (exec_from_reg && vpeekc() == ':') (void)vgetc(); - return getcmdline(c, 1L, indent); + return getcmdline(c, 1L, indent, do_concat); } /* @@ -2706,7 +2708,8 @@ getexmodeline( int promptc, /* normally ':', NUL for ":append" and '?' for :s prompt */ void *cookie UNUSED, - int indent) /* indent for inside conditionals */ + int indent, /* indent for inside conditionals */ + int do_concat UNUSED) { garray_T line_ga; char_u *pend; @@ -7409,7 +7412,7 @@ script_get(exarg_T *eap, char_u *cmd) #ifdef FEAT_EVAL eap->cstack->cs_looplevel > 0 ? -1 : #endif - NUL, eap->cookie, 0); + NUL, eap->cookie, 0, TRUE); if (theline == NULL || STRCMP(end_pattern, theline) == 0) { diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -6237,7 +6237,7 @@ nv_search(cmdarg_T *cap) /* When using 'incsearch' the cursor may be moved to set a different search * start position. */ - cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0); + cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0, TRUE); if (cap->searchbuf == NULL) { diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -788,7 +788,7 @@ get_expr_register(void) { char_u *new_line; - new_line = getcmdline('=', 0L, 0); + new_line = getcmdline('=', 0L, 0, TRUE); if (new_line == NULL) return NUL; if (*new_line == NUL) /* use previous line */ diff --git a/src/proto/autocmd.pro b/src/proto/autocmd.pro --- a/src/proto/autocmd.pro +++ b/src/proto/autocmd.pro @@ -30,7 +30,7 @@ int has_completechanged(void); void block_autocmds(void); void unblock_autocmds(void); int is_autocmd_blocked(void); -char_u *getnextac(int c, void *cookie, int indent); +char_u *getnextac(int c, void *cookie, int indent, int do_concat); int has_autocmd(event_T event, char_u *sfname, buf_T *buf); char_u *get_augroup_name(expand_T *xp, int idx); char_u *set_context_in_autocmd(expand_T *xp, char_u *arg, int doautocmd); diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro --- a/src/proto/ex_cmds2.pro +++ b/src/proto/ex_cmds2.pro @@ -81,7 +81,7 @@ void ex_scriptnames(exarg_T *eap); void scriptnames_slash_adjust(void); char_u *get_scriptname(scid_T id); void free_scriptnames(void); -char_u *getsourceline(int c, void *cookie, int indent); +char_u *getsourceline(int c, void *cookie, int indent, int do_concat); void script_line_start(void); void script_line_exec(void); void script_line_end(void); @@ -89,7 +89,7 @@ void ex_scriptencoding(exarg_T *eap); void ex_scriptversion(exarg_T *eap); void ex_finish(exarg_T *eap); void do_finish(exarg_T *eap, int reanimate); -int source_finished(char_u *(*fgetline)(int, void *, int), void *cookie); +int source_finished(char_u *(*fgetline)(int, void *, int, int), void *cookie); void ex_checktime(exarg_T *eap); char_u *get_mess_lang(void); void set_lang_var(void); diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -1,9 +1,9 @@ /* ex_docmd.c */ void do_exmode(int improved); int do_cmdline_cmd(char_u *cmd); -int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int), void *cookie, int flags); -int getline_equal(char_u *(*fgetline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int)); -void *getline_cookie(char_u *(*fgetline)(int, void *, int), void *cookie); +int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int, int), void *cookie, int flags); +int getline_equal(char_u *(*fgetline)(int, void *, int, int), void *cookie, char_u *(*func)(int, void *, int, int)); +void *getline_cookie(char_u *(*fgetline)(int, void *, int, int), void *cookie); int parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only); int parse_cmd_address(exarg_T *eap, char **errormsg, int silent); int checkforcmd(char_u **pp, char *cmd, int len); diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro --- a/src/proto/ex_getln.pro +++ b/src/proto/ex_getln.pro @@ -1,14 +1,14 @@ /* ex_getln.c */ void cmdline_init(void); -char_u *getcmdline(int firstc, long count, int indent); +char_u *getcmdline(int firstc, long count, int indent, int do_concat); char_u *getcmdline_prompt(int firstc, char_u *prompt, int attr, int xp_context, char_u *xp_arg); int text_locked(void); void text_locked_msg(void); char *get_text_locked_msg(void); int curbuf_locked(void); int allbuf_locked(void); -char_u *getexline(int c, void *cookie, int indent); -char_u *getexmodeline(int promptc, void *cookie, int indent); +char_u *getexline(int c, void *cookie, int indent, int do_concat); +char_u *getexmodeline(int promptc, void *cookie, int indent, int do_concat); int cmdline_overstrike(void); int cmdline_at_end(void); colnr_T cmdline_getvcol_cursor(void); diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -30,7 +30,7 @@ void ex_call(exarg_T *eap); int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv); void discard_pending_return(void *rettv); char_u *get_return_cmd(void *rettv); -char_u *get_func_line(int c, void *cookie, int indent); +char_u *get_func_line(int c, void *cookie, int indent, int do_concat); void func_line_start(void *cookie); void func_line_exec(void *cookie); void func_line_end(void *cookie); diff --git a/src/testdir/test_let.vim b/src/testdir/test_let.vim --- a/src/testdir/test_let.vim +++ b/src/testdir/test_let.vim @@ -237,6 +237,14 @@ END END call assert_equal(['something', 'endfunc'], var1) + " not concatenate lines + let var1 =<< END +some + \thing + \ else +END + call assert_equal(['some', ' \thing', ' \ else'], var1) + " ignore "python << xx" let var1 =<getline == NULL) - theline = getcmdline(':', 0L, indent); + theline = getcmdline(':', 0L, indent, do_concat); else - theline = eap->getline(':', eap->cookie, indent); + theline = eap->getline(':', eap->cookie, indent, do_concat); line_to_free = theline; } if (KeyTyped) @@ -2334,6 +2335,7 @@ ex_function(exarg_T *eap) { VIM_CLEAR(skip_until); VIM_CLEAR(trimmed); + do_concat = TRUE; } } } @@ -2458,6 +2460,7 @@ ex_function(exarg_T *eap) skip_until = vim_strsave((char_u *)"."); else skip_until = vim_strnsave(p, (int)(skiptowhite(p) - p)); + do_concat = FALSE; } } @@ -3511,7 +3514,8 @@ get_return_cmd(void *rettv) get_func_line( int c UNUSED, void *cookie, - int indent UNUSED) + int indent UNUSED, + int do_concat UNUSED) { funccall_T *fcp = (funccall_T *)cookie; ufunc_T *fp = fcp->func; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1588, +/**/ 1587, /**/ 1586,