mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	 d5308637bf
			
		
	
	d5308637bf
	
	
	
		
			
			Problem:  exception handling can be improved
Solution: add v:stacktrace and getstacktrace()
closes: vim/vim#16360
663d18d610
Co-authored-by: ichizok <gclient.gaap@gmail.com>
Co-authored-by: Naruhiko Nishino <naru123456789@gmail.com>
		
	
		
			
				
	
	
		
			3923 lines
		
	
	
		
			135 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			3923 lines
		
	
	
		
			135 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| *eval.txt*	Nvim
 | |
| 
 | |
| 
 | |
| 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
 | |
| 
 | |
| 
 | |
| Expression evaluation		*vimscript* *expression* *expr* *E15* *eval*
 | |
| 
 | |
| Using expressions is introduced in chapter 41 of the user manual |usr_41.txt|.
 | |
| 
 | |
| 				      Type |gO| to see the table of contents.
 | |
| 
 | |
| ==============================================================================
 | |
| 1. Variables						*variables*
 | |
| 
 | |
| 1.1 Variable types ~
 | |
| 						*E712* *E896* *E897* *E899*
 | |
| There are seven 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'
 | |
| 
 | |
| 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)
 | |
| 
 | |
| 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"}
 | |
| 
 | |
| 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 is done by converting the first digits to
 | |
| a number.  Hexadecimal "0xf9", Octal "017" or "0o17", and Binary "0b10"
 | |
| numbers are recognized.  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|.
 | |
| 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.
 | |
| 
 | |
| 				*E745* *E728* *E703* *E729* *E730* *E731*
 | |
| 				*E974* *E975* *E976*
 | |
| |List|, |Dictionary|, |Funcref|, and |Blob| 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*
 | |
| 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 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: >
 | |
| 
 | |
| 	: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')
 | |
| 
 | |
| 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 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('$', 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.
 | |
| 						*literal-Dict* *#{}*
 | |
| To avoid having to put quotes around every key the #{} form can be used.  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 #{}.
 | |
| 
 | |
| 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)
 | |
| 
 | |
| 
 | |
| 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.
 | |
| 
 | |
| 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')
 | |
| 
 | |
| 
 | |
| 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 ~
 | |
| 							*blob-concatenation*
 | |
| Two blobs can be concatenated with the "+" operator: >
 | |
| 	:let longblob = myblob + 0z4455
 | |
| 	:let longblob = 0z4455 + myblob
 | |
| <
 | |
| A blob can be concatenated with another one in-place using |:let+=|: >
 | |
| 	:let myblob += 0z6677
 | |
| <
 | |
| See |blob-modification| below for more about changing a blob in-place.
 | |
| 
 | |
| 
 | |
| 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 Blob the
 | |
| length minus one is used: >
 | |
| 	:echo myblob[2:8]		" result: 0z2233
 | |
| 
 | |
| 
 | |
| Blob modification ~
 | |
| 							*blob-modification*
 | |
| 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
 | |
| 
 | |
| To add items to a Blob in-place, you can use |:let+=| (|blob-concatenation|): >
 | |
| 	:let blobA = 0z1122
 | |
| 	:let blobA += 0z3344
 | |
| <
 | |
| When two variables refer to the same Blob, changing one Blob in-place will
 | |
| cause the referenced Blob to be changed in-place: >
 | |
| 	:let blobA = 0z1122
 | |
| 	:let blobB = blobA
 | |
| 	:let blobB += 0z3344
 | |
| 	:echo blobA
 | |
| 	0z11223344
 | |
| <
 | |
| 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 'shada' option, global variables that
 | |
| start with an uppercase letter, and don't contain a lowercase letter, are
 | |
| stored in the shada file |shada-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		shada file
 | |
| 
 | |
| 
 | |
| It's possible to form a variable name with curly braces, see
 | |
| |curly-braces-names|.
 | |
| 
 | |
| ==============================================================================
 | |
| 2. Expression syntax					*expression-syntax*
 | |
| 
 | |
| 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 ...	number addition, list or blob concatenation
 | |
| 	expr6 -	 expr6 ...	number subtraction
 | |
| 	expr6 .	 expr6 ...	string concatenation
 | |
| 	expr6 .. expr6 ...	string concatenation
 | |
| 
 | |
| |expr6|	expr7
 | |
| 	expr7 *	 expr7 ...	number multiplication
 | |
| 	expr7 /	 expr7 ...	number division
 | |
| 	expr7 %	 expr7 ...	number modulo
 | |
| 
 | |
| |expr7|	expr8
 | |
| 	! expr7			logical NOT
 | |
| 	- expr7			unary minus
 | |
| 	+ expr7			unary plus
 | |
| 
 | |
| |expr8|	expr9
 | |
| 	expr8[expr1]		byte of a String or item of a |List|
 | |
| 	expr8[expr1 : expr1]	substring of a String or sublist of a |List|
 | |
| 	expr8.name		entry in a |Dictionary|
 | |
| 	expr8(expr1, ...)	function call with |Funcref| variable
 | |
| 	expr8->name(expr1, ...)	|method| call
 | |
| 
 | |
| |expr9|	number			number constant
 | |
| 	"string"		string constant, backslash is special
 | |
| 	`'string'`		string constant, ' is doubled
 | |
| 	[expr1, ...]		|List|
 | |
| 	`{expr1: expr1, ...}`	|Dictionary|
 | |
| 	#{key: expr1, ...}	|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}`	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 ~
 | |
| 
 | |
| 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 ':'.
 | |
| 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.
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| 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.  The arguments
 | |
| are (converted to) Numbers.  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*
 | |
| 
 | |
| expr5 {cmp} expr5
 | |
| 
 | |
| Compare two expr5 expressions, resulting in a 0 if it evaluates to false, or 1
 | |
| if it evaluates to true.
 | |
| 
 | |
| 			*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?*
 | |
| 		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
 | |
| 
 | |
| 							*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
 | |
| 
 | |
| 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" is 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.
 | |
| 
 | |
| 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.
 | |
| 
 | |
| 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 and expr6						*expr5* *expr6*
 | |
| 
 | |
| expr6 + expr6   Number addition, |List| or |Blob| concatenation	*expr-+*
 | |
| expr6 - expr6   Number subtraction				*expr--*
 | |
| expr6 . expr6   String concatenation				*expr-.*
 | |
| expr6 .. expr6  String concatenation				*expr-..*
 | |
| 
 | |
| For |Lists| only "+" is possible and then both expr6 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.
 | |
| 
 | |
| expr7 * expr7  Number multiplication				*expr-star*
 | |
