]> granicus.if.org Git - vim/commitdiff
patch 8.2.0555: Vim9: line continuation is not always needed v8.2.0555
authorBram Moolenaar <Bram@vim.org>
Sun, 12 Apr 2020 14:38:57 +0000 (16:38 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 12 Apr 2020 14:38:57 +0000 (16:38 +0200)
Problem:    Vim9: line continuation is not always needed.
Solution:   Recognize continuation lines automatically in list and dict.

runtime/doc/vim9.txt
src/testdir/test_vim9_expr.vim
src/testdir/test_vim9_script.vim
src/version.c
src/vim9compile.c

index 1337d4a6d36e971d3564cbd153b5fcf910c71361..b7b05b4974d536870678c94ce4840d44ed3ebcce 100644 (file)
@@ -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.
index f34041b5d2caddb5cba1568ab2881af601cad3e7..a965bdf39d0316cb2d692df97aa7778644fae79a 100644 (file)
@@ -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:')
index 4e0dc1b2ca8fceea0203e1919a9c089756c9a223..358d4e876db0b888b5fac279eaa49e76bf442fa2 100644 (file)
@@ -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
index 08a95a56d42cffecd4c382de622bda2a4087cca7..375ae6dbb74ddbb3a38aa0f7ab6ba5dc86932145 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    555,
 /**/
     554,
 /**/
index 772e29f353d1fb8c64f2cfa068358c7e4a6be788..8d536eb08965695948ba301f77f557d393e519fc 100644 (file)
@@ -2534,6 +2534,27 @@ need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
     return OK;
 }
 
+/*
+ * 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;