Skip to content

Implement interpolated strings#10327

Closed
LemonBoy wants to merge 5 commits intovim:masterfrom
LemonBoy:interp-string
Closed

Implement interpolated strings#10327
LemonBoy wants to merge 5 commits intovim:masterfrom
LemonBoy:interp-string

Conversation

@LemonBoy
Copy link
Contributor

The syntax for interpolated strings in Vim (both Vim9 and pre-Vim9) is
heavily inspired by C# and previous discussions on vim_dev ML.

The interpolated strings are prefixed with the dollar $ sign and the
inner expression are surrounded with braces { }.

The syntax for interpolated strings in Vim (both Vim9 and pre-Vim9) is
heavily inspired by C# and previous discussions on vim_dev ML.

The interpolated strings are prefixed with the dollar `$` sign and the
inner expression are surrounded with braces `{` `}`.
@codecov
Copy link

codecov bot commented Apr 30, 2022

Codecov Report

Merging #10327 (7e76274) into master (a5d3590) will decrease coverage by 0.00%.
The diff coverage is 95.14%.

@@            Coverage Diff             @@
##           master   #10327      +/-   ##
==========================================
- Coverage   81.01%   81.00%   -0.01%     
==========================================
  Files         161      161              
  Lines      185619   185812     +193     
  Branches    41972    42003      +31     
==========================================
+ Hits       150376   150522     +146     
- Misses      22736    22790      +54     
+ Partials    12507    12500       -7     
Flag Coverage Δ
huge-clang-none 82.49% <95.14%> (+0.01%) ⬆️
linux 82.49% <95.14%> (+0.01%) ⬆️
mingw-x64-HUGE 0.00% <0.00%> (ø)
mingw-x64-HUGE-gui 77.28% <96.62%> (+<0.01%) ⬆️
windows 76.07% <95.55%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/vim9compile.c 92.03% <88.63%> (-0.08%) ⬇️
src/eval.c 92.32% <100.00%> (+0.01%) ⬆️
src/evalvars.c 91.61% <100.00%> (+0.08%) ⬆️
src/typval.c 93.43% <100.00%> (+<0.01%) ⬆️
src/vim9expr.c 90.12% <100.00%> (+0.02%) ⬆️
src/os_mswin.c 49.47% <0.00%> (-1.51%) ⬇️
src/profiler.c 83.14% <0.00%> (-0.67%) ⬇️
src/gui_gtk_x11.c 52.06% <0.00%> (-0.34%) ⬇️
src/os_unix.c 66.86% <0.00%> (-0.22%) ⬇️
... and 29 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a5d3590...7e76274. Read the comment docs.

reverse() doesn't work on strings.
@brammool
Copy link
Contributor

brammool commented May 1, 2022

How does this relate to #4634 ?

@LemonBoy
Copy link
Contributor Author

LemonBoy commented May 1, 2022

How does this relate to #4634 ?

  • Up to date with master.
  • Simpler implementation.
  • The compiler for the interpolated strings is implemented for Vim9.
  • Less noisy syntax, $"{bar}" reads much better than $"${bar}", this syntax is similar to what's been adopted by Python's f-strings, C#, Typescript and so on.

@brammool
Copy link
Contributor

brammool commented May 1, 2022 via email

@dkearns
Copy link
Contributor

dkearns commented May 2, 2022

Is there a reason the syntax for interpolated expressions differs from that used with heredocs?

@LemonBoy
Copy link
Contributor Author

LemonBoy commented May 2, 2022

Is there a reason the syntax for interpolated expressions differs from that used with heredocs?

I mentioned this point in #10129 but got no feedback, the use of backticks was discouraged in #4491 with the following reasoning (which I agree with):

Backticks are hard to use on some keyboards, and also they are hard to distinguish from single quotes.

According to this comment the syntax for heredoc placeholders had no objections, but I'd like to see a single style used consistently across heredocs and strings.

@lacygoill
Copy link

lacygoill commented May 3, 2022

I'd like to see a single style used consistently across heredocs and strings.

I suggested the backtick equal syntax, because – at the time – it was the closest syntax I could think of. However, if this PR is merged, then the closest syntax would become ${}, because backtick equal is for Ex commands, while ${} is for strings. So, I definitely agree that – to be as consistent as possible – we should use ${} in heredocs too. I doubt many people would complain about the change considering that the ability to nest expressions inside heredocs was added in patch 8.2.4770, which is only about 2 weeks old.