| expr7 / expr7  Number division					*expr-/*
 | |
| expr7 % expr7  Number modulo					*expr-%*
 | |
| 
 | |
| For all, except "." and "..", Strings are converted to Numbers.
 | |
| For bitwise operators see |and()|, |or()| and |xor()|.
 | |
| 
 | |
| Note the difference between "+" and ".":
 | |
| 	"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, 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)
 | |
| 
 | |
| 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*
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| expr7							*expr7*
 | |
| 
 | |
| ! expr7			logical NOT		*expr-!*
 | |
| - expr7			unary minus		*expr-unary--*
 | |
| + expr7			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.
 | |
| 
 | |
| A String will be converted to a Number first.
 | |
| 
 | |
| These three can be repeated and mixed.  Examples:
 | |
| 	!-1	    == 0
 | |
| 	!!8	    == 1
 | |
| 	--9	    == 9
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| expr8							*expr8*
 | |
| 
 | |
| This expression is either |expr9| or a sequence of the alternatives below,
 | |
| in any order.  E.g., these are all possible:
 | |
| 	expr8[expr1].name
 | |
| 	expr8.name[expr1]
 | |
| 	expr8(expr1, ...)[expr1].name
 | |
| 	expr8->(expr1, ...)[expr1]
 | |
| Evaluation is always from left to right.
 | |
| 
 | |
| 
 | |
| expr8[expr1]		item of String or |List|	*expr-[]* *E111*
 | |
| 							*subscript*
 | |
| In legacy Vim script:
 | |
| If expr8 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
 | |
| 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]
 | |
| 
 | |
| Index zero gives the first byte.  This is like it works in C.  Careful:
 | |
| text column numbers start with one!  Example, to get the byte under the
 | |
| cursor: >
 | |
| 	:let c = getline(".")[col(".") - 1]
 | |
| 
 | |
| Index zero gives the first byte.  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.
 | |
| 
 | |
| If expr8 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.
 | |
| 
 | |
| 
 | |
| expr8[expr1a : expr1b]	substring or |sublist|		*expr-[:]* *substring*
 | |
| 
 | |
| If expr8 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,
 | |
| 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 expr8 is
 | |
| a Number it is first converted to a String.
 | |
| 
 | |
| 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 expr8 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 expr8 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 expr8[expr1] or expr8[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!
 | |
| 
 | |
| 
 | |
| expr8.name		entry in a |Dictionary|		*expr-entry*
 | |
| 
 | |
| If expr8 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:
 | |
| expr8[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.
 | |
| 
 | |
| 
 | |
| expr8(expr1, ...)	|Funcref| function call		*E1085*
 | |
| 
 | |
| When expr8 is a |Funcref| type variable, invoke the function it refers to.
 | |
| 
 | |
| 
 | |
| expr8->name([args])	method call			*method* *->*
 | |
| expr8->{lambda}([args])
 | |
| 
 | |
| 							*E260* *E276*
 | |
| For methods that are also available as global functions this is the same as: >
 | |
| 	name(expr8 [, args])
 | |
| There can also be methods specifically for the type of "expr8".
 | |
| 
 | |
| 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 |expr7| operators will be applied first, thus: >
 | |
| 	-1.234->string()
 | |
| Is equivalent to: >
 | |
| 	(-1.234)->string()
 | |
| And NOT: >
 | |
| 	-(1.234->string())
 | |
| <
 | |
| 							*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
 | |
| (.
 | |
| 
 | |
| 
 | |
| 							*expr9*
 | |
| ------------------------------------------------------------------------------
 | |
| 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).
 | |
| 
 | |
| 						*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.
 | |
| [-+] 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 values to copy&paste: >
 | |
| 	:let pi = 3.14159265359
 | |
| 	:let e  = 2.71828182846
 | |
| Or, if you don't want to write them in as floating-point literals, you can
 | |
| also use functions, like the following: >
 | |
| 	:let pi = acos(-1.0)
 | |
| 	:let e  = exp(1.0)
 | |
| <
 | |
| 						*floating-point-precision*
 | |
| The precision and range of floating points numbers depends on what "double"
 | |
| means in the library Vim was compiled with.  There is no way to change this at
 | |
| runtime.
 | |
| 
 | |
| The default for displaying a |Float| is to use 6 decimal places, like using
 | |
| printf("%g", f).  You can select something else when using the |printf()|
 | |
| function.  Example: >
 | |
| 	:echo printf('%.15e', atan(1))
 | |
| <	7.853981633974483e-01
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| string					*string* *String* *expr-string* *E114*
 | |
| 
 | |
| "string"		string constant		*expr-quote*
 | |
| 
 | |
| Note that double quotes are used.
 | |
| 
 | |
| A string constant accepts these special characters:
 | |
| \...	three-digit octal number (e.g., "\316")
 | |
| \..	two-digit octal number (must be followed by non-digit)
 | |
| \.	one-digit octal number (must be followed by non-digit)
 | |
| \x..	byte specified with two hex numbers (e.g., "\x1f")
 | |
| \x.	byte specified with one hex number (must be followed by non-hex char)
 | |
| \X..	same as \x..
 | |
| \X.	same as \x.
 | |
| \u....	character specified with up to 4 hex numbers, stored as UTF-8
 | |
| 	(e.g., "\u02a4")
 | |
| \U....	same as \u but allows up to 8 hex numbers.
 | |
| \b	backspace <BS>
 | |
| \e	escape <Esc>
 | |
| \f	formfeed 0x0C
 | |
| \n	newline <NL>
 | |
| \r	return <CR>
 | |
| \t	tab <Tab>
 | |
| \\	backslash
 | |
| \"	double quote
 | |
| \<xxx>	Special key named "xxx".  e.g. "\<C-W>" for CTRL-W.  This is for use
 | |
| 	in mappings, the 0x80 byte is escaped.
 | |
| 	To use the double quote character it must be escaped: "<M-\">".
 | |
| 	Don't use <Char-xxxx> to get a UTF-8 character, use \uxxxx as
 | |
| 	mentioned above.
 | |
| \<*xxx>	Like \<xxx> but prepends a modifier instead of including it in the
 | |
| 	character.  E.g. "\<C-w>" is one character 0x17 while "\<*C-w>" is four
 | |
| 	bytes: 3 for the CTRL modifier and then character "W".
 | |
| 
 | |
| Note that "\xff" is stored as the byte 255, which may be invalid in some
 | |
| encodings.  Use "\u00ff" to store character 255 correctly as UTF-8.
 | |
| 
 | |
| Note that "\000" and "\x00" force the end of the string.
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| blob-literal				*blob-literal* *E973*
 | |
| 
 | |
| Hexadecimal starting with 0z or 0Z, with an arbitrary number of bytes.
 | |
| The sequence must be an even number of hex characters.  Example: >
 | |
| 	:let b = 0zFF00ED015DAF
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| literal-string						*literal-string* *E115*
 | |
| 
 | |
| 'string'		string constant			*expr-'*
 | |
| 
 | |
| Note that single quotes are used.
 | |
| 
 | |
| This string is taken as it is.  No backslashes are removed or have a special
 | |
| meaning.  The only exception is that two quotes stand for one quote.
 | |
| 
 | |
| Single quoted strings are useful for patterns, so that backslashes do not need
 | |
| to be doubled.  These two commands are equivalent: >
 | |
| 	if a =~ "\\s*"
 | |
| 	if a =~ '\s*'
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| interpolated-string				*$quote* *interpolated-string*
 | |
| 
 | |
| $"string"		interpolated string constant		*expr-$quote*
 | |
| $'string'		interpolated literal string constant	*expr-$'*
 | |
| 
 | |
| Interpolated strings are an extension of the |string| and |literal-string|,
 | |
| allowing the inclusion of Vim script expressions (see |expr1|).  Any
 | |
| expression returning a value can be enclosed between curly braces.  The value
 | |
| is converted to a string.  All the text and results of the expressions
 | |
| are concatenated to make a new string.
 | |
| 								*E1278*
 | |
| To include an opening brace '{' or closing brace '}' in the string content
 | |
| double it.  For double quoted strings using a backslash also works.  A single
 | |
| closing brace '}' will result in an error.
 | |
| 
 | |
| Examples: >
 | |
| 	let your_name = input("What's your name? ")
 | |
| <	What's your name?  Peter ~
 | |
| >
 | |
| 	echo
 | |
| 	echo $"Hello, {your_name}!"
 | |
| <	Hello, Peter! ~
 | |
| >
 | |
| 	echo $"The square root of {{9}} is {sqrt(9)}"
 | |
| <	The square root of {9} is 3.0 ~
 | |
| 
 | |
| 						*string-offset-encoding*
 | |
| A string consists of multiple characters.  UTF-8 uses one byte for ASCII
 | |
| characters, two bytes for other latin characters and more bytes for other
 | |
| characters.
 | |
| 
 | |
| A string offset can count characters or bytes.  Other programs may use
 | |
| UTF-16 encoding (16-bit words) and an offset of UTF-16 words.  Some functions
 | |
| use byte offsets, usually for UTF-8 encoding.  Other functions use character
 | |
| offsets, in which case the encoding doesn't matter.
 | |
| 
 | |
| The different offsets for the string "a©😊" are below:
 | |
| 
 | |
|   UTF-8 offsets:
 | |
|       [0]: 61, [1]: C2, [2]: A9, [3]: F0, [4]: 9F, [5]: 98, [6]: 8A
 | |
|   UTF-16 offsets:
 | |
|       [0]: 0061, [1]: 00A9, [2]: D83D, [3]: DE0A
 | |
|   UTF-32 (character) offsets:
 | |
|       [0]: 00000061, [1]: 000000A9, [2]: 0001F60A
 | |
| 
 | |
| You can use the "g8" and "ga" commands on a character to see the
 | |
| decimal/hex/octal values.
 | |
| 
 | |
| The functions |byteidx()|, |utf16idx()| and |charidx()| can be used to convert
 | |
| between these indices.  The functions |strlen()|, |strutf16len()| and
 | |
| |strcharlen()| return the number of bytes, UTF-16 code units and characters in
 | |
| a string respectively.
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| option						*expr-option* *E112* *E113*
 | |
| 
 | |
| &option			option value, local value if possible
 | |
| &g:option		global option value
 | |
| &l:option		local option value
 | |
| 
 | |
| Examples: >
 | |
| 	echo "tabstop is " .. &tabstop
 | |
| 	if &expandtab
 | |
| 
 | |
| Any option name can be used here.  See |options|.  When using the local value
 | |
| and there is no buffer-local or window-local value, the global value is used
 | |
| anyway.
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| register						*expr-register* *@r*
 | |
| 
 | |
| @r			contents of register 'r'
 | |
| 
 | |
| The result is the contents of the named register, as a single string.
 | |
| Newlines are inserted where required.  To get the contents of the unnamed
 | |
| register use @" or @@.  See |registers| for an explanation of the available
 | |
| registers.
 | |
| 
 | |
| When using the '=' register you get the expression itself, not what it
 | |
| evaluates to.  Use |eval()| to evaluate it.
 | |
| 
 | |
| 
 | |
| nesting							*expr-nesting* *E110*
 | |
| -------
 | |
| (expr1)			nested expression
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| environment variable					*expr-env*
 | |
| 
 | |
| $VAR			environment variable
 | |
| 
 | |
| The String value of any environment variable.  When it is not defined, the
 | |
| result is an empty string.
 | |
| 
 | |
| The functions `getenv()` and `setenv()` can also be used and work for
 | |
| environment variables with non-alphanumeric names.
 | |
| The function `environ()` can be used to get a Dict with all environment
 | |
| variables.
 | |
| 
 | |
| 
 | |
| 						*expr-env-expand*
 | |
| Note that there is a difference between using $VAR directly and using
 | |
| expand("$VAR").  Using it directly will only expand environment variables that
 | |
| are known inside the current Vim session.  Using expand() will first try using
 | |
| the environment variables known inside the current Vim session.  If that
 | |
| fails, a shell will be used to expand the variable.  This can be slow, but it
 | |
| does expand all variables that the shell knows about.  Example: >
 | |
| 	:echo $shell
 | |
| 	:echo expand("$shell")
 | |
| The first one probably doesn't echo anything, the second echoes the $shell
 | |
| variable (if your shell supports it).
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| internal variable					*expr-variable*
 | |
| 
 | |
| variable		internal variable
 | |
| See below |internal-variables|.
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| function call		*expr-function* *E116* *E118* *E119* *E120*
 | |
| 
 | |
| function(expr1, ...)	function call
 | |
| See below |functions|.
 | |
| 
 | |
| 
 | |
| ------------------------------------------------------------------------------
 | |
| lambda expression				*expr-lambda* *lambda*
 | |
| 
 | |
| `{args -> expr1}`	lambda expression			*E451*
 | |
| 
 | |
| A lambda expression creates a new unnamed function which returns the result of
 | |
| evaluating |expr1|.  Lambda expressions differ from |user-function|s in
 | |
| the following ways:
 | |
| 
 | |
| 1. The body of the lambda expression is an |expr1| and not a sequence of |Ex|
 | |
|    commands.
 | |
| 2. The prefix "a:" should not be used for arguments.  E.g.: >
 | |
| 	:let F = {arg1, arg2 -> arg1 - arg2}
 | |
| 	:echo F(5, 2)
 | |
| <	3
 | |
| 
 | |
| The arguments are optional.  Example: >
 | |
| 	:let F = {-> 'error function'}
 | |
| 	:echo F('ignored')
 | |
| <	error function
 | |
| 							*closure*
 | |
| Lambda expressions can access outer scope variables and arguments.  This is
 | |
| often called a closure.  Example where "i" and "a:arg" are used in a lambda
 | |
| while they already exist in the function scope.  They remain valid even after
 | |
| the function returns: >
 | |
| 	:function Foo(arg)
 | |
| 	:  let i = 3
 | |
| 	:  return {x -> x + i - a:arg}
 | |
| 	:endfunction
 | |
| 	:let Bar = Foo(4)
 | |
| 	:echo Bar(6)
 | |
| <	5
 | |
| Note that the variables must exist in the outer scope before the lambda is
 | |
| defined for this to work.  See also |:func-closure|.
 | |
| 
 | |
| Lambda and closure support can be checked with: >
 | |
| 	if has('lambda')
 | |
| 
 | |
| Examples for using a lambda expression with |sort()|, |map()| and |filter()|: >
 | |
| 	:echo map([1, 2, 3], {idx, val -> val + 1})
 | |
| <	[2, 3, 4] >
 | |
| 	:echo sort([3,7,2,1,4], {a, b -> a - b})
 | |
| <	[1, 2, 3, 4, 7]
 | |
| 
 | |
| The lambda expression is also useful for jobs and timers: >
 | |
| 	:let timer = timer_start(500,
 | |
| 			\ {-> execute("echo 'Handler called'", "")},
 | |
| 			\ {'repeat': 3})
 | |
| <	Handler called
 | |
| 	Handler called
 | |
| 	Handler called
 | |
| 
 | |
| Note that it is possible to cause memory to be used and not freed if the
 | |
| closure is referenced by the context it depends on: >
 | |
| 	function Function()
 | |
| 	   let x = 0
 | |
| 	   let F = {-> x}
 | |
| 	 endfunction
 | |
| The closure uses "x" from the function scope, and "F" in that same scope
 | |
| refers to the closure.  This cycle results in the memory not being freed.
 | |
| Recommendation: don't do this.
 | |
| 
 | |
| Notice how execute() is used to execute an Ex command.  That's ugly though.
 | |
| 
 | |
| 
 | |
| Lambda expressions have internal names like '<lambda>42'.  If you get an error
 | |
| for a lambda expression, you can find what it is with the following command: >
 | |
| 	:function <lambda>42
 | |
| See also: |numbered-function|
 | |
| 
 | |
| ==============================================================================
 | |
| 3. Internal variable				*internal-variables* *E461*
 | |
| 
 | |
| 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
 | |
| |curly-braces-names|.
 | |
| 
 | |
| An internal variable is created with the ":let" command |:let|.
 | |
| An internal variable is explicitly destroyed with the ":unlet" command
 | |
| |:unlet|.
 | |
| Using a name that is not an internal variable or refers to a variable that has
 | |
| been destroyed results in an error.
 | |
| 
 | |
| 						*variable-scope*
 | |
| There are several name spaces for variables.  Which one is to be used is
 | |
| specified by what is prepended:
 | |
| 
 | |
| 		(nothing) In a function: local to a function; otherwise: global
 | |
| |buffer-variable|    b:	  Local to the current buffer.
 | |
| |window-variable|    w:	  Local to the current window.
 | |
| |tabpage-variable|   t:	  Local to the current tab page.
 | |
| |global-variable|    g:	  Global.
 | |
| |local-variable|     l:	  Local to a function.
 | |
| |script-variable|    s:	  Local to a |:source|d Vim script.
 | |
| |function-argument|  a:	  Function argument (only inside a function).
 | |
| |vim-variable|       v:	  Global, predefined by Vim.
 | |
| 
 | |
| The scope name by itself can be used as a |Dictionary|.  For example, to
 | |
| delete all script-local variables: >
 | |
| 	:for k in keys(s:)
 | |
| 	:    unlet s:[k]
 | |
| 	:endfor
 | |
| <
 | |
| 						*buffer-variable* *b:var* *b:*
 | |
| 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.
 | |
| This kind of variable is deleted when the buffer is wiped out or deleted with
 | |
| |:bdelete|.
 | |
| 
 | |
| One local buffer variable is predefined:
 | |
| 					*b:changedtick* *changetick*
 | |
| b:changedtick	The total number of changes to the current buffer.  It is
 | |
| 		incremented for each change.  An undo command is also a change
 | |
| 		in this case.  Resetting 'modified' when writing the buffer is
 | |
| 		also counted.
 | |
| 		This can be used to perform an action only when the buffer has
 | |
| 		changed.  Example: >
 | |
| 		    :if my_changedtick != b:changedtick
 | |
| 		    :	let my_changedtick = b:changedtick
 | |
| 		    :	call My_Update()
 | |
| 		    :endif
 | |
| <		You cannot change or delete the b:changedtick variable.
 | |
| 
 | |
| 						*window-variable* *w:var* *w:*
 | |
| A variable name that is preceded with "w:" is local to the current window.  It
 | |
| is deleted when the window is closed.
 | |
| 
 | |
| 						*tabpage-variable* *t:var* *t:*
 | |
| A variable name that is preceded with "t:" is local to the current tab page,
 | |
| It is deleted when the tab page is closed.
 | |
| 
 | |
| 						*global-variable* *g:var* *g:*
 | |
| Inside functions global variables are accessed with "g:".  Omitting this will
 | |
| access a variable local to a function.  But "g:" can also be used in any other
 | |
| place if you like.
 | |
| 
 | |
| 						*local-variable* *l:var* *l:*
 | |
| Inside functions local variables are accessed without prepending anything.
 | |
| But you can also prepend "l:" if you like.  However, without prepending "l:"
 | |
| you may run into reserved variable names.  For example "count".  By itself it
 | |
| refers to "v:count".  Using "l:count" you can have a local variable with the
 | |
| same name.
 | |
| 
 | |
| 						*script-variable* *s:var*
 | |
| In a Vim script variables starting with "s:" can be used.  They cannot be
 | |
| accessed from outside of the scripts, thus are local to the script.
 | |
| 
 | |
| They can be used in:
 | |
| - commands executed while the script is sourced
 | |
| - functions defined in the script
 | |
| - autocommands defined in the script
 | |
| - functions and autocommands defined in functions and autocommands which were
 | |
|   defined in the script (recursively)
 | |
| - user defined commands defined in the script
 | |
| Thus not in:
 | |
| - other scripts sourced from this one
 | |
| - mappings
 | |
| - menus
 | |
| - etc.
 | |
| 
 | |
| Script variables can be used to avoid conflicts with global variable names.
 | |
| Take this example: >
 | |
| 
 | |
| 	let s:counter = 0
 | |
| 	function MyCounter()
 | |
| 	  let s:counter = s:counter + 1
 | |
| 	  echo s:counter
 | |
| 	endfunction
 | |
| 	command Tick call MyCounter()
 | |
| 
 | |
| You can now invoke "Tick" from any script, and the "s:counter" variable in
 | |
| that script will not be changed, only the "s:counter" in the script where
 | |
| "Tick" was defined is used.
 | |
| 
 | |
| Another example that does the same: >
 | |
| 
 | |
| 	let s:counter = 0
 | |
| 	command Tick let s:counter = s:counter + 1 | echo s:counter
 | |
| 
 | |
| When calling a function and invoking a user-defined command, the context for
 | |
| script variables is set to the script where the function or command was
 | |
| defined.
 | |
| 
 | |
| The script variables are also available when a function is defined inside a
 | |
| function that is defined in a script.  Example: >
 | |
| 
 | |
| 	let s:counter = 0
 | |
| 	function StartCounting(incr)
 | |
| 	  if a:incr
 | |
| 	    function MyCounter()
 | |
| 	      let s:counter = s:counter + 1
 | |
| 	    endfunction
 | |
| 	  else
 | |
| 	    function MyCounter()
 | |
| 	      let s:counter = s:counter - 1
 | |
| 	    endfunction
 | |
| 	  endif
 | |
| 	endfunction
 | |
| 
 | |
| This defines the MyCounter() function either for counting up or counting down
 | |
| when calling StartCounting().  It doesn't matter from where StartCounting() is
 | |
| called, the s:counter variable will be accessible in MyCounter().
 | |
| 
 | |
| When the same script is sourced again it will use the same script variables.
 | |
| They will remain valid as long as Vim is running.  This can be used to
 | |
| maintain a counter: >
 | |
| 
 | |
| 	if !exists("s:counter")
 | |
| 	  let s:counter = 1
 | |
| 	  echo "script executed for the first time"
 | |
| 	else
 | |
| 	  let s:counter = s:counter + 1
 | |
| 	  echo "script executed " .. s:counter .. " times now"
 | |
| 	endif
 | |
| 
 | |
| Note that this means that filetype plugins don't get a different set of script
 | |
| variables for each buffer.  Use local buffer variables instead |b:var|.
 | |
| 
 | |
| 
 | |
| PREDEFINED VIM VARIABLES			*vim-variable* *v:var* *v:*
 | |
| 								*E963*
 | |
| 
 | |
| The alphabetic list of all builtin variables and details are in a separate
 | |
| help file: |vvars|.
 | |
| 
 | |
| ==============================================================================
 | |
| 4. Builtin Functions				*vim-function* *functions*
 | |
| 
 | |
| The Vimscript subsystem (referred to as "eval" internally) provides builtin
 | |
| functions.  Scripts can also define |user-function|s.
 | |
| 
 | |
| See |function-list| to browse functions by topic.
 | |
| 
 | |
| The alphabetic list of all builtin functions and details are in a separate
 | |
| help file: |builtin-functions|.
 | |
| 
 | |
| ==============================================================================
 | |
| 5. Defining functions					*user-function*
 | |
| 
 | |
| New functions can be defined.  These can be called just like builtin
 | |
| functions.  The function takes arguments, executes a sequence of Ex commands
 | |
| and can return a value.
 | |
| 
 | |
| You can find most information about defining functions in |userfunc.txt|.
 | |
| 
 | |
| ==============================================================================
 | |
| 6. Curly braces names					*curly-braces-names*
 | |
| 
 | |
| In most places where you can use a variable, you can use a "curly braces name"
 | |
| variable.  This is a regular variable name with one or more expressions
 | |
| wrapped in braces {} like this: >
 | |
| 	my_{adjective}_variable
 | |
| 
 | |
| 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
 | |
| name.  So in the above example, if the variable "adjective" was set to
 | |
| "noisy", then the reference would be to "my_noisy_variable", whereas if
 | |
| "adjective" was set to "quiet", then it would be to "my_quiet_variable".
 | |
| 
 | |
| One application for this is to create a set of variables governed by an option
 | |
| value.  For example, the statement >
 | |
| 	echo my_{&background}_message
 | |
| 
 | |
| would output the contents of "my_dark_message" or "my_light_message" depending
 | |
| on the current value of 'background'.
 | |
| 
 | |
| You can use multiple brace pairs: >
 | |
| 	echo my_{adverb}_{adjective}_message
 | |
| ..or even nest them: >
 | |
| 	echo my_{ad{end_of_word}}_message
 | |
| where "end_of_word" is either "verb" or "jective".
 | |
| 
 | |
| However, the expression inside the braces must evaluate to a valid single
 | |
| variable name, e.g. this is invalid: >
 | |
| 	:let foo='a + b'
 | |
| 	:echo c{foo}d
 | |
| .. since the result of expansion is "ca + bd", which is not a variable name.
 | |
| 
 | |
| 						*curly-braces-function-names*
 | |
| You can call and define functions by an evaluated name in a similar way.
 | |
| Example: >
 | |
| 	:let func_end='whizz'
 | |
| 	:call my_func_{func_end}(parameter)
 | |
| 
 | |
| This would call the function "my_func_whizz(parameter)".
 | |
| 
 | |
| This does NOT work: >
 | |
|   :let i = 3
 | |
|   :let @{i} = ''  " error
 | |
|   :echo @{i}      " error
 | |
| 
 | |
| ==============================================================================
 | |
| 7. Commands						*expression-commands*
 | |
| 
 | |
| :let {var-name} = {expr1}				*:let* *E18*
 | |
| 			Set internal variable {var-name} to the result of the
 | |
| 			expression {expr1}.  The variable will get the type
 | |
| 			from the {expr}.  If {var-name} didn't exist yet, it
 | |
| 			is created.
 | |
| 
 | |
| :let {var-name}[{idx}] = {expr1}			*E689*
 | |
| 			Set a list item to the result of the expression
 | |
| 			{expr1}.  {var-name} must refer to a list and {idx}
 | |
| 			must be a valid index in that list.  For nested list
 | |
| 			the index can be repeated.
 | |
| 			This cannot be used to add an item to a |List|.
 | |
| 			This cannot be used to set a byte in a String.  You
 | |
| 			can do that like this: >
 | |
| 				:let var = var[0:2] .. 'X' .. var[4:]
 | |
| <			When {var-name} is a |Blob| then {idx} can be the
 | |
| 			length of the blob, in which case one byte is
 | |
| 			appended.
 | |
| 
 | |
| 							*E711* *E719*
 | |
| :let {var-name}[{idx1}:{idx2}] = {expr1}		*E708* *E709* *E710*
 | |
| 			Set a sequence of items in a |List| to the result of
 | |
| 			the expression {expr1}, which must be a list with the
 | |
| 			correct number of items.
 | |
| 			{idx1} can be omitted, zero is used instead.
 | |
| 			{idx2} can be omitted, meaning the end of the list.
 | |
| 			When the selected range of items is partly past the
 | |
| 			end of the list, items will be added.
 | |
| 
 | |
| 			*:let+=* *:let-=* *:letstar=*
 | |
| 			*:let/=* *:let%=* *:let.=* *:let..=* *E734*
 | |
| :let {var} += {expr1}	Like ":let {var} = {var} + {expr1}".
 | |
| :let {var} -= {expr1}	Like ":let {var} = {var} - {expr1}".
 | |
| `:let {var} *= {expr1}`	Like ":let {var} = {var} * {expr1}".
 | |
| :let {var} /= {expr1}	Like ":let {var} = {var} / {expr1}".
 | |
| :let {var} %= {expr1}	Like ":let {var} = {var} % {expr1}".
 | |
| :let {var} .= {expr1}	Like ":let {var} = {var} . {expr1}".
 | |
| :let {var} ..= {expr1}	Like ":let {var} = {var} .. {expr1}".
 | |
| 			These fail if {var} was not set yet and when the type
 | |
| 			of {var} and {expr1} don't fit the operator.
 | |
| 			`+=` modifies a |List| or a |Blob| in-place instead of
 | |
| 			creating a new one.
 | |
| 
 | |
| 
 | |
| :let ${env-name} = {expr1}			*:let-environment* *:let-$*
 | |
| 			Set environment variable {env-name} to the result of
 | |
| 			the expression {expr1}.  The type is always String.
 | |
| :let ${env-name} .= {expr1}
 | |
| 			Append {expr1} to the environment variable {env-name}.
 | |
| 			If the environment variable didn't exist yet this
 | |
| 			works like "=".
 | |
| 
 | |
| :let @{reg-name} = {expr1}			*:let-register* *:let-@*
 | |
| 			Write the result of the expression {expr1} in register
 | |
| 			{reg-name}.  {reg-name} must be a single letter, and
 | |
| 			must be the name of a writable register (see
 | |
| 			|registers|).  "@@" can be used for the unnamed
 | |
| 			register, "@/" for the search pattern.
 | |
| 			If the result of {expr1} ends in a <CR> or <NL>, the
 | |
| 			register will be linewise, otherwise it will be set to
 | |
| 			charwise.
 | |
| 			This can be used to clear the last search pattern: >
 | |
| 				:let @/ = ""
 | |
| <			This is different from searching for an empty string,
 | |
| 			that would match everywhere.
 | |
| 
 | |
| :let @{reg-name} .= {expr1}
 | |
| 			Append {expr1} to register {reg-name}.  If the
 | |
| 			register was empty it's like setting it to {expr1}.
 | |
| 
 | |
| :let &{option-name} = {expr1}			*:let-option* *:let-&*
 | |
| 			Set option {option-name} to the result of the
 | |
| 			expression {expr1}.  A String or Number value is
 | |
| 			always converted to the type of the option.
 | |
| 			For an option local to a window or buffer the effect
 | |
| 			is just like using the |:set| command: both the local
 | |
| 			value and the global value are changed.
 | |
| 			Example: >
 | |
| 				:let &path = &path .. ',/usr/local/include'
 | |
| 
 | |
| :let &{option-name} .= {expr1}
 | |
| 			For a string option: Append {expr1} to the value.
 | |
| 			Does not insert a comma like |:set+=|.
 | |
| 
 | |
| :let &{option-name} += {expr1}
 | |
| :let &{option-name} -= {expr1}
 | |
| 			For a number or boolean option: Add or subtract
 | |
| 			{expr1}.
 | |
| 
 | |
| :let &l:{option-name} = {expr1}
 | |
| :let &l:{option-name} .= {expr1}
 | |
| :let &l:{option-name} += {expr1}
 | |
| :let &l:{option-name} -= {expr1}
 | |
| 			Like above, but only set the local value of an option
 | |
| 			(if there is one).  Works like |:setlocal|.
 | |
| 
 | |
| :let &g:{option-name} = {expr1}
 | |
| :let &g:{option-name} .= {expr1}
 | |
| :let &g:{option-name} += {expr1}
 | |
| :let &g:{option-name} -= {expr1}
 | |
| 			Like above, but only set the global value of an option
 | |
| 			(if there is one).  Works like |:setglobal|.
 | |
| 
 | |
| :let [{name1}, {name2}, ...] = {expr1}		*:let-unpack* *E687* *E688*
 | |
| 			{expr1} must evaluate to a |List|.  The first item in
 | |
| 			the list is assigned to {name1}, the second item to
 | |
| 			{name2}, etc.
 | |
| 			The number of names must match the number of items in
 | |
| 			the |List|.
 | |
| 			Each name can be one of the items of the ":let"
 | |
| 			command as mentioned above.
 | |
| 			Example: >
 | |
| 				:let [s, item] = GetItem(s)
 | |
| <			Detail: {expr1} is evaluated first, then the
 | |
| 			assignments are done in sequence.  This matters if
 | |
| 			{name2} depends on {name1}.  Example: >
 | |
| 				:let x = [0, 1]
 | |
| 				:let i = 0
 | |
| 				:let [i, x[i]] = [1, 2]
 | |
| 				:echo x
 | |
| <			The result is [0, 2].
 | |
| 
 | |
| :let [{name1}, {name2}, ...] .= {expr1}
 | |
| :let [{name1}, {name2}, ...] += {expr1}
 | |
| :let [{name1}, {name2}, ...] -= {expr1}
 | |
| 			Like above, but append/add/subtract the value for each
 | |
| 			|List| item.
 | |
| 
 | |
| :let [{name}, ..., ; {lastname}] = {expr1}				*E452*
 | |
| 			Like |:let-unpack| above, but the |List| may have more
 | |
| 			items than there are names.  A list of the remaining
 | |
| 			items is assigned to {lastname}.  If there are no
 | |
| 			remaining items {lastname} is set to an empty list.
 | |
| 			Example: >
 | |
| 				:let [a, b; rest] = ["aval", "bval", 3, 4]
 | |
| <
 | |
| :let [{name}, ..., ; {lastname}] .= {expr1}
 | |
| :let [{name}, ..., ; {lastname}] += {expr1}
 | |
| :let [{name}, ..., ; {lastname}] -= {expr1}
 | |
| 			Like above, but append/add/subtract the value for each
 | |
| 			|List| item.
 | |
| 
 | |
| 						*:let=<<* *:let-heredoc*
 | |
| 					*E990* *E991* *E172* *E221* *E1145*
 | |
| :let {var-name} =<< [trim] [eval] {endmarker}
 | |
| text...
 | |
| text...
 | |
| {endmarker}
 | |
| 			Set internal variable {var-name} to a |List|
 | |
| 			containing the lines of text bounded by the string
 | |
| 			{endmarker}.
 | |
| 
 | |
| 			If "eval" is not specified, then each line of text is
 | |
| 			used as a |literal-string|, except that single quotes
 | |
| 			does not need to be doubled.
 | |
| 			If "eval" is specified, then any Vim expression in the
 | |
| 			form {expr} is evaluated and the result replaces the
 | |
| 			expression, like with |interpolated-string|.
 | |
| 			Example where $HOME is expanded: >
 | |
| 				let lines =<< trim eval END
 | |
| 				  some text
 | |
| 				  See the file {$HOME}/.vimrc
 | |
| 				  more text
 | |
| 				END
 | |
| <			There can be multiple Vim expressions in a single line
 | |
| 			but an expression cannot span multiple lines.  If any
 | |
| 			expression evaluation fails, then the assignment fails.
 | |
| 
 | |
| 			{endmarker} must not contain white space.
 | |
| 			{endmarker} cannot start with a lower case character.
 | |
| 			The last line should end only with the {endmarker}
 | |
| 			string without any other character.  Watch out for
 | |
| 			white space after {endmarker}!
 | |
| 
 | |
| 			Without "trim" any white space characters in the lines
 | |
| 			of text are preserved.  If "trim" is specified before
 | |
| 			{endmarker}, then indentation is stripped so you can
 | |
| 			do: >
 | |
| 				let text =<< trim END
 | |
| 				   if ok
 | |
| 				     echo 'done'
 | |
| 				   endif
 | |
| 				END
 | |
| <			Results in: `["if ok", "  echo 'done'", "endif"]`
 | |
| 			The marker must line up with "let" and the indentation
 | |
| 			of the first line is removed from all the text lines.
 | |
| 			Specifically: all the leading indentation exactly
 | |
| 			matching the leading indentation of the first
 | |
| 			non-empty text line is stripped from the input lines.
 | |
| 			All leading indentation exactly matching the leading
 | |
| 			indentation before `let` is stripped from the line
 | |
| 			containing {endmarker}.  Note that the difference
 | |
| 			between space and tab matters here.
 | |
| 
 | |
| 			If {var-name} didn't exist yet, it is created.
 | |
| 			Cannot be followed by another command, but can be
 | |
| 			followed by a comment.
 | |
| 
 | |
| 			To avoid line continuation to be applied, consider
 | |
| 			adding 'C' to 'cpoptions': >
 | |
| 				set cpo+=C
 | |
| 				let var =<< END
 | |
| 				   \ leading backslash
 | |
| 				END
 | |
| 				set cpo-=C
 | |
| <
 | |
| 			Examples: >
 | |
| 				let var1 =<< END
 | |
| 				Sample text 1
 | |
| 				    Sample text 2
 | |
| 				Sample text 3
 | |
| 				END
 | |
| 
 | |
| 				let data =<< trim DATA
 | |
| 					1 2 3 4
 | |
| 					5 6 7 8
 | |
| 				DATA
 | |
| 
 | |
| 				let code =<< trim eval CODE
 | |
| 				   let v = {10 + 20}
 | |
| 				   let h = "{$HOME}"
 | |
| 				   let s = "{Str1()} abc {Str2()}"
 | |
| 				   let n = {MyFunc(3, 4)}
 | |
| 				CODE
 | |
| <
 | |
| 								*E121*
 | |
| :let {var-name}	..	List the value of variable {var-name}.  Multiple
 | |
| 			variable names may be given.  Special names recognized
 | |
| 			here:				*E738*
 | |
| 			  g:	global variables
 | |
| 			  b:	local buffer variables
 | |
| 			  w:	local window variables
 | |
| 			  t:	local tab page variables
 | |
| 			  s:	script-local variables
 | |
| 			  l:	local function variables
 | |
| 			  v:	Vim variables.
 | |
| 
 | |
| :let			List the values of all variables.  The type of the
 | |
| 			variable is indicated before the value:
 | |
| 			    <nothing>	String
 | |
| 				#	Number
 | |
| 				*	Funcref
 | |
| 
 | |
| 
 | |
| :unl[et][!] {name} ...				*:unlet* *:unl* *E108* *E795*
 | |
| 			Remove the internal variable {name}.  Several variable
 | |
| 			names can be given, they are all removed.  The name
 | |
| 			may also be a |List| or |Dictionary| item.
 | |
| 			With [!] no error message is given for non-existing
 | |
| 			variables.
 | |
| 			One or more items from a |List| can be removed: >
 | |
| 				:unlet list[3]	  " remove fourth item
 | |
| 				:unlet list[3:]   " remove fourth item to last
 | |
| <			One item from a |Dictionary| can be removed at a time: >
 | |
| 				:unlet dict['two']
 | |
| 				:unlet dict.two
 | |
| <			This is especially useful to clean up used global
 | |
| 			variables and script-local variables (these are not
 | |
| 			deleted when the script ends).  Function-local
 | |
| 			variables are automatically deleted when the function
 | |
| 			ends.
 | |
| 
 | |
| :unl[et] ${env-name} ...			*:unlet-environment* *:unlet-$*
 | |
| 			Remove environment variable {env-name}.
 | |
| 			Can mix {name} and ${env-name} in one :unlet command.
 | |
| 			No error message is given for a non-existing
 | |
| 			variable, also without !.
 | |
| 			If the system does not support deleting an environment
 | |
| 			variable, it is made empty.
 | |
| 
 | |
| 						*:cons* *:const*
 | |
| :cons[t] {var-name} = {expr1}
 | |
| :cons[t] [{name1}, {name2}, ...] = {expr1}
 | |
| :cons[t] [{name}, ..., ; {lastname}] = {expr1}
 | |
| :cons[t] {var-name} =<< [trim] [eval] {marker}
 | |
| text...
 | |
| text...
 | |
| {marker}
 | |
| 			Similar to |:let|, but additionally lock the variable
 | |
| 			after setting the value.  This is the same as locking
 | |
| 			the variable with |:lockvar| just after |:let|, thus: >
 | |
| 				:const x = 1
 | |
| <			is equivalent to: >
 | |
| 				:let x = 1
 | |
| 				:lockvar! x
 | |
| <			This is useful if you want to make sure the variable
 | |
| 			is not modified.  If the value is a List or Dictionary
 | |
| 			literal then the items also cannot be changed: >
 | |
| 				const ll = [1, 2, 3]
 | |
| 				let ll[1] = 5  " Error!
 | |
| <			Nested references are not locked: >
 | |
| 				let lvar = ['a']
 | |
| 				const lconst = [0, lvar]
 | |
| 				let lconst[0] = 2  " Error!
 | |
| 				let lconst[1][0] = 'b'  " OK
 | |
| <							*E995*
 | |
| 			It is an error to specify an existing variable with
 | |
| 			|:const|. >
 | |
| 				:let x = 1
 | |
| 				:const x = 1  " Error!
 | |
| <							*E996*
 | |
| 			Note that environment variables, option values and
 | |
| 			register values cannot be used here, since they cannot
 | |
| 			be locked.
 | |
| 
 | |
| :cons[t]
 | |
| :cons[t] {var-name}
 | |
| 			If no argument is given or only {var-name} is given,
 | |
| 			the behavior is the same as |:let|.
 | |
| 
 | |
| :lockv[ar][!] [depth] {name} ...			*:lockvar* *:lockv*
 | |
| 			Lock the internal variable {name}.  Locking means that
 | |
| 			it can no longer be changed (until it is unlocked).
 | |
| 			A locked variable can be deleted: >
 | |
| 				:lockvar v
 | |
| 				:let v = 'asdf'	  " fails!
 | |
| 				:unlet v	  " works
 | |
| <							*E741* *E940* *E1122*
 | |
| 			If you try to change a locked variable you get an
 | |
| 			error message: "E741: Value is locked: {name}".
 | |
| 			If you try to lock or unlock a built-in variable you
 | |
| 			will get an error message "E940: Cannot lock or unlock
 | |
| 			variable {name}".
 | |
| 
 | |
| 			[depth] is relevant when locking a |List| or
 | |
| 			|Dictionary|.  It specifies how deep the locking goes:
 | |
| 				0	Lock the variable {name} but not its
 | |
| 					value.
 | |
| 				1	Lock the |List| or |Dictionary| itself,
 | |
| 					cannot add or remove items, but can
 | |
| 					still change their values.
 | |
| 				2	Also lock the values, cannot change
 | |
| 					the items.  If an item is a |List| or
 | |
| 					|Dictionary|, cannot add or remove
 | |
| 					items, but can still change the
 | |
| 					values.
 | |
| 				3	Like 2 but for the |List| /
 | |
| 					|Dictionary| in the |List| /
 | |
| 					|Dictionary|, one level deeper.
 | |
| 			The default [depth] is 2, thus when {name} is a |List|
 | |
| 			or |Dictionary| the values cannot be changed.
 | |
| 
 | |
| 			Example with [depth] 0: >
 | |
| 				let mylist = [1, 2, 3]
 | |
| 				lockvar 0 mylist
 | |
| 				let mylist[0] = 77	" OK
 | |
| 				call add(mylist, 4)	" OK
 | |
| 				let mylist = [7, 8, 9]  " Error!
 | |
| <								*E743*
 | |
| 			For unlimited depth use [!] and omit [depth].
 | |
| 			However, there is a maximum depth of 100 to catch
 | |
| 			loops.
 | |
| 
 | |
| 			Note that when two variables refer to the same |List|
 | |
| 			and you lock one of them, the |List| will also be
 | |
| 			locked when used through the other variable.
 | |
| 			Example: >
 | |
| 				:let l = [0, 1, 2, 3]
 | |
| 				:let cl = l
 | |
| 				:lockvar l
 | |
| 				:let cl[1] = 99		" won't work!
 | |
| <			You may want to make a copy of a list to avoid this.
 | |
| 			See |deepcopy()|.
 | |
| 
 | |
| 
 | |
| :unlo[ckvar][!] [depth] {name} ...			*:unlockvar* *:unlo*
 | |
| 			Unlock the internal variable {name}.  Does the
 | |
| 			opposite of |:lockvar|.
 | |
| 
 | |
| 			No error is given if {name} does not exist.
 | |
| 
 | |
| :if {expr1}			*:if* *:end* *:endif* *:en* *E171* *E579* *E580*
 | |
| :en[dif]		Execute the commands until the next matching `:else`
 | |
| 			or `:endif` if {expr1} evaluates to non-zero.
 | |
| 			Although the short forms work, it is recommended to
 | |
| 			always use `:endif` to avoid confusion and to make
 | |
| 			auto-indenting work properly.
 | |
| 
 | |
| 			From Vim version 4.5 until 5.0, every Ex command in
 | |
| 			between the `:if` and `:endif` is ignored.  These two
 | |
| 			commands were just to allow for future expansions in a
 | |
| 			backward compatible way.  Nesting was allowed.  Note
 | |
| 			that any `:else` or `:elseif` was ignored, the `else`
 | |
| 			part was not executed either.
 | |
| 
 | |
| 			You can use this to remain compatible with older
 | |
| 			versions: >
 | |
| 				:if version >= 500
 | |
| 				:  version-5-specific-commands
 | |
| 				:endif
 | |
| <			The commands still need to be parsed to find the
 | |
| 			`endif`.  Sometimes an older Vim has a problem with a
 | |
| 			new command.  For example, `:silent` is recognized as
 | |
| 			a `:substitute` command.  In that case `:execute` can
 | |
| 			avoid problems: >
 | |
| 				:if version >= 600
 | |
| 				:  execute "silent 1,$delete"
 | |
| 				:endif
 | |
| <
 | |
| 			NOTE: The `:append` and `:insert` commands don't work
 | |
| 			properly in between `:if` and `:endif`.
 | |
| 
 | |
| 						*:else* *:el* *E581* *E583*
 | |
| :el[se]			Execute the commands until the next matching `:else`
 | |
| 			or `:endif` if they previously were not being
 | |
| 			executed.
 | |
| 
 | |
| 					*:elseif* *:elsei* *E582* *E584*
 | |
| :elsei[f] {expr1}	Short for `:else` `:if`, with the addition that there
 | |
| 			is no extra `:endif`.
 | |
| 
 | |
| :wh[ile] {expr1}			*:while* *:endwhile* *:wh* *:endw*
 | |
| 						*E170* *E585* *E588* *E733*
 | |
| :endw[hile]		Repeat the commands between `:while` and `:endwhile`,
 | |
| 			as long as {expr1} evaluates to non-zero.
 | |
| 			When an error is detected from a command inside the
 | |
| 			loop, execution continues after the `endwhile`.
 | |
| 			Example: >
 | |
| 				:let lnum = 1
 | |
| 				:while lnum <= line("$")
 | |
| 				   :call FixLine(lnum)
 | |
| 				   :let lnum = lnum + 1
 | |
| 				:endwhile
 | |
| <
 | |
| 			NOTE: The `:append` and `:insert` commands don't work
 | |
| 			properly inside a `:while` and `:for` loop.
 | |
| 
 | |
| :for {var} in {object}					*:for* *E690* *E732*
 | |
| :endfo[r]						*:endfo* *:endfor*
 | |
| 			Repeat the commands between `:for` and `:endfor` for
 | |
| 			each item in {object}.  {object} can be a |List|,
 | |
| 			a |Blob| or a |String|.
 | |
| 
 | |
| 			Variable {var} is set to the value of each item.
 | |
| 
 | |
| 			When an error is detected for a command inside the
 | |
| 			loop, execution continues after the `endfor`.
 | |
| 			Changing {object} inside the loop affects what items
 | |
| 			are used.  Make a copy if this is unwanted: >
 | |
| 				:for item in copy(mylist)
 | |
| <
 | |
| 			When {object} is a |List| and not making a copy, Vim
 | |
| 			stores a reference to the next item in the |List|
 | |
| 			before executing the commands with the current item.
 | |
| 			Thus the current item can be removed without effect.
 | |
| 			Removing any later item means it will not be found.
 | |
| 			Thus the following example works (an inefficient way
 | |
| 			to make a |List| empty): >
 | |
| 				for item in mylist
 | |
| 				   call remove(mylist, 0)
 | |
| 				endfor
 | |
| <			Note that reordering the |List| (e.g., with sort() or
 | |
| 			reverse()) may have unexpected effects.
 | |
| 
 | |
| 			When {object} is a |Blob|, Vim always makes a copy to
 | |
| 			iterate over.  Unlike with |List|, modifying the
 | |
| 			|Blob| does not affect the iteration.
 | |
| 
 | |
| 			When {object} is a |String| each item is a string with
 | |
| 			one character, plus any combining characters.
 | |
| 
 | |
| :for [{var1}, {var2}, ...] in {listlist}
 | |
| :endfo[r]
 | |
| 			Like `:for` above, but each item in {listlist} must be
 | |
| 			a list, of which each item is assigned to {var1},
 | |
| 			{var2}, etc.  Example: >
 | |
| 				:for [lnum, col] in [[1, 3], [2, 5], [3, 8]]
 | |
| 				   :echo getline(lnum)[col]
 | |
| 				:endfor
 | |
| <
 | |
| 						*:continue* *:con* *E586*
 | |
| :con[tinue]		When used inside a `:while` or `:for` loop, jumps back
 | |
| 			to the start of the loop.
 | |
| 
 | |
| 			If it is used after a `:try` inside the loop but
 | |
| 			before the matching `:finally` (if present), the
 | |
| 			commands following the `:finally` up to the matching
 | |
| 			`:endtry` are executed first.  This process applies to
 | |
| 			all nested `:try`s inside the loop.  The outermost
 | |
| 			`:endtry` then jumps back to the start of the loop.
 | |
| 
 | |
| 						*:break* *:brea* *E587*
 | |
| :brea[k]		When used inside a `:while` or `:for` loop, skips to
 | |
| 			the command after the matching `:endwhile` or
 | |
| 			`:endfor`.
 | |
| 			If it is used after a `:try` inside the loop but
 | |
| 			before the matching `:finally` (if present), the
 | |
| 			commands following the `:finally` up to the matching
 | |
| 			`:endtry` are executed first.  This process applies to
 | |
| 			all nested `:try`s inside the loop.  The outermost
 | |
| 			`:endtry` then jumps to the command after the loop.
 | |
| 
 | |
| :try				*:try* *:endt* *:endtry* *E600* *E601* *E602*
 | |
| :endt[ry]		Change the error handling for the commands between
 | |
| 			`:try` and `:endtry` including everything being
 | |
| 			executed across `:source` commands, function calls,
 | |
| 			or autocommand invocations.
 | |
| 
 | |
| 			When an error or interrupt is detected and there is
 | |
| 			a `:finally` command following, execution continues
 | |
| 			after the `:finally`.  Otherwise, or when the
 | |
| 			`:endtry` is reached thereafter, the next
 | |
| 			(dynamically) surrounding `:try` is checked for
 | |
| 			a corresponding `:finally` etc.  Then the script
 | |
| 			processing is terminated.  Whether a function
 | |
| 			definition has an "abort" argument does not matter.
 | |
| 			Example: >
 | |
| 		try | call Unknown() | finally | echomsg "cleanup" | endtry
 | |
| 		echomsg "not reached"
 | |
| <
 | |
| 			Moreover, an error or interrupt (dynamically) inside
 | |
| 			`:try` and `:endtry` is converted to an exception.  It
 | |
| 			can be caught as if it were thrown by a `:throw`
 | |
| 			command (see `:catch`).  In this case, the script
 | |
| 			processing is not terminated.
 | |
| 
 | |
| 			The value "Vim:Interrupt" is used for an interrupt
 | |
| 			exception.  An error in a Vim command is converted
 | |
| 			to a value of the form "Vim({command}):{errmsg}",
 | |
| 			other errors are converted to a value of the form
 | |
| 			"Vim:{errmsg}".  {command} is the full command name,
 | |
| 			and {errmsg} is the message that is displayed if the
 | |
| 			error exception is not caught, always beginning with
 | |
| 			the error number.
 | |
| 			Examples: >
 | |
| 		try | sleep 100 | catch /^Vim:Interrupt$/ | endtry
 | |
| 		try | edit | catch /^Vim(edit):E\d\+/ | echo "error" | endtry
 | |
| <
 | |
| 					*:cat* *:catch* *E603* *E604* *E605*
 | |
| :cat[ch] /{pattern}/	The following commands until the next `:catch`,
 | |
| 			`:finally`, or `:endtry` that belongs to the same
 | |
| 			`:try` as the `:catch` are executed when an exception
 | |
| 			matching {pattern} is being thrown and has not yet
 | |
| 			been caught by a previous `:catch`.  Otherwise, these
 | |
| 			commands are skipped.
 | |
| 			When {pattern} is omitted all errors are caught.
 | |
| 			Examples: >
 | |
| 		:catch /^Vim:Interrupt$/	 " catch interrupts (CTRL-C)
 | |
| 		:catch /^Vim\%((\a\+)\)\=:E/	 " catch all Vim errors
 | |
| 		:catch /^Vim\%((\a\+)\)\=:/	 " catch errors and interrupts
 | |
| 		:catch /^Vim(write):/		 " catch all errors in :write
 | |
| 		:catch /^Vim\%((\a\+)\)\=:E123:/ " catch error E123
 | |
| 		:catch /my-exception/		 " catch user exception
 | |
| 		:catch /.*/			 " catch everything
 | |
