0
0
mirror of https://github.com/vim/vim.git synced 2025-09-28 04:24:06 -04:00

patch 8.2.4883: string interpolation only works in heredoc

Problem:    String interpolation only works in heredoc.
Solution:   Support interpolated strings.  Use syntax for heredoc consistent
            with strings, similar to C#. (closes #10327)
This commit is contained in:
LemonBoy
2022-05-06 13:14:50 +01:00
committed by Bram Moolenaar
parent e7d6dbc572
commit 2eaef106e4
16 changed files with 364 additions and 137 deletions

View File

@@ -603,59 +603,88 @@ list_script_vars(int *first)
}
/*
* Evaluate all the Vim expressions (`=expr`) in string "str" and return the
* Evaluate all the Vim expressions ({expr}) in string "str" and return the
* resulting string. The caller must free the returned string.
*/
static char_u *
char_u *
eval_all_expr_in_str(char_u *str)
{
garray_T ga;
char_u *s;
char_u *p;
char_u save_c;
char_u *exprval;
int status;
char_u *expr_val;
ga_init2(&ga, 1, 80);
p = str;
// Look for `=expr`, evaluate the expression and replace `=expr` with the
// result.
while (*p != NUL)
{
s = p;
while (*p != NUL && (*p != '`' || p[1] != '='))
p++;
ga_concat_len(&ga, s, p - s);
char_u *lit_start;
char_u *block_start;
char_u *block_end;
int escaped_brace = FALSE;
// Look for a block start.
lit_start = p;
while (*p != '{' && *p != '}' && *p != NUL)
++p;
if (*p != NUL && *p == p[1])
{
// Escaped brace, unescape and continue.
// Include the brace in the literal string.
++p;
escaped_brace = TRUE;
}
else if (*p == '}')
{
semsg(_(e_stray_closing_curly_str), str);
ga_clear(&ga);
return NULL;
}
// Append the literal part.
ga_concat_len(&ga, lit_start, (size_t)(p - lit_start));
if (*p == NUL)
break; // no backtick expression found
break;
s = p;
p += 2; // skip `=
status = *p == NUL ? OK : skip_expr(&p, NULL);
if (status == FAIL || *p != '`')
if (escaped_brace)
{
// invalid expression or missing ending backtick
if (status != FAIL)
emsg(_(e_missing_backtick));
vim_free(ga.ga_data);
// Skip the second brace.
++p;
continue;
}
// Skip the opening {.
block_start = ++p;
block_end = block_start;
if (*block_start != NUL && skip_expr(&block_end, NULL) == FAIL)
{
ga_clear(&ga);
return NULL;
}
s += 2; // skip `=
save_c = *p;
*p = NUL;
exprval = eval_to_string(s, TRUE);
*p = save_c;
p++;
if (exprval == NULL)
block_end = skipwhite(block_end);
// The block must be closed by a }.
if (*block_end != '}')
{
// expression evaluation failed
vim_free(ga.ga_data);
semsg(_(e_missing_close_curly_str), str);
ga_clear(&ga);
return NULL;
}
ga_concat(&ga, exprval);
vim_free(exprval);
save_c = *block_end;
*block_end = NUL;
expr_val = eval_to_string(block_start, TRUE);
*block_end = save_c;
if (expr_val == NULL)
{
ga_clear(&ga);
return NULL;
}
ga_concat(&ga, expr_val);
vim_free(expr_val);
p = block_end + 1;
}
ga_append(&ga, NUL);
@@ -825,7 +854,7 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile)
str = theline + ti;
if (vim9compile)
{
if (compile_heredoc_string(str, evalstr, cctx) == FAIL)
if (compile_all_expr_in_str(str, evalstr, cctx) == FAIL)
{
vim_free(theline);
vim_free(text_indent);