]> granicus.if.org Git - vim/commitdiff
patch 8.2.0294: cannot use Ex command that is also a function name v8.2.0294
authorBram Moolenaar <Bram@vim.org>
Fri, 21 Feb 2020 17:42:43 +0000 (18:42 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 21 Feb 2020 17:42:43 +0000 (18:42 +0100)
Problem:    Cannot use Ex command that is also a function name.
Solution:   Recognize an Ex command by a colon prefix.

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

index da4f1634b245f917c958e024a4732d5fb0b89f33..c79ae62de103ab70e8c3572a2829f345e936c875 100644 (file)
@@ -1,4 +1,4 @@
-*vim9.txt*     For Vim version 8.2.  Last change: 2020 Feb 13
+*vim9.txt*     For Vim version 8.2.  Last change: 2020 Feb 21
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -140,6 +140,13 @@ identifier or can't be an Ex command.  It does not work for string constants: >
        "foobar"->Process()             " does NOT work
        eval "foobar"->Process()        " works
 
+In case there is ambiguity between a function name and an Ex command, use ":"
+to make clear you want to use the Ex command.  For example, there is both the
+`:substitute` command and the `substitute()` function.  When the line starts
+with `substitute(` this will use the function, prepend a colon to use the
+command instead: >
+       :substitute(pattern(replacement(
+
 
 No curly braces expansion ~
 
@@ -175,6 +182,9 @@ White space is not allowed:
        call Func(arg)     " OK
        call Func(
             \ arg)        " OK
+       call Func(
+            \ arg         " OK
+            \ )
 
 
 Conditions and expressions ~
@@ -254,6 +264,12 @@ THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE
 :enddef                        End of a function defined with `:def`.
 
 
+If the script the function is defined in is Vim9 script, then script-local
+variables can be accessed without the "s:" prefix.  They must be defined
+before the function.  If the script the function is defined in is legacy
+script, then script-local variables must be accessed with the "s:" prefix.
+
+
                                                *:disa* *:disassemble*
 :disa[ssemble] {func}  Show the instructions generated for {func}.
                        This is for debugging and testing.
index f7205b3d5c57a32981aa84db9a1e8077f1924833..107ee02450637116204d289e09b92e0a85af4910 100644 (file)
@@ -570,5 +570,12 @@ def Test_delfunc()
   delete('XToDelFunc')
 enddef
 
+def Test_substitute_cmd()
+  new
+  setline(1, 'something')
+  :substitute(some(other(
+  assert_equal('otherthing', getline(1))
+enddef
+
 
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
index 196941ff416830ca0d655b6543f8bfd24c7a8545..043931dd6ca95bbdbb7070186bd2fa71f51fdeef 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    294,
 /**/
     293,
 /**/
index e35494454773ee350171b9d8b9783c84ee562be1..aeb950ca6a939182f98624217ae20acaa6ed2dae 100644 (file)
@@ -4739,6 +4739,8 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
      */
     for (;;)
     {
+       int     is_ex_command;
+
        if (line != NULL && *line == '|')
            // the line continues after a '|'
            ++line;
@@ -4793,6 +4795,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
            line = compile_block(ea.cmd, &cctx);
            continue;
        }
+       is_ex_command = *ea.cmd == ':';
 
        /*
         * COMMAND MODIFIERS
@@ -4810,48 +4813,53 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
        if (checkforcmd(&ea.cmd, "call", 3))
            ea.cmd = skipwhite(ea.cmd);
 
-       // Assuming the command starts with a variable or function name, find
-       // what follows.  Also "&opt = val", "$ENV = val" and "@r = val".
-       p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
-                                                        ? ea.cmd + 1 : ea.cmd;
-       p = to_name_end(p);
-       if (p > ea.cmd && *p != NUL)
+       if (!is_ex_command)
        {
-           int oplen;
-           int heredoc;
-
-           // "funcname(" is always a function call.
-           // "varname[]" is an expression.
-           // "varname->expr" is an expression.
-           if (*p == '('
-                   || *p == '['
-                   || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
-                   || (*p == '-' && p[1] == '>'))
-           {
-               // TODO
-           }
-
-           oplen = assignment_len(skipwhite(p), &heredoc);
-           if (oplen > 0)
+           // Assuming the command starts with a variable or function name,
+           // find what follows.  Also "&opt = val", "$ENV = val" and "@r =
+           // val".
+           p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
+                                                        ? ea.cmd + 1 : ea.cmd;
+           p = to_name_end(p);
+           if (p > ea.cmd && *p != NUL)
            {
-               // Recognize an assignment if we recognize the variable name:
-               // "g:var = expr"
-               // "var = expr"  where "var" is a local var name.
-               // "&opt = expr"
-               // "$ENV = expr"
-               // "@r = expr"
-               if (*ea.cmd == '&'
-                       || *ea.cmd == '$'
-                       || *ea.cmd == '@'
+               int oplen;
+               int heredoc;
+
+               // "funcname(" is always a function call.
+               // "varname[]" is an expression.
+               // "varname->expr" is an expression.
+               if (*p == '('
+                       || *p == '['
                        || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
-                       || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
-                       || lookup_script(ea.cmd, p - ea.cmd) == OK
-                       || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
+                       || (*p == '-' && p[1] == '>'))
                {
-                   line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
-                   if (line == NULL)
-                       goto erret;
-                   continue;
+                   // TODO
+               }
+
+               oplen = assignment_len(skipwhite(p), &heredoc);
+               if (oplen > 0)
+               {
+                   // Recognize an assignment if we recognize the variable
+                   // name:
+                   // "g:var = expr"
+                   // "var = expr"  where "var" is a local var name.
+                   // "&opt = expr"
+                   // "$ENV = expr"
+                   // "@r = expr"
+                   if (*ea.cmd == '&'
+                           || *ea.cmd == '$'
+                           || *ea.cmd == '@'
+                           || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
+                           || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
+                           || lookup_script(ea.cmd, p - ea.cmd) == OK
+                           || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
+                   {
+                       line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
+                       if (line == NULL)
+                           goto erret;
+                       continue;
+                   }
                }
            }
        }
@@ -4860,7 +4868,8 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
         * COMMAND after range
         */
        ea.cmd = skip_range(ea.cmd, NULL);
-       p = find_ex_command(&ea, NULL, lookup_local, &cctx);
+       p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
+                                                                       &cctx);
 
        if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
        {