| 		:catch				 " same as /.*/
 | |
| <
 | |
| 			Another character can be used instead of / around the
 | |
| 			{pattern}, so long as it does not have a special
 | |
| 			meaning (e.g., '|' or '"') and doesn't occur inside
 | |
| 			{pattern}.
 | |
| 			Information about the exception is available in
 | |
| 			|v:exception|.  Also see |throw-variables|.
 | |
| 			NOTE: It is not reliable to ":catch" the TEXT of
 | |
| 			an error message because it may vary in different
 | |
| 			locales.
 | |
| 
 | |
| 					*:fina* *:finally* *E606* *E607*
 | |
| :fina[lly]		The following commands until the matching `:endtry`
 | |
| 			are executed whenever the part between the matching
 | |
| 			`:try` and the `:finally` is left:  either by falling
 | |
| 			through to the `:finally` or by a `:continue`,
 | |
| 			`:break`, `:finish`, or `:return`, or by an error or
 | |
| 			interrupt or exception (see `:throw`).
 | |
| 
 | |
| 							*:th* *:throw* *E608*
 | |
| :th[row] {expr1}	The {expr1} is evaluated and thrown as an exception.
 | |
| 			If the `:throw` is used after a `:try` but before the
 | |
| 			first corresponding `:catch`, commands are skipped
 | |
