diff options
Diffstat (limited to 'src/nvim/eval/vars.c')
-rw-r--r-- | src/nvim/eval/vars.c | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 65e648b625..37199cd95d 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -62,8 +62,8 @@ static const char e_double_semicolon_in_list_of_variables[] static const char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s"); static const char e_setting_v_str_to_value_with_wrong_type[] = N_("E963: Setting v:%s to value with wrong type"); -static const char e_cannot_use_heredoc_here[] - = N_("E991: Cannot use =<< here"); +static const char e_missing_end_marker_str[] = N_("E990: Missing end marker '%s'"); +static const char e_cannot_use_heredoc_here[] = N_("E991: Cannot use =<< here"); /// Evaluate one Vim expression {expr} in string "p" and append the /// resulting string to "gap". "p" points to the opening "{". @@ -179,8 +179,15 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) int text_indent_len = 0; char *text_indent = NULL; char dot[] = "."; - - if (eap->ea_getline == NULL) { + bool heredoc_in_string = false; + char *line_arg = NULL; + char *nl_ptr = vim_strchr(cmd, '\n'); + + if (nl_ptr != NULL) { + heredoc_in_string = true; + line_arg = nl_ptr + 1; + *nl_ptr = NUL; + } else if (eap->ea_getline == NULL) { emsg(_(e_cannot_use_heredoc_here)); return NULL; } @@ -216,11 +223,12 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) break; } + const char comment_char = '"'; // The marker is the next word. - if (*cmd != NUL && *cmd != '"') { + if (*cmd != NUL && *cmd != comment_char) { marker = skipwhite(cmd); char *p = skiptowhite(marker); - if (*skipwhite(p) != NUL && *skipwhite(p) != '"') { + if (*skipwhite(p) != NUL && *skipwhite(p) != comment_char) { semsg(_(e_trailing_arg), p); return NULL; } @@ -246,13 +254,34 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) int mi = 0; int ti = 0; - xfree(theline); - theline = eap->ea_getline(NUL, eap->cookie, 0, false); - if (theline == NULL) { - if (!script_get) { - semsg(_("E990: Missing end marker '%s'"), marker); + if (heredoc_in_string) { + // heredoc in a string separated by newlines. Get the next line + // from the string. + + if (*line_arg == NUL) { + if (!script_get) { + semsg(_(e_missing_end_marker_str), marker); + } + break; + } + + theline = line_arg; + char *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 { + xfree(theline); + theline = eap->ea_getline(NUL, eap->cookie, 0, false); + if (theline == NULL) { + if (!script_get) { + semsg(_(e_missing_end_marker_str), marker); + } + break; } - break; } // with "trim": skip the indent matching the :let line to find the @@ -298,13 +327,17 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) eval_failed = true; continue; } - xfree(theline); - theline = str; + tv_list_append_allocated_string(l, str); + } else { + tv_list_append_string(l, str, -1); } - - tv_list_append_string(l, str, -1); } - xfree(theline); + if (heredoc_in_string) { + // Next command follows the heredoc in the string. + eap->nextcmd = line_arg; + } else { + xfree(theline); + } xfree(text_indent); if (eval_failed) { |