💾 Archived View for gmi.noulin.net › vim › eval.gmi captured on 2024-03-21 at 17:42:36. Gemini links have been rewritten to link to archived content
View Raw
More Information
⬅️ Previous capture (2024-02-05)
➡️ Next capture (2024-05-12)
🚧 View Differences
-=-=-=-=-=-=-
- eval.txt* For Vim version 9.1. Last change: 2024 Feb 08
VIM REFERENCE MANUAL by Bram Moolenaar
Expression evaluation *expression* *expr* *E15* *eval*
*E1002*
Using expressions is introduced in chapter 41 of the user manual |usr_41.txt|.
Note: Expression evaluation can be disabled at compile time. If this has been
done, the features in this document are not available. See |+eval| and
|no-eval-feature|.
This file is mainly about the backwards compatible (legacy) Vim script. For
specifics of Vim9 script, which can execute much faster, supports type
checking and much more, see |vim9.txt|. Where the syntax or semantics differ
a remark is given.
1. Variables |variables|
1.1 Variable types
1.2 Function references |Funcref|
1.3 Lists |Lists|
1.4 Dictionaries |Dictionaries|
1.5 Blobs |Blobs|
1.6 More about variables |more-variables|
2. Expression syntax |expression-syntax|
3. Internal variable |internal-variables|
4. Builtin Functions |functions|
5. Defining functions |user-functions|
6. Curly braces names |curly-braces-names|
7. Commands |expression-commands|
8. Exception handling |exception-handling|
9. Examples |eval-examples|
10. Vim script version |vimscript-version|
11. No +eval feature |no-eval-feature|
12. The sandbox |eval-sandbox|
13. Textlock |textlock|
14. Vim script library |vim-script-library|
Testing support is documented in |testing.txt|.
Profiling is documented at |profiling|.
==============================================================================
1. Variables *variables*
1.1 Variable types ~
*E712* *E896* *E897* *E899* *E1098*
*E1107* *E1135* *E1138*
There are ten types of variables:
*Number* *Integer*
Number A 32 or 64 bit signed number. |expr-number|
The number of bits is available in |v:numbersize|.
Examples: -123 0x10 0177 0o177 0b1011
Float A floating point number. |floating-point-format| *Float*
Examples: 123.456 1.15e-6 -1.1e3
String A NUL terminated string of 8-bit unsigned characters (bytes).
|expr-string| Examples: "ab\txx\"--" 'x-z''a,c'
List An ordered sequence of items, see |List| for details.
Example: [1, 2, ['a', 'b']]
Dictionary An associative, unordered array: Each entry has a key and a
value. |Dictionary|
Examples:
{'blue': "#0000ff", 'red': "#ff0000"}
#{blue: "#0000ff", red: "#ff0000"}
Funcref A reference to a function |Funcref|.
Example: function("strlen")
It can be bound to a dictionary and arguments, it then works
like a Partial.
Example: function("Callback", [arg], myDict)
Special |v:false|, |v:true|, |v:none| and |v:null|. *Special*
Job Used for a job, see |job_start()|. *Job* *Jobs*
Channel Used for a channel, see |ch_open()|. *Channel* *Channels*
Blob Binary Large Object. Stores any sequence of bytes. See |Blob|
for details
Example: 0zFF00ED015DAF
0z is an empty Blob.
The Number and String types are converted automatically, depending on how they
are used.
Conversion from a Number to a String is by making the ASCII representation of
the Number. Examples:
Number 123 --> String "123" ~
Number 0 --> String "0" ~
Number -1 --> String "-1" ~
*octal*
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.
Hexadecimal "0xf9", Octal "017" or "0o17", and Binary "0b10"
numbers are recognized
NOTE: when using |Vim9| script or |scriptversion-4| octal with a leading "0"
is not recognized. The 0o notation requires patch 8.2.0886.
If the String doesn't start with digits, the result is zero.
Examples:
String "456" --> Number 456 ~
String "6bar" --> Number 6 ~
String "foo" --> Number 0 ~
String "0xf1" --> Number 241 ~
String "0100" --> Number 64 ~
String "0o100" --> Number 64 ~
String "0b101" --> Number 5 ~
String "-8" --> Number -8 ~
String "+8" --> Number 0 ~
To force conversion from String to Number, add zero to it: >
:echo "0100" + 0
< 64 ~
To avoid a leading zero to cause octal conversion, or for using a different
base, use |str2nr()|.
*TRUE* *FALSE* *Boolean*
For boolean operators Numbers are used. Zero is FALSE, non-zero is TRUE.
You can also use |v:false| and |v:true|, in Vim9 script |false| and |true|.
When TRUE is returned from a function it is the Number one, FALSE is the
number zero.
Note that in the command: >
:if "foo"
:" NOT executed
"foo" is converted to 0, which means FALSE. If the string starts with a
non-zero number it means TRUE: >
:if "8foo"
:" executed
To test for a non-empty string, use empty(): >
:if !empty("foo")
< *falsy* *truthy*
An expression can be used as a condition, ignoring the type and only using
whether the value is "sort of true" or "sort of false". Falsy is:
the number zero
empty string, blob, list or dictionary
Other values are truthy. Examples:
0 falsy
1 truthy
-1 truthy
0.0 falsy
0.1 truthy
'' falsy
'x' truthy
[] falsy
[0] truthy
{} falsy
#{x: 1} truthy
0z falsy
0z00 truthy
*non-zero-arg*
Function arguments often behave slightly different from |TRUE|: If the
argument is present and it evaluates to a non-zero Number, |v:true| or a
non-empty String, then the value is considered to be TRUE.
Note that " " and "0" are also non-empty strings, thus considered to be TRUE.
A List, Dictionary or Float is not a Number or String, thus evaluate to FALSE.
*E611* *E745* *E728* *E703* *E729* *E730* *E731* *E908* *E910*
*E913* *E974* *E975* *E976* *E1319* *E1320* *E1321* *E1322*
*E1323* *E1324*
|List|, |Dictionary|, |Funcref|, |Job|, |Channel|, |Blob|, |Class| and
|object| types are not automatically converted.
*E805* *E806* *E808*
When mixing Number and Float the Number is converted to Float. Otherwise
there is no automatic conversion of Float. You can use str2float() for String
to Float, printf() for Float to String and float2nr() for Float to Number.
*E362* *E891* *E892* *E893* *E894* *E907* *E911* *E914*
When expecting a Float a Number can also be used, but nothing else.
*no-type-checking*
You will not get an error if you try to change the type of a variable.
1.2 Function references ~
*Funcref* *E695* *E718* *E1192*
A Funcref variable is obtained with the |function()| function, the |funcref()|
function, (in |Vim9| script) the name of a function, or created with the
lambda expression |expr-lambda|. It can be used in an expression in the place
of a function name, before the parenthesis around the arguments, to invoke the
function it refers to. Example in |Vim9| script: >
:var Fn = MyFunc
:echo Fn()
Legacy script: >
:let Fn = function("MyFunc")
:echo Fn()
< *E704* *E705* *E707*
A Funcref variable must start with a capital, "s:", "w:", "t:" or "b:". You
can use "g:" but the following name must still start with a capital. You
cannot have both a Funcref variable and a function with the same name.
A special case is defining a function and directly assigning its Funcref to a
Dictionary entry. Example: >
:function dict.init() dict
: let self.val = 0
:endfunction
The key of the Dictionary can start with a lower case letter. The actual
function name is not used here. Also see |numbered-function|.
A Funcref can also be used with the |:call| command: >
:call Fn()
:call dict.init()
The name of the referenced function can be obtained with |string()|. >
:let func = string(Fn)
You can use |call()| to invoke a Funcref and use a list variable for the
arguments: >
:let r = call(Fn, mylist)
<
*Partial*
A Funcref optionally binds a Dictionary and/or arguments. This is also called
a Partial. This is created by passing the Dictionary and/or arguments to
function() or funcref(). When calling the function the Dictionary and/or
arguments will be passed to the function. Example: >
let Cb = function('Callback', ['foo'], myDict)
call Cb('bar')
This will invoke the function as if using: >
call myDict.Callback('foo', 'bar')
This is very useful when passing a function around, e.g. in the arguments of
|ch_open()|.
Note that binding a function to a Dictionary also happens when the function is
a member of the Dictionary: >
let myDict.myFunction = MyFunction
call myDict.myFunction()
Here MyFunction() will get myDict passed as "self". This happens when the
"myFunction" member is accessed. When making assigning "myFunction" to
otherDict and calling it, it will be bound to otherDict: >
let otherDict.myFunction = myDict.myFunction
call otherDict.myFunction()
Now "self" will be "otherDict". But when the dictionary was bound explicitly
this won't happen: >
let myDict.myFunction = function(MyFunction, myDict)
let otherDict.myFunction = myDict.myFunction
call otherDict.myFunction()
Here "self" will be "myDict", because it was bound explicitly.
1.3 Lists ~
*list* *List* *Lists* *E686*
A List is an ordered sequence of items. An item can be of any type. Items
can be accessed by their index number. Items can be added and removed at any
position in the sequence.
List creation ~
*E696* *E697*
A List is created with a comma-separated list of items in square brackets.
Examples: >
:let mylist = [1, two, 3, "four"]
:let emptylist = []
An item can be any expression. Using a List for an item creates a
List of Lists: >
:let nestlist = [[11, 12], [21, 22], [31, 32]]
An extra comma after the last item is ignored.
List index ~
*list-index* *E684*
An item in the List can be accessed by putting the index in square brackets
after the List. Indexes are zero-based, thus the first item has index zero. >
:let item = mylist[0] " get the first item: 1
:let item = mylist[2] " get the third item: 3
When the resulting item is a list this can be repeated: >
:let item = nestlist[0][1] " get the first list, second item: 12
<
A negative index is counted from the end. Index -1 refers to the last item in
the List, -2 to the last but one item, etc. >
:let last = mylist[-1] " get the last item: "four"
To avoid an error for an invalid index use the |get()| function. When an item
is not available it returns zero or the default value you specify: >
:echo get(mylist, idx)
:echo get(mylist, idx, "NONE")
List concatenation ~
*list-concatenation*
Two lists can be concatenated with the "+" operator: >
:let longlist = mylist + [5, 6]
:let longlist = [5, 6] + mylist
To prepend or append an item, turn it into a list by putting [] around it.
A list can be concatenated with another one in-place using |:let+=| or
|extend()|: >
:let mylist += [7, 8]
:call extend(mylist, [7, 8])
<
See |list-modification| below for more about changing a list in-place.
Sublist ~
*sublist*
A part of the List can be obtained by specifying the first and last index,
separated by a colon in square brackets: >
:let shortlist = mylist[2:-1] " get List [3, "four"]
Omitting the first index is similar to zero. Omitting the last index is
similar to -1. >
:let endlist = mylist[2:] " from item 2 to the end: [3, "four"]
:let shortlist = mylist[2:2] " List with one item: [3]
:let otherlist = mylist[:] " make a copy of the List
Notice that the last index is inclusive. If you prefer using an exclusive
index use the |slice()| method.
If the first index is beyond the last item of the List or the second item is
before the first item, the result is an empty list. There is no error
message.
If the second index is equal to or greater than the length of the list the
length minus one is used: >
:let mylist = [0, 1, 2, 3]
:echo mylist[2:8] " result: [2, 3]
NOTE: mylist[s:e] means using the variable "s:e" as index. Watch out for
using a single letter variable before the ":". Insert a space when needed:
mylist[s : e].
List identity ~
*list-identity*
When variable "aa" is a list and you assign it to another variable "bb", both
variables refer to the same list. Thus changing the list "aa" will also
change "bb": >
:let aa = [1, 2, 3]
:let bb = aa
:call add(aa, 4)
:echo bb
< [1, 2, 3, 4]
Making a copy of a list is done with the |copy()| function. Using [:] also
works, as explained above. This creates a shallow copy of the list: Changing
a list item in the list will also change the item in the copied list: >
:let aa = [[1, 'a'], 2, 3]
:let bb = copy(aa)
:call add(aa, 4)
:let aa[0][1] = 'aaa'
:echo aa
< [[1, aaa], 2, 3, 4] >
:echo bb
< [[1, aaa], 2, 3]
To make a completely independent list use |deepcopy()|. This also makes a
copy of the values in the list, recursively. Up to a hundred levels deep.
The operator "is" can be used to check if two variables refer to the same
List. "isnot" does the opposite. In contrast "==" compares if two lists have
the same value. >
:let alist = [1, 2, 3]
:let blist = [1, 2, 3]
:echo alist is blist
< 0 >
:echo alist == blist
< 1
Note about comparing lists: Two lists are considered equal if they have the
same length and all items compare equal, as with using "==". There is one
exception: When comparing a number with a string they are considered
different. There is no automatic type conversion, as with using "==" on
variables. Example: >
echo 4 == "4"
< 1 >
echo [4] == ["4"]
< 0
Thus comparing Lists is more strict than comparing numbers and strings. You
can compare simple values this way too by putting them in a list: >
:let a = 5
:let b = "5"
:echo a == b
< 1 >
:echo [a] == [b]
< 0
List unpack ~
To unpack the items in a list to individual variables, put the variables in
square brackets, like list items: >
:let [var1, var2] = mylist
When the number of variables does not match the number of items in the list
this produces an error. To handle any extra items from the list append ";"
and a variable name: >
:let [var1, var2; rest] = mylist
This works like: >
:let var1 = mylist[0]
:let var2 = mylist[1]
:let rest = mylist[2:]
Except that there is no error if there are only two items. "rest" will be an
empty list then.
List modification ~
*list-modification*
To change a specific item of a list use |:let| this way: >
:let list[4] = "four"
:let listlist[0][3] = item
To change part of a list you can specify the first and last item to be
modified. The value must at least have the number of items in the range: >
:let list[3:5] = [3, 4, 5]
To add items to a List in-place, you can use |:let+=| (|list-concatenation|): >
:let listA = [1, 2]
:let listA += [3, 4]
<
When two variables refer to the same List, changing one List in-place will
cause the referenced List to be changed in-place: >
:let listA = [1, 2]
:let listB = listA
:let listB += [3, 4]
:echo listA
[1, 2, 3, 4]
<
Adding and removing items from a list is done with functions. Here are a few
examples: >
:call insert(list, 'a') " prepend item 'a'
:call insert(list, 'a', 3) " insert item 'a' before list[3]
:call add(list, "new") " append String item
:call add(list, [1, 2]) " append a List as one new item
:call extend(list, [1, 2]) " extend the list with two more items
:let i = remove(list, 3) " remove item 3
:unlet list[3] " idem
:let l = remove(list, 3, -1) " remove items 3 to last item
:unlet list[3 : ] " idem
:call filter(list, 'v:val !~ "x"') " remove items with an 'x'
Changing the order of items in a list: >
:call sort(list) " sort a list alphabetically
:call reverse(list) " reverse the order of items
:call uniq(sort(list)) " sort and remove duplicates
For loop ~
The |:for| loop executes commands for each item in a List, String or Blob.
A variable is set to each item in sequence. Example with a List: >
:for item in mylist
: call Doit(item)
:endfor
This works like: >
:let index = 0
:while index < len(mylist)
: let item = mylist[index]
: :call Doit(item)
: let index = index + 1
:endwhile
If all you want to do is modify each item in the list then the |map()|
function will be a simpler method than a for loop.
Just like the |:let| command, |:for| also accepts a list of variables. This
requires the argument to be a List of Lists. >
:for [lnum, col] in [[1, 3], [2, 8], [3, 0]]
: call Doit(lnum, col)
:endfor
This works like a |:let| command is done for each list item. Again, the types
must remain the same to avoid an error.
It is also possible to put remaining items in a List variable: >
:for [i, j; rest] in listlist
: call Doit(i, j)
: if !empty(rest)
: echo "remainder: " .. string(rest)
: endif
:endfor
For a Blob one byte at a time is used.
For a String one character, including any composing characters, is used as a
String. Example: >
for c in text
echo 'This character is ' .. c
endfor
List functions ~
*E714*
Functions that are useful with a List: >
:let r = call(funcname, list) " call a function with an argument list
:if empty(list) " check if list is empty
:let l = len(list) " number of items in list
:let big = max(list) " maximum value in list
:let small = min(list) " minimum value in list
:let xs = count(list, 'x') " count nr of times 'x' appears in list
:let i = index(list, 'x') " index of first 'x' in list
:let lines = getline(1, 10) " get ten text lines from buffer
:call append('