| 			until the first `:catch` matching {expr1} is reached.
 | |
| 			If there is no such `:catch` or if the `:throw` is
 | |
| 			used after a `:catch` but before the `:finally`, the
 | |
| 			commands following the `:finally` (if present) up to
 | |
| 			the matching `:endtry` are executed.  If the `:throw`
 | |
| 			is after the `:finally`, commands up to the `:endtry`
 | |
| 			are skipped.  At the `:endtry`, this process applies
 | |
| 			again for the next dynamically surrounding `:try`
 | |
| 			(which may be found in a calling function or sourcing
 | |
| 			script), until a matching `:catch` has been found.
 | |
| 			If the exception is not caught, the command processing
 | |
| 			is terminated.
 | |
| 			Example: >
 | |
| 		:try | throw "oops" | catch /^oo/ | echo "caught" | endtry
 | |
| <			Note that "catch" may need to be on a separate line
 | |
| 			for when an error causes the parsing to skip the whole
 | |
| 			line and not see the "|" that separates the commands.
 | |
| 
 | |
| 							*:ec* *:echo*
 | |
| :ec[ho] {expr1} ..	Echoes each {expr1}, with a space in between.  The
 | |
| 			first {expr1} starts on a new line.
 | |
| 			Also see |:comment|.
 | |
| 			Use "\n" to start a new line.  Use "\r" to move the
 | |
| 			cursor to the first column.
 | |
| 			Uses the highlighting set by the `:echohl` command.
 | |
| 			Cannot be followed by a comment.
 | |
| 			Example: >
 | |
| 		:echo "the value of 'shell' is" &shell
 | |
| <							*:echo-redraw*
 | |
| 			A later redraw may make the message disappear again.
 | |
| 			And since Vim mostly postpones redrawing until it's
 | |
| 			finished with a sequence of commands this happens
 | |
| 			quite often.  To avoid that a command from before the
 | |
| 			`:echo` causes a redraw afterwards (redraws are often
 | |
| 			postponed until you type something), force a redraw
 | |
| 			with the `:redraw` command.  Example: >
 | |
| 		:new | redraw | echo "there is a new window"
 | |
| <							*:echo-self-refer*
 | |
| 			When printing nested containers echo prints second
 | |
| 			occurrence of the self-referencing container using
 | |
| 			"[...@level]" (self-referencing |List|) or
 | |
| 			"{...@level}" (self-referencing |Dict|): >
 | |
| 		:let l = []
 | |
| 		:call add(l, l)
 | |
| 		:let l2 = []
 | |
| 		:call add(l2, [l2])
 | |
| 		:echo l l2
 | |
| <			echoes "[[...@0]] [[[...@0]]]". Echoing "[l]" will
 | |
| 			echo "[[[...@1]]]" because l first occurs at second
 | |
| 			level.
 | |
| 
 | |
| 							*:echon*
 | |
| :echon {expr1} ..	Echoes each {expr1}, without anything added.  Also see
 | |
| 			|:comment|.
 | |
| 			Uses the highlighting set by the `:echohl` command.
 | |
| 			Cannot be followed by a comment.
 | |
| 			Example: >
 | |
| 				:echon "the value of 'shell' is " &shell
 | |
| <
 | |
| 			Note the difference between using `:echo`, which is a
 | |
| 			Vim command, and `:!echo`, which is an external shell
 | |
| 			command: >
 | |
| 		:!echo %		--> filename
 | |
| <			The arguments of ":!" are expanded, see |:_%|. >
 | |
| 		:!echo "%"		--> filename or "filename"
 | |
| <			Like the previous example.  Whether you see the double
 | |
| 			quotes or not depends on your 'shell'. >
 | |
| 		:echo %			--> nothing
 | |
| <			The '%' is an illegal character in an expression. >
 | |
| 		:echo "%"		--> %
 | |
| <			This just echoes the '%' character. >
 | |
| 		:echo expand("%")	--> filename
 | |
| <			This calls the expand() function to expand the '%'.
 | |
| 
 | |
| 							*:echoh* *:echohl*
 | |
| :echoh[l] {name}	Use the highlight group {name} for the following
 | |
| 			`:echo`, `:echon` and `:echomsg` commands.  Also used
 | |
| 			for the `input()` prompt.  Example: >
 | |
| 		:echohl WarningMsg | echo "Don't panic!" | echohl None
 | |
| <			Don't forget to set the group back to "None",
 | |
| 			otherwise all following echo's will be highlighted.
 | |
| 
 | |
| 							*:echom* *:echomsg*
 | |
| :echom[sg] {expr1} ..	Echo the expression(s) as a true message, saving the
 | |
| 			message in the |message-history|.
 | |
