Here I will list all incompatibilities between old and new VimL implementations. Some may be fixed, so it is also a place for discussion. Please discuss incompatibilities with separate issues in separate issues. ### Expressions parser incompatibilities - Dot subscripts are not always read correctly (#240). - E15 errors are not not just “E15: Invalid expression”: there are (invalid expressions) - “E15: expected variable name” (`\x80\xFD\x52`) - “E15: expected expr7 (value)” (`+`) - “E15: missing closing curly brace” (`a{1`) - E116 error was renamed: “E116: expected closing parenthesis”. - No nested expr errors: `function(a{})` will produce one “E15: expected expr7 (value)”, not E15, E15, E116 and E15 errors at once (only E15 can be caught though). - Positions of error may differ. - Environment variable name is determined on the parsing stage. But what part of a string is environment variable name depends on &isident option which may be different on the stage where expression is actually run. (I really would rather prefer to remove dependency completely: say work like if value is non-standard `@,48-57,_,128-255` effectively including all UTF-8 characters (just in case), but not things like `/`. Standard ones are `@,48-57,_,128-167,224-235` (MS-DOS, Win32, OS/2) and `@,48-57,_,192-255` (otherwise) which means that e.g. `$ENV«»` is parsed as `($ENV)`: pretty useless.) ### Command parser incompatibilities - `append` works slightly different: append abc . is always correct with my parser, but it may be not correct with old vim parser: depends on context. I failed to comprehend why, but inside functions append *with indented first line and same indented dot* does not work, while it works correctly inside files. - Missing block endings (`:endif`, `:endfor`, etc) in `:autocmd` do generate errors. - Incomplete blocks (`:if`, etc) in `:autocmd` definition are not supported. - If you mix tabs and spaces in indentation `append` uses the value of `&tabstop` option to deduce whether dot is on its place (which is *very* strange because code suggests it uses 8-wide tabs: I must have missed something (like fgetline transforming tabs to spaces)). My parser uses only 8-wide tabs. - `endfunction` in vim is a marker that is read by `ex_function()` which is the reason why `function A()|endfunction` does not work. In my parser it is a separate command that ends a `:function` block, so there is no requirement for `:endfunction` to be the first command in the line. - `:call` accepts any function calls, not necessary calls in the form `funcname(args)` (`funcname` may actually be something like `dic{"tionary"}['name']`, but not `(function("tr"))`). I.e. it will work as long as top node is function call node. - “E129: Function name required” was renamed to “E129: :call accepts only function calls”. - “E117: Unknown function” may be replaced with “E117: Attempt to call a non-function” when using `:call`. - `:for`/`:let` messages are different: `E475` was split into - “E475: Expected variable name or a list of variable names” (`for 1 in []`) (was “E690: Missing "in" after :for” for for) - “E475: Expected non-empty list of variable names” (`for [] in []`) - “E475: Expected variable name” (`for [1] in []`) - `:let` E474 is now “E474: To list multiple variables use "let var|let var2", not ":let [var, var2]"”. - `:let 1` will show “E475: Expected variable name or a list of variable names”, not “E121: Undefined variable”. - “E125: Illegal argument” was split into - “E125: Argument expected, got nothing” (`:function Abc(,)`) - “E125: Function argument cannot start with a digit” (`:function Abc(1)`) - “E125: Names "firstline" and "lastline" are reserved” (`:function Abc(firstline)`) - “E475” for `:function` now looks either like “E475: Expected end of arguments list” or “E475: Expected end of arguments list or comma”. - “E475” for `:behave` now looks like “E475: :behave command currently only supports mswin and xterm”. - For debug commands “E475” was split into - “E475: Profile commands only accept `func' and `file' as their first argument” (for `:profile foo`), - “E475: Debug commands only accept `func', `file' and `here'” (for `:break… foo`), - “E475: Expecting function name or pattern” (for `:break… func`, `:break… func 123` or `:profile… func` without further arguments) and - “E475: Expecting file name or pattern” (for `:break… file`, `:break… file 123` or `:profile… file` without further arguments). - “E474” from `:cbuffer` and friends is now “E474: Expected buffer number”. - `:fu Abc()|echo1|endf` is parsed as a correct function definition. Used to produce missing endfunction errors. - Certain function definitions cannot be parsed. See #425. - `ilist /inslashes/afterslashes` will complain about trailing characters, but not run anything (in Vim it will first search then complain). Same for similar commands. - “E216” is always “No such event” (in Vim this may have been “No such group or event”). Any string that does not start with a star and contains no whitespaces is treated like an autocmd group name. Note: `augroup` accepts *any* sequence of characters as an autocmd group, including `BufWritePre` and `this is a group name with spaces and \| bar`. I cannot do anything with groups with whitespaces, but anything else is accepted. - Leading autocmd group name which is identical to some autocmd event name (e.g. `BufWritePre`), `*` or a list of event names (e.g. `BufWritePre,BufReadPre`) is not parsed as an autocmd group name when parsing `:au` definition (I really have no idea why this should be allowed, but even if I thought having group name like `BufWritePre` is a good idea I cannot do anything with this at the parsing stage). - “E474” from `:delmarks` was transformed into “E474: :delmarks must be called either without bang or without arguments” (`:delmarks! some_argument`). - “E475” from `:delmarks` was split into - “E475: Trying to construct range out of marks from different sets” (`:delmarks 0-A`). - “E475: Upper range bound is less then lower range bound” (`:delmarks z-a`). - “E475: Unknown mark” (`:delmarks @`). - “E471” from `:delmarks` is now “E471: You must specify register(s)”. - “E474” from `:digraphs` was transformed into “E474: Expected second digraph character, but got nothing” (`:digraphs a`) - `:digraphs` accepts two characters in the digraph definition (was: two bytes, which I consider a bug). - “E475” from `:later`/`:earlier` was split into - “E475: Expected 's', 'm', 'h', 'd', 'f' or nothing after number” (`:later 10x`). - “E475: Trailing characters” (`:later 10mx`). - “E475: Expected numeric argument” (`:later x`). - “E475” from `:filetype` is now “E475: Invalid syntax: expected `filetype[ [plugin|indent]... {on|off|detect}]'”. - `++opt` E474 was split into - “E474: Expected ++[no]bin or ++[no]binary” (`e ++binxxx`) - “E474: Unknown ++opt” (`e ++unknown`) - “E474: Option requires argument: use ++opt=arg” (`e ++enc`) - “E474: Invalid ++bad argument: use "keep", "drop" or a single-byte character” (`e ++bad=xxx`) - “E474: Invalid ++ff argument” (`e ++ff=ttt`) - “E488” from `:history` was split into - “E488: Expected history type name or nothing” (`:history garbage`) - “E488: Expected valid history lines range” (`:history ,`) - “E488” from `:clist` and friends is now “E488: Expected valid integer range”. - “E471” from `:mark`/`:k` is now “E471: Expected mark name”. - `:mark` no longer allows setting `<`, `>`, `[`, `]` and `"` marks (according to the doc it never did). - “E475” from `:redir` was split into - “E475: Expected \`END', \`>[>] {file}', \`@{register}[>[>]]' or \`=> {variable}': redir!!!” (`:redir` without arguments or with invalid argument) - “E475: Expected `END'” (`:redir e`) - “E475: Expected register name; one of A-Z, a-z, ", * and +” (`:redir @?`) - “E475: Expected \`>' and variable name” - “E475” from `:match` is now “E475: Expected regular expression” (`:match HlGroup` without last argument). - “E474” from `:set` was split into - “E474: Expected \`>'” (`:set >`). - “E474” from `:sign` was split into - “E474: Cannot use \`\*' when identifier was already given” (`:sign unplace 1 *`). - “E474: Unknown property” (`:sign place 1 foo`). - “E474: Must provide either buffer= or file= as the last argument” (`:sign place 1 line=10 name=Foo`). - “E474: Cannot use zero as sign id” (`:sign place 0`). - “E474: Cannot use line= and name= without a sign id” (`:sign place line=10 buffer=1`). - “E474: Cannot use line= and name= with :sign jump” (`:sign jump 10 line=10 buffer=1`). - “E474: Cannot use line= and name= with :sign unplace” (`:sign unplace 10 line=10 buffer=1`). - “E474: Missing sign name” (`:sign place 10 line=10 buffer=1`). - “E488” from `:sign` may now be “E488: buffer= argument must be the last one”. - “E158” from `:sign` is now only (it used to be emitted for any error regarding buffers failed to be found) “E158: Buffer number can only be positive” (`:sign place 1 line=10 name=Foo buffer=-10`). - “E885” from `:sign` is now only “E885: Can only use positive line numbers” (`:sign place 1 line=-1`). - Calling `:sign` with non-positive line number fails always (used to fail only if placed sign identifier is new identifier). - “E390” from `:syntax case` is now “E390: Expected match or ignore”. - “E390” from `:syntax conceal` is now “E390: Expected on or off”. - `:syn cluster Foo add=A,B,C remove=C add=C` or similar will probably not do what you want: such things are parsed into `syn cluster Foo add=A,B,C,C remove=C` (separate arguments are always parsed into one list and thus you will most likely end up with `C` in `Foo` cluster). - `:syn cluster` subarguments order is not preserved, executors are supposed to process them in order contains, add, remove. - “E475” from `:syn cluster` is now “E475: Expecting group name followed by an argument”. - “E402” from `:syn match` and others that accept patterns may be “E402: Expected offset anchor designator (\`s' or \`e')” (`syn match Foo /e/ms=x`) or “E402: Garbage after pattern” like it was previously. - “E399” from `:syn region` may either be “E399: Expected group name” (`syn region Foo matchgroup=`) or “E399: Expected syntax pattern” (`syn region Foo start=`). - “E404” from `:syn sync` was split into - “E404: Expected \`=number'” (`syntax sync lines=x`/`syntax sync lines`). - “E404: Pattern end not found” (`syntax sync linecont /foo`). - “E404: Unknown argument” (`syntax sync xxx`). - “E475” from `:syntax keyword` is now one of - “E475: Expected group name” (`syntax keyword`). - “E475: Expected keywords” (`syntax keyword Foo`). - “E475” from `:syntax match` is now one of - “E475: Expected group name followed by an argument” (`syntax match Foo` and `syntax match`). - “E475: Trailing characters” (`syntax match Foo /bar/ /bar/`). ### Translator incompatibilities - Parser errors out on the parsing stage in many cases, without leaving neovim a chance to evaluate any code. But vim errors out on the execution stage (as it does not have any other stages), evaluating whatever was placed before the error. E.g. in the following code: let list = [system('echo abc > def'), my parser is just going to complain about missing `]`, Vim is going to create file `def` *and then* complain about missing `]`. - In `E119`/`E118` messages (not enough/too many arguments for function) in user functions function name are used *exactly* as they were defined. E.g. for the following function: let d = {} function d.Abc(a, b, c) endfunction call Abc(1) It will show E119: Not enough arguments for function: d.Abc , not E119: Not enough arguments for function: 42 . I am planning to use this variant everywhere I need a function name: numbers are not descriptive at all. - Functions defined inside a dictionary are no longer dictionary functions (see below about relations between regular functions and `self`). Reasoning: I have lots of non-dictionary dictionary functions just because I have a reason to define them inside a dictionary in place of using regular `s:` functions. I do not like having to always care about `{}` as a third argument to `call()` in this case. ### Lua implementation incompatibilities - E15 errors are not not just “E15: Invalid expression”: there are (invalid expressions) - “E15: Can only call a Funcref” (`let d={'a':1}|let i=d.a(1)`) - `string[{}]`, `string[[]]` and `string[function('tr')]` will complain about using Dictionary/List/Funcref as a Number, not as a String. Same for `list[...]`. Not the case for `dictionary[...]`. - `string[0.0]` will not raise `E806: Using Float as a String`. Same for `list[0.0]`. Not the case for `dictionary[...]`. - `[] == {}` and `{} == []` in Vim both complain about lists that can only be compared with lists. After translation first complains about comparing lists, second about comparing dictionaries. - Trying to define function inside a dictionary if corresponding key already exists may throw “E718: Funcref required” if existing value is not a function and “E717: Dictionary entry already exists” if existing value is a function. I think that first error is a bug and always raise “E717”. - Using `:delfunction` acts like `:unlet`, but also deletes global function if it exists. The difference is that if you put function reference into a dictionary this reference will be removed from the dictionary when you run `delfunction`. But it will not be removed at least from a) scope variables and b) lists. Code: ```VimL execute "function S()\nendfunction" execute "function L()\nendfunction" let Funcref = function('S') let l = [function('L')] delfunction Funcref echo Funcref " Will complain about undefined variable in my branch and show S in Vim delfunction l echo l " Will output [function('L')] in Vim, [] in my translator. ``` - Trying to delete a slice with `:delfunction` will emit “E475: Expecting function reference, not List” in place of “E475: Invalid argument”. - Trying to add two dictionaries (`{} + {}`) will result in “E728: Using Dictionary as a Number” and not “E731: Using Dictionary as a String”. Same for `{} + []`. - Trying to represent recursive containers will result in lots of brackets and a error. I do not have explicit recursion limit (lua(jit) may have one though) and do not use iterative version of `string()`, but both `string()` and `:echo` check for recursive containers resulting in the former emitting error earlier: ```VimL let l = [] call add(l, l) echo string(l) " Vim: echoes “E724: Variable nested too deep for displaying” and " [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{E724}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] " (One hundred of opening brackets, exactly. Same for closing, of course.) " My translator: echoes “E724: Recursive data type detected” and " [{E724}] ``` - Trying to change the value of the variable never raises E706. Reasoning: I never saw this error making me do anything useful, but constantly saw it as a source of bugs when processing heterogenous lists. - “E710” error message changed: “List value has too many items” (in Vim: “List value has more items than target”). Reason: consistency with “E711: List value has not enough items”. - “E684: List index out of range” is sometimes seen as “E684: First index is greater than the second”. Specifically this happens when trying to (un)lock or unlet `[1:0]`. - When deleting variable with `:unlet` locks are ignored, but not if `:unlet g:.var` syntax is used (i.e. locks are ignored only when using `:unlet g:var`). Current implementation ignores locks always when deleting from scope dictionaries, no matter how they are accessed. - `string()` always uses `%e` format for floating-point values. ### Other - Dictionary and non-dictionary user functions have the only difference of requiring to have self dictionary for calling them. E.g. calling dictionary function without a dictionary will fail, but one may - Call non-dictionary function with a dictionary and observe `self` variable set to this dictionary. Since E706 is out it only makes difference for the case when one tries to access `self` without setting it which should be rare (usually this name is not used anywhere, but in dictionary functions). - Set `self` in a dictionary function to a different value (in Vim it raises E46). - Due to the nature of the idea of having a parser it currently needs to parse the whole block before executing something. I.e. if in Vim you type `:while 1echo 1` you will immediately see `1`, but it will not repeat until `endwhile`. I can add some hacks to preserve this behavior, but do not see any sense in doing this right now and see not very much sense in doing this later.