To: vim_dev@googlegroups.com Subject: Patch 8.2.0294 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0294 Problem: Cannot use Ex command that is also a function name. Solution: Recognize an Ex command by a colon prefix. Files: src/vim9compile.c, src/testdir/test_vim9_script.vim, runtime/doc/vim9.txt *** ../vim-8.2.0293/src/vim9compile.c 2020-02-20 22:54:39.609505358 +0100 --- src/vim9compile.c 2020-02-21 18:32:38.511509409 +0100 *************** *** 4739,4744 **** --- 4739,4746 ---- */ for (;;) { + int is_ex_command; + if (line != NULL && *line == '|') // the line continues after a '|' ++line; *************** *** 4793,4798 **** --- 4795,4801 ---- line = compile_block(ea.cmd, &cctx); continue; } + is_ex_command = *ea.cmd == ':'; /* * COMMAND MODIFIERS *************** *** 4810,4857 **** 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) { ! 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) ! { ! // 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; } } } --- 4813,4865 ---- if (checkforcmd(&ea.cmd, "call", 3)) ea.cmd = skipwhite(ea.cmd); ! if (!is_ex_command) { ! // 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) { ! 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) { ! // 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,4866 **** * COMMAND after range */ ea.cmd = skip_range(ea.cmd, NULL); ! p = find_ex_command(&ea, NULL, lookup_local, &cctx); if (p == ea.cmd && ea.cmdidx != CMD_SIZE) { --- 4868,4875 ---- * COMMAND after range */ ea.cmd = skip_range(ea.cmd, NULL); ! p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local, ! &cctx); if (p == ea.cmd && ea.cmdidx != CMD_SIZE) { *** ../vim-8.2.0293/src/testdir/test_vim9_script.vim 2020-02-20 23:08:30.746951116 +0100 --- src/testdir/test_vim9_script.vim 2020-02-21 18:22:49.573571232 +0100 *************** *** 570,574 **** --- 570,581 ---- 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 *** ../vim-8.2.0293/runtime/doc/vim9.txt 2020-01-26 15:52:33.011833294 +0100 --- runtime/doc/vim9.txt 2020-02-21 18:39:54.278249893 +0100 *************** *** 113,119 **** } echo temp " Error! ! An existing variable cannot be assigend to with `:let`, since that implies a declaration. An exception is global variables: these can be both used with and without `:let`, because there is no rule about where they are declared. --- 113,119 ---- } echo temp " Error! ! An existing variable cannot be assigned to with `:let`, since that implies a declaration. An exception is global variables: these can be both used with and without `:let`, because there is no rule about where they are declared. *************** *** 128,134 **** Functions can be called without `:call`: > writefile(lines, 'file') ! Using `:call` is still posible, but this is discouraged. A method call without `eval` is possible, so long as the start is an identifier or can't be an Ex command. It does not work for string constants: > --- 128,134 ---- Functions can be called without `:call`: > writefile(lines, 'file') ! Using `:call` is still possible, but this is discouraged. A method call without `eval` is possible, so long as the start is an identifier or can't be an Ex command. It does not work for string constants: > *************** *** 140,154 **** "foobar"->Process() " does NOT work eval "foobar"->Process() " works No curly braces expansion ~ |curly-braces-names| cannot be used. ! Comperators ~ ! The 'ignorecase' option is not used for comperators that use strings. White space ~ --- 140,166 ---- "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 ~ |curly-braces-names| cannot be used. ! No :append, :change or :insert ~ ! ! These commands are too quickly confused with local variable names. ! ! Comparators ~ ! ! The 'ignorecase' option is not used for comparators that use strings. White space ~ *************** *** 170,175 **** --- 182,190 ---- call Func(arg) " OK call Func( \ arg) " OK + call Func( + \ arg " OK + \ ) Conditions and expressions ~ *************** *** 226,236 **** the function follows in the next lines, until the matching `:enddef`. ! When {return-type} is omitted the return type will be ! decided upon by the first encountered `return` ! statement in the function. E.g., for: > ! return 'message' ! < The return type will be "string". {arguments} is a sequence of zero or more argument declarations. There are three forms: --- 241,248 ---- the function follows in the next lines, until the matching `:enddef`. ! When {return-type} is omitted the function is not ! expected to return anything. {arguments} is a sequence of zero or more argument declarations. There are three forms: *************** *** 242,253 **** --- 254,279 ---- The second and third form are optional arguments. When the caller omits an argument the {value} is used. + NOTE: It is possible to nest `:def` inside another + `:def`, but it is not possible to nest `:def` inside + `:function`, for backwards compatibility. + [!] is used as with `:function`. *:enddef* :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. + ============================================================================== 4. Types *vim9-types* *************** *** 325,331 **** Namespace ~ *:vim9script* *:vim9* ! To recognize an file that can be imported the `vim9script` statement must appear as the first statement in the file. It tells Vim to interpret the script in its own namespace, instead of the global namespace. If a file starts with: > --- 351,357 ---- Namespace ~ *:vim9script* *:vim9* ! To recognize a file that can be imported the `vim9script` statement must appear as the first statement in the file. It tells Vim to interpret the script in its own namespace, instead of the global namespace. If a file starts with: > *************** *** 371,377 **** To import multiple items at the same time: > import {someValue, MyClass} from "thatscript.vim" ! In case the name is ambigiuous, another name can be specified: > import MyClass as ThatClass from "myclass.vim" import {someValue, MyClass as ThatClass} from "myclass.vim" --- 397,403 ---- To import multiple items at the same time: > import {someValue, MyClass} from "thatscript.vim" ! In case the name is ambiguous, another name can be specified: > import MyClass as ThatClass from "myclass.vim" import {someValue, MyClass as ThatClass} from "myclass.vim" *************** *** 404,410 **** Import in an autoload script ~ For optimal startup speed, loading scripts should be postponed until they are ! actually needed. A recommended mechamism: 1. In the plugin define user commands, functions and/or mappings that refer to an autoload script. > --- 430,436 ---- Import in an autoload script ~ For optimal startup speed, loading scripts should be postponed until they are ! actually needed. A recommended mechanism: 1. In the plugin define user commands, functions and/or mappings that refer to an autoload script. > *************** *** 445,451 **** The :def command ~ Plugin writers have asked for a much faster Vim script. Investigation have ! shown that keeping the existing semantics of funtion calls make this close to impossible, because of the overhead involved with calling a function, setting up the local function scope and executing lines. There are many details that need to be handled, such as error messages and exceptions. The need to create --- 471,477 ---- The :def command ~ Plugin writers have asked for a much faster Vim script. Investigation have ! shown that keeping the existing semantics of function calls make this close to impossible, because of the overhead involved with calling a function, setting up the local function scope and executing lines. There are many details that need to be handled, such as error messages and exceptions. The need to create *************** *** 483,489 **** Script writers have complained that the Vim script syntax is unexpectedly different from what they are used to. To reduce this complaint popular languages will be used as an example. At the same time, we do not want to ! abondon the well-known parts of legacy Vim script. Since Vim already uses `:let` and `:const` and optional type checking is desirable, the JavaScript/TypeScript syntax fits best for variable --- 509,515 ---- Script writers have complained that the Vim script syntax is unexpectedly different from what they are used to. To reduce this complaint popular languages will be used as an example. At the same time, we do not want to ! abandon the well-known parts of legacy Vim script. Since Vim already uses `:let` and `:const` and optional type checking is desirable, the JavaScript/TypeScript syntax fits best for variable *** ../vim-8.2.0293/src/version.c 2020-02-21 17:54:41.834235694 +0100 --- src/version.c 2020-02-21 18:40:18.402174252 +0100 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 294, /**/ -- I AM THANKFUL... ...for all the complaining I hear about the government because it means we have freedom of speech. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///