0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

patch 8.2.3913: help for expressions does not mention Vim9 syntax

Problem:    Help for expressions does not mention Vim9 syntax.
Solution:   Add the rules for Vim9 to the expression help.  Rename functions
            to match the help.
This commit is contained in:
Bram Moolenaar
2021-12-27 15:39:57 +00:00
parent bf7ff61af4
commit 5da36052a4
4 changed files with 203 additions and 124 deletions

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.2. Last change: 2021 Dec 24 *eval.txt* For Vim version 8.2. Last change: 2021 Dec 27
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -97,8 +97,8 @@ Conversion from a String to a Number only happens in legacy Vim script, not in
Vim9 script. It is done by converting the first digits to a number. Vim9 script. It is done by converting the first digits to a number.
Hexadecimal "0xf9", Octal "017" or "0o17", and Binary "0b10" Hexadecimal "0xf9", Octal "017" or "0o17", and Binary "0b10"
numbers are recognized numbers are recognized
NOTE: when using |scriptversion-4| octal with a leading "0" is not recognized. NOTE: when using |Vim9| script or |scriptversion-4| octal with a leading "0"
The 0o notation requires patch 8.2.0886. is not recognized. The 0o notation requires patch 8.2.0886.
If the String doesn't start with digits, the result is zero. If the String doesn't start with digits, the result is zero.
Examples: Examples:
String "456" --> Number 456 ~ String "456" --> Number 456 ~
@@ -523,12 +523,16 @@ String automatically. Thus the String '4' and the number 4 will find the same
entry. Note that the String '04' and the Number 04 are different, since the entry. Note that the String '04' and the Number 04 are different, since the
Number will be converted to the String '4'. The empty string can also be used Number will be converted to the String '4'. The empty string can also be used
as a key. as a key.
In |Vim9| script literaly keys can be used if the key consists of alphanumeric
characters, underscore and dash, see |vim9-literal-dict|.
*literal-Dict* *#{}* *literal-Dict* *#{}*
To avoid having to put quotes around every key the #{} form can be used. This To avoid having to put quotes around every key the #{} form can be used in
does require the key to consist only of ASCII letters, digits, '-' and '_'. legacy script. This does require the key to consist only of ASCII letters,
Example: > digits, '-' and '_'. Example: >
:let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3} :let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3}
Note that 333 here is the string "333". Empty keys are not possible with #{}. Note that 333 here is the string "333". Empty keys are not possible with #{}.
In |Vim9| script the #{} form cannot be used.
A value can be any expression. Using a Dictionary for a value creates a A value can be any expression. Using a Dictionary for a value creates a
nested Dictionary: > nested Dictionary: >
@@ -825,7 +829,7 @@ My_Var_6 session file
MY_VAR_6 viminfo file MY_VAR_6 viminfo file
It's possible to form a variable name with curly braces, see In legacy script it is possible to form a variable name with curly braces, see
|curly-braces-names|. |curly-braces-names|.
============================================================================== ==============================================================================
@@ -873,23 +877,26 @@ Expression syntax summary, from least to most significant:
expr7 % expr7 ... number modulo expr7 % expr7 ... number modulo
|expr7| expr8 |expr7| expr8
! expr7 logical NOT <type>expr8 type check and conversion (|Vim9| only)
- expr7 unary minus
+ expr7 unary plus
|expr8| expr9 |expr8| expr9
expr8[expr1] byte of a String or item of a |List| ! expr8 logical NOT
expr8[expr1 : expr1] substring of a String or sublist of a |List| - expr8 unary minus
expr8.name entry in a |Dictionary| + expr8 unary plus
expr8(expr1, ...) function call with |Funcref| variable
expr8->name(expr1, ...) |method| call
|expr9| number number constant |expr9| expr10
expr9[expr1] byte of a String or item of a |List|
expr9[expr1 : expr1] substring of a String or sublist of a |List|
expr9.name entry in a |Dictionary|
expr9(expr1, ...) function call with |Funcref| variable
expr9->name(expr1, ...) |method| call
|expr10| number number constant
"string" string constant, backslash is special "string" string constant, backslash is special
'string' string constant, ' is doubled 'string' string constant, ' is doubled
[expr1, ...] |List| [expr1, ...] |List|
{expr1: expr1, ...} |Dictionary| {expr1: expr1, ...} |Dictionary|
#{key: expr1, ...} |Dictionary| #{key: expr1, ...} legacy |Dictionary|
&option option value &option option value
(expr1) nested expression (expr1) nested expression
variable internal variable variable internal variable
@@ -898,7 +905,8 @@ Expression syntax summary, from least to most significant:
@r contents of register 'r' @r contents of register 'r'
function(expr1, ...) function call function(expr1, ...) function call
func{ti}on(expr1, ...) function call with curly braces func{ti}on(expr1, ...) function call with curly braces
{args -> expr1} lambda expression {args -> expr1} legacy lambda expression
(args) => expr1 Vim9 lambda expression
"..." indicates that the operations in this level can be concatenated. "..." indicates that the operations in this level can be concatenated.
@@ -916,9 +924,14 @@ The falsy operator: expr2 ?? expr1
Trinary operator ~ Trinary operator ~
The expression before the '?' is evaluated to a number. If it evaluates to In legacy script the expression before the '?' is evaluated to a number. If
|TRUE|, the result is the value of the expression between the '?' and ':', it evaluates to |TRUE|, the result is the value of the expression between the
otherwise the result is the value of the expression after the ':'. '?' and ':', otherwise the result is the value of the expression after the
':'.
In |Vim9| script the first expression must evaluate to a boolean, see
|vim9-boolean|.
Example: > Example: >
:echo lnum == 1 ? "top" : lnum :echo lnum == 1 ? "top" : lnum
@@ -952,7 +965,8 @@ value for an expression that may result in zero or empty: >
These are similar, but not equal: > These are similar, but not equal: >
expr2 ?? expr1 expr2 ?? expr1
expr2 ? expr2 : expr1 expr2 ? expr2 : expr1
In the second line "expr2" is evaluated twice. In the second line "expr2" is evaluated twice. And in |Vim9| script the type
of expr2 before "?" must be a boolean.
expr2 and expr3 *expr2* *expr3* expr2 and expr3 *expr2* *expr3*
@@ -961,9 +975,14 @@ expr2 and expr3 *expr2* *expr3*
expr3 || expr3 .. logical OR *expr-barbar* expr3 || expr3 .. logical OR *expr-barbar*
expr4 && expr4 .. logical AND *expr-&&* expr4 && expr4 .. logical AND *expr-&&*
The "||" and "&&" operators take one argument on each side. The arguments The "||" and "&&" operators take one argument on each side.
are (converted to) Numbers. The result is:
In legacy script the arguments are (converted to) Numbers.
In |Vim9| script the values must be boolean, see |vim9-boolean|. Use "!!" to
convert any type to a boolean.
The result is:
input output ~ input output ~
n1 n2 n1 || n2 n1 && n2 ~ n1 n2 n1 || n2 n1 && n2 ~
|FALSE| |FALSE| |FALSE| |FALSE| |FALSE| |FALSE| |FALSE| |FALSE|
@@ -999,8 +1018,9 @@ expr4 *expr4*
expr5 {cmp} expr5 expr5 {cmp} expr5
Compare two expr5 expressions, resulting in a 0 if it evaluates to false, or 1 Compare two expr5 expressions. In legacy script the result is a 0 if it
if it evaluates to true. evaluates to false, or 1 if it evaluates to true. In |Vim9| script the result
is |true| or |false|.
*expr-==* *expr-!=* *expr->* *expr->=* *expr-==* *expr-!=* *expr->* *expr->=*
*expr-<* *expr-<=* *expr-=~* *expr-!~* *expr-<* *expr-<=* *expr-=~* *expr-!~*
@@ -1026,6 +1046,7 @@ Examples:
"abc" ==# "Abc" evaluates to 0 "abc" ==# "Abc" evaluates to 0
"abc" ==? "Abc" evaluates to 1 "abc" ==? "Abc" evaluates to 1
"abc" == "Abc" evaluates to 1 if 'ignorecase' is set, 0 otherwise "abc" == "Abc" evaluates to 1 if 'ignorecase' is set, 0 otherwise
NOTE: In |Vim9| script 'ignorecase' is not used.
*E691* *E692* *E691* *E692*
A |List| can only be compared with a |List| and only "equal", "not equal", A |List| can only be compared with a |List| and only "equal", "not equal",
@@ -1064,8 +1085,9 @@ a different type means the values are different: >
0 0
"is#"/"isnot#" and "is?"/"isnot?" can be used to match and ignore case. "is#"/"isnot#" and "is?"/"isnot?" can be used to match and ignore case.
When comparing a String with a Number, the String is converted to a Number, In legacy script, when comparing a String with a Number, the String is
and the comparison is done on Numbers. This means that: > converted to a Number, and the comparison is done on Numbers. This means
that: >
echo 0 == 'x' echo 0 == 'x'
1 1
because 'x' converted to a Number is zero. However: > because 'x' converted to a Number is zero. However: >
@@ -1073,6 +1095,8 @@ because 'x' converted to a Number is zero. However: >
0 0
Inside a List or Dictionary this conversion is not used. Inside a List or Dictionary this conversion is not used.
In |Vim9| script the types must match.
When comparing two Strings, this is done with strcmp() or stricmp(). This When comparing two Strings, this is done with strcmp() or stricmp(). This
results in the mathematical difference (comparing byte values), not results in the mathematical difference (comparing byte values), not
necessarily the alphabetical difference in the local language. necessarily the alphabetical difference in the local language.
@@ -1110,29 +1134,36 @@ result is a new list with the two lists Concatenated.
For String concatenation ".." is preferred, since "." is ambiguous, it is also For String concatenation ".." is preferred, since "." is ambiguous, it is also
used for |Dict| member access and floating point numbers. used for |Dict| member access and floating point numbers.
When |vimscript-version| is 2 or higher, using "." is not allowed. In |Vim9| script and when |vimscript-version| is 2 or higher, using "." is not
allowed.
In |Vim9| script the arguments of ".." are converted to String for simple
types: Number, Float, Special and Bool. For other types |string()| should be
used.
expr7 * expr7 Number multiplication *expr-star* expr7 * expr7 Number multiplication *expr-star*
expr7 / expr7 Number division *expr-/* expr7 / expr7 Number division *expr-/*
expr7 % expr7 Number modulo *expr-%* expr7 % expr7 Number modulo *expr-%*
For all, except "." and "..", Strings are converted to Numbers. In legacy script, for all operators except "." and "..", Strings are converted
to Numbers.
For bitwise operators see |and()|, |or()| and |xor()|. For bitwise operators see |and()|, |or()| and |xor()|.
Note the difference between "+" and ".": Note the difference between "+" and ".." in legacy script:
"123" + "456" = 579 "123" + "456" = 579
"123" . "456" = "123456" "123" .. "456" = "123456"
Since '.' has the same precedence as '+' and '-', you need to read: > Since '..' has the same precedence as '+' and '-', you need to read: >
1 . 90 + 90.0 1 .. 90 + 90.0
As: > As: >
(1 . 90) + 90.0 (1 .. 90) + 90.0
That works, since the String "190" is automatically converted to the Number That works in legacy script, since the String "190" is automatically converted
190, which can be added to the Float 90.0. However: > to the Number 190, which can be added to the Float 90.0. However: >
1 . 90 * 90.0 1 .. 90 * 90.0
Should be read as: > Should be read as: >
1 . (90 * 90.0) 1 .. (90 * 90.0)
Since '.' has lower precedence than '*'. This does NOT work, since this Since '..' has lower precedence than '*'. This does NOT work, since this
attempts to concatenate a Float and a String. attempts to concatenate a Float and a String.
When dividing a Number by zero the result depends on the value: When dividing a Number by zero the result depends on the value:
@@ -1150,20 +1181,35 @@ When the righthand side of '%' is zero, the result is 0.
None of these work for |Funcref|s. None of these work for |Funcref|s.
. and % do not work for Float. *E804* ".", ".." and "%" do not work for Float. *E804*
expr7 *expr7* expr7 *expr7*
----- -----
! expr7 logical NOT *expr-!* <type>expr8
- expr7 unary minus *expr-unary--*
+ expr7 unary plus *expr-unary-+* This is only available in |Vim9| script, see |type-casting|.
expr8 *expr8*
-----
! expr8 logical NOT *expr-!*
- expr8 unary minus *expr-unary--*
+ expr8 unary plus *expr-unary-+*
For '!' |TRUE| becomes |FALSE|, |FALSE| becomes |TRUE| (one). For '!' |TRUE| becomes |FALSE|, |FALSE| becomes |TRUE| (one).
For '-' the sign of the number is changed. For '-' the sign of the number is changed.
For '+' the number is unchanged. Note: "++" has no effect. For '+' the number is unchanged. Note: "++" has no effect.
A String will be converted to a Number first. In legacy script a String will be converted to a Number first. Note that if
the string does not start with a digit you likely don't get what you expect.
In |Vim9| script an error is given when "-" or "+" is used and the type is not
a number.
In |Vim9| script "!" can be used for any type and the result is always a
boolean. Use "!!" to convert any type to a boolean, according to whether the
value is |falsy|.
These three can be repeated and mixed. Examples: These three can be repeated and mixed. Examples:
!-1 == 0 !-1 == 0
@@ -1171,30 +1217,30 @@ These three can be repeated and mixed. Examples:
--9 == 9 --9 == 9
expr8 *expr8* expr9 *expr9*
----- -----
This expression is either |expr9| or a sequence of the alternatives below, This expression is either |expr10| or a sequence of the alternatives below,
in any order. E.g., these are all possible: in any order. E.g., these are all possible:
expr8[expr1].name expr9[expr1].name
expr8.name[expr1] expr9.name[expr1]
expr8(expr1, ...)[expr1].name expr9(expr1, ...)[expr1].name
expr8->(expr1, ...)[expr1] expr9->(expr1, ...)[expr1]
Evaluation is always from left to right. Evaluation is always from left to right.
expr8[expr1] item of String or |List| *expr-[]* *E111* expr9[expr1] item of String or |List| *expr-[]* *E111*
*E909* *subscript* *E909* *subscript*
In legacy Vim script: In legacy Vim script:
If expr8 is a Number or String this results in a String that contains the If expr9 is a Number or String this results in a String that contains the
expr1'th single byte from expr8. expr8 is used as a String (a number is expr1'th single byte from expr9. expr9 is used as a String (a number is
automatically converted to a String), expr1 as a Number. This doesn't automatically converted to a String), expr1 as a Number. This doesn't
recognize multibyte encodings, see `byteidx()` for an alternative, or use recognize multibyte encodings, see `byteidx()` for an alternative, or use
`split()` to turn the string into a list of characters. Example, to get the `split()` to turn the string into a list of characters. Example, to get the
byte under the cursor: > byte under the cursor: >
:let c = getline(".")[col(".") - 1] :let c = getline(".")[col(".") - 1]
In Vim9 script: In |Vim9| script:
If expr8 is a String this results in a String that contains the expr1'th If expr9 is a String this results in a String that contains the expr1'th
single character (including any composing characters) from expr8. To use byte single character (including any composing characters) from expr9. To use byte
indexes use |strpart()|. indexes use |strpart()|.
Index zero gives the first byte or character. Careful: text column numbers Index zero gives the first byte or character. Careful: text column numbers
@@ -1205,7 +1251,7 @@ String. A negative index always results in an empty string (reason: backward
compatibility). Use [-1:] to get the last byte or character. compatibility). Use [-1:] to get the last byte or character.
In Vim9 script a negative index is used like with a list: count from the end. In Vim9 script a negative index is used like with a list: count from the end.
If expr8 is a |List| then it results the item at index expr1. See |list-index| If expr9 is a |List| then it results the item at index expr1. See |list-index|
for possible index values. If the index is out of range this results in an for possible index values. If the index is out of range this results in an
error. Example: > error. Example: >
:let item = mylist[-1] " get last item :let item = mylist[-1] " get last item
@@ -1215,14 +1261,14 @@ Generally, if a |List| index is equal to or higher than the length of the
error. error.
expr8[expr1a : expr1b] substring or sublist *expr-[:]* expr9[expr1a : expr1b] substring or sublist *expr-[:]*
If expr8 is a String this results in the substring with the bytes or If expr9 is a String this results in the substring with the bytes or
characters from expr1a to and including expr1b. expr8 is used as a String, characters from expr1a to and including expr1b. expr9 is used as a String,
expr1a and expr1b are used as a Number. expr1a and expr1b are used as a Number.
In legacy Vim script the indexes are byte indexes. This doesn't recognize In legacy Vim script the indexes are byte indexes. This doesn't recognize
multibyte encodings, see |byteidx()| for computing the indexes. If expr8 is multibyte encodings, see |byteidx()| for computing the indexes. If expr9 is
a Number it is first converted to a String. a Number it is first converted to a String.
In Vim9 script the indexes are character indexes and include composing In Vim9 script the indexes are character indexes and include composing
@@ -1249,20 +1295,20 @@ Examples: >
:let s = s[:-3] " remove last two bytes :let s = s[:-3] " remove last two bytes
< <
*slice* *slice*
If expr8 is a |List| this results in a new |List| with the items indicated by If expr9 is a |List| this results in a new |List| with the items indicated by
the indexes expr1a and expr1b. This works like with a String, as explained the indexes expr1a and expr1b. This works like with a String, as explained
just above. Also see |sublist| below. Examples: > just above. Also see |sublist| below. Examples: >
:let l = mylist[:3] " first four items :let l = mylist[:3] " first four items
:let l = mylist[4:4] " List with one item :let l = mylist[4:4] " List with one item
:let l = mylist[:] " shallow copy of a List :let l = mylist[:] " shallow copy of a List
If expr8 is a |Blob| this results in a new |Blob| with the bytes in the If expr9 is a |Blob| this results in a new |Blob| with the bytes in the
indexes expr1a and expr1b, inclusive. Examples: > indexes expr1a and expr1b, inclusive. Examples: >
:let b = 0zDEADBEEF :let b = 0zDEADBEEF
:let bs = b[1:2] " 0zADBE :let bs = b[1:2] " 0zADBE
:let bs = b[:] " copy of 0zDEADBEEF :let bs = b[:] " copy of 0zDEADBEEF
Using expr8[expr1] or expr8[expr1a : expr1b] on a |Funcref| results in an Using expr9[expr1] or expr9[expr1a : expr1b] on a |Funcref| results in an
error. error.
Watch out for confusion between a namespace and a variable followed by a colon Watch out for confusion between a namespace and a variable followed by a colon
@@ -1271,11 +1317,11 @@ for a sublist: >
mylist[s:] " uses namespace s:, error! mylist[s:] " uses namespace s:, error!
expr8.name entry in a |Dictionary| *expr-entry* expr9.name entry in a |Dictionary| *expr-entry*
If expr8 is a |Dictionary| and it is followed by a dot, then the following If expr9 is a |Dictionary| and it is followed by a dot, then the following
name will be used as a key in the |Dictionary|. This is just like: name will be used as a key in the |Dictionary|. This is just like:
expr8[name]. expr9[name].
The name must consist of alphanumeric characters, just like a variable name, The name must consist of alphanumeric characters, just like a variable name,
but it may start with a number. Curly braces cannot be used. but it may start with a number. Curly braces cannot be used.
@@ -1292,17 +1338,17 @@ Note that the dot is also used for String concatenation. To avoid confusion
always put spaces around the dot for String concatenation. always put spaces around the dot for String concatenation.
expr8(expr1, ...) |Funcref| function call expr9(expr1, ...) |Funcref| function call
When expr8 is a |Funcref| type variable, invoke the function it refers to. When expr9 is a |Funcref| type variable, invoke the function it refers to.
expr8->name([args]) method call *method* *->* expr9->name([args]) method call *method* *->*
expr8->{lambda}([args]) expr9->{lambda}([args])
*E276* *E276*
For methods that are also available as global functions this is the same as: > For methods that are also available as global functions this is the same as: >
name(expr8 [, args]) name(expr9 [, args])
There can also be methods specifically for the type of "expr8". There can also be methods specifically for the type of "expr9".
This allows for chaining, passing the value that one method returns to the This allows for chaining, passing the value that one method returns to the
next method: > next method: >
@@ -1311,7 +1357,7 @@ next method: >
Example of using a lambda: > Example of using a lambda: >
GetPercentage()->{x -> x * 100}()->printf('%d%%') GetPercentage()->{x -> x * 100}()->printf('%d%%')
< <
When using -> the |expr7| operators will be applied first, thus: > When using -> the |expr8| operators will be applied first, thus: >
-1.234->string() -1.234->string()
Is equivalent to: > Is equivalent to: >
(-1.234)->string() (-1.234)->string()
@@ -1331,7 +1377,7 @@ When using the lambda form there must be no white space between the } and the
(. (.
*expr9* *expr10*
number number
------ ------
number number constant *expr-number* number number constant *expr-number*
@@ -1535,7 +1581,8 @@ See below |functions|.
lambda expression *expr-lambda* *lambda* lambda expression *expr-lambda* *lambda*
----------------- -----------------
{args -> expr1} lambda expression {args -> expr1} legacy lambda expression
(args) => expr1 |Vim9| lambda expression
A lambda expression creates a new unnamed function which returns the result of A lambda expression creates a new unnamed function which returns the result of
evaluating |expr1|. Lambda expressions differ from |user-functions| in evaluating |expr1|. Lambda expressions differ from |user-functions| in
@@ -1553,7 +1600,8 @@ The arguments are optional. Example: >
:echo F('ignored') :echo F('ignored')
< error function < error function
Note that in Vim9 script another kind of lambda can be used: |vim9-lambda|. The |Vim9| lambda does not only use a different syntax, it also adds type
checking and can be split over multiple lines, see |vim9-lambda|.
*closure* *closure*
Lambda expressions can access outer scope variables and arguments. This is Lambda expressions can access outer scope variables and arguments. This is
@@ -1610,27 +1658,31 @@ See also: |numbered-function|
3. Internal variable *internal-variables* *E461* 3. Internal variable *internal-variables* *E461*
An internal variable name can be made up of letters, digits and '_'. But it An internal variable name can be made up of letters, digits and '_'. But it
cannot start with a digit. It's also possible to use curly braces, see cannot start with a digit. In legacy script it also possible to use curly
|curly-braces-names|. braces, see |curly-braces-names|.
An internal variable is created with the ":let" command |:let|. In legacy script ann internal variable is created with the ":let" command
An internal variable is explicitly destroyed with the ":unlet" command |:let|. An internal variable is explicitly destroyed with the ":unlet"
|:unlet|. command |:unlet|.
Using a name that is not an internal variable or refers to a variable that has Using a name that is not an internal variable or refers to a variable that has
been destroyed results in an error. been destroyed results in an error.
In |Vim9| script `:let` is not used and variables work differently, see |:var|.
*variable-scope* *variable-scope*
There are several name spaces for variables. Which one is to be used is There are several name spaces for variables. Which one is to be used is
specified by what is prepended: specified by what is prepended:
(nothing) In a function: local to a function; otherwise: global (nothing) In a function: local to the function;
in a legacy script: global;
in a |Vim9| script: local to the script
|buffer-variable| b: Local to the current buffer. |buffer-variable| b: Local to the current buffer.
|window-variable| w: Local to the current window. |window-variable| w: Local to the current window.
|tabpage-variable| t: Local to the current tab page. |tabpage-variable| t: Local to the current tab page.
|global-variable| g: Global. |global-variable| g: Global.
|local-variable| l: Local to a function. |local-variable| l: Local to a function (only in a legacy function)
|script-variable| s: Local to a |:source|'ed Vim script. |script-variable| s: Local to a |:source|'ed Vim script.
|function-argument| a: Function argument (only inside a function). |function-argument| a: Function argument (only in a legacy function).
|vim-variable| v: Global, predefined by Vim. |vim-variable| v: Global, predefined by Vim.
The scope name by itself can be used as a |Dictionary|. For example, to The scope name by itself can be used as a |Dictionary|. For example, to
@@ -1639,8 +1691,8 @@ delete all script-local variables: >
: unlet s:[k] : unlet s:[k]
:endfor :endfor
Note: in Vim9 script this is different, see |vim9-scopes|. Note: in Vim9 script variables can also be local to a block of commands, see
|vim9-scopes|.
*buffer-variable* *b:var* *b:* *buffer-variable* *b:var* *b:*
A variable name that is preceded with "b:" is local to the current buffer. A variable name that is preceded with "b:" is local to the current buffer.
Thus you can have several "b:foo" variables, one for each buffer. Thus you can have several "b:foo" variables, one for each buffer.
@@ -1982,6 +2034,7 @@ v:false A Number with value zero. Used to put "false" in JSON. See
< v:false ~ < v:false ~
That is so that eval() can parse the string back to the same That is so that eval() can parse the string back to the same
value. Read-only. value. Read-only.
In |Vim9| script "false" can be used which has a boolean type.
*v:fcs_reason* *fcs_reason-variable* *v:fcs_reason* *fcs_reason-variable*
v:fcs_reason The reason why the |FileChangedShell| event was triggered. v:fcs_reason The reason why the |FileChangedShell| event was triggered.
@@ -2145,6 +2198,7 @@ v:null An empty String. Used to put "null" in JSON. See
< v:null ~ < v:null ~
That is so that eval() can parse the string back to the same That is so that eval() can parse the string back to the same
value. Read-only. value. Read-only.
In |Vim9| script "null" can be used without "v:".
*v:numbermax* *numbermax-variable* *v:numbermax* *numbermax-variable*
v:numbermax Maximum value of a number. v:numbermax Maximum value of a number.
@@ -2429,6 +2483,7 @@ v:true A Number with value one. Used to put "true" in JSON. See
< v:true ~ < v:true ~
That is so that eval() can parse the string back to the same That is so that eval() can parse the string back to the same
value. Read-only. value. Read-only.
In |Vim9| script "true" can be used which has a boolean type.
*v:val* *val-variable* *v:val* *val-variable*
v:val Value of the current item of a |List| or |Dictionary|. Only v:val Value of the current item of a |List| or |Dictionary|. Only
valid while evaluating the expression used with |map()| and valid while evaluating the expression used with |map()| and
@@ -4923,6 +4978,9 @@ filter({expr1}, {expr2}) *filter()*
< If you do not use "val" you can leave it out: > < If you do not use "val" you can leave it out: >
call filter(myList, {idx -> idx % 2 == 1}) call filter(myList, {idx -> idx % 2 == 1})
< <
In |Vim9| script the result must be true, false, zero or one.
Other values will result in a type error.
For a |List| and a |Dictionary| the operation is done For a |List| and a |Dictionary| the operation is done
in-place. If you want it to remain unmodified make a copy in-place. If you want it to remain unmodified make a copy
first: > first: >
@@ -12579,18 +12637,22 @@ builtin functions. To prevent from using the same name in different scripts
avoid obvious, short names. A good habit is to start the function name with avoid obvious, short names. A good habit is to start the function name with
the name of the script, e.g., "HTMLcolor()". the name of the script, e.g., "HTMLcolor()".
It's also possible to use curly braces, see |curly-braces-names|. And the In legacy script it is also possible to use curly braces, see
|autoload| facility is useful to define a function only when it's called. |curly-braces-names|.
The |autoload| facility is useful to define a function only when it's called.
*local-function* *local-function*
A function local to a script must start with "s:". A local script function A function local to a legacy script must start with "s:". A local script
can only be called from within the script and from functions, user commands function can only be called from within the script and from functions, user
and autocommands defined in the script. It is also possible to call the commands and autocommands defined in the script. It is also possible to call
function from a mapping defined in the script, but then |<SID>| must be used the function from a mapping defined in the script, but then |<SID>| must be
instead of "s:" when the mapping is expanded outside of the script. used instead of "s:" when the mapping is expanded outside of the script.
There are only script-local functions, no buffer-local or window-local There are only script-local functions, no buffer-local or window-local
functions. functions.
In |Vim9| script functions are local to the script by default, prefix "g:" to
define a global function.
*:fu* *:function* *E128* *E129* *E123* *:fu* *:function* *E128* *E129* *E123*
:fu[nction] List all functions and their arguments. :fu[nction] List all functions and their arguments.
@@ -12852,7 +12914,11 @@ This function can then be called with: >
Call a function. The name of the function and its arguments Call a function. The name of the function and its arguments
are as specified with `:function`. Up to 20 arguments can be are as specified with `:function`. Up to 20 arguments can be
used. The returned value is discarded. used. The returned value is discarded.
Without a range and for functions that accept a range, the In |Vim9| script using `:call` is optional, these two lines do
the same thing: >
call SomeFunc(arg)
SomeFunc(arg)
< Without a range and for functions that accept a range, the
function is called once. When a range is given the cursor is function is called once. When a range is given the cursor is
positioned at the start of the first line before executing the positioned at the start of the first line before executing the
function. function.
@@ -12997,6 +13063,8 @@ variable. This is a regular variable name with one or more expressions
wrapped in braces {} like this: > wrapped in braces {} like this: >
my_{adjective}_variable my_{adjective}_variable
This only works in legacy Vim script, not in |Vim9| script.
When Vim encounters this, it evaluates the expression inside the braces, puts When Vim encounters this, it evaluates the expression inside the braces, puts
that in place of the expression, and re-interprets the whole as a variable that in place of the expression, and re-interprets the whole as a variable
name. So in the above example, if the variable "adjective" was set to name. So in the above example, if the variable "adjective" was set to
@@ -13038,8 +13106,8 @@ This does NOT work: >
============================================================================== ==============================================================================
7. Commands *expression-commands* 7. Commands *expression-commands*
Note: in Vim9 script `:let` is used for variable declaration, not assignment. Note: in |Vim9| script `:let` is not used. `:var` is used for variable
An assignment leaves out the `:let` command. |vim9-declaration| declarations and assignments do not use a command. |vim9-declaration|
:let {var-name} = {expr1} *:let* *E18* :let {var-name} = {expr1} *:let* *E18*
Set internal variable {var-name} to the result of the Set internal variable {var-name} to the result of the
@@ -13457,25 +13525,34 @@ text...
:endfo[r] *:endfo* *:endfor* :endfo[r] *:endfo* *:endfor*
Repeat the commands between ":for" and ":endfor" for Repeat the commands between ":for" and ":endfor" for
each item in {object}. {object} can be a |List| or each item in {object}. {object} can be a |List| or
a |Blob|. Variable {var} is set to the value of each a |Blob|.
item. When an error is detected for a command inside
the loop, execution continues after the "endfor". Variable {var} is set to the value of each item.
In |Vim9| script the loop variable must not have been
declared yet, unless when it is a
global/window/tab/buffer variable.
When an error is detected for a command inside the
loop, execution continues after the "endfor".
Changing {object} inside the loop affects what items Changing {object} inside the loop affects what items
are used. Make a copy if this is unwanted: > are used. Make a copy if this is unwanted: >
:for item in copy(mylist) :for item in copy(mylist)
< <
When {object} is a |List| and not making a copy, Vim When {object} is a |List| and not making a copy, in
stores a reference to the next item in the |List| legacy script Vim stores a reference to the next item
before executing the commands with the current item. in the |List| before executing the commands with the
Thus the current item can be removed without effect. current item. Thus the current item can be removed
Removing any later item means it will not be found. without effect. Removing any later item means it will
Thus the following example works (an inefficient way not be found. Thus the following example works (an
to make a |List| empty): > inefficient way to make a |List| empty): >
for item in mylist for item in mylist
call remove(mylist, 0) call remove(mylist, 0)
endfor endfor
< Note that reordering the |List| (e.g., with sort() or < Note that reordering the |List| (e.g., with sort() or
reverse()) may have unexpected effects. reverse()) may have unexpected effects.
In |Vim9| script the index is used. If an item before
the current one is deleted the next item will be
skipped.
When {object} is a |Blob|, Vim always makes a copy to When {object} is a |Blob|, Vim always makes a copy to
iterate over. Unlike with |List|, modifying the iterate over. Unlike with |List|, modifying the

View File

@@ -1,4 +1,4 @@
*vim9.txt* For Vim version 8.2. Last change: 2021 Dec 26 *vim9.txt* For Vim version 8.2. Last change: 2021 Dec 27
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -81,7 +81,7 @@ script and `:def` functions; details are below:
echo "hello " echo "hello "
.. yourName .. yourName
.. ", how are you?" .. ", how are you?"
- White space is required in many places. - White space is required in many places to improve readability.
- Assign values without `:let`, declare variables with `:var`: > - Assign values without `:let`, declare variables with `:var`: >
var count = 0 var count = 0
count += 3 count += 3
@@ -94,8 +94,8 @@ script and `:def` functions; details are below:
def CallMe(count: number, message: string): bool def CallMe(count: number, message: string): bool
- Call functions without `:call`: > - Call functions without `:call`: >
writefile(['done'], 'file.txt') writefile(['done'], 'file.txt')
- You cannot use `:xit`, `:t`, `:k`, `:append`, `:change`, `:insert`, `:open`, - You cannot use old Ex commands `:xit`, `:t`, `:k`, `:append`, `:change`,
and `:s` or `:d` with only flags. `:insert`, `:open`, and `:s` or `:d` with only flags.
- You cannot use curly-braces names. - You cannot use curly-braces names.
- A range before a command must be prefixed with a colon: > - A range before a command must be prefixed with a colon: >
:%s/this/that :%s/this/that
@@ -353,7 +353,7 @@ default to the number zero.
In Vim9 script `:let` cannot be used. An existing variable is assigned to In Vim9 script `:let` cannot be used. An existing variable is assigned to
without any command. The same for global, window, tab, buffer and Vim without any command. The same for global, window, tab, buffer and Vim
variables, because they are not really declared. They can also be deleted variables, because they are not really declared. Those can also be deleted
with `:unlet`. with `:unlet`.
`:lockvar` does not work on local variables. Use `:const` and `:final` `:lockvar` does not work on local variables. Use `:const` and `:final`
@@ -597,7 +597,7 @@ Also when confused with the start of a command block: >
Automatic line continuation ~ Automatic line continuation ~
*vim9-line-continuation*
In many cases it is obvious that an expression continues on the next line. In In many cases it is obvious that an expression continues on the next line. In
those cases there is no need to prefix the line with a backslash (see those cases there is no need to prefix the line with a backslash (see
|line-continuation|). For example, when a list spans multiple lines: > |line-continuation|). For example, when a list spans multiple lines: >
@@ -775,7 +775,7 @@ No curly braces expansion ~
Dictionary literals ~ Dictionary literals ~
*vim9-literal-dict*
Traditionally Vim has supported dictionary literals with a {} syntax: > Traditionally Vim has supported dictionary literals with a {} syntax: >
let dict = {'key': value} let dict = {'key': value}
@@ -865,7 +865,7 @@ first if needed.
Conditions and expressions ~ Conditions and expressions ~
*vim9-boolean*
Conditions and expressions are mostly working like they do in other languages. Conditions and expressions are mostly working like they do in other languages.
Some values are different from legacy Vim script: Some values are different from legacy Vim script:
value legacy Vim script Vim9 script ~ value legacy Vim script Vim9 script ~
@@ -917,8 +917,8 @@ always converted to string: >
'hello ' .. 123 == 'hello 123' 'hello ' .. 123 == 'hello 123'
'hello ' .. v:true == 'hello true' 'hello ' .. v:true == 'hello true'
Simple types are string, float, special and bool. For other types |string()| Simple types are Number, Float, Special and Bool. For other types |string()|
can be used. should be used.
*false* *true* *null* *false* *true* *null*
In Vim9 script one can use "true" for v:true, "false" for v:false and "null" In Vim9 script one can use "true" for v:true, "false" for v:false and "null"
for v:null. When converting a boolean to a string "false" and "true" are for v:null. When converting a boolean to a string "false" and "true" are

View File

@@ -749,6 +749,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
3913,
/**/ /**/
3912, 3912,
/**/ /**/