@brammool
Copy link
Contributor

brammool commented May 4, 2022 via email

@LemonBoy
Copy link
Contributor Author

LemonBoy commented May 5, 2022

Python does this for both opening and closing curly braces.

I didn't require the closing braces to be duplicated because it doesn't really matter, once we see an open block the whole expression is parsed according to Vim's rules and we only check if there's a trailing }. It's probably not that consistent but it is documented and makes the parser simpiler/faster as we don't have to add a whole other check for } and can use a single strchr.

This said, this is not a hill I'd die on, if you feel the double-everywhere rule is better I'll amend the parser.

@brammool
Copy link
Contributor

brammool commented May 5, 2022 via email

LemonBoy added 3 commits May 5, 2022 20:42
- Unescape both {{ and }}.
- Skip leading whitespace in the expression.
Address another issue raised during the code review.
@LemonBoy
Copy link
Contributor Author

LemonBoy commented May 5, 2022

Done. I also took this chance to change the heredoc markers and simplify a bit the code.
I don't like writing docs that much so please amend those as needed.

Right now the only missing piece are multiline expressions, but let's focus on a MVP for the moment.

@brammool
Copy link
Contributor

brammool commented May 6, 2022

I found one problem (which can be fixed later): quotes in the expression need to be escaped.
I'll add a test with a FIXME mark for that.

@lacygoill
Copy link

We might want to update :help :let-heredoc which still documents the old syntax:

diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 39208e48d..19f3ddd46 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -3253,19 +3253,19 @@ text...
 
 			If "eval" is not specified, then each line of text is
 			used as a |literal-string|.  If "eval" is specified,
-			then any Vim expression in the form ``={expr}`` is
+			then any Vim expression in the form `{expr}` is
 			evaluated and the result replaces the expression.
 			Example where $HOME is expanded: >
 				let lines =<< trim eval END
 				  some text
-				  See the file `=$HOME`/.vimrc
+				  See the file {$HOME}/.vimrc
 				  more text
 				END
 <			There can be multiple Vim expressions in a single line
 			but an expression cannot span multiple lines.  If any
 			expression evaluation fails, then the assignment fails.
-			once the "`=" has been found {expr} and a backtick
-			must follow.  {expr} cannot be empty.
+			Once the `{` has been found, an expression and a `}`
+			must follow.  `expr` cannot be empty.
 
 			{endmarker} must not contain white space.
 			{endmarker} cannot start with a lower case character.

@brammool
Copy link
Contributor

brammool commented May 6, 2022

The help was already updated, will go out soon.

@LemonBoy
Copy link
Contributor Author

LemonBoy commented May 7, 2022

I found one problem (which can be fixed later): quotes in the expression need to be escaped.

That's by design, interpolated strings are still strings and so the usual rules apply. The expression evaluation happens at a later stage, once the whole string has been parsed and escaped, this makes the parsing (and highlighting) easier, beside making the expression easier to read for the user without having to guess which quote belongs to the string part and which to the expression.

@brammool
Copy link
Contributor

brammool commented May 7, 2022 via email

@dkearns
Copy link
Contributor

dkearns commented May 7, 2022

C# allows any valid expression as do other languages like JavaScript, Ruby and Dart.

I'd much prefer that expressions didn't require any special escaping. I certainly wouldn't find it easier to read.

zeertzjq added a commit to zeertzjq/neovim that referenced this pull request Apr 15, 2023
Problem:    String interpolation only works in heredoc.
Solution:   Support interpolated strings.  Use syntax for heredoc consistent
            with strings, similar to C#. (closes vim/vim#10327)

vim/vim@2eaef10

Cherry-pick Test_Debugger_breakadd_expr() from Vim.

Co-authored-by: LemonBoy <thatlemon@gmail.com>
folke pushed a commit to folke/neovim that referenced this pull request May 22, 2023
Problem:    String interpolation only works in heredoc.
Solution:   Support interpolated strings.  Use syntax for heredoc consistent
            with strings, similar to C#. (closes vim/vim#10327)

vim/vim@2eaef10

Cherry-pick Test_Debugger_breakadd_expr() from Vim.

Co-authored-by: LemonBoy <thatlemon@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants