UNPKG

tea-test-dao

Version:
1,474 lines (1,150 loc) 173 kB
*eval.txt* For Vim version 9.1. Last change: 2023 Dec 09 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 mylist += [7, 8] To prepend or append an item, turn the item into a list by putting [] around it. To change a list in-place, refer to |list-modification| below. 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] 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('$', lines) " append text lines in buffer :let list = split("a b c") " create list from items in a string :let string = join(list, ', ') " create string from list items :let s = string(list) " String representation of list :call map(list, '">> " .. v:val') " prepend ">> " to each item Don't forget that a combination of features can make things simple. For example, to add up all the numbers in a list: > :exe 'let sum = ' .. join(nrlist, '+') 1.4 Dictionaries ~ *dict* *Dict* *Dictionaries* *Dictionary* A Dictionary is an associative array: Each entry has a key and a value. The entry can be located with the key. The entries are stored without a specific ordering. Dictionary creation ~ *E720* *E721* *E722* *E723* A Dictionary is created with a comma-separated list of entries in curly braces. Each entry has a key and a value, separated by a colon. Each key can only appear once. Examples: > :let mydict = {1: 'one', 2: 'two', 3: 'three'} :let emptydict = {} < *E713* *E716* *E717* A key is always a String. You can use a Number, it will be converted to a 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 Number will be converted to the String '4', leading zeros are dropped. The empty string can also be used as a key. In |Vim9| script a literal key can be used if it consists only of alphanumeric characters, underscore and dash, see |vim9-literal-dict|. *literal-Dict* *#{}* To avoid having to put quotes around every key the #{} form can be used in legacy script. This does require the key to consist only of ASCII letters, digits, '-' and '_'. Example: > :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 #{}. In |Vim9| script the #{} form cannot be used because it can be confused with the start of a comment. A value can be any expression. Using a Dictionary for a value creates a nested Dictionary: > :let nestdict = {1: {11: 'a', 12: 'b'}, 2: {21: 'c'}} An extra comma after the last entry is ignored. Accessing entries ~ The normal way to access an entry is by putting the key in square brackets: > :let val = mydict["one"] :let mydict["four"] = 4 You can add new entries to an existing Dictionary this way, unlike Lists. For keys that consist entirely of letters, digits and underscore the following form can be used |expr-entry|: > :let val = mydict.one :let mydict.four = 4 Since an entry can be any type, also a List and a Dictionary, the indexing and key lookup can be repeated: > :echo dict.key[idx].key Dictionary to List conversion ~ You may want to loop over the entries in a dictionary. For this you need to turn the Dictionary into a List and pass it to |:for|. Most often you want to loop over the keys, using the |keys()| function: > :for key in keys(mydict) : echo key .. ': ' .. mydict[key] :endfor The List of keys is unsorted. You may want to sort them first: > :for key in sort(keys(mydict)) To loop over the values use the |values()| function: > :for v in values(mydict) : echo "value: " .. v :endfor If you want both the key and the value use the |items()| function. It returns a List in which each item is a List with two items, the key and the value: > :for [key, value] in items(mydict) : echo key .. ': ' .. value :endfor Dictionary identity ~ *dict-identity* Just like Lists you need to use |copy()| and |deepcopy()| to make a copy of a Dictionary. Otherwise, assignment results in referring to the same Dictionary: > :let onedict = {'a': 1, 'b': 2} :let adict = onedict :let adict['a'] = 11 :echo onedict['a'] 11 Two Dictionaries compare equal if all the key-value pairs compare equal. For more info see |list-identity|. Dictionary modification ~ *dict-modification* To change an already existing entry of a Dictionary, or to add a new entry, use |:let| this way: > :let dict[4] = "four" :let dict['one'] = item Removing an entry from a Dictionary is done with |remove()| or |:unlet|. Three ways to remove the entry with key "aaa" from dict: > :let i = remove(dict, 'aaa') :unlet dict.aaa :unlet dict['aaa'] Merging a Dictionary with another is done with |extend()|: > :call extend(adict, bdict) This extends adict with all entries from bdict. Duplicate keys cause entries in adict to be overwritten. An optional third argument can change this. Note that the order of entries in a Dictionary is irrelevant, thus don't expect ":echo adict" to show the items from bdict after the older entries in adict. Weeding out entries from a Dictionary can be done with |filter()|: > :call filter(dict, 'v:val =~ "x"') This removes all entries from "dict" with a value not matching 'x'. This can also be used to remove all entries: > call filter(dict, 0) In some situations it is not allowed to remove or add entries to a Dictionary. Especially when iterating over all the entries. You will get *E1313* or another error in that case. Dictionary function ~ *Dictionary-function* *self* *E725* *E862* When a function is defined with the "dict" attribute it can be used in a special way with a dictionary. Example: > :function Mylen() dict : return len(self.data) :endfunction :let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")} :echo mydict.len() This is like a method in object oriented programming. The entry in the Dictionary is a |Funcref|. The local variable "self" refers to the dictionary the function was invoked from. When using |Vim9| script you can use classes and objects, see `:class`. It is also possible to add a function without the "dict" attribute as a Funcref to a Dictionary, but the "self" variable is not available then. *numbered-function* *anonymous-function* To avoid the extra name for the function it can be defined and directly assigned to a Dictionary in this way: > :let mydict = {'data': [0, 1, 2, 3]} :function mydict.len() : return len(self.data) :endfunction :echo mydict.len() The function will then get a number and the value of dict.len is a |Funcref| that references this function. The function can only be used through a |Funcref|. It will automatically be deleted when there is no |Funcref| remaining that refers to it. It is not necessary to use the "dict" attribute for a numbered function. If you get an error for a numbered function, you can find out what it is with a trick. Assuming the function is 42, the command is: > :function g:42 Functions for Dictionaries ~ *E715* Functions that can be used with a Dictionary: > :if has_key(dict, 'foo') " TRUE if dict has entry with key "foo" :if empty(dict) " TRUE if dict is empty :let l = len(dict) " number of items in dict :let big = max(dict) " maximum value in dict :let small = min(dict) " minimum value in dict :let xs = count(dict, 'x') " count nr of times 'x' appears in dict :let s = string(dict) " String representation of dict :call map(dict, '">> " .. v:val') " prepend ">> " to each item 1.5 Blobs ~ *blob* *Blob* *Blobs* *E978* A Blob is a binary object. It can be used to read an image from a file and send it over a channel, for example. A Blob mostly behaves like a |List| of numbers, where each number has the value of an 8-bit byte, from 0 to 255. Blob creation ~ A Blob can be created with a |blob-literal|: > :let b = 0zFF00ED015DAF Dots can be inserted between bytes (pair of hex characters) for readability, they don't change the value: > :let b = 0zFF00.ED01.5DAF A blob can be read from a file with |readfile()| passing the {type} argument set to "B", for example: > :let b = readfile('image.png', 'B') A blob can be read from a channel with the |ch_readblob()| function. Blob index ~ *blob-index* *E979* A byte in the Blob can be accessed by putting the index in square brackets after the Blob. Indexes are zero-based, thus the first byte has index zero. > :let myblob = 0z00112233 :let byte = myblob[0] " get the first byte: 0x00 :let byte = myblob[2] " get the third byte: 0x22 A negative index is counted from the end. Index -1 refers to the last byte in the Blob, -2 to the last but one byte, etc. > :let last = myblob[-1] " get the last byte: 0x33 To avoid an error for an invalid index use the |get()| function. When an item is not available it returns -1 or the default value you specify: > :echo get(myblob, idx) :echo get(myblob, idx, 999) Blob iteration ~ The |:for| loop executes commands for each byte of a Blob. The loop variable is set to each byte in the Blob. Example: > :for byte in 0z112233 : call Doit(byte) :endfor This calls Doit() with 0x11, 0x22 and 0x33. Blob concatenation ~ Two blobs can be concatenated with the "+" operator: > :let longblob = myblob + 0z4455 :let myblob += 0z6677 To change a blob in-place see |blob-modification| below. Part of a blob ~ A part of the Blob can be obtained by specifying the first and last index, separated by a colon in square brackets: > :let myblob = 0z00112233 :let shortblob = myblob[1:2] " get 0z1122 :let shortblob = myblob[2:-1] " get 0z2233 Omitting the first index is similar to zero. Omitting the last index is similar to -1. > :let endblob = myblob[2:] " from item 2 to the end: 0z2233 :let shortblob = myblob[2:2] " Blob with one byte: 0z22 :let otherblob = myblob[:] " make a copy of the Blob If the first index is beyond the last byte of the Blob or the second index is before the first index, the result is an empty Blob. 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: > :echo myblob[2:8] " result: 0z2233 Blob modification ~ *blob-modification* *E1182* *E1184* To change a specific byte of a blob use |:let| this way: > :let blob[4] = 0x44 When the index is just one beyond the end of the Blob, it is appended. Any higher index is an error. To change a sequence of bytes the [:] notation can be used: > let blob[1:3] = 0z445566 The length of the replaced bytes must be exactly the same as the value provided. *E972* To change part of a blob you can specify the first and last byte to be modified. The value must have the same number of bytes in the range: > :let blob[3:5] = 0z334455 You can also use the functions |add()|, |remove()| and |insert()|. Blob identity ~ Blobs can be compared for equality: > if blob == 0z001122 And for equal identity: > if blob is otherblob < *blob-identity* *E977* When variable "aa" is a Blob and you assign it to another variable "bb", both variables refer to the same Blob. Then the "is" operator returns true. When making a copy using [:] or |copy()| the values are the same, but the identity is different: > :let blob = 0z112233 :let blob2 = blob :echo blob == blob2 < 1 > :echo blob is blob2 < 1 > :let blob3 = blob[:] :echo blob == blob3 < 1 > :echo blob is blob3 < 0 Making a copy of a Blob is done with the |copy()| function. Using [:] also works, as explained above. 1.6 More about variables ~ *more-variables* If you need to know the type of a variable or expression, use the |type()| function. When the '!' flag is included in the 'viminfo' option, global variables that start with an uppercase letter, and don't contain a lowercase letter, are stored in the viminfo file |viminfo-file|. When the 'sessionoptions' option contains "global", global variables that start with an uppercase letter and contain at least one lowercase letter are stored in the session file |session-file|. variable name can be stored where ~ my_var_6 not My_Var_6 session file MY_VAR_6 viminfo file In legacy script it is possible to form a variable name with curly braces, see |curly-braces-names|. ============================================================================== 2. Expression syntax *expression-syntax* *E1143* Expression syntax summary, from least to most significant: |expr1| expr2 expr2 ? expr1 : expr1 if-then-else |expr2| expr3 expr3 || expr3 ... logical OR |expr3| expr4 expr4 && expr4 ... logical AND |expr4| expr5 expr5 == expr5 equal expr5 != expr5 not equal expr5 > expr5 greater than expr5 >= expr5 greater than or equal expr5 < expr5 smaller than expr5 <= expr5 smaller than or equal expr5 =~ expr5 regexp matches expr5 !~ expr5 regexp doesn't match expr5 ==? expr5 equal, ignoring case expr5 ==# expr5 equal, match case etc. As above, append ? for ignoring case, # for matching case expr5 is expr5 same |List|, |Dictionary| or |Blob| instance expr5 isnot expr5 different |List|, |Dictionary| or |Blob| instance |expr5| expr6 expr6 << expr6 bitwise left shift expr6 >> expr6 bitwise right shift |expr6| expr7 expr7 + expr7 ... number addition, list or blob concatenation expr7 - expr7 ... number subtraction expr7 . expr7 ... string concatenation expr7 .. expr7 ... string concatenation |expr7| expr8 expr8 * expr8 ... number multiplication expr8 / expr8 ... number division expr8 % expr8 ... number modulo |expr8| expr9 <type>expr9 type check and conversion (|Vim9| only) |expr9| expr10 ! expr9 logical NOT - expr9 unary minus + expr9 unary plus |expr10| expr11 expr10[expr1] byte of a String or item of a |List| expr10[expr1 : expr1] substring of a String or sublist of a |List| expr10.name entry in a |Dictionary| expr10(expr1, ...) function call with |Funcref| variable expr10->name(expr1, ...) |method| call |expr11| number number constant "string" string constant, backslash is special 'string' string constant, ' is doubled [expr1, ...] |List| {expr1: expr1, ...} |Dictionary| #{key: expr1, ...} legacy |Dictionary| &option option value (expr1) nested expression variable internal variable va{ria}ble internal variable with curly braces $VAR environment variable @r contents of register 'r' function(expr1, ...) function call func{ti}on(expr1, ...) function call with curly braces {args -> expr1} legacy lambda expression (args) => expr1 Vim9 lambda expression "..." indicates that the operations in this level can be concatenated. Example: > &nu || &list && &shell == "csh" All expressions within one level are parsed from left to right. Expression nesting is limited to 1000 levels deep (300 when build with MSVC) to avoid running out of stack and crashing. *E1169* expr1 *expr1* *ternary* *falsy-operator* *??* *E109* ----- The ternary operator: expr2 ? expr1 : expr1 The falsy operator: expr2 ?? expr1 Ternary operator ~ In legacy script the expression before the '?' is evaluated to a number. If it evaluates to |TRUE|, the result is the value of the expression between 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: > :echo lnum == 1 ? "top" : lnum Since the first expression is an "expr2", it cannot contain another ?:. The other two expressions can, thus allow for recursive use of ?:. Example: > :echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum To keep this readable, using |line-continuation| is suggested: > :echo lnum == 1 :\ ? "top" :\ : lnum == 1000 :\ ? "last" :\ : lnum You should always put a space before the ':', otherwise it can be mistaken for use in a variable such as "a:1". Falsy operator ~ This is also known as the "null coalescing operator", but that's too complicated, thus we just call it the falsy operator. The expression before the '??' is evaluated. If it evaluates to |truthy|, this is used as the result. Otherwise the expression after the '??' is evaluated and used as the result. This is most useful to have a default value for an expression that may result in zero or empty: > echo theList ?? 'list is empty' echo GetName() ?? 'unknown' These are similar, but not equal: > expr2 ?? expr1 expr2 ? expr2 : expr1 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* --------------- expr3 || expr3 .. logical OR *expr-barbar* expr4 && expr4 .. logical AND *expr-&&* The "||" and "&&" operators take one argument on each side. 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 ~ n1 n2 n1 || n2 n1 && n2 ~ |FALSE| |FALSE| |FALSE| |FALSE| |FALSE| |TRUE| |TRUE| |FALSE| |TRUE| |FALSE| |TRUE| |FALSE| |TRUE| |TRUE| |TRUE| |TRUE| The operators can be concatenated, for example: > &nu || &list && &shell == "csh" Note that "&&" takes precedence over "||", so this has the meaning of: > &nu || (&list && &shell == "csh") Once the result is known, the expression "short-circuits", that is, further arguments are not evaluated. This is like what happens in C. For example: > let a = 1 echo a || b This is valid even if there is no variable called "b" because "a" is |TRUE|, so the result must be |TRUE|. Similarly below: > echo exists("b") && b == "yes" This is valid whether "b" has been defined or not. The second clause will only be evaluated if "b" has been defined. expr4 *expr4* *E1153* ----- expr5 {cmp} expr5 Compare two expr5 expressions. In legacy script the result is a 0 if it 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-!~#* *expr-==?* *expr-!=?* *expr->?* *expr->=?* *expr-<?* *expr-<=?* *expr-=~?* *expr-!~?* *expr-is* *expr-isnot* *expr-is#* *expr-isnot#* *expr-is?* *expr-isnot?* *E1072* use 'ignorecase' match case ignore case ~ equal == ==# ==? not equal != !=# !=? greater than > ># >? greater than or equal >= >=# >=? smaller than < <# <? smaller than or equal <= <=# <=? regexp matches =~ =~# =~? regexp doesn't match !~ !~# !~? same instance is is# is? different instance isnot isnot# isnot? Examples: "abc" ==# "Abc" evaluates to 0 "abc" ==? "Abc" evaluates to 1 "abc" == "Abc" evaluates to 1 if 'ignorecase' is set, 0 otherwise NOTE: In |Vim9| script 'ignorecase' is not used. *E691* *E692* A |List| can only be compared with a |List| and only "equal", "not equal", "is" and "isnot" can be used. This compares the values of the list, recursively. Ignoring case means case is ignored when comparing item values. *E735* *E736* A |Dictionary| can only be compared with a |Dictionary| and only "equal", "not equal", "is" and "isnot" can be used. This compares the key/values of the |Dictionary| recursively. Ignoring case means case is ignored when comparing item values. *E694* A |Funcref| can only be compared with a |Funcref| and only "equal", "not equal", "is" and "isnot" can be used. Case is never ignored. Whether arguments or a Dictionary are bound (with a partial) matters. The Dictionaries must also be equal (or the same, in case of "is") and the arguments must be equal (or the same). To compare Funcrefs to see if they refer to the same function, ignoring bound Dictionary and arguments, use |get()| to get the function name: > if get(Part1, 'name') == get(Part2, 'name') " Part1 and Part2 refer to the same function < *E1037* Using "is" or "isnot" with a |List|, |Dictionary| or |Blob| checks whether the expressions are referring to the same |List|, |Dictionary| or |Blob| instance. A copy of a |List| is different from the original |List|. When using "is" without a |List|, |Dictionary| or |Blob|, it is equivalent to using "equal", using "isnot" equivalent to using "not equal". Except that a different type means the values are different: > echo 4 == '4' 1 echo 4 is '4' 0 echo 0 is [] 0 "is#"/"isnot#" and "is?"/"isnot?" can be used to match and ignore case. In |Vim9| script this doesn't work, two strings are never identical. In legacy script, when comparing a String with a Number, the String is converted to a Number, and the comparison is done on Numbers. This means that: > echo 0 == 'x' 1 because 'x' converted to a Number is zero. However: > echo [0] == ['x'] 0 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 results in the mathematical difference (comparing byte values), not necessarily the alphabetical difference in the local language. When using the operators with a trailing '#', or the short version and 'ignorecase' is off, the comparing is done with strcmp(): case matters. When using the operators with a trailing '?', or the short version and 'ignorecase' is set, the comparing is done with stricmp(): case is ignored. 'smartcase' is not used. The "=~" and "!~" operators match the lefthand argument with the righthand argument, which is used as a pattern. See |pattern| for what a pattern is. This matching is always done like 'magic' was set and 'cpoptions' is empty, no matter what the actual value of 'magic' or 'cpoptions' is. This makes scripts portable. To avoid backslashes in the regexp pattern to be doubled, use a single-quote string, see |literal-string|. Since a string is considered to be a single line, a multi-line pattern (containing \n, backslash-n) will not match. However, a literal NL character can be matched like an ordinary character. Examples: "foo\nbar" =~ "\n" evaluates to 1 "foo\nbar" =~ "\\n" evaluates to 0 expr5 *expr5* *bitwise-shift* ----- expr6 << expr6 bitwise left shift *expr-<<* expr6 >> expr6 bitwise right shift *expr->>* *E1282* *E1283* The "<<" and ">>" operators can be used to perform bitwise left or right shift of the left operand by the number of bits specified by the right operand. The operands are used as positive numbers. When shifting right with ">>" the topmost bit (sometimes called the sign bit) is cleared. If the right operand (shift amount) is more than the maximum number of bits in a number (|v:numbersize|) the result is zero. expr6 and expr7 *expr6* *expr7* *E1036* *E1051* --------------- expr7 + expr7 Number addition, |List| or |Blob| concatenation *expr-+* expr7 - expr7 Number subtraction *expr--* expr7 . expr7 String concatenation *expr-.* expr7 .. expr7 String concatenation *expr-..* For |Lists| only "+" is possible and then both expr7 must be a list. The result is a new list with the two lists Concatenated. For String concatenation ".." is preferred, since "." is ambiguous, it is also used for |Dict| member access and floating point numbers. 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. expr8 * expr8 Number multiplication *expr-star* expr8 / expr8 Number division *expr-/* expr8 % expr8 Number modulo *expr-%* In legacy script, for all operators except "." and "..", Strings are converted to Numbers. For bitwise operators see |and()|, |or()| and |xor()|. Note the difference between "+" and ".." in legacy script: "123" + "456" = 579 "123" .. "456" = "123456" Since '..' has the same precedence as '+' and '-', you need to read: > 1 .. 90 + 90.0 As: > (1 .. 90) + 90.0 That works in legacy script, since the String "190" is automatically converted to the Number 190, which can be added to the Float 90.0. However: > 1 .. 90 * 90.0 Should be read as: > 1 .. (90 * 90.0) Since '..' has lower precedence than '*'. This does NOT work, since this attempts to concatenate a Float and a String. When dividing a Number by zero the result depends on the value: 0 / 0 = -0x80000000 (like NaN for Float) >0 / 0 = 0x7fffffff (like positive infinity) <0 / 0 = -0x7fffffff (like negative infinity) (before Vim 7.2 it was always 0x7fffffff) In |Vim9| script dividing a number by zero is an error. *E1154* When 64-bit Number support is enabled: 0 / 0 = -0x8000000000000000 (like NaN for Float) >0 / 0 = 0x7fffffffffffffff (like positive infinity) <0 / 0 = -0x7fffffffffffffff (like negative infinity) When the righthand side of '%' is zero, the result is 0. None of these work for |Funcref|s. ".", ".." and "%" do not work for Float. *E804* *E1035* expr8 *expr8* ----- <type>expr9 This is only available in |Vim9| script, see |type-casting|. expr9 *expr9* ----- ! expr9 logical NOT *expr-!* - expr9 unary minus *expr-unary--* + expr9 unary plus *expr-unary-+* For '!' |TRUE| becomes |FALSE|, |FALSE| becomes |TRUE| (one). For '-' the sign of the number is changed. For '+' the number is unchanged. Note: "++" has no effect. 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: !-1 == 0 !!8 == 1 --9 == 9 expr10 *expr10* ------ This expression is either |expr11| or a sequence of the alternatives below, in any order. E.g., these are all possible: expr10[expr1].name expr10.name[expr1] expr10(expr1, ...)[expr1].name expr10->(expr1, ...)[expr1] Evaluation is always from left to right. expr10[expr1] item of String or |List| *expr-[]* *E111* *E909* *subscript* *E1062* In legacy Vim script: If expr10 is a Number or String this results in a String that contains the expr1'th single byte from expr10. expr10 is used as a String (a number is automatically converted to a String), expr1 as a Number. This doesn't recognize multibyte encodings, see `byteidx()` for an alternative, or use `split()` to turn the string into a list of characters. Example, to get the byte under the cursor: > :let c = getline(".")[col(".") - 1] In |Vim9| script: *E1147* *E1148* If expr10 is a String this results in a String that contains the expr1'th single character (including any composing characters) from expr10. To use byte indexes use |strpart()|. Index zero gives the first byte or character. Careful: text column numbers start with one! If the length of the String is less than the index, the result is an empty String. A negative index always results in an empty string (reason: backward 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. If expr10 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 error. Example: > :let item = mylist[-1] " get last item Generally, if a |List| index is equal to or higher than the length of the |List|, or more negative than the length of the |List|, this results in an error. expr10[expr1a : expr1b] substring or |sublist| *expr-[:]* *substring* If expr10 is a String this results in the substring with the bytes or characters from expr1a to and including expr1b. expr10 is used as a String, expr1a and expr1b are used as a Number. In legacy Vim script the indexes are byte indexes. This doesn't recognize multibyte encodings, see |byteidx()| for computing the indexes. If expr10 is a Number it is first converted to a String. In Vim9 script the indexes are character indexes and include composing characters. To use byte indexes use |strpart()|. To use character indexes without including composing characters use |strcharpart()|. The item at index expr1b is included, it is inclusive. For an exclusive index use the |slice()| function. If expr1a is omitted zero is used. If expr1b is omitted the length of the string minus one is used. A negative number can be used to measure from the end of the string. -1 is the last character, -2 the last but one, etc. If an index goes out of range for the string characters are omitted. If expr1b is smaller than expr1a the result is an empty string. Examples: > :let c = name[-1:] " last byte of a string :let c = name[0:-1] " the whole string :let c = name[-2:-2] " last but one byte of a string :let s = line(".")[4:] " from the fifth byte to the end :let s = s[:-3] " remove last two bytes < *slice* If expr10 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 just above. Also see |sublist| below. Examples: > :let l = mylist[:3] " first four items :let l = mylist[4:4] " List with one item :let l = mylist[:] " shallow copy of a List If expr10 is a |Blob| this results in a new |Blob| with the bytes in the indexes expr1a and expr1b, inclusive. Examples: > :let b = 0zDEADBEEF :let bs = b[1:2] " 0zADBE :let bs = b[:] " copy of 0zDEADBEEF Using expr10[expr1] or expr10[expr1a : expr1b] on a |Funcref| results in an error. Watch out for confusion between a namespace and a variable followed by a colon for a sublist: > mylist[n:] " uses variable n mylist[s:] " uses namespace s:, error! expr10.name entry in a |Dictionary| *expr-entry* *E1203* *E1229* If expr10 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: expr10[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. There must not be white space before or after the dot. Examples: > :let dict = {"one": 1, 2: "two"} :echo dict.one " shows "1" :echo dict.2 " shows "two" :echo dict .2 " error because of space before the dot Note that the dot is also used for String concatenation. To avoid confusion always put spaces around the dot for String concatenation. expr10(expr1, ...) |Funcref| function call *E1085* When expr10 is a |Funcref| type variable, invoke the function it refers to. expr10->name([args]) method call *method* *->* expr10->{lambda}([args]) *E260* *E276* *E1265* For methods that are also available as global functions this is the same as: > name(expr10 [, args]) There can also be methods specifically for the type of "expr10". This allows for chaining, passing the value that one method returns to the next method: > mylist->filter(filterexpr)->map(mapexpr)->sort()->join() < Example of using a lambda: > GetPercentage()->{x -> x * 100}()->printf('%d%%') < When using -> the |expr9| operators will be applied first, thus: > -1.234->string() Is equivalent to: > (-1.234)->string() And NOT: > -(1.234->string()) What comes after "->" can be a name, a simple expression (not containing any parenthesis), or any expression in parentheses: > base->name(args) base->some.name(args) base->alist[idx](args) base->(getFuncRef())(args) Note that in the last call the base is passed to the function resulting from "(getFuncRef())", inserted before "args". *E1275* *E274* "->name(" must not contain white space. There can be white space before the "->" and after the "(", thus you can split the lines like this: > mylist \ ->filter(filterexpr) \ ->map(mapexpr) \ ->sort() \ ->join() When using the lambda form there must be no white space between the } and the (. *expr11* number ------ number number constant *expr-number* *0x* *hex-number* *0o* *octal-number* *binary-number* Decimal, Hexadecimal (starting with 0x or 0X), Binary (starting with 0b or 0B) and Octal (starting with 0, 0o or 0O). Assuming 64 bit numbers are used (see |v:numbersize|) an unsigned number is truncated to 0x7fffffffffffffff or 9223372036854775807. You can use -1 to get 0xffffffffffffffff. *floating-point-format* Floating point numbers can be written in two forms: [-+]{N}.{M} [-+]{N}.{M}[eE][-+]{exp} {N} and {M} are numbers. Both {N} and {M} must be present and can only contain digits, except that in |Vim9| script in {N} single quotes between digits are ignored. [-+] means there is an optional plus or minus sign. {exp} is the exponent, power of 10. Only a decimal point is accepted, not a comma. No matter what the current locale is. Examples: 123.456 +0.0001 55.0 -0.123 1.234e03 1.0E-6 -3.1416e+88 These are INVALID: 3. empty {M} 1e40 missing .{M} Rationale: Before floating point was introduced, the text "123.456" was interpreted as the two numbers "123" and "456", both converted to a string and concatenated, resulting in the string "123456". Since this was considered pointless, and we could not find it intentionally being used in Vim scripts, this backwards incompatibility was accepted in favor of being able to use the normal notation for floating point numbers. *float-pi* *float-e* A few useful va