diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-10-13 15:04:34 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-10-13 15:04:34 +0100 |
commit | 7b829268921e8fc1c63c34d245063c1c4e7d21af (patch) | |
tree | a98bfde122c275ec816159fadb69b7280d1dc380 | |
parent | fff10d9a76099aa9b944f3c33a911127ca1a0c72 (diff) | |
download | vim-git-7b829268921e8fc1c63c34d245063c1c4e7d21af.tar.gz |
patch 8.2.3503: Vim9: using g:pat:cmd is confusingv8.2.3503
Problem: Vim9: using g:pat:cmd is confusing.
Solution: Do not recognize g: as the :global command. Also for s:pat:repl.
(closes #8982)
-rw-r--r-- | runtime/doc/vim9.txt | 15 | ||||
-rw-r--r-- | src/errors.h | 4 | ||||
-rw-r--r-- | src/ex_cmds.c | 6 | ||||
-rw-r--r-- | src/ex_docmd.c | 9 | ||||
-rw-r--r-- | src/proto/vim9compile.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_vim9_cmd.vim | 49 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 26 |
8 files changed, 111 insertions, 1 deletions
diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index b6feebf84..b66109780 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -942,9 +942,22 @@ Ex command ranges need to be prefixed with a colon. > Some Ex commands can be confused with assignments in Vim9 script: > g:name = value # assignment - g:pattern:cmd # invalid command - ERROR :g:pattern:cmd # :global command +To avoid confusion between a `:global` or `:substitute` command and an +expression or assignment, a few separators cannot be used when these commands +are abbreviated to a single character: ':', '-' and '.'. > + g:pattern:cmd # invalid command - ERROR + s:pattern:repl # invalid command - ERROR + g-pattern-cmd # invalid command - ERROR + s-pattern-repl # invalid command - ERROR + g.pattern.cmd # invalid command - ERROR + s.pattern.repl # invalid command - ERROR + +Also, there cannot be a space between the command and the separator: > + g /pattern/cmd # invalid command - ERROR + s /pattern/repl # invalid command - ERROR + Functions defined with `:def` compile the whole function. Legacy functions can bail out, and the following lines are not parsed: > func Maybe() diff --git a/src/errors.h b/src/errors.h index 4cc50e42c..a2a1394e8 100644 --- a/src/errors.h +++ b/src/errors.h @@ -666,3 +666,7 @@ EXTERN char e_invalid_value_for_blob_nr[] INIT(= N_("E1239: Invalid value for blob: %d")); EXTERN char e_resulting_text_too_long[] INIT(= N_("E1240: Resulting text too long")); +EXTERN char e_separator_not_supported_str[] + INIT(= N_("E1241: Separator not supported: %s")); +EXTERN char e_no_white_space_allowed_before_separator_str[] + INIT(= N_("E1242: No white space allowed before separator: %s")); diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 5c92e094e..78a87e76a 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3724,6 +3724,9 @@ ex_substitute(exarg_T *eap) // don't accept alphanumeric for separator if (check_regexp_delim(*cmd) == FAIL) return; + if (in_vim9script() && check_global_and_subst(eap->cmd, eap->arg) + == FAIL) + return; /* * undocumented vi feature: @@ -4899,6 +4902,9 @@ ex_global(exarg_T *eap) cmd = eap->arg; which_pat = RE_LAST; // default: use last used regexp + if (in_vim9script() && check_global_and_subst(eap->cmd, eap->arg) == FAIL) + return; + /* * undocumented vi feature: * "\/" and "\?": use previous search pattern. diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 08a48305e..072effdec 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3600,6 +3600,15 @@ find_ex_command( } } + // "g:", "s:" and "l:" are always assumed to be a variable, thus start + // an expression. A global/substitute/list command needs to use a + // longer name. + if (vim_strchr((char_u *)"gsl", *p) != NULL && p[1] == ':') + { + eap->cmdidx = CMD_eval; + return eap->cmd; + } + // If it is an ID it might be a variable with an operator on the next // line, if the variable exists it can't be an Ex command. if (p > eap->cmd && ends_excmd(*skipwhite(p)) diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 2b62b6c88..5910c67d6 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -17,6 +17,7 @@ void fill_exarg_from_cctx(exarg_T *eap, cctx_T *cctx); int assignment_len(char_u *p, int *heredoc); void vim9_declare_error(char_u *name); int check_vim9_unlet(char_u *name); +int check_global_and_subst(char_u *cmd, char_u *arg); int compile_def_function(ufunc_T *ufunc, int check_return_type, compiletype_T compile_type, cctx_T *outer_cctx); void set_function_type(ufunc_T *ufunc); void delete_instr(isn_T *isn); diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index 93b1295d4..802bae363 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -1489,5 +1489,54 @@ def Test_cmdwin_block() au! justTesting enddef +def Test_var_not_cmd() + var lines =<< trim END + g:notexist:cmd + END + CheckDefAndScriptFailure2(lines, 'E488: Trailing characters: :cmd', 'E121: Undefined variable: g:notexist', 1) + + lines =<< trim END + g-pat-cmd + END + CheckDefAndScriptFailure(lines, 'E1241:', 1) + + lines =<< trim END + s:notexist:repl + END + CheckDefAndScriptFailure2(lines, 'E488: Trailing characters: :repl', 'E121: Undefined variable: s:notexist', 1) + + lines =<< trim END + s-pat-repl + END + CheckDefAndScriptFailure(lines, 'E1241:', 1) + + lines =<< trim END + w:notexist->len() + END + CheckDefExecAndScriptFailure(lines, 'E121: Undefined variable: w:notexist', 1) + + lines =<< trim END + b:notexist->len() + END + CheckDefExecAndScriptFailure(lines, 'E121: Undefined variable: b:notexist', 1) + + lines =<< trim END + t:notexist->len() + END + CheckDefExecAndScriptFailure(lines, 'E121: Undefined variable: t:notexist', 1) +enddef + +def Test_no_space_after_command() + var lines =<< trim END + g /pat/cmd + END + CheckDefAndScriptFailure(lines, 'E1242:', 1) + + lines =<< trim END + s /pat/repl + END + CheckDefAndScriptFailure(lines, 'E1242:', 1) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 764015321..1be4d5440 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3503, +/**/ 3502, /**/ 3501, diff --git a/src/vim9compile.c b/src/vim9compile.c index e9931731c..5bb0359ae 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -9473,6 +9473,26 @@ compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx) #endif /* + * Check if the separator for a :global or :substitute command is OK. + */ + int +check_global_and_subst(char_u *cmd, char_u *arg) +{ + if (arg == cmd + 1 && vim_strchr(":-.", *arg) != NULL) + { + semsg(_(e_separator_not_supported_str), arg); + return FAIL; + } + if (VIM_ISWHITE(cmd[1])) + { + semsg(_(e_no_white_space_allowed_before_separator_str), cmd); + return FAIL; + } + return OK; +} + + +/* * Add a function to the list of :def functions. * This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet. */ @@ -10066,6 +10086,8 @@ compile_def_function( break; case CMD_substitute: + if (check_global_and_subst(ea.cmd, p) == FAIL) + goto erret; if (cctx.ctx_skip == SKIP_YES) line = (char_u *)""; else @@ -10132,6 +10154,10 @@ compile_def_function( line = compile_script(line, &cctx); break; + case CMD_global: + if (check_global_and_subst(ea.cmd, p) == FAIL) + goto erret; + // FALLTHROUGH default: // Not recognized, execute with do_cmdline_cmd(). ea.arg = p; |