From e74cad3321ce1dcefc1fc64f617511275b6cd930 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Fri, 12 Apr 2024 18:48:35 +0200 Subject: patch 9.1.0312: heredocs are not supported for :commands Problem: heredocs are not supported for :commands (@balki) Solution: Add heredoc support (Yegappan Lakshmanan) fixes: #14491 closes: #14528 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- src/evalvars.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 11 deletions(-) (limited to 'src/evalvars.c') diff --git a/src/evalvars.c b/src/evalvars.c index f16d4757f2..62728ed8ab 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -779,8 +779,10 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile) int eval_failed = FALSE; cctx_T *cctx = vim9compile ? eap->cookie : NULL; int count = 0; + int heredoc_in_string = FALSE; + char_u *line_arg = NULL; - if (eap->ea_getline == NULL) + if (eap->ea_getline == NULL && vim_strchr(cmd, '\n') == NULL) { emsg(_(e_cannot_use_heredoc_here)); return NULL; @@ -824,8 +826,14 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile) if (*cmd != NUL && *cmd != comment_char) { marker = skipwhite(cmd); - p = skiptowhite(marker); - if (*skipwhite(p) != NUL && *skipwhite(p) != comment_char) + p = skiptowhite_or_nl(marker); + if (*p == NL) + { + // heredoc in a string + line_arg = p + 1; + heredoc_in_string = TRUE; + } + else if (*skipwhite(p) != NUL && *skipwhite(p) != comment_char) { semsg(_(e_trailing_characters_str), p); return NULL; @@ -859,12 +867,38 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile) int mi = 0; int ti = 0; - vim_free(theline); - theline = eap->ea_getline(NUL, eap->cookie, 0, FALSE); - if (theline == NULL) + if (heredoc_in_string) { - semsg(_(e_missing_end_marker_str), marker); - break; + char_u *next_line; + + // heredoc in a string separated by newlines. Get the next line + // from the string. + + if (*line_arg == NUL) + { + semsg(_(e_missing_end_marker_str), marker); + break; + } + + theline = line_arg; + next_line = vim_strchr(theline, '\n'); + if (next_line == NULL) + line_arg += STRLEN(line_arg); + else + { + *next_line = NUL; + line_arg = next_line + 1; + } + } + else + { + vim_free(theline); + theline = eap->ea_getline(NUL, eap->cookie, 0, FALSE); + if (theline == NULL) + { + semsg(_(e_missing_end_marker_str), marker); + break; + } } // with "trim": skip the indent matching the :let line to find the @@ -911,6 +945,8 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile) } else { + int free_str = FALSE; + if (evalstr && !eap->skip) { str = eval_all_expr_in_str(str); @@ -920,15 +956,20 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile) eval_failed = TRUE; continue; } - vim_free(theline); - theline = str; + free_str = TRUE; } if (list_append_string(l, str, -1) == FAIL) break; + if (free_str) + vim_free(str); } } - vim_free(theline); + if (heredoc_in_string) + // Next command follows the heredoc in the string. + eap->nextcmd = line_arg; + else + vim_free(theline); vim_free(text_indent); if (vim9compile && cctx->ctx_skip != SKIP_YES && !eval_failed) -- cgit v1.2.3