| 			Spaces are placed between the arguments as with the
 | |
| 			`:echo` command.  But unprintable characters are
 | |
| 			displayed, not interpreted.
 | |
| 			The parsing works slightly different from `:echo`,
 | |
| 			more like `:execute`.  All the expressions are first
 | |
| 			evaluated and concatenated before echoing anything.
 | |
| 			If expressions does not evaluate to a Number or
 | |
| 			String, string() is used to turn it into a string.
 | |
| 			Uses the highlighting set by the `:echohl` command.
 | |
| 			Example: >
 | |
| 		:echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see."
 | |
| <			See |:echo-redraw| to avoid the message disappearing
 | |
| 			when the screen is redrawn.
 | |
| 							*:echoe* *:echoerr*
 | |
| :echoe[rr] {expr1} ..	Echo the expression(s) as an error message, saving the
 | |
| 			message in the |message-history|.  When used in a
 | |
| 			script or function the line number will be added.
 | |
| 			Spaces are placed between the arguments as with the
 | |
| 			`:echomsg` command.  When used inside a try conditional,
 | |
| 			the message is raised as an error exception instead
 | |
| 			(see |try-echoerr|).
 | |
| 			Example: >
 | |
| 		:echoerr "This script just failed!"
 | |
| <			If you just want a highlighted message use `:echohl`.
 | |
| 			And to get a beep: >
 | |
| 		:exe "normal \<Esc>"
 | |
| <
 | |
| 							*:eval*
 | |
| :eval {expr}		Evaluate {expr} and discard the result.  Example: >
 | |
| 				:eval Getlist()->Filter()->append('$')
 | |
| 
 | |
| <			The expression is supposed to have a side effect,
 | |
| 			since the resulting value is not used.  In the example
 | |
| 			the `append()` call appends the List with text to the
 | |
| 			buffer.  This is similar to `:call` but works with any
 | |
| 			expression.
 | |
| 
 | |
| 			The command can be shortened to `:ev` or `:eva`, but
 | |
| 			these are hard to recognize and therefore not to be
 | |
| 			used.
 | |
| 
 | |
| 			The command cannot be followed by "|" and another
 | |
| 			command, since "|" is seen as part of the expression.
 | |
| 
 | |
| 
 | |
| 							*:exe* *:execute*
 | |
| :exe[cute] {expr1} ..	Executes the string that results from the evaluation
 | |
| 			of {expr1} as an Ex command.
 | |
| 			Multiple arguments are concatenated, with a space in
 | |
| 			between.  To avoid the extra space use the ".."
 | |
| 			operator to concatenate strings into one argument.
 | |
| 			{expr1} is used as the processed command, command line
 | |
| 			editing keys are not recognized.
 | |
| 			Cannot be followed by a comment.
 | |
| 			Examples: >
 | |
| 		:execute "buffer" nextbuf
 | |
| 		:execute "normal" count .. "w"
 | |
| <
 | |
| 			":execute" can be used to append a command to commands
 | |
| 			that don't accept a '|'.  Example: >
 | |
| 		:execute '!ls' | echo "theend"
 | |
| 
 | |
| <			":execute" is also a nice way to avoid having to type
 | |
| 			control characters in a Vim script for a ":normal"
 | |
| 			command: >
 | |
| 		:execute "normal ixxx\<Esc>"
 | |
| <			This has an <Esc> character, see |expr-string|.
 | |
| 
 | |
| 			Be careful to correctly escape special characters in
 | |
| 			file names.  The |fnameescape()| function can be used
 | |
| 			for Vim commands, |shellescape()| for |:!| commands.
 | |
| 			Examples: >
 | |
| 		:execute "e " .. fnameescape(filename)
 | |
| 		:execute "!ls " .. shellescape(filename, 1)
 | |
| <
 | |
| 			Note: The executed string may be any command-line, but
 | |
| 			starting or ending "if", "while" and "for" does not
 | |
| 			always work, because when commands are skipped the
 | |
| 			":execute" is not evaluated and Vim loses track of
 | |
| 			where blocks start and end.  Also "break" and
 | |
| 			"continue" should not be inside ":execute".
 | |
| 			This example does not work, because the ":execute" is
 | |
| 			not evaluated and Vim does not see the "while", and
 | |
| 			gives an error for finding an ":endwhile": >
 | |
| 		:if 0
 | |
| 		: execute 'while i > 5'
 | |
| 		:  echo "test"
 | |
| 		: endwhile
 | |
| 		:endif
 | |
| <
 | |
| 			It is allowed to have a "while" or "if" command
 | |
| 			completely in the executed string: >
 | |
| 		:execute 'while i < 5 | echo i | let i = i + 1 | endwhile'
 | |
| <
 | |
| 
 | |
| 							*:exe-comment*
 | |
| 			":execute", ":echo" and ":echon" cannot be followed by
 | |
| 			a comment directly, because they see the '"' as the
 | |
| 			start of a string.  But, you can use '|' followed by a
 | |
| 			comment.  Example: >
 | |
| 		:echo "foo" | "this is a comment
 | |
| 
 | |
| ==============================================================================
 | |
| 8. Exception handling					*exception-handling*
 | |
| 
 | |
| The Vim script language comprises an exception handling feature.  This section
 | |
| explains how it can be used in a Vim script.
 | |
| 
 | |
| Exceptions may be raised by Vim on an error or on interrupt, see
 | |
| |catch-errors| and |catch-interrupt|.  You can also explicitly throw an
 | |
| exception by using the ":throw" command, see |throw-catch|.
 | |
| 
 | |
| 
 | |
| TRY CONDITIONALS					*try-conditionals*
 | |
| 
 | |
| Exceptions can be caught or can cause cleanup code to be executed.  You can
 | |
| use a try conditional to specify catch clauses (that catch exceptions) and/or
 | |
| a finally clause (to be executed for cleanup).
 | |
|    A try conditional begins with a |:try| command and ends at the matching
 | |
| |:endtry| command.  In between, you can use a |:catch| command to start
 | |
| a catch clause, or a |:finally| command to start a finally clause.  There may
 | |
| be none or multiple catch clauses, but there is at most one finally clause,
 | |
| which must not be followed by any catch clauses.  The lines before the catch
 | |
| clauses and the finally clause is called a try block. >
 | |
| 
 | |
|      :try
 | |
|      :	...
 | |
|      :	...				TRY BLOCK
 | |
|      :	...
 | |
|      :catch /{pattern}/
 | |
|      :	...
 | |
|      :	...				CATCH CLAUSE
 | |
|      :	...
 | |
|      :catch /{pattern}/
 | |
|      :	...
 | |
|      :	...				CATCH CLAUSE
 | |
|      :	...
 | |
|      :finally
 | |
|      :	...
 | |
|      :	...				FINALLY CLAUSE
 | |
|      :	...
 | |
|      :endtry
 | |
| 
 | |
| The try conditional allows to watch code for exceptions and to take the
 | |
| appropriate actions.  Exceptions from the try block may be caught.  Exceptions
 | |
| from the try block and also the catch clauses may cause cleanup actions.
 | |
|    When no exception is thrown during execution of the try block, the control
 | |
| is transferred to the finally clause, if present.  After its execution, the
 | |
| script continues with the line following the ":endtry".
 | |
|    When an exception occurs during execution of the try block, the remaining
 | |
| lines in the try block are skipped.  The exception is matched against the
 | |
| patterns specified as arguments to the ":catch" commands.  The catch clause
 | |
| after the first matching ":catch" is taken, other catch clauses are not
 | |
| executed.  The catch clause ends when the next ":catch", ":finally", or
 | |
| ":endtry" command is reached - whatever is first.  Then, the finally clause
 | |
| (if present) is executed.  When the ":endtry" is reached, the script execution
 | |
| continues in the following line as usual.
 | |
|    When an exception that does not match any of the patterns specified by the
 | |
| ":catch" commands is thrown in the try block, the exception is not caught by
 | |
| that try conditional and none of the catch clauses is executed.  Only the
 | |
| finally clause, if present, is taken.  The exception pends during execution of
 | |
| the finally clause.  It is resumed at the ":endtry", so that commands after
 | |
| the ":endtry" are not executed and the exception might be caught elsewhere,
 | |
| see |try-nesting|.
 | |
|    When during execution of a catch clause another exception is thrown, the
 | |
| remaining lines in that catch clause are not executed.  The new exception is
 | |
| not matched against the patterns in any of the ":catch" commands of the same
 | |
| try conditional and none of its catch clauses is taken.  If there is, however,
 | |
| a finally clause, it is executed, and the exception pends during its
 | |
| execution.  The commands following the ":endtry" are not executed.  The new
 | |
| exception might, however, be caught elsewhere, see |try-nesting|.
 | |
|    When during execution of the finally clause (if present) an exception is
 | |
| thrown, the remaining lines in the finally clause are skipped.  If the finally
 | |
| clause has been taken because of an exception from the try block or one of the
 | |
| catch clauses, the original (pending) exception is discarded.  The commands
 | |
| following the ":endtry" are not executed, and the exception from the finally
 | |
| clause is propagated and can be caught elsewhere, see |try-nesting|.
 | |
| 
 | |
| The finally clause is also executed, when a ":break" or ":continue" for
 | |
| a ":while" loop enclosing the complete try conditional is executed from the
 | |
| try block or a catch clause.  Or when a ":return" or ":finish" is executed
 | |
| from the try block or a catch clause of a try conditional in a function or
 | |
| sourced script, respectively.  The ":break", ":continue", ":return", or
 | |
| ":finish" pends during execution of the finally clause and is resumed when the
 | |
| ":endtry" is reached.  It is, however, discarded when an exception is thrown
 | |
| from the finally clause.
 | |
|    When a ":break" or ":continue" for a ":while" loop enclosing the complete
 | |
| try conditional or when a ":return" or ":finish" is encountered in the finally
 | |
| clause, the rest of the finally clause is skipped, and the ":break",
 | |
| ":continue", ":return" or ":finish" is executed as usual.  If the finally
 | |
| clause has been taken because of an exception or an earlier ":break",
 | |
| ":continue", ":return", or ":finish" from the try block or a catch clause,
 | |
| this pending exception or command is discarded.
 | |
| 
 | |
| For examples see |throw-catch| and |try-finally|.
 | |
| 
 | |
| 
 | |
| NESTING OF TRY CONDITIONALS				*try-nesting*
 | |
| 
 | |
| Try conditionals can be nested arbitrarily.  That is, a complete try
 | |
| conditional can be put into the try block, a catch clause, or the finally
 | |
| clause of another try conditional.  If the inner try conditional does not
 | |
| catch an exception thrown in its try block or throws a new exception from one
 | |
| of its catch clauses or its finally clause, the outer try conditional is
 | |
| checked according to the rules above.  If the inner try conditional is in the
 | |
| try block of the outer try conditional, its catch clauses are checked, but
 | |
| otherwise only the finally clause is executed.  It does not matter for
 | |
| nesting, whether the inner try conditional is directly contained in the outer
 | |
| one, or whether the outer one sources a script or calls a function containing
 | |
| the inner try conditional.
 | |
| 
 | |
| When none of the active try conditionals catches an exception, just their
 | |
| finally clauses are executed.  Thereafter, the script processing terminates.
 | |
| An error message is displayed in case of an uncaught exception explicitly
 | |
| thrown by a ":throw" command.  For uncaught error and interrupt exceptions
 | |
| implicitly raised by Vim, the error message(s) or interrupt message are shown
 | |
| as usual.
 | |
| 
 | |
| For examples see |throw-catch|.
 | |
| 
 | |
| 
 | |
| EXAMINING EXCEPTION HANDLING CODE			*except-examine*
 | |
| 
 | |
| Exception handling code can get tricky.  If you are in doubt what happens, set
 | |
| 'verbose' to 13 or use the ":13verbose" command modifier when sourcing your
 | |
| script file.  Then you see when an exception is thrown, discarded, caught, or
 | |
| finished.  When using a verbosity level of at least 14, things pending in
 | |
| a finally clause are also shown.  This information is also given in debug mode
 | |
| (see |debug-scripts|).
 | |
| 
 | |
| 
 | |
| THROWING AND CATCHING EXCEPTIONS			*throw-catch*
 | |
| 
 | |
| You can throw any number or string as an exception.  Use the |:throw| command
 | |
| and pass the value to be thrown as argument: >
 | |
| 	:throw 4711
 | |
| 	:throw "string"
 | |
| <							*throw-expression*
 | |
| You can also specify an expression argument.  The expression is then evaluated
 | |
| first, and the result is thrown: >
 | |
| 	:throw 4705 + strlen("string")
 | |
| 	:throw strpart("strings", 0, 6)
 | |
| 
 | |
| An exception might be thrown during evaluation of the argument of the ":throw"
 | |
| command.  Unless it is caught there, the expression evaluation is abandoned.
 | |
| The ":throw" command then does not throw a new exception.
 | |
|    Example: >
 | |
| 
 | |
| 	:function! Foo(arg)
 | |
| 	:  try
 | |
| 	:    throw a:arg
 | |
| 	:  catch /foo/
 | |
| 	:  endtry
 | |
| 	:  return 1
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:function! Bar()
 | |
| 	:  echo "in Bar"
 | |
| 	:  return 4710
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:throw Foo("arrgh") + Bar()
 | |
| 
 | |
| This throws "arrgh", and "in Bar" is not displayed since Bar() is not
 | |
| executed. >
 | |
| 	:throw Foo("foo") + Bar()
 | |
| however displays "in Bar" and throws 4711.
 | |
| 
 | |
| Any other command that takes an expression as argument might also be
 | |
| abandoned by an (uncaught) exception during the expression evaluation.  The
 | |
| exception is then propagated to the caller of the command.
 | |
|    Example: >
 | |
| 
 | |
| 	:if Foo("arrgh")
 | |
| 	:  echo "then"
 | |
| 	:else
 | |
| 	:  echo "else"
 | |
| 	:endif
 | |
| 
 | |
| Here neither of "then" or "else" is displayed.
 | |
| 
 | |
| 							*catch-order*
 | |
| Exceptions can be caught by a try conditional with one or more |:catch|
 | |
| commands, see |try-conditionals|.   The values to be caught by each ":catch"
 | |
| command can be specified as a pattern argument.  The subsequent catch clause
 | |
| gets executed when a matching exception is caught.
 | |
|    Example: >
 | |
| 
 | |
| 	:function! Foo(value)
 | |
| 	:  try
 | |
| 	:    throw a:value
 | |
| 	:  catch /^\d\+$/
 | |
| 	:    echo "Number thrown"
 | |
| 	:  catch /.*/
 | |
| 	:    echo "String thrown"
 | |
| 	:  endtry
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:call Foo(0x1267)
 | |
| 	:call Foo('string')
 | |
| 
 | |
| The first call to Foo() displays "Number thrown", the second "String thrown".
 | |
| An exception is matched against the ":catch" commands in the order they are
 | |
| specified.  Only the first match counts.  So you should place the more
 | |
| specific ":catch" first.  The following order does not make sense: >
 | |
| 
 | |
| 	:  catch /.*/
 | |
| 	:    echo "String thrown"
 | |
| 	:  catch /^\d\+$/
 | |
| 	:    echo "Number thrown"
 | |
| 
 | |
| The first ":catch" here matches always, so that the second catch clause is
 | |
| never taken.
 | |
| 
 | |
| 							*throw-variables*
 | |
| If you catch an exception by a general pattern, you may access the exact value
 | |
| in the variable |v:exception|: >
 | |
| 
 | |
| 	:  catch /^\d\+$/
 | |
| 	:    echo "Number thrown.  Value is" v:exception
 | |
| 
 | |
| You may also be interested where an exception was thrown.  This is stored in
 | |
| |v:throwpoint|.  And you can obtain the stack trace from |v:stacktrace|.
 | |
| Note that "v:exception", "v:stacktrace" and "v:throwpoint" are valid for the
 | |
| exception most recently caught as long it is not finished.
 | |
|    Example: >
 | |
| 
 | |
| 	:function! Caught()
 | |
| 	:  if v:exception != ""
 | |
| 	:    echo 'Caught "' .. v:exception .. '" in ' .. v:throwpoint
 | |
| 	:  else
 | |
| 	:    echo 'Nothing caught'
 | |
