Commit: patch 9.2.1142: Vim9: line in :def starting with a quote mistaken for heredoc

2 views
Skip to first unread message

Christian Brabandt

unread,
Sep 28, 2026, 4:00:20 PM (2 days ago) Sep 28
to vim...@googlegroups.com
patch 9.2.1142: Vim9: line in :def starting with a quote mistaken for heredoc

Commit: https://github.com/vim/vim/commit/265dbb84d7a0422af4a69549f98e6c76a46b9912
Author: Hirohito Higashi <h.eas...@gmail.com>
Date: Mon Sep 28 19:52:09 2026 +0000

patch 9.2.1142: Vim9: line in :def starting with a quote mistaken for heredoc

Problem: In a :def function a line that starts with a single-quoted
string reading like "name =<< END" is taken as the start of
a heredoc, giving E1145 and swallowing the rest of the file.
Solution: Only skip a range when a colon precedes it, since in Vim9
script a leading "'" without one starts a string, not a
mark (Hirohito Higashi).

closes: #21377

Assisted-by: Claude
Signed-off-by: Hirohito Higashi <h.eas...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index d09c7c930..31d5ab53f 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -640,6 +640,21 @@ def Test_command_block_heredoc()
v9.CheckSourceSuccess(lines)
enddef

+" A line in a :def that starts with a string is not a heredoc, even when the
+" string reads like one.
+def Test_def_line_starting_with_string_not_heredoc()
+ var lines =<< trim CODE
+ vim9script
+ def F(): list<string>
+ var l = ['a',
+ 'text =<< END', 'b']
+ return l
+ enddef
+ assert_equal(['a', 'text =<< END', 'b'], F())
+ CODE
+ v9.CheckSourceSuccess(lines)
+enddef
+
def Test_autocommand_block()
au BufNew *.xml {
g:otherVar = 'other'
diff --git a/src/userfunc.c b/src/userfunc.c
index b6a4d2f8d..f04dae097 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1117,10 +1117,14 @@ get_function_body(
int c;
char_u *end;
char_u *cmd;
+ bool colon = false;

// skip ':' and blanks
for (p = theline; VIM_ISWHITE(*p) || *p == ':'; ++p)
- ;
+ {
+ if (*p == ':')
+ colon = true;
+ }

// Check for "endfunction", "enddef" or "}".
// When a ":" follows it must be a dict key; "enddef: value,"
@@ -1276,7 +1280,11 @@ get_function_body(
}

// Check for ":append", ":change", ":insert". Not for :def.
- char_u *tp = p = skip_range(p, FALSE, NULL);
+ // In Vim9 script a range comes after a colon; without one a
+ // leading "'" starts a string, not a mark.
+ if (!vim9_function || colon)
+ p = skip_range(p, FALSE, NULL);
+ char_u *tp = p;
if (!vim9_function
&& (checkforcmd(&p, "append", 1)
|| checkforcmd(&p, "change", 1)
diff --git a/src/version.c b/src/version.c
index 8c16ad046..293edecec 100644
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1142,
/**/
1141,
/**/
Reply all
Reply to author
Forward
0 new messages