# HG changeset patch # User Bram Moolenaar # Date 1587068104 -7200 # Node ID de756b3f4dee8bee7546c92b14a8296774c0e186 # Parent bc03e6cae23686062c007c473fc5cb603c78aaac patch 8.2.0585: Vim9: # comment not recognized after :vim9script Commit: https://github.com/vim/vim/commit/7a09224583b2ad0d9d0648b53cc2d989d45ae96e Author: Bram Moolenaar Date: Thu Apr 16 22:10:49 2020 +0200 patch 8.2.0585: Vim9: # comment not recognized after :vim9script Problem: Vim9: # comment not recognized after :vim9script. Solution: Check script type. Make comment after ":echo" work. And in several other places. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -6061,7 +6061,7 @@ ex_echo(exarg_T *eap) if (eap->skip) ++emsg_skip; - while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int) + while ((!ends_excmd2(eap->cmd, arg) || *arg == '"') && !got_int) { // If eval1() causes an error message the text from the command may // still need to be cleared. E.g., "echo 22,44". diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -1835,7 +1835,10 @@ do_one_cmd( * If we find a '|' or '\n' we set ea.nextcmd. */ if (*ea.cmd == NUL || *ea.cmd == '"' - || (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL) +#ifdef FEAT_EVAL + || (*ea.cmd == '#' && !starts_with_colon && in_vim9script()) +#endif + || (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL) { /* * strange vi behaviour: @@ -4761,12 +4764,31 @@ ex_blast(exarg_T *eap) do_cmdline_cmd(eap->do_ecmd_cmd); } +/* + * Check if "c" ends an Ex command. + * In Vim9 script does not check for white space before #. + */ int ends_excmd(int c) { #ifdef FEAT_EVAL if (c == '#') - // TODO: should check for preceding white space + return in_vim9script(); +#endif + return (c == NUL || c == '|' || c == '"' || c == '\n'); +} + +/* + * Like ends_excmd() but checks that a # in Vim9 script either has "cmd" equal + * to "cmd_start" or has a white space character before it. + */ + int +ends_excmd2(char_u *cmd_start, char_u *cmd) +{ + int c = *cmd; + +#ifdef FEAT_EVAL + if (c == '#' && (cmd == cmd_start || VIM_ISWHITE(cmd[-1]))) return in_vim9script(); #endif return (c == NUL || c == '|' || c == '"' || c == '\n'); diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -19,6 +19,7 @@ void separate_nextcmd(exarg_T *eap); char_u *skip_cmd_arg(char_u *p, int rembs); int get_bad_opt(char_u *p, exarg_T *eap); int ends_excmd(int c); +int ends_excmd2(char_u *before, char_u *cmd); char_u *find_nextcmd(char_u *p); char_u *check_nextcmd(char_u *p); char_u *get_command_name(expand_T *xp, int idx); 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 @@ -10,11 +10,17 @@ func CheckDefFailure(lines, error) call delete('Xdef') endfunc -func CheckScriptFailure(lines, error) - call writefile(a:lines, 'Xdef') - call assert_fails('so Xdef', a:error, a:lines) - call delete('Xdef') -endfunc +def CheckScriptFailure(lines: list, error: string) + writefile(lines, 'Xdef') + assert_fails('so Xdef', error, lines) + delete('Xdef') +enddef + +def CheckScriptSuccess(lines: list) + writefile(lines, 'Xdef') + so Xdef + delete('Xdef') +enddef def Test_syntax() let var = 234 @@ -269,15 +275,15 @@ enddef def Test_try_catch() let l = [] - try + try # comment add(l, '1') throw 'wrong' add(l, '2') - catch + catch # comment add(l, v:exception) - finally + finally # comment add(l, '3') - endtry + endtry # comment assert_equal(['1', 'wrong', '3'], l) enddef @@ -1003,6 +1009,58 @@ def Test_automatic_line_continuation() ) enddef +def Test_vim9_comment() + CheckScriptSuccess([ + 'vim9script', + '# something', + ]) + CheckScriptFailure([ + 'vim9script', + ':# something', + ], 'E488:') + CheckScriptFailure([ + '# something', + ], 'E488:') + CheckScriptFailure([ + ':# something', + ], 'E488:') + + CheckScriptSuccess([ + 'vim9script', + 'echo "yes" # something', + ]) + CheckScriptFailure([ + 'vim9script', + 'echo "yes"# something', + ], 'E121:') + CheckScriptFailure([ + 'vim9script', + 'echo# something', + ], 'E121:') + CheckScriptFailure([ + 'echo "yes" # something', + ], 'E121:') + + CheckDefFailure([ + 'try# comment', + 'echo "yes"', + 'catch', + 'endtry', + ], 'E488:') + CheckDefFailure([ + 'try', + 'echo "yes"', + 'catch# comment', + 'endtry', + ], 'E488:') + CheckDefFailure([ + 'try', + 'echo "yes"', + 'catch', + 'endtry# comment', + ], 'E488:') +enddef + " Keep this last, it messes up highlighting. def Test_substitute_cmd() new diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 585, +/**/ 584, /**/ 583, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -108,6 +108,7 @@ typedef struct { struct cctx_S { ufunc_T *ctx_ufunc; // current function int ctx_lnum; // line number in current function + char_u *ctx_line_start; // start of current line or NULL garray_T ctx_instr; // generated instructions garray_T ctx_locals; // currently visible local variables @@ -2055,14 +2056,18 @@ free_imported(cctx_T *cctx) static char_u * next_line_from_context(cctx_T *cctx) { - char_u *line = NULL; + char_u *line; do { ++cctx->ctx_lnum; if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len) + { + line = NULL; break; + } line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]; + cctx->ctx_line_start = line; SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum + cctx->ctx_lnum + 1; } while (line == NULL || *skipwhite(line) == NUL); @@ -5448,7 +5453,7 @@ compile_catch(char_u *arg, cctx_T *cctx } p = skipwhite(arg); - if (ends_excmd(*p)) + if (ends_excmd2(arg, p)) { scope->se_u.se_try.ts_caught_all = TRUE; scope->se_u.se_try.ts_catch_label = 0; @@ -5782,7 +5787,9 @@ compile_def_function(ufunc_T *ufunc, int if (line != NULL && *line == '|') // the line continues after a '|' ++line; - else if (line != NULL && *line != NUL) + else if (line != NULL && *line != NUL + && !(*line == '#' && (line == cctx.ctx_line_start + || VIM_ISWHITE(line[-1])))) { semsg(_("E488: Trailing characters: %s"), line); goto erret;