| 	:  endif
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:function! Foo()
 | |
| 	:  try
 | |
| 	:    try
 | |
| 	:      try
 | |
| 	:	 throw 4711
 | |
| 	:      finally
 | |
| 	:	 call Caught()
 | |
| 	:      endtry
 | |
| 	:    catch /.*/
 | |
| 	:      call Caught()
 | |
| 	:      throw "oops"
 | |
| 	:    endtry
 | |
| 	:  catch /.*/
 | |
| 	:    call Caught()
 | |
| 	:  finally
 | |
| 	:    call Caught()
 | |
| 	:  endtry
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:call Foo()
 | |
| 
 | |
| This displays >
 | |
| 
 | |
| 	Nothing caught
 | |
| 	Caught "4711" in function Foo, line 4
 | |
| 	Caught "oops" in function Foo, line 10
 | |
| 	Nothing caught
 | |
| 
 | |
| A practical example:  The following command ":LineNumber" displays the line
 | |
| number in the script or function where it has been used: >
 | |
| 
 | |
| 	:function! LineNumber()
 | |
| 	:    return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "")
 | |
| 	:endfunction
 | |
| 	:command! LineNumber try | throw "" | catch | echo LineNumber() | endtry
 | |
| <
 | |
| 							*try-nested*
 | |
| An exception that is not caught by a try conditional can be caught by
 | |
| a surrounding try conditional: >
 | |
| 
 | |
| 	:try
 | |
| 	:  try
 | |
| 	:    throw "foo"
 | |
| 	:  catch /foobar/
 | |
| 	:    echo "foobar"
 | |
| 	:  finally
 | |
| 	:    echo "inner finally"
 | |
| 	:  endtry
 | |
| 	:catch /foo/
 | |
| 	:  echo "foo"
 | |
| 	:endtry
 | |
| 
 | |
| The inner try conditional does not catch the exception, just its finally
 | |
| clause is executed.  The exception is then caught by the outer try
 | |
| conditional.  The example displays "inner finally" and then "foo".
 | |
| 
 | |
| 							*throw-from-catch*
 | |
| You can catch an exception and throw a new one to be caught elsewhere from the
 | |
| catch clause: >
 | |
| 
 | |
| 	:function! Foo()
 | |
| 	:  throw "foo"
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:function! Bar()
 | |
| 	:  try
 | |
| 	:    call Foo()
 | |
| 	:  catch /foo/
 | |
| 	:    echo "Caught foo, throw bar"
 | |
| 	:    throw "bar"
 | |
| 	:  endtry
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:try
 | |
| 	:  call Bar()
 | |
| 	:catch /.*/
 | |
| 	:  echo "Caught" v:exception
 | |
| 	:endtry
 | |
| 
 | |
| This displays "Caught foo, throw bar" and then "Caught bar".
 | |
| 
 | |
| 							*rethrow*
 | |
| There is no real rethrow in the Vim script language, but you may throw
 | |
| "v:exception" instead: >
 | |
| 
 | |
| 	:function! Bar()
 | |
| 	:  try
 | |
| 	:    call Foo()
 | |
| 	:  catch /.*/
 | |
| 	:    echo "Rethrow" v:exception
 | |
| 	:    throw v:exception
 | |
| 	:  endtry
 | |
| 	:endfunction
 | |
| <							*try-echoerr*
 | |
| Note that this method cannot be used to "rethrow" Vim error or interrupt
 | |
| exceptions, because it is not possible to fake Vim internal exceptions.
 | |
| Trying so causes an error exception.  You should throw your own exception
 | |
| denoting the situation.  If you want to cause a Vim error exception containing
 | |
| the original error exception value, you can use the |:echoerr| command: >
 | |
| 
 | |
| 	:try
 | |
| 	:  try
 | |
| 	:    asdf
 | |
| 	:  catch /.*/
 | |
| 	:    echoerr v:exception
 | |
| 	:  endtry
 | |
| 	:catch /.*/
 | |
| 	:  echo v:exception
 | |
| 	:endtry
 | |
| 
 | |
| This code displays
 | |
| 
 | |
| 	Vim(echoerr):Vim:E492: Not an editor command:	asdf ~
 | |
| 
 | |
| 
 | |
| CLEANUP CODE						*try-finally*
 | |
| 
 | |
| Scripts often change global settings and restore them at their end.  If the
 | |
| user however interrupts the script by pressing CTRL-C, the settings remain in
 | |
| an inconsistent state.  The same may happen to you in the development phase of
 | |
| a script when an error occurs or you explicitly throw an exception without
 | |
| catching it.  You can solve these problems by using a try conditional with
 | |
| a finally clause for restoring the settings.  Its execution is guaranteed on
 | |
| normal control flow, on error, on an explicit ":throw", and on interrupt.
 | |
| (Note that errors and interrupts from inside the try conditional are converted
 | |
| to exceptions.  When not caught, they terminate the script after the finally
 | |
| clause has been executed.)
 | |
| Example: >
 | |
| 
 | |
| 	:try
 | |
| 	:  let s:saved_ts = &ts
 | |
| 	:  set ts=17
 | |
| 	:
 | |
| 	:  " Do the hard work here.
 | |
| 	:
 | |
| 	:finally
 | |
| 	:  let &ts = s:saved_ts
 | |
| 	:  unlet s:saved_ts
 | |
| 	:endtry
 | |
| 
 | |
| This method should be used locally whenever a function or part of a script
 | |
| changes global settings which need to be restored on failure or normal exit of
 | |
| that function or script part.
 | |
| 
 | |
| 							*break-finally*
 | |
| Cleanup code works also when the try block or a catch clause is left by
 | |
| a ":continue", ":break", ":return", or ":finish".
 | |
|    Example: >
 | |
| 
 | |
| 	:let first = 1
 | |
| 	:while 1
 | |
| 	:  try
 | |
| 	:    if first
 | |
| 	:      echo "first"
 | |
| 	:      let first = 0
 | |
| 	:      continue
 | |
| 	:    else
 | |
| 	:      throw "second"
 | |
| 	:    endif
 | |
| 	:  catch /.*/
 | |
| 	:    echo v:exception
 | |
| 	:    break
 | |
| 	:  finally
 | |
| 	:    echo "cleanup"
 | |
| 	:  endtry
 | |
| 	:  echo "still in while"
 | |
| 	:endwhile
 | |
| 	:echo "end"
 | |
| 
 | |
| This displays "first", "cleanup", "second", "cleanup", and "end". >
 | |
| 
 | |
| 	:function! Foo()
 | |
| 	:  try
 | |
| 	:    return 4711
 | |
| 	:  finally
 | |
| 	:    echo "cleanup\n"
 | |
| 	:  endtry
 | |
| 	:  echo "Foo still active"
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:echo Foo() "returned by Foo"
 | |
| 
 | |
| This displays "cleanup" and "4711 returned by Foo".  You don't need to add an
 | |
| extra ":return" in the finally clause.  (Above all, this would override the
 | |
| return value.)
 | |
| 
 | |
| 							*except-from-finally*
 | |
| Using either of ":continue", ":break", ":return", ":finish", or ":throw" in
 | |
| a finally clause is possible, but not recommended since it abandons the
 | |
| cleanup actions for the try conditional.  But, of course, interrupt and error
 | |
| exceptions might get raised from a finally clause.
 | |
|    Example where an error in the finally clause stops an interrupt from
 | |
| working correctly: >
 | |
| 
 | |
| 	:try
 | |
| 	:  try
 | |
| 	:    echo "Press CTRL-C for interrupt"
 | |
| 	:    while 1
 | |
| 	:    endwhile
 | |
| 	:  finally
 | |
| 	:    unlet novar
 | |
| 	:  endtry
 | |
| 	:catch /novar/
 | |
| 	:endtry
 | |
| 	:echo "Script still running"
 | |
| 	:sleep 1
 | |
| 
 | |
| If you need to put commands that could fail into a finally clause, you should
 | |
| think about catching or ignoring the errors in these commands, see
 | |
| |catch-errors| and |ignore-errors|.
 | |
| 
 | |
| 
 | |
| CATCHING ERRORS						*catch-errors*
 | |
| 
 | |
| If you want to catch specific errors, you just have to put the code to be
 | |
| watched in a try block and add a catch clause for the error message.  The
 | |
| presence of the try conditional causes all errors to be converted to an
 | |
| exception.  No message is displayed and |v:errmsg| is not set then.  To find
 | |
| the right pattern for the ":catch" command, you have to know how the format of
 | |
| the error exception is.
 | |
|    Error exceptions have the following format: >
 | |
| 
 | |
| 	Vim({cmdname}):{errmsg}
 | |
| or >
 | |
| 	Vim:{errmsg}
 | |
| 
 | |
| {cmdname} is the name of the command that failed; the second form is used when
 | |
| the command name is not known.  {errmsg} is the error message usually produced
 | |
| when the error occurs outside try conditionals.  It always begins with
 | |
| a capital "E", followed by a two or three-digit error number, a colon, and
 | |
| a space.
 | |
| 
 | |
| Examples:
 | |
| 
 | |
| The command >
 | |
| 	:unlet novar
 | |
| normally produces the error message >
 | |
| 	E108: No such variable: "novar"
 | |
| which is converted inside try conditionals to an exception >
 | |
| 	Vim(unlet):E108: No such variable: "novar"
 | |
| 
 | |
| The command >
 | |
| 	:dwim
 | |
| normally produces the error message >
 | |
| 	E492: Not an editor command: dwim
 | |
| which is converted inside try conditionals to an exception >
 | |
| 	Vim:E492: Not an editor command: dwim
 | |
| 
 | |
| You can catch all ":unlet" errors by a >
 | |
| 	:catch /^Vim(unlet):/
 | |
| or all errors for misspelled command names by a >
 | |
| 	:catch /^Vim:E492:/
 | |
| 
 | |
| Some error messages may be produced by different commands: >
 | |
| 	:function nofunc
 | |
| and >
 | |
| 	:delfunction nofunc
 | |
| both produce the error message >
 | |
| 	E128: Function name must start with a capital: nofunc
 | |
| which is converted inside try conditionals to an exception >
 | |
| 	Vim(function):E128: Function name must start with a capital: nofunc
 | |
| or >
 | |
| 	Vim(delfunction):E128: Function name must start with a capital: nofunc
 | |
| respectively.  You can catch the error by its number independently on the
 | |
| command that caused it if you use the following pattern: >
 | |
| 	:catch /^Vim(\a\+):E128:/
 | |
| 
 | |
| Some commands like >
 | |
| 	:let x = novar
 | |
| produce multiple error messages, here: >
 | |
| 	E121: Undefined variable: novar
 | |
| 	E15: Invalid expression:  novar
 | |
| Only the first is used for the exception value, since it is the most specific
 | |
| one (see |except-several-errors|).  So you can catch it by >
 | |
| 	:catch /^Vim(\a\+):E121:/
 | |
| 
 | |
| You can catch all errors related to the name "nofunc" by >
 | |
| 	:catch /\<nofunc\>/
 | |
| 
 | |
| You can catch all Vim errors in the ":write" and ":read" commands by >
 | |
| 	:catch /^Vim(\(write\|read\)):E\d\+:/
 | |
| 
 | |
| You can catch all Vim errors by the pattern >
 | |
| 	:catch /^Vim\((\a\+)\)\=:E\d\+:/
 | |
| <
 | |
| 							*catch-text*
 | |
| NOTE: You should never catch the error message text itself: >
 | |
| 	:catch /No such variable/
 | |
| only works in the English locale, but not when the user has selected
 | |
| a different language by the |:language| command.  It is however helpful to
 | |
| cite the message text in a comment: >
 | |
| 	:catch /^Vim(\a\+):E108:/   " No such variable
 | |
| 
 | |
| 
 | |
| IGNORING ERRORS						*ignore-errors*
 | |
| 
 | |
| You can ignore errors in a specific Vim command by catching them locally: >
 | |
| 
 | |
| 	:try
 | |
| 	:  write
 | |
| 	:catch
 | |
| 	:endtry
 | |
| 
 | |
| But you are strongly recommended NOT to use this simple form, since it could
 | |
| catch more than you want.  With the ":write" command, some autocommands could
 | |
| be executed and cause errors not related to writing, for instance: >
 | |
| 
 | |
| 	:au BufWritePre * unlet novar
 | |
| 
 | |
| There could even be such errors you are not responsible for as a script
 | |
| writer: a user of your script might have defined such autocommands.  You would
 | |
| then hide the error from the user.
 | |
|    It is much better to use >
 | |
| 
 | |
| 	:try
 | |
| 	:  write
 | |
| 	:catch /^Vim(write):/
 | |
| 	:endtry
 | |
| 
 | |
| which only catches real write errors.  So catch only what you'd like to ignore
 | |
| intentionally.
 | |
| 
 | |
| For a single command that does not cause execution of autocommands, you could
 | |
| even suppress the conversion of errors to exceptions by the ":silent!"
 | |
| command: >
 | |
| 	:silent! nunmap k
 | |
| This works also when a try conditional is active.
 | |
| 
 | |
| 
 | |
| CATCHING INTERRUPTS					*catch-interrupt*
 | |
| 
 | |
| When there are active try conditionals, an interrupt (CTRL-C) is converted to
 | |
| the exception "Vim:Interrupt".  You can catch it like every exception.  The
 | |
| script is not terminated, then.
 | |
|    Example: >
 | |
| 
 | |
| 	:function! TASK1()
 | |
| 	:  sleep 10
 | |
| 	:endfunction
 | |
| 
 | |
| 	:function! TASK2()
 | |
| 	:  sleep 20
 | |
| 	:endfunction
 | |
| 
 | |
| 	:while 1
 | |
| 	:  let command = input("Type a command: ")
 | |
| 	:  try
 | |
| 	:    if command == ""
 | |
| 	:      continue
 | |
| 	:    elseif command == "END"
 | |
| 	:      break
 | |
| 	:    elseif command == "TASK1"
 | |
| 	:      call TASK1()
 | |
| 	:    elseif command == "TASK2"
 | |
| 	:      call TASK2()
 | |
| 	:    else
 | |
| 	:      echo "\nIllegal command:" command
 | |
| 	:      continue
 | |
| 	:    endif
 | |
| 	:  catch /^Vim:Interrupt$/
 | |
| 	:    echo "\nCommand interrupted"
 | |
| 	:    " Caught the interrupt.  Continue with next prompt.
 | |
| 	:  endtry
 | |
| 	:endwhile
 | |
| 
 | |
| You can interrupt a task here by pressing CTRL-C; the script then asks for
 | |
| a new command.  If you press CTRL-C at the prompt, the script is terminated.
 | |
| 
 | |
| For testing what happens when CTRL-C would be pressed on a specific line in
 | |
| your script, use the debug mode and execute the |>quit| or |>interrupt|
 | |
| command on that line.  See |debug-scripts|.
 | |
| 
 | |
| 
 | |
| CATCHING ALL						*catch-all*
 | |
| 
 | |
| The commands >
 | |
| 
 | |
| 	:catch /.*/
 | |
| 	:catch //
 | |
| 	:catch
 | |
| 
 | |
| catch everything, error exceptions, interrupt exceptions and exceptions
 | |
| explicitly thrown by the |:throw| command.  This is useful at the top level of
 | |
| a script in order to catch unexpected things.
 | |
|    Example: >
 | |
| 
 | |
| 	:try
 | |
| 	:
 | |
| 	:  " do the hard work here
 | |
| 	:
 | |
| 	:catch /MyException/
 | |
| 	:
 | |
| 	:  " handle known problem
 | |
| 	:
 | |
| 	:catch /^Vim:Interrupt$/
 | |
| 	:    echo "Script interrupted"
 | |
| 	:catch /.*/
 | |
| 	:  echo "Internal error (" .. v:exception .. ")"
 | |
| 	:  echo " - occurred at " .. v:throwpoint
 | |
| 	:endtry
 | |
| 	:" end of script
 | |
| 
 | |
| Note: Catching all might catch more things than you want.  Thus, you are
 | |
| strongly encouraged to catch only for problems that you can really handle by
 | |
| specifying a pattern argument to the ":catch".
 | |
|    Example: Catching all could make it nearly impossible to interrupt a script
 | |
| by pressing CTRL-C: >
 | |
| 
 | |
| 	:while 1
 | |
