# HG changeset patch # User Bram Moolenaar # Date 1586781904 -7200 # Node ID c85d4e173cc9d19eaaeb29a592005691cfb04285 # Parent fb9a66d81a390440f0ecddfb4295c6a5e0b4e8b4 patch 8.2.0567: Vim9: cannot put comments halfway expressions Commit: https://github.com/vim/vim/commit/2c330432cfb12181c61d698b5459bfd73d2610df Author: Bram Moolenaar Date: Mon Apr 13 14:41:35 2020 +0200 patch 8.2.0567: Vim9: cannot put comments halfway expressions Problem: Vim9: cannot put comments halfway expressions. Solution: Support # comments in many places. diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -58,6 +58,15 @@ 2. Differences from legacy Vim script THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE +Comments starting with # ~ + +In Vim script comments normally start with double quote. That can also be the +start of a string, thus in many places it cannot be used. In Vim9 script a +comment can also start with #. Normally this is a command to list text with +numbers, but you can also use `:number` for that. > + let count = 0 # number of occurences of Ni! + + Vim9 functions ~ `:def` has no extra arguments like `:function` does: "range", "abort", "dict" @@ -241,6 +250,9 @@ Vim9 script enforces proper use of white let var =234 " Error! There must be white space before and after the "=": > let var = 234 " OK +White space must also be put before the # that starts a comment: > + let var = 234# Error! + let var = 234 # OK White space is required around most operators. diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -4764,6 +4764,9 @@ ex_blast(exarg_T *eap) int ends_excmd(int c) { + if (c == '#') + // TODO: should check for preceding white space + return in_vim9script(); return (c == NUL || c == '|' || c == '"' || c == '\n'); } diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -569,6 +569,14 @@ def MultiLine( return arg1 .. arg2 .. join(rest, '-') enddef +def MultiLineComment( + arg1: string, # comment + arg2 = 1234, # comment + ...rest: list # comment + ): string # comment + return arg1 .. arg2 .. join(rest, '-') +enddef + def Test_multiline() assert_equal('text1234', MultiLine('text')) assert_equal('text777', MultiLine('text', 777)) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -983,10 +983,17 @@ def Test_automatic_line_continuation() } " comment assert_equal({'one': 1, 'two': 2, 'three': 3}, mydict) mydict = #{ - one: 1, " comment - two: - 2, - three: 3 " comment + one: 1, # comment + two: # comment + 2, # comment + three: 3 # comment + } + assert_equal(#{one: 1, two: 2, three: 3}, mydict) + mydict = #{ + one: 1, + two: + 2, + three: 3 } assert_equal(#{one: 1, two: 2, three: 3}, mydict) diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -154,6 +154,7 @@ get_function_args( int c; int any_default = FALSE; char_u *expr; + char_u *whitep = arg; if (newargs != NULL) ga_init2(newargs, (int)sizeof(char_u *), 3); @@ -170,7 +171,8 @@ get_function_args( */ while (*p != endchar) { - if (eap != NULL && *p == NUL && eap->getline != NULL) + while (eap != NULL && eap->getline != NULL + && (*p == NUL || (VIM_ISWHITE(*whitep) && *p == '#'))) { char_u *theline; @@ -180,6 +182,7 @@ get_function_args( break; vim_free(*line_to_free); *line_to_free = theline; + whitep = (char_u *)" "; p = skipwhite(theline); } @@ -228,6 +231,7 @@ get_function_args( // find the end of the expression (doesn't evaluate it) any_default = TRUE; p = skipwhite(p) + 1; + whitep = p; p = skipwhite(p); expr = p; if (eval1(&p, &rettv, FALSE) != FAIL) @@ -264,6 +268,7 @@ get_function_args( else mustend = TRUE; } + whitep = p; p = skipwhite(p); } @@ -2595,7 +2600,8 @@ ex_function(exarg_T *eap) // Makes 'exe "func Test()\n...\nendfunc"' work. if (*p == '\n') line_arg = p + 1; - else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg) + else if (*p != NUL && *p != '"' && !(eap->cmdidx == CMD_def && *p == '#') + && !eap->skip && !did_emsg) emsg(_(e_trailing)); /* diff --git a/src/version.c b/src/version.c --- 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 */ /**/ + 567, +/**/ 566, /**/ 565, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2070,13 +2070,23 @@ next_line_from_context(cctx_T *cctx) } /* + * Return TRUE if "p" points at a "#" but not at "#{". + */ + static int +comment_start(char_u *p) +{ + return p[0] == '#' && p[1] != '{'; +} + +/* * If "*arg" is at the end of the line, advance to the next line. + * Also when "whitep" points to white space and "*arg" is on a "#". * Return FAIL if beyond the last line, "*arg" is unmodified then. */ static int -may_get_next_line(char_u **arg, cctx_T *cctx) +may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx) { - if (**arg == NUL) + if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg))) { char_u *next = next_line_from_context(cctx); @@ -2321,15 +2331,17 @@ theend: static int compile_arguments(char_u **arg, cctx_T *cctx, int *argcount) { - char_u *p = *arg; + char_u *p = *arg; + char_u *whitep = *arg; for (;;) { - if (*p == NUL) + while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p))) { p = next_line_from_context(cctx); if (p == NULL) - break; + goto failret; + whitep = (char_u *)" "; p = skipwhite(p); } if (*p == ')') @@ -2353,9 +2365,10 @@ compile_arguments(char_u **arg, cctx_T * if (*p != NUL && !VIM_ISWHITE(*p)) semsg(_(e_white_after), ","); } + whitep = p; p = skipwhite(p); } - +failret: emsg(_(e_missing_close)); return FAIL; } @@ -2589,11 +2602,12 @@ need_type(type_T *actual, type_T *expect compile_list(char_u **arg, cctx_T *cctx) { char_u *p = skipwhite(*arg + 1); + char_u *whitep = *arg + 1; int count = 0; for (;;) { - if (*p == NUL) + while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p))) { p = next_line_from_context(cctx); if (p == NULL) @@ -2601,6 +2615,7 @@ compile_list(char_u **arg, cctx_T *cctx) semsg(_(e_list_end), *arg); return FAIL; } + whitep = (char_u *)" "; p = skipwhite(p); } if (*p == ']') @@ -2616,6 +2631,7 @@ compile_list(char_u **arg, cctx_T *cctx) ++count; if (*p == ',') ++p; + whitep = p; p = skipwhite(p); } *arg = p; @@ -2713,6 +2729,8 @@ compile_dict(char_u **arg, cctx_T *cctx, int count = 0; dict_T *d = dict_alloc(); dictitem_T *item; + char_u *whitep = *arg; + char_u *p; if (d == NULL) return FAIL; @@ -2721,11 +2739,13 @@ compile_dict(char_u **arg, cctx_T *cctx, { char_u *key = NULL; - if (**arg == NUL || (literal && **arg == '"')) + while (**arg == NUL || (literal && **arg == '"') + || (VIM_ISWHITE(*whitep) && comment_start(*arg))) { *arg = next_line_from_context(cctx); if (*arg == NULL) goto failret; + whitep = (char_u *)" "; *arg = skipwhite(*arg); } @@ -2734,17 +2754,17 @@ compile_dict(char_u **arg, cctx_T *cctx, if (literal) { - char_u *p = to_name_end(*arg, !literal); - - if (p == *arg) + char_u *end = to_name_end(*arg, !literal); + + if (end == *arg) { semsg(_("E1014: Invalid key: %s"), *arg); return FAIL; } - key = vim_strnsave(*arg, p - *arg); + key = vim_strnsave(*arg, end - *arg); if (generate_PUSHS(cctx, key) == FAIL) return FAIL; - *arg = p; + *arg = end; } else { @@ -2784,12 +2804,14 @@ compile_dict(char_u **arg, cctx_T *cctx, return FAIL; } + whitep = *arg + 1; *arg = skipwhite(*arg + 1); - if (**arg == NUL) + while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg))) { *arg = next_line_from_context(cctx); if (*arg == NULL) goto failret; + whitep = (char_u *)" "; *arg = skipwhite(*arg); } @@ -2797,12 +2819,16 @@ compile_dict(char_u **arg, cctx_T *cctx, return FAIL; ++count; - if (**arg == NUL || *skipwhite(*arg) == '"') + whitep = *arg; + p = skipwhite(*arg); + while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p))) { *arg = next_line_from_context(cctx); if (*arg == NULL) goto failret; + whitep = (char_u *)" "; *arg = skipwhite(*arg); + p = *arg; } if (**arg == '}') break; @@ -2811,13 +2837,15 @@ compile_dict(char_u **arg, cctx_T *cctx, semsg(_(e_missing_dict_comma), *arg); goto failret; } + whitep = *arg + 1; *arg = skipwhite(*arg + 1); } *arg = *arg + 1; // Allow for following comment, after at least one space. - if (VIM_ISWHITE(**arg) && *skipwhite(*arg) == '"') + p = skipwhite(*arg); + if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p))) *arg += STRLEN(*arg); dict_unref(d); @@ -3422,7 +3450,7 @@ compile_expr6(char_u **arg, cctx_T *cctx return FAIL; } *arg = skipwhite(op + 1); - if (may_get_next_line(arg, cctx) == FAIL) + if (may_get_next_line(op + 1, arg, cctx) == FAIL) return FAIL; // get the second variable @@ -3470,7 +3498,7 @@ compile_expr5(char_u **arg, cctx_T *cctx } *arg = skipwhite(op + oplen); - if (may_get_next_line(arg, cctx) == FAIL) + if (may_get_next_line(op + oplen, arg, cctx) == FAIL) return FAIL; // get the second variable @@ -3608,7 +3636,7 @@ compile_expr4(char_u **arg, cctx_T *cctx // get the second variable *arg = skipwhite(p + len); - if (may_get_next_line(arg, cctx) == FAIL) + if (may_get_next_line(p + len, arg, cctx) == FAIL) return FAIL; if (compile_expr5(arg, cctx) == FAIL) @@ -3658,7 +3686,7 @@ compile_and_or(char_u **arg, cctx_T *cct // eval the next expression *arg = skipwhite(p + 2); - if (may_get_next_line(arg, cctx) == FAIL) + if (may_get_next_line(p + 2, arg, cctx) == FAIL) return FAIL; if ((opchar == '|' ? compile_expr3(arg, cctx) @@ -3771,7 +3799,7 @@ compile_expr1(char_u **arg, cctx_T *cct // evaluate the second expression; any type is accepted *arg = skipwhite(p + 1); - if (may_get_next_line(arg, cctx) == FAIL) + if (may_get_next_line(p + 1, arg, cctx) == FAIL) return FAIL; if (compile_expr1(arg, cctx) == FAIL) @@ -3803,7 +3831,7 @@ compile_expr1(char_u **arg, cctx_T *cct // evaluate the third expression *arg = skipwhite(p + 1); - if (may_get_next_line(arg, cctx) == FAIL) + if (may_get_next_line(p + 1, arg, cctx) == FAIL) return FAIL; if (compile_expr1(arg, cctx) == FAIL)