diff options
author | LemonBoy <thatlemon@gmail.com> | 2022-05-06 13:14:50 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-05-06 13:14:50 +0100 |
commit | 2eaef106e4a7fc9dc74a7e672b5f550ec1f9786e (patch) | |
tree | 543832333e5ef90b9e51477457a7e65572274227 /src/evalvars.c | |
parent | e7d6dbc5721342e3d6b04cf285e4510b5569e707 (diff) | |
download | vim-git-2eaef106e4a7fc9dc74a7e672b5f550ec1f9786e.tar.gz |
patch 8.2.4883: string interpolation only works in heredocv8.2.4883
Problem: String interpolation only works in heredoc.
Solution: Support interpolated strings. Use syntax for heredoc consistent
with strings, similar to C#. (closes #10327)
Diffstat (limited to 'src/evalvars.c')
-rw-r--r-- | src/evalvars.c | 93 |
1 files changed, 61 insertions, 32 deletions
diff --git a/src/evalvars.c b/src/evalvars.c index c51b5976d..2f285189b 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -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 `= + if (escaped_brace) + { + // Skip the second brace. + ++p; + continue; + } - status = *p == NUL ? OK : skip_expr(&p, NULL); - if (status == FAIL || *p != '`') + // Skip the opening {. + block_start = ++p; + block_end = block_start; + if (*block_start != NUL && skip_expr(&block_end, NULL) == FAIL) { - // invalid expression or missing ending backtick - if (status != FAIL) - emsg(_(e_missing_backtick)); - vim_free(ga.ga_data); + 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); |