| 	:  try
 | |
| 	:    sleep 1
 | |
| 	:  catch
 | |
| 	:  endtry
 | |
| 	:endwhile
 | |
| 
 | |
| 
 | |
| EXCEPTIONS AND AUTOCOMMANDS				*except-autocmd*
 | |
| 
 | |
| Exceptions may be used during execution of autocommands.  Example: >
 | |
| 
 | |
| 	:autocmd User x try
 | |
| 	:autocmd User x   throw "Oops!"
 | |
| 	:autocmd User x catch
 | |
| 	:autocmd User x   echo v:exception
 | |
| 	:autocmd User x endtry
 | |
| 	:autocmd User x throw "Arrgh!"
 | |
| 	:autocmd User x echo "Should not be displayed"
 | |
| 	:
 | |
| 	:try
 | |
| 	:  doautocmd User x
 | |
| 	:catch
 | |
| 	:  echo v:exception
 | |
| 	:endtry
 | |
| 
 | |
| This displays "Oops!" and "Arrgh!".
 | |
| 
 | |
| 							*except-autocmd-Pre*
 | |
| For some commands, autocommands get executed before the main action of the
 | |
| command takes place.  If an exception is thrown and not caught in the sequence
 | |
| of autocommands, the sequence and the command that caused its execution are
 | |
| abandoned and the exception is propagated to the caller of the command.
 | |
|    Example: >
 | |
| 
 | |
| 	:autocmd BufWritePre * throw "FAIL"
 | |
| 	:autocmd BufWritePre * echo "Should not be displayed"
 | |
| 	:
 | |
| 	:try
 | |
| 	:  write
 | |
| 	:catch
 | |
| 	:  echo "Caught:" v:exception "from" v:throwpoint
 | |
| 	:endtry
 | |
| 
 | |
| Here, the ":write" command does not write the file currently being edited (as
 | |
| you can see by checking 'modified'), since the exception from the BufWritePre
 | |
| autocommand abandons the ":write".  The exception is then caught and the
 | |
| script displays: >
 | |
| 
 | |
| 	Caught: FAIL from BufWrite Auto commands for "*"
 | |
| <
 | |
| 							*except-autocmd-Post*
 | |
| For some commands, autocommands get executed after the main action of the
 | |
| command has taken place.  If this main action fails and the command is inside
 | |
| an active try conditional, the autocommands are skipped and an error exception
 | |
| is thrown that can be caught by the caller of the command.
 | |
|    Example: >
 | |
| 
 | |
| 	:autocmd BufWritePost * echo "File successfully written!"
 | |
| 	:
 | |
| 	:try
 | |
| 	:  write /i/m/p/o/s/s/i/b/l/e
 | |
| 	:catch
 | |
| 	:  echo v:exception
 | |
| 	:endtry
 | |
| 
 | |
| This just displays: >
 | |
| 
 | |
| 	Vim(write):E212: Can't open file for writing (/i/m/p/o/s/s/i/b/l/e)
 | |
| 
 | |
| If you really need to execute the autocommands even when the main action
 | |
| fails, trigger the event from the catch clause.
 | |
|    Example: >
 | |
| 
 | |
| 	:autocmd BufWritePre  * set noreadonly
 | |
| 	:autocmd BufWritePost * set readonly
 | |
| 	:
 | |
| 	:try
 | |
| 	:  write /i/m/p/o/s/s/i/b/l/e
 | |
| 	:catch
 | |
| 	:  doautocmd BufWritePost /i/m/p/o/s/s/i/b/l/e
 | |
| 	:endtry
 | |
| <
 | |
| You can also use ":silent!": >
 | |
| 
 | |
| 	:let x = "ok"
 | |
| 	:let v:errmsg = ""
 | |
| 	:autocmd BufWritePost * if v:errmsg != ""
 | |
| 	:autocmd BufWritePost *   let x = "after fail"
 | |
| 	:autocmd BufWritePost * endif
 | |
| 	:try
 | |
| 	:  silent! write /i/m/p/o/s/s/i/b/l/e
 | |
| 	:catch
 | |
| 	:endtry
 | |
| 	:echo x
 | |
| 
 | |
| This displays "after fail".
 | |
| 
 | |
| If the main action of the command does not fail, exceptions from the
 | |
| autocommands will be catchable by the caller of the command:  >
 | |
| 
 | |
| 	:autocmd BufWritePost * throw ":-("
 | |
| 	:autocmd BufWritePost * echo "Should not be displayed"
 | |
| 	:
 | |
| 	:try
 | |
| 	:  write
 | |
| 	:catch
 | |
| 	:  echo v:exception
 | |
| 	:endtry
 | |
| <
 | |
| 							*except-autocmd-Cmd*
 | |
| For some commands, the normal action can be replaced by a sequence of
 | |
| autocommands.  Exceptions from that sequence will be catchable by the caller
 | |
| of the command.
 | |
|    Example:  For the ":write" command, the caller cannot know whether the file
 | |
| had actually been written when the exception occurred.  You need to tell it in
 | |
| some way. >
 | |
| 
 | |
| 	:if !exists("cnt")
 | |
| 	:  let cnt = 0
 | |
| 	:
 | |
| 	:  autocmd BufWriteCmd * if &modified
 | |
| 	:  autocmd BufWriteCmd *   let cnt = cnt + 1
 | |
| 	:  autocmd BufWriteCmd *   if cnt % 3 == 2
 | |
| 	:  autocmd BufWriteCmd *     throw "BufWriteCmdError"
 | |
| 	:  autocmd BufWriteCmd *   endif
 | |
| 	:  autocmd BufWriteCmd *   write | set nomodified
 | |
| 	:  autocmd BufWriteCmd *   if cnt % 3 == 0
 | |
| 	:  autocmd BufWriteCmd *     throw "BufWriteCmdError"
 | |
| 	:  autocmd BufWriteCmd *   endif
 | |
| 	:  autocmd BufWriteCmd *   echo "File successfully written!"
 | |
| 	:  autocmd BufWriteCmd * endif
 | |
| 	:endif
 | |
| 	:
 | |
| 	:try
 | |
| 	:	write
 | |
| 	:catch /^BufWriteCmdError$/
 | |
| 	:  if &modified
 | |
| 	:    echo "Error on writing (file contents not changed)"
 | |
| 	:  else
 | |
| 	:    echo "Error after writing"
 | |
| 	:  endif
 | |
| 	:catch /^Vim(write):/
 | |
| 	:    echo "Error on writing"
 | |
| 	:endtry
 | |
| 
 | |
| When this script is sourced several times after making changes, it displays
 | |
| first >
 | |
| 	File successfully written!
 | |
| then >
 | |
| 	Error on writing (file contents not changed)
 | |
| then >
 | |
| 	Error after writing
 | |
| etc.
 | |
| 
 | |
| 							*except-autocmd-ill*
 | |
| You cannot spread a try conditional over autocommands for different events.
 | |
| The following code is ill-formed: >
 | |
| 
 | |
| 	:autocmd BufWritePre  * try
 | |
| 	:
 | |
| 	:autocmd BufWritePost * catch
 | |
| 	:autocmd BufWritePost *   echo v:exception
 | |
| 	:autocmd BufWritePost * endtry
 | |
| 	:
 | |
| 	:write
 | |
| 
 | |
| 
 | |
| EXCEPTION HIERARCHIES AND PARAMETERIZED EXCEPTIONS	*except-hier-param*
 | |
| 
 | |
| Some programming languages allow to use hierarchies of exception classes or to
 | |
| pass additional information with the object of an exception class.  You can do
 | |
| similar things in Vim.
 | |
|    In order to throw an exception from a hierarchy, just throw the complete
 | |
| class name with the components separated by a colon, for instance throw the
 | |
| string "EXCEPT:MATHERR:OVERFLOW" for an overflow in a mathematical library.
 | |
|    When you want to pass additional information with your exception class, add
 | |
| it in parentheses, for instance throw the string "EXCEPT:IO:WRITEERR(myfile)"
 | |
| for an error when writing "myfile".
 | |
|    With the appropriate patterns in the ":catch" command, you can catch for
 | |
| base classes or derived classes of your hierarchy.  Additional information in
 | |
| parentheses can be cut out from |v:exception| with the ":substitute" command.
 | |
|    Example: >
 | |
| 
 | |
| 	:function! CheckRange(a, func)
 | |
| 	:  if a:a < 0
 | |
| 	:    throw "EXCEPT:MATHERR:RANGE(" .. a:func .. ")"
 | |
| 	:  endif
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:function! Add(a, b)
 | |
| 	:  call CheckRange(a:a, "Add")
 | |
| 	:  call CheckRange(a:b, "Add")
 | |
| 	:  let c = a:a + a:b
 | |
| 	:  if c < 0
 | |
| 	:    throw "EXCEPT:MATHERR:OVERFLOW"
 | |
| 	:  endif
 | |
| 	:  return c
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:function! Div(a, b)
 | |
| 	:  call CheckRange(a:a, "Div")
 | |
| 	:  call CheckRange(a:b, "Div")
 | |
| 	:  if (a:b == 0)
 | |
| 	:    throw "EXCEPT:MATHERR:ZERODIV"
 | |
| 	:  endif
 | |
| 	:  return a:a / a:b
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:function! Write(file)
 | |
| 	:  try
 | |
| 	:    execute "write" fnameescape(a:file)
 | |
| 	:  catch /^Vim(write):/
 | |
| 	:    throw "EXCEPT:IO(" .. getcwd() .. ", " .. a:file .. "):WRITEERR"
 | |
| 	:  endtry
 | |
| 	:endfunction
 | |
| 	:
 | |
| 	:try
 | |
| 	:
 | |
| 	:  " something with arithmetic and I/O
 | |
| 	:
 | |
| 	:catch /^EXCEPT:MATHERR:RANGE/
 | |
| 	:  let function = substitute(v:exception, '.*(\(\a\+\)).*', '\1', "")
 | |
| 	:  echo "Range error in" function
 | |
| 	:
 | |
| 	:catch /^EXCEPT:MATHERR/	" catches OVERFLOW and ZERODIV
 | |
| 	:  echo "Math error"
 | |
| 	:
 | |
| 	:catch /^EXCEPT:IO/
 | |
| 	:  let dir = substitute(v:exception, '.*(\(.\+\),\s*.\+).*', '\1', "")
 | |
| 	:  let file = substitute(v:exception, '.*(.\+,\s*\(.\+\)).*', '\1', "")
 | |
| 	:  if file !~ '^/'
 | |
| 	:    let file = dir .. "/" .. file
 | |
| 	:  endif
 | |
| 	:  echo 'I/O error for "' .. file .. '"'
 | |
| 	:
 | |
| 	:catch /^EXCEPT/
 | |
| 	:  echo "Unspecified error"
 | |
| 	:
 | |
| 	:endtry
 | |
| 
 | |
| The exceptions raised by Vim itself (on error or when pressing CTRL-C) use
 | |
| a flat hierarchy:  they are all in the "Vim" class.  You cannot throw yourself
 | |
| exceptions with the "Vim" prefix; they are reserved for Vim.
 | |
|    Vim error exceptions are parameterized with the name of the command that
 | |
| failed, if known.  See |catch-errors|.
 | |
| 
 | |
| 
 | |
| PECULIARITIES
 | |
| 							*except-compat*
 | |
| The exception handling concept requires that the command sequence causing the
 | |
| exception is aborted immediately and control is transferred to finally clauses
 | |
| and/or a catch clause.
 | |
| 
 | |
| In the Vim script language there are cases where scripts and functions
 | |
| continue after an error: in functions without the "abort" flag or in a command
 | |
| after ":silent!", control flow goes to the following line, and outside
 | |
| functions, control flow goes to the line following the outermost ":endwhile"
 | |
| or ":endif".  On the other hand, errors should be catchable as exceptions
 | |
| (thus, requiring the immediate abortion).
 | |
| 
 | |
| This problem has been solved by converting errors to exceptions and using
 | |
| immediate abortion (if not suppressed by ":silent!") only when a try
 | |
| conditional is active.  This is no restriction since an (error) exception can
 | |
| be caught only from an active try conditional.  If you want an immediate
 | |
| termination without catching the error, just use a try conditional without
 | |
| catch clause.  (You can cause cleanup code being executed before termination
 | |
| by specifying a finally clause.)
 | |
| 
 | |
| When no try conditional is active, the usual abortion and continuation
 | |
| behavior is used instead of immediate abortion.  This ensures compatibility of
 | |
| scripts written for Vim 6.1 and earlier.
 | |
| 
 | |
| However, when sourcing an existing script that does not use exception handling
 | |
| commands (or when calling one of its functions) from inside an active try
 | |
| conditional of a new script, you might change the control flow of the existing
 | |
| script on error.  You get the immediate abortion on error and can catch the
 | |
| error in the new script.  If however the sourced script suppresses error
 | |
| messages by using the ":silent!" command (checking for errors by testing
 | |
| |v:errmsg| if appropriate), its execution path is not changed.  The error is
 | |
| not converted to an exception.  (See |:silent|.)  So the only remaining cause
 | |
| where this happens is for scripts that don't care about errors and produce
 | |
| error messages.  You probably won't want to use such code from your new
 | |
| scripts.
 | |
| 
 | |
| 							*except-syntax-err*
 | |
| Syntax errors in the exception handling commands are never caught by any of
 | |
| the ":catch" commands of the try conditional they belong to.  Its finally
 | |
| clauses, however, is executed.
 | |
|    Example: >
 | |
| 
 | |
| 	:try
 | |
| 	:  try
 | |
| 	:    throw 4711
 | |