View File

@@ -1883,7 +1883,7 @@ compile_subscript(
* trailing ->name() method call * trailing ->name() method call
*/ */
static int static int
compile_expr7( compile_expr8(
char_u **arg, char_u **arg,
cctx_T *cctx, cctx_T *cctx,
ppconst_T *ppconst) ppconst_T *ppconst)
@@ -2119,10 +2119,10 @@ compile_expr7(
} }
/* /*
* <type>expr7: runtime type check / conversion * <type>expr8: runtime type check / conversion
*/ */
static int static int
compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{ {
type_T *want_type = NULL; type_T *want_type = NULL;
@@ -2147,7 +2147,7 @@ compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
return FAIL; return FAIL;
} }
if (compile_expr7(arg, cctx, ppconst) == FAIL) if (compile_expr8(arg, cctx, ppconst) == FAIL)
return FAIL; return FAIL;
if (want_type != NULL) if (want_type != NULL)
@@ -2182,7 +2182,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
int ppconst_used = ppconst->pp_used; int ppconst_used = ppconst->pp_used;
// get the first expression // get the first expression
if (compile_expr7t(arg, cctx, ppconst) == FAIL) if (compile_expr7(arg, cctx, ppconst) == FAIL)
return FAIL; return FAIL;
/* /*
@@ -2208,7 +2208,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
return FAIL; return FAIL;
// get the second expression // get the second expression
if (compile_expr7t(arg, cctx, ppconst) == FAIL) if (compile_expr7(arg, cctx, ppconst) == FAIL)
return FAIL; return FAIL;
if (ppconst->pp_used == ppconst_used + 2 if (ppconst->pp_used == ppconst_used + 2