summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-04-12 16:38:57 +0200
committerBram Moolenaar <Bram@vim.org>2020-04-12 16:38:57 +0200
commit4fdae9996fb9a9bc1291a61e7b85cb360feb7599 (patch)
treedf24dd3ca0ab0120654db41a1a64d07bd9613795
parentacc770a10f65107131473ea2ab4ae5d429dfe172 (diff)
patch 8.2.0555: Vim9: line continuation is not always neededv8.2.0555
Problem: Vim9: line continuation is not always needed. Solution: Recognize continuation lines automatically in list and dict.
-rw-r--r--runtime/doc/vim9.txt11
-rw-r--r--src/testdir/test_vim9_expr.vim2
-rw-r--r--src/testdir/test_vim9_script.vim24
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c87
5 files changed, 111 insertions, 15 deletions
diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt
index 1337d4a6d3..b7b05b4974 100644
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -175,6 +175,17 @@ When using `function()` the resulting type is "func", a function with any
number of arguments and any return type. The function can be defined later.
+Automatic line continuation ~
+
+In many cases it is obvious that an expression continues on the next line. In
+those cases there is no need to prefix the line with a backslash. For
+example, when a list spans multiple lines: >
+ let mylist = [
+ 'one',
+ 'two',
+ ]
+
+
No curly braces expansion ~
|curly-braces-names| cannot be used.
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index f34041b5d2..a965bdf39d 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -767,7 +767,7 @@ def Test_expr7_dict()
call CheckDefFailure("let x = #{8: 8}", 'E1014:')
call CheckDefFailure("let x = #{xxx}", 'E720:')
- call CheckDefFailure("let x = #{xxx: 1", 'E722:')
+ call CheckDefFailure("let x = #{xxx: 1", 'E723:')
call CheckDefFailure("let x = #{xxx: 1,", 'E723:')
call CheckDefFailure("let x = {'a': xxx}", 'E1001:')
call CheckDefFailure("let x = {xxx: 8}", 'E1001:')
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 4e0dc1b2ca..358d4e876d 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -966,6 +966,30 @@ def Test_interrupt_loop()
assert_true(caught, 'should have caught an exception')
enddef
+def Test_automatic_line_continuation()
+ let mylist = [
+ 'one',
+ 'two',
+ 'three',
+ ] " comment
+ assert_equal(['one', 'two', 'three'], mylist)
+
+ let mydict = {
+ 'one': 1,
+ 'two': 2,
+ 'three':
+ 3,
+ } " comment
+ assert_equal({'one': 1, 'two': 2, 'three': 3}, mydict)
+ mydict = #{
+ one: 1, " comment
+ two:
+ 2,
+ three: 3 " comment
+ }
+ assert_equal(#{one: 1, two: 2, three: 3}, mydict)
+enddef
+
" Keep this last, it messes up highlighting.
def Test_substitute_cmd()
new
diff --git a/src/version.c b/src/version.c
index 08a95a56d4..375ae6dbb7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -739,6 +739,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 555,
+/**/
554,
/**/
553,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 772e29f353..8d536eb089 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2535,6 +2535,27 @@ need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
}
/*
+ * Get the next line of the function from "cctx".
+ * Returns NULL when at the end.
+ */
+ static char_u *
+next_line_from_context(cctx_T *cctx)
+{
+ char_u *line = NULL;
+
+ do
+ {
+ ++cctx->ctx_lnum;
+ if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
+ break;
+ line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
+ SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
+ + cctx->ctx_lnum + 1;
+ } while (line == NULL);
+ return line;
+}
+
+/*
* parse a list: [expr, expr]
* "*arg" points to the '['.
*/
@@ -2544,12 +2565,25 @@ compile_list(char_u **arg, cctx_T *cctx)
char_u *p = skipwhite(*arg + 1);
int count = 0;
- while (*p != ']')
+ for (;;)
{
if (*p == NUL)
{
- semsg(_(e_list_end), *arg);
- return FAIL;
+ p = next_line_from_context(cctx);
+ if (p == NULL)
+ {
+ semsg(_(e_list_end), *arg);
+ return FAIL;
+ }
+ p = skipwhite(p);
+ }
+ if (*p == ']')
+ {
+ ++p;
+ // Allow for following comment, after at least one space.
+ if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
+ p += STRLEN(p);
+ break;
}
if (compile_expr1(&p, cctx) == FAIL)
break;
@@ -2558,7 +2592,7 @@ compile_list(char_u **arg, cctx_T *cctx)
++p;
p = skipwhite(p);
}
- *arg = p + 1;
+ *arg = p;
generate_NEWLIST(cctx, count);
return OK;
@@ -2657,10 +2691,21 @@ compile_dict(char_u **arg, cctx_T *cctx, int literal)
if (d == NULL)
return FAIL;
*arg = skipwhite(*arg + 1);
- while (**arg != '}' && **arg != NUL)
+ for (;;)
{
char_u *key = NULL;
+ if (**arg == NUL || (literal && **arg == '"'))
+ {
+ *arg = next_line_from_context(cctx);
+ if (*arg == NULL)
+ goto failret;
+ *arg = skipwhite(*arg);
+ }
+
+ if (**arg == '}')
+ break;
+
if (literal)
{
char_u *p = to_name_end(*arg, !literal);
@@ -2714,10 +2759,25 @@ compile_dict(char_u **arg, cctx_T *cctx, int literal)
}
*arg = skipwhite(*arg + 1);
+ if (**arg == NUL)
+ {
+ *arg = next_line_from_context(cctx);
+ if (*arg == NULL)
+ goto failret;
+ *arg = skipwhite(*arg);
+ }
+
if (compile_expr1(arg, cctx) == FAIL)
return FAIL;
++count;
+ if (**arg == NUL || *skipwhite(*arg) == '"')
+ {
+ *arg = next_line_from_context(cctx);
+ if (*arg == NULL)
+ goto failret;
+ *arg = skipwhite(*arg);
+ }
if (**arg == '}')
break;
if (**arg != ',')
@@ -2735,10 +2795,16 @@ compile_dict(char_u **arg, cctx_T *cctx, int literal)
}
*arg = *arg + 1;
+ // Allow for following comment, after at least one space.
+ if (VIM_ISWHITE(**arg) && *skipwhite(*arg) == '"')
+ *arg += STRLEN(*arg);
+
dict_unref(d);
return generate_NEWDICT(cctx, count);
failret:
+ if (*arg == NULL)
+ semsg(_(e_missing_dict_end), _("[end of lines]"));
dict_unref(d);
return FAIL;
}
@@ -5645,16 +5711,9 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
}
else
{
- do
- {
- ++cctx.ctx_lnum;
- if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
- break;
- line = ((char_u **)ufunc->uf_lines.ga_data)[cctx.ctx_lnum];
- } while (line == NULL);
- if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
+ line = next_line_from_context(&cctx);
+ if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
break;
- SOURCING_LNUM = ufunc->uf_script_ctx.sc_lnum + cctx.ctx_lnum + 1;
}
emsg_before = called_emsg;