| 	:  catch /\(/
 | |
| 	:    echo "in catch with syntax error"
 | |
| 	:  catch
 | |
| 	:    echo "inner catch-all"
 | |
| 	:  finally
 | |
| 	:    echo "inner finally"
 | |
| 	:  endtry
 | |
| 	:catch
 | |
| 	:  echo 'outer catch-all caught "' .. v:exception .. '"'
 | |
| 	:  finally
 | |
| 	:    echo "outer finally"
 | |
| 	:endtry
 | |
| 
 | |
| This displays: >
 | |
|     inner finally
 | |
|     outer catch-all caught "Vim(catch):E54: Unmatched \("
 | |
|     outer finally
 | |
| The original exception is discarded and an error exception is raised, instead.
 | |
| 
 | |
| 							*except-single-line*
 | |
| The ":try", ":catch", ":finally", and ":endtry" commands can be put on
 | |
| a single line, but then syntax errors may make it difficult to recognize the
 | |
| "catch" line, thus you better avoid this.
 | |
|    Example: >
 | |
| 	:try | unlet! foo # | catch | endtry
 | |
| raises an error exception for the trailing characters after the ":unlet!"
 | |
| argument, but does not see the ":catch" and ":endtry" commands, so that the
 | |
| error exception is discarded and the "E488: Trailing characters" message gets
 | |
| displayed.
 | |
| 
 | |
| 							*except-several-errors*
 | |
| When several errors appear in a single command, the first error message is
 | |
| usually the most specific one and therefore converted to the error exception.
 | |
|    Example: >
 | |
| 	echo novar
 | |
| causes >
 | |
| 	E121: Undefined variable: novar
 | |
| 	E15: Invalid expression: novar
 | |
| The value of the error exception inside try conditionals is: >
 | |
| 	Vim(echo):E121: Undefined variable: novar
 | |
| <							*except-syntax-error*
 | |
| But when a syntax error is detected after a normal error in the same command,
 | |
| the syntax error is used for the exception being thrown.
 | |
|    Example: >
 | |
| 	unlet novar #
 | |
| causes >
 | |
| 	E108: No such variable: "novar"
 | |
| 	E488: Trailing characters
 | |
| The value of the error exception inside try conditionals is: >
 | |
| 	Vim(unlet):E488: Trailing characters
 | |
| This is done because the syntax error might change the execution path in a way
 | |
| not intended by the user.  Example: >
 | |
| 	try
 | |
| 	    try | unlet novar # | catch | echo v:exception | endtry
 | |
| 	catch /.*/
 | |
| 	    echo "outer catch:" v:exception
 | |
| 	endtry
 | |
| This displays "outer catch: Vim(unlet):E488: Trailing characters", and then
 | |
| a "E600: Missing :endtry" error message is given, see |except-single-line|.
 | |
| 
 | |
| ==============================================================================
 | |
| 9. Examples						*eval-examples*
 | |
| 
 | |
| Printing in Binary ~
 | |
| >
 | |
|   :" The function Nr2Bin() returns the binary string representation of a number.
 | |
|   :func Nr2Bin(nr)
 | |
|   :  let n = a:nr
 | |
|   :  let r = ""
 | |
|   :  while n
 | |
|   :    let r = '01'[n % 2] .. r
 | |
|   :    let n = n / 2
 | |
|   :  endwhile
 | |
|   :  return r
 | |
|   :endfunc
 | |
| 
 | |
|   :" The function String2Bin() converts each character in a string to a
 | |
|   :" binary string, separated with dashes.
 | |
|   :func String2Bin(str)
 | |
|   :  let out = ''
 | |
|   :  for ix in range(strlen(a:str))
 | |
|   :    let out = out .. '-' .. Nr2Bin(char2nr(a:str[ix]))
 | |
|   :  endfor
 | |
|   :  return out[1:]
 | |
|   :endfunc
 | |
| 
 | |
| Example of its use: >
 | |
|   :echo Nr2Bin(32)
 | |
| result: "100000" >
 | |
|   :echo String2Bin("32")
 | |
| result: "110011-110010"
 | |
| 
 | |
| 
 | |
| Sorting lines ~
 | |
| 
 | |
| This example sorts lines with a specific compare function. >
 | |
| 
 | |
|   :func SortBuffer()
 | |
|   :  let lines = getline(1, '$')
 | |
|   :  call sort(lines, function("Strcmp"))
 | |
|   :  call setline(1, lines)
 | |
|   :endfunction
 | |
| 
 | |
| As a one-liner: >
 | |
|   :call setline(1, sort(getline(1, '$'), function("Strcmp")))
 | |
| <
 | |
| 
 | |
| scanf() replacement ~
 | |
| 							*sscanf*
 | |
| There is no sscanf() function in Vim.  If you need to extract parts from a
 | |
| line, you can use matchstr() and substitute() to do it.  This example shows
 | |
| how to get the file name, line number and column number out of a line like
 | |
| "foobar.txt, 123, 45". >
 | |
|    :" Set up the match bit
 | |
|    :let mx='\(\f\+\),\s*\(\d\+\),\s*\(\d\+\)'
 | |
|    :"get the part matching the whole expression
 | |
|    :let l = matchstr(line, mx)
 | |
|    :"get each item out of the match
 | |
|    :let file = substitute(l, mx, '\1', '')
 | |
|    :let lnum = substitute(l, mx, '\2', '')
 | |
|    :let col = substitute(l, mx, '\3', '')
 | |
| 
 | |
| The input is in the variable "line", the results in the variables "file",
 | |
| "lnum" and "col". (idea from Michael Geddes)
 | |
| 
 | |
| 
 | |
| getting the scriptnames in a Dictionary ~
 | |
| 						*scriptnames-dictionary*
 | |
| The `:scriptnames` command can be used to get a list of all script files that
 | |
| have been sourced.  There is also the `getscriptinfo()` function, but the
 | |
| information returned is not exactly the same.  In case you need to manipulate
 | |
| the output of `scriptnames` this code can be used: >
 | |
|     " Get the output of ":scriptnames" in the scriptnames_output variable.
 | |
|     let scriptnames_output = ''
 | |
|     redir => scriptnames_output
 | |
|     silent scriptnames
 | |
|     redir END
 | |
| 
 | |
|     " Split the output into lines and parse each line.	Add an entry to the
 | |
|     " "scripts" dictionary.
 | |
|     let scripts = {}
 | |
|     for line in split(scriptnames_output, "\n")
 | |
|       " Only do non-blank lines.
 | |
|       if line =~ '\S'
 | |
| 	" Get the first number in the line.
 | |
| 	let nr = matchstr(line, '\d\+')
 | |
| 	" Get the file name, remove the script number " 123: ".
 | |
| 	let name = substitute(line, '.\+:\s*', '', '')
 | |
| 	" Add an item to the Dictionary
 | |
| 	let scripts[nr] = name
 | |
|       endif
 | |
|     endfor
 | |
|     unlet scriptnames_output
 | |
| 
 | |
| ==============================================================================
 | |
| The sandbox					*eval-sandbox* *sandbox*
 | |
| 
 | |
| The 'foldexpr', 'formatexpr', 'includeexpr', 'indentexpr', 'statusline' and
 | |
| 'foldtext' options may be evaluated in a sandbox.  This means that you are
 | |
| protected from these expressions having nasty side effects.  This gives some
 | |
| safety for when these options are set from a modeline.  It is also used when
 | |
| the command from a tags file is executed and for CTRL-R = in the command line.
 | |
| The sandbox is also used for the |:sandbox| command.
 | |
| 
 | |
| 								*E48*
 | |
| These items are not allowed in the sandbox:
 | |
| 	- changing the buffer text
 | |
| 	- defining or changing mapping, autocommands, user commands
 | |
| 	- setting certain options (see |option-summary|)
 | |
| 	- setting certain v: variables (see |v:var|)  *E794*
 | |
| 	- executing a shell command
 | |
| 	- reading or writing a file
 | |
| 	- jumping to another buffer or editing a file
 | |
| 	- executing Python, Perl, etc. commands
 | |
| This is not guaranteed 100% secure, but it should block most attacks.
 | |
| 
 | |
| 							*:san* *:sandbox*
 | |
| :san[dbox] {cmd}	Execute {cmd} in the sandbox.  Useful to evaluate an
 | |
| 			option that may have been set from a modeline, e.g.
 | |
| 			'foldexpr'.
 | |
| 
 | |
| 							*sandbox-option*
 | |
| A few options contain an expression.  When this expression is evaluated it may
 | |
| have to be done in the sandbox to avoid a security risk.  But the sandbox is
 | |
| restrictive, thus this only happens when the option was set from an insecure
 | |
| location.  Insecure in this context are:
 | |
| - sourcing a .nvimrc or .exrc in the current directory
 | |
| - while executing in the sandbox
 | |
| - value coming from a modeline
 | |
| - executing a function that was defined in the sandbox
 | |
| 
 | |
| Note that when in the sandbox and saving an option value and restoring it, the
 | |
| option will still be marked as it was set in the sandbox.
 | |
| 
 | |
| ==============================================================================
 | |
| Textlock							*textlock*
 | |
| 
 | |
| In a few situations it is not allowed to change the text in the buffer, jump
 | |
| to another window and some other things that might confuse or break what Vim
 | |
| is currently doing.  This mostly applies to things that happen when Vim is
 | |
| actually doing something else.  For example, a TextYankPost autocommand cannot
 | |
| edit the text it is yanking.
 | |
| 
 | |
| This is not allowed when the textlock is active:
 | |
| 	- changing the buffer text
 | |
| 	- jumping to another buffer or window
 | |
| 	- editing another file
 | |
| 	- closing a window or quitting Vim
 | |
| 	- etc.
 | |
| 
 | |
| ==============================================================================
 | |
| Vim script library					*vim-script-library*
 | |
| 
 | |
| Vim comes bundled with a Vim script library, that can be used by runtime,
 | |
| script authors.  Currently, it only includes very few functions, but it may
 | |
| grow over time.
 | |
| 
 | |
| 								*dist#vim*
 | |
| The functions make use of the autoloaded prefix "dist#vim".
 | |
| 
 | |
| The following functions are available:
 | |
| 
 | |
| dist#vim#IsSafeExecutable(filetype, executable) ~
 | |
| 
 | |
| This function takes a filetype and an executable and checks whether it is safe
 | |
| to execute the given executable.  For security reasons users may not want to
 | |
| have Vim execute random executables or may have forbidden to do so for
 | |
| specific filetypes by setting the "<filetype>_exec" variable (|plugin_exec|).
 | |
| 
 | |
| It returns |TRUE| or |FALSE| to indicate whether the plugin should run the given
 | |
| executable.  It takes the following arguments:
 | |
| 
 | |
| 	argument	type ~
 | |
| 
 | |
| 	filetype	string
 | |
| 	executable	string
 | |
| 
 | |
| ==============================================================================
 | |
| Command-line expressions highlighting		*expr-highlight*
 | |
| 
 | |
| Expressions entered by the user in |i_CTRL-R_=|, |c_CTRL-\_e|, |quote=| are
 | |
| highlighted by the built-in expressions parser.  It uses highlight groups
 | |
| described in the table below, which may be overridden by colorschemes.
 | |
| 							*hl-NvimInvalid*
 | |
| Besides the "Nvim"-prefixed highlight groups described below, there are
 | |
| "NvimInvalid"-prefixed highlight groups which have the same meaning but
 | |
| indicate that the token contains an error or that an error occurred just
 | |
| before it.  They have mostly the same hierarchy, except that (by default) in
 | |
| place of any non-Nvim-prefixed group NvimInvalid linking to `Error` is used
 | |
| and some other intermediate groups are present.
 | |
| 
 | |
| Group                              Default link            Colored expression ~
 | |
| *hl-NvimInternalError*               None, red/red           Parser bug
 | |
| 
 | |
| *hl-NvimAssignment*                  Operator                Generic assignment
 | |
| *hl-NvimPlainAssignment*             NvimAssignment          `=` in |:let|
 | |
| *hl-NvimAugmentedAssignment*         NvimAssignment          Generic, `+=`/`-=`/`.=`
 | |
| *hl-NvimAssignmentWithAddition*      NvimAugmentedAssignment `+=` in |:let+=|
 | |
| *hl-NvimAssignmentWithSubtraction*   NvimAugmentedAssignment `-=` in |:let-=|
 | |
| *hl-NvimAssignmentWithConcatenation* NvimAugmentedAssignment `.=` in |:let.=|
 | |
| 
 | |
| *hl-NvimOperator*                    Operator                Generic operator
 | |
| 
 | |
| *hl-NvimUnaryOperator*               NvimOperator            Generic unary op
 | |
| *hl-NvimUnaryPlus*                   NvimUnaryOperator       |expr-unary-+|
 | |
| *hl-NvimUnaryMinus*                  NvimUnaryOperator       |expr-unary--|
 | |
| *hl-NvimNot*                         NvimUnaryOperator       |expr-!|
 | |
| 
 | |
| *hl-NvimBinaryOperator*              NvimOperator            Generic binary op
 | |
| *hl-NvimComparison*                  NvimBinaryOperator      Any |expr4| operator
 | |
| *hl-NvimComparisonModifier*          NvimComparison          `#`/`?` near |expr4| op
 | |
| *hl-NvimBinaryPlus*                  NvimBinaryOperator      |expr-+|
 | |
| *hl-NvimBinaryMinus*                 NvimBinaryOperator      |expr--|
 | |
| *hl-NvimConcat*                      NvimBinaryOperator      |expr-.|
 | |
| *hl-NvimConcatOrSubscript*           NvimConcat              |expr-.| or |expr-entry|
 | |
| *hl-NvimOr*                          NvimBinaryOperator      |expr-barbar|
 | |
| *hl-NvimAnd*                         NvimBinaryOperator      |expr-&&|
 | |
| *hl-NvimMultiplication*              NvimBinaryOperator      |expr-star|
 | |
| *hl-NvimDivision*                    NvimBinaryOperator      |expr-/|
 | |
| *hl-NvimMod*                         NvimBinaryOperator      |expr-%|
 | |
| 
 | |
| *hl-NvimTernary*                     NvimOperator            `?` in |expr1|
 | |
| *hl-NvimTernaryColon*                NvimTernary             `:` in |expr1|
 | |
| 
 | |
| *hl-NvimParenthesis*                 Delimiter               Generic bracket
 | |
| *hl-NvimLambda*                      NvimParenthesis         `{`/`}` in |lambda|
 | |
| *hl-NvimNestingParenthesis*          NvimParenthesis         `(`/`)` in |expr-nesting|
 | |
| *hl-NvimCallingParenthesis*          NvimParenthesis         `(`/`)` in |expr-function|
 | |
| 
 | |
| *hl-NvimSubscript*                   NvimParenthesis         Generic subscript
 | |
| *hl-NvimSubscriptBracket*            NvimSubscript           `[`/`]` in |expr-[]|
 | |
| *hl-NvimSubscriptColon*              NvimSubscript           `:` in |expr-[:]|
 | |
| *hl-NvimCurly*                       NvimSubscript           `{`/`}` in
 | |
|                                                            |curly-braces-names|
 | |
| 
 | |
| *hl-NvimContainer*                   NvimParenthesis         Generic container
 | |
| *hl-NvimDict*                        NvimContainer           `{`/`}` in |dict| literal
 | |
| *hl-NvimList*                        NvimContainer           `[`/`]` in |list| literal
 | |
| 
 | |
| *hl-NvimIdentifier*                  Identifier              Generic identifier
 | |
| *hl-NvimIdentifierScope*             NvimIdentifier          Namespace: letter
 | |
|                                                            before `:` in
 | |
|                                                            |internal-variables|
 | |
| *hl-NvimIdentifierScopeDelimiter*    NvimIdentifier          `:` after namespace
 | |
|                                                            letter
 | |
| *hl-NvimIdentifierName*              NvimIdentifier          Rest of the ident
 | |
| *hl-NvimIdentifierKey*               NvimIdentifier          Identifier after
 | |
|                                                            |expr-entry|
 | |
| 
 | |
| *hl-NvimColon*                       Delimiter               `:` in |dict| literal
 | |
| *hl-NvimComma*                       Delimiter               `,` in |dict| or |list|
 | |
|                                                            literal or
 | |
|                                                            |expr-function|
 | |
| *hl-NvimArrow*                       Delimiter               `->` in |lambda|
 | |
| 
 | |
| *hl-NvimRegister*                    SpecialChar             |expr-register|
 | |
| *hl-NvimNumber*                      Number                  Non-prefix digits
 | |
|                                                            in integer
 | |
|                                                            |expr-number|
 | |
| *hl-NvimNumberPrefix*                Type                    `0` for |octal-number|
 | |
|                                                            `0x` for |hex-number|
 | |
|                                                            `0b` for |binary-number|
 | |
| *hl-NvimFloat*                       NvimNumber              Floating-point
 | |
|                                                            number
 | |
| 
 | |
| *hl-NvimOptionSigil*                 Type                    `&` in |expr-option|
 | |
| *hl-NvimOptionScope*                 NvimIdentifierScope     Option scope if any
 | |
| *hl-NvimOptionScopeDelimiter*        NvimIdentifierScopeDelimiter
 | |
|                                                            `:` after option scope
 | |
| *hl-NvimOptionName*                  NvimIdentifier          Option name
 | |
| 
 | |
| *hl-NvimEnvironmentSigil*            NvimOptionSigil         `$` in |expr-env|
 | |
| *hl-NvimEnvironmentName*             NvimIdentifier          Env variable name
 | |
| 
 | |
| *hl-NvimString*                      String                  Generic string
 | |
| *hl-NvimStringBody*                  NvimString              Generic string
 | |
|                                                            literal body
 | |
| *hl-NvimStringQuote*                 NvimString              Generic string quote
 | |
| *hl-NvimStringSpecial*               SpecialChar             Generic string
 | |
|                                                            non-literal body
 | |
| 
 | |
| *hl-NvimSingleQuote*                 NvimStringQuote         `'` in |expr-'|
 | |
| *hl-NvimSingleQuotedBody*            NvimStringBody          Literal part of
 | |
|                                                            |expr-'| string body
 | |
| *hl-NvimSingleQuotedQuote*           NvimStringSpecial       `''` inside |expr-'|
 | |
|                                                            string body
 | |
| 
 | |
| *hl-NvimDoubleQuote*                 NvimStringQuote         `"` in |expr-quote|
 | |
| *hl-NvimDoubleQuotedBody*            NvimStringBody          Literal part of
 | |
|                                                            |expr-quote| body
 | |
| *hl-NvimDoubleQuotedEscape*          NvimStringSpecial       Valid |expr-quote|
 | |
|                                                            escape sequence
 | |
| *hl-NvimDoubleQuotedUnknownEscape*   NvimInvalidValue        Unrecognized
 | |
|                                                            |expr-quote| escape
 | |
|                                                            sequence
 | |
| 
 | |
|  vim:tw=78:ts=8:noet:ft=help:norl:
 |