| 
									
										
										
										
											2020-07-17 20:36:00 +02:00
										 |  |  | *vim9.txt*	For Vim version 8.2.  Last change: 2020 Jul 17 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		  VIM REFERENCE MANUAL	  by Bram Moolenaar | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | Vim9 script commands and expressions.			*vim9* | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Most expression help is in |eval.txt|.  This file is about the new syntax and | 
					
						
							|  |  |  | features in Vim9 script. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1   What is Vim9 script?		|vim9-script| | 
					
						
							|  |  |  | 2.  Differences				|vim9-differences| | 
					
						
							|  |  |  | 3.  New style functions			|fast-functions| | 
					
						
							|  |  |  | 4.  Types				|vim9-types| | 
					
						
							|  |  |  | 5.  Namespace, Import and Export	|vim9script| | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 9.  Rationale				|vim9-rationale| | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ============================================================================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1. What is Vim9 script?					*vim9-script* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | Vim script has been growing over time, while preserving backwards | 
					
						
							|  |  |  | compatibility.  That means bad choices from the past often can't be changed | 
					
						
							| 
									
										
										
										
											2020-06-21 22:12:03 +02:00
										 |  |  | and compatibility with Vi restricts possible solutions.  Execution is quite | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | slow, each line is parsed every time it is executed. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | The main goal of Vim9 script is to drastically improve performance.  This is | 
					
						
							|  |  |  | accomplished by compiling commands into instructions that can be efficiently | 
					
						
							|  |  |  | executed.  An increase in execution speed of 10 to 100 times can be expected. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A secondary goal is to avoid Vim-specific constructs and get closer to | 
					
						
							|  |  |  | commonly used programming languages, such as JavaScript, TypeScript and Java. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | The performance improvements can only be achieved by not being 100% backwards | 
					
						
							| 
									
										
										
										
											2020-05-26 21:20:45 +02:00
										 |  |  | compatible.  For example, making function arguments available in the | 
					
						
							|  |  |  | "a:" dictionary adds quite a lot of overhead.  In a Vim9 function this | 
					
						
							|  |  |  | dictionary is not available.  Other differences are more subtle, such as how | 
					
						
							|  |  |  | errors are handled. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | The Vim9 script syntax and semantics are used in: | 
					
						
							|  |  |  | - a function defined with the `:def` command | 
					
						
							|  |  |  | - a script file where the first command is `vim9script` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When using `:function` in a Vim9 script file the legacy syntax is used. | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | However, this can be confusing and is therefore discouraged. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | Vim9 script and legacy Vim script can be mixed.  There is no requirement to | 
					
						
							|  |  |  | rewrite old scripts, they keep working as before. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | ============================================================================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2. Differences from legacy Vim script			*vim9-differences* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 14:41:35 +02:00
										 |  |  | Comments starting with # ~ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 20:36:00 +02:00
										 |  |  | In legacy Vim script comments start with double quote.  In Vim9 script | 
					
						
							|  |  |  | comments start with #. > | 
					
						
							|  |  |  | 	# declarations | 
					
						
							| 
									
										
										
										
											2020-06-21 22:12:03 +02:00
										 |  |  | 	let count = 0  # number of occurrences | 
					
						
							| 
									
										
										
										
											2020-04-13 14:41:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 20:36:00 +02:00
										 |  |  | The reason is that a double quote can also be the start of a string. In many | 
					
						
							|  |  |  | places, especially halfway an expression with a line break, it's hard to tell | 
					
						
							|  |  |  | what the meaning is.  To avoid confusion only # comments are recognized. | 
					
						
							|  |  |  | This is the same as in shell scripts and Python programs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In Vi # is a command to list text with numbers.  In Vim9 script you can use | 
					
						
							|  |  |  | `:number` for that. > | 
					
						
							|  |  |  | 	101number | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To improve readability there must be a space between a command and the # | 
					
						
							| 
									
										
										
										
											2020-04-20 19:52:53 +02:00
										 |  |  | that starts a comment.  Note that #{ is the start of a dictionary, therefore | 
					
						
							|  |  |  | it cannot start a comment. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 14:41:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | Vim9 functions ~ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | A function defined with `:def` is compiled.  Execution is many times faster, | 
					
						
							|  |  |  | often 10x to 100x times. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 21:20:45 +02:00
										 |  |  | Many errors are already found when compiling, before the function is executed. | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | The syntax is strict, to enforce code that is easy to read and understand. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 21:20:45 +02:00
										 |  |  | Compilation is done when the function is first called, or when the | 
					
						
							|  |  |  | `:defcompile` command is encountered in the script where the function was | 
					
						
							|  |  |  | defined. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `:def` has no options like `:function` does: "range", "abort", "dict" or | 
					
						
							|  |  |  | "closure".  A `:def` function always aborts on an error, does not get a range | 
					
						
							|  |  |  | passed and cannot be a "dict" function. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | The argument types and return type need to be specified.  The "any" type can | 
					
						
							|  |  |  | be used, type checking will then be done at runtime, like with legacy | 
					
						
							|  |  |  | functions. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Arguments are accessed by name, without "a:".  There is no "a:" dictionary or | 
					
						
							|  |  |  | "a:000" list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variable arguments are defined as the last argument, with a name and have a | 
					
						
							|  |  |  | list type, similar to Typescript.  For example, a list of numbers: > | 
					
						
							|  |  |  |   	def MyFunc(...itemlist: list<number>) | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 	   for item in itemlist | 
					
						
							|  |  |  | 	     ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | Functions and variables are script-local by default ~ | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | 							*vim9-scopes* | 
					
						
							| 
									
										
										
										
											2020-04-20 19:52:53 +02:00
										 |  |  | When using `:function` or `:def` to specify a new function at the script level | 
					
						
							|  |  |  | in a Vim9 script, the function is local to the script, as if "s:" was | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | prefixed.  Using the "s:" prefix is optional. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To define or use a global function or variable the "g:" prefix must be used. | 
					
						
							| 
									
										
										
										
											2020-04-20 19:52:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | When using `:function` or `:def` to specify a new function inside a function, | 
					
						
							|  |  |  | the function is local to the function.  It is not possible to define a | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | script-local function inside a function. It is possible to define a global | 
					
						
							|  |  |  | function, using the "g:" prefix. | 
					
						
							| 
									
										
										
										
											2020-04-20 19:52:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | When referring to a function and no "s:" or "g:" prefix is used, Vim will | 
					
						
							|  |  |  | search for the function in this order: | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | - Local to the current scope and outer scopes up to the function scope. | 
					
						
							| 
									
										
										
										
											2020-04-20 19:52:53 +02:00
										 |  |  | - Local to the current script file. | 
					
						
							|  |  |  | - Imported functions, see `:import`. | 
					
						
							| 
									
										
										
										
											2020-05-26 21:20:45 +02:00
										 |  |  | In all cases the function must be defined before used.  That is when it is | 
					
						
							|  |  |  | first called or when `:defcompile` causes the call to be compiled. | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | The result is that functions and variables without a namespace can always be | 
					
						
							|  |  |  | found in the script, either defined there or imported.  Global functions and | 
					
						
							|  |  |  | variables could be defined anywhere (good luck finding where!). | 
					
						
							| 
									
										
										
										
											2020-04-20 19:52:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 18:56:00 +02:00
										 |  |  | Global functions can be still be defined and deleted at nearly any time.  In | 
					
						
							|  |  |  | Vim9 script script-local functions are defined once when the script is sourced | 
					
						
							| 
									
										
										
										
											2020-05-26 21:20:45 +02:00
										 |  |  | and cannot be deleted or replaced. | 
					
						
							| 
									
										
										
										
											2020-04-20 19:52:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | Variable declarations with :let and :const ~ | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | 							*vim9-declaration* | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | Local variables need to be declared with `:let`.  Local constants need to be | 
					
						
							|  |  |  | declared with `:const`.  We refer to both as "variables". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variables can be local to a script, function or code block: > | 
					
						
							|  |  |  | 	vim9script | 
					
						
							|  |  |  | 	let script_var = 123 | 
					
						
							|  |  |  | 	def SomeFunc() | 
					
						
							|  |  |  | 	  let func_var = script_var | 
					
						
							|  |  |  | 	  if cond | 
					
						
							|  |  |  | 	    let block_var = func_var | 
					
						
							|  |  |  | 	  ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The variables are only visible in the block where they are defined and nested | 
					
						
							|  |  |  | blocks.  Once the block ends the variable is no longer accessible: > | 
					
						
							|  |  |  | 	if cond | 
					
						
							|  |  |  | 	   let inner = 5 | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	   let inner = 0 | 
					
						
							|  |  |  | 	endif | 
					
						
							|  |  |  | 	echo inner  " Error! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The declaration must be done earlier: > | 
					
						
							|  |  |  | 	let inner: number | 
					
						
							|  |  |  | 	if cond | 
					
						
							|  |  |  | 	   inner = 5 | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	   inner = 0 | 
					
						
							|  |  |  | 	endif | 
					
						
							|  |  |  | 	echo inner | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 21:20:45 +02:00
										 |  |  | To intentionally avoid a variable being available later, a block can be used: | 
					
						
							|  |  |  | > | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	   let temp = 'temp' | 
					
						
							|  |  |  | 	   ... | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	echo temp  " Error! | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 22:53:05 +01:00
										 |  |  | An existing variable cannot be assigned to with `:let`, since that implies a | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | declaration.  An exception is global variables: these can be both used with | 
					
						
							|  |  |  | and without `:let`, because there is no rule about where they are declared. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variables cannot shadow previously defined variables. | 
					
						
							|  |  |  | Variables may shadow Ex commands, rename the variable if needed. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | Global variables and user defined functions must be prefixed with "g:", also | 
					
						
							|  |  |  | at the script level. > | 
					
						
							| 
									
										
										
										
											2020-04-10 22:10:56 +02:00
										 |  |  | 	vim9script | 
					
						
							|  |  |  | 	let script_local = 'text' | 
					
						
							|  |  |  | 	let g:global = 'value' | 
					
						
							| 
									
										
										
										
											2020-05-01 16:07:38 +02:00
										 |  |  | 	let Funcref = g:ThatFunction | 
					
						
							| 
									
										
										
										
											2020-04-10 22:10:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | Since "&opt = value" is now assigning a value to option "opt", ":&" cannot be | 
					
						
							|  |  |  | used to repeat a `:substitute` command. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Omitting :call and :eval ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Functions can be called without `:call`: > | 
					
						
							|  |  |  |   	writefile(lines, 'file') | 
					
						
							| 
									
										
										
										
											2020-02-04 22:53:05 +01:00
										 |  |  | Using `:call` is still possible, but this is discouraged. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | A method call without `eval` is possible, so long as the start is an | 
					
						
							| 
									
										
										
										
											2020-02-22 18:36:32 +01:00
										 |  |  | identifier or can't be an Ex command.  It does NOT work for string constants: > | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 	myList->add(123)		" works | 
					
						
							|  |  |  | 	g:myList->add(123)		" works | 
					
						
							|  |  |  | 	[1, 2, 3]->Process()		" works | 
					
						
							|  |  |  | 	#{a: 1, b: 2}->Process()	" works | 
					
						
							|  |  |  | 	{'a': 1, 'b': 2}->Process()	" works | 
					
						
							|  |  |  | 	"foobar"->Process()		" does NOT work | 
					
						
							| 
									
										
										
										
											2020-02-22 18:36:32 +01:00
										 |  |  | 	("foobar")->Process()		" works | 
					
						
							|  |  |  | 	'foobar'->Process()		" does NOT work | 
					
						
							|  |  |  | 	('foobar')->Process()		" works | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 18:42:43 +01:00
										 |  |  | In case there is ambiguity between a function name and an Ex command, use ":" | 
					
						
							|  |  |  | to make clear you want to use the Ex command.  For example, there is both the | 
					
						
							|  |  |  | `:substitute` command and the `substitute()` function.  When the line starts | 
					
						
							|  |  |  | with `substitute(` this will use the function, prepend a colon to use the | 
					
						
							|  |  |  | command instead: > | 
					
						
							| 
									
										
										
										
											2020-02-22 18:36:32 +01:00
										 |  |  | 	:substitute(pattern (replacement ( | 
					
						
							| 
									
										
										
										
											2020-02-21 18:42:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-29 22:06:30 +01:00
										 |  |  | Note that while variables need to be defined before they can be used, | 
					
						
							|  |  |  | functions can be called before being defined.  This is required to be able | 
					
						
							|  |  |  | have cyclic dependencies between functions.  It is slightly less efficient, | 
					
						
							|  |  |  | since the function has to be looked up by name.  And a typo in the function | 
					
						
							|  |  |  | name will only be found when the call is executed. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 22:10:56 +02:00
										 |  |  | Omitting function() ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A user defined function can be used as a function reference in an expression | 
					
						
							|  |  |  | without `function()`. The argument types and return type will then be checked. | 
					
						
							|  |  |  | The function must already have been defined. > | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	let Funcref = MyFunction | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When using `function()` the resulting type is "func", a function with any | 
					
						
							|  |  |  | number of arguments and any return type.  The function can be defined later. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-12 16:38:57 +02:00
										 |  |  | Automatic line continuation ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In many cases it is obvious that an expression continues on the next line.  In | 
					
						
							|  |  |  | those cases there is no need to prefix the line with a backslash.  For | 
					
						
							|  |  |  | example, when a list spans multiple lines: > | 
					
						
							|  |  |  | 	let mylist = [ | 
					
						
							|  |  |  | 		'one', | 
					
						
							|  |  |  | 		'two', | 
					
						
							|  |  |  | 		] | 
					
						
							| 
									
										
										
										
											2020-04-12 20:19:16 +02:00
										 |  |  | And when a dict spans multiple lines: > | 
					
						
							|  |  |  | 	let mydict = #{ | 
					
						
							|  |  |  | 		one: 1, | 
					
						
							|  |  |  | 		two: 2, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | Function call: > | 
					
						
							|  |  |  | 	let result = Func( | 
					
						
							|  |  |  | 			arg1, | 
					
						
							|  |  |  | 			arg2 | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 23:02:51 +02:00
										 |  |  | For binary operators in expressions not in [], {} or () a line break is | 
					
						
							|  |  |  | possible just before or after the operator.  For example: > | 
					
						
							|  |  |  | 	let text = lead | 
					
						
							|  |  |  | 		   .. middle | 
					
						
							|  |  |  | 		   .. end | 
					
						
							| 
									
										
										
										
											2020-04-12 20:55:20 +02:00
										 |  |  | 	let total = start + | 
					
						
							|  |  |  | 	            end - | 
					
						
							|  |  |  | 		    correction | 
					
						
							| 
									
										
										
										
											2020-06-22 23:02:51 +02:00
										 |  |  | 	let result = positive | 
					
						
							|  |  |  | 			? PosFunc(arg) | 
					
						
							|  |  |  | 			: NegFunc(arg) | 
					
						
							| 
									
										
										
										
											2020-04-12 20:55:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-21 22:12:03 +02:00
										 |  |  | 	let result = GetBuilder() | 
					
						
							|  |  |  | 			->BuilderSetWidth(333) | 
					
						
							|  |  |  | 			->BuilderSetHeight(777) | 
					
						
							|  |  |  | 			->BuilderBuild() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 23:02:51 +02:00
										 |  |  | <							*E1050* | 
					
						
							|  |  |  | To make it possible for the operator at the start of the line to be | 
					
						
							| 
									
										
										
										
											2020-07-10 22:00:53 +02:00
										 |  |  | recognized, it is required to put a colon before a range.  This will add | 
					
						
							| 
									
										
										
										
											2020-06-22 23:02:51 +02:00
										 |  |  | "start" and print: > | 
					
						
							|  |  |  | 	let result = start | 
					
						
							|  |  |  | 	+ print | 
					
						
							| 
									
										
										
										
											2020-07-10 22:00:53 +02:00
										 |  |  | Like this: > | 
					
						
							|  |  |  | 	let result = start + print | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 23:02:51 +02:00
										 |  |  | This will assign "start" and print a line: > | 
					
						
							|  |  |  | 	let result = start | 
					
						
							|  |  |  | 	:+ print | 
					
						
							| 
									
										
										
										
											2020-04-12 16:38:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-12 21:53:00 +02:00
										 |  |  | It is also possible to split a function header over multiple lines, in between | 
					
						
							|  |  |  | arguments: > | 
					
						
							|  |  |  | 	def MyFunc( | 
					
						
							|  |  |  | 		text: string, | 
					
						
							|  |  |  | 		separator = '-' | 
					
						
							|  |  |  | 		): string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 22:00:53 +02:00
										 |  |  | Notes: | 
					
						
							|  |  |  | - "enddef" cannot be used at the start of a continuation line, it ends the | 
					
						
							|  |  |  |   current function. | 
					
						
							|  |  |  | - No line break is allowed in the LHS of an assignment.  Specifically when | 
					
						
							|  |  |  |   unpacking a list |:let-unpack|. This is OK: > | 
					
						
							|  |  |  |   	[var1, var2] = | 
					
						
							|  |  |  | 		Func() | 
					
						
							|  |  |  | <  This does not work: > | 
					
						
							|  |  |  |   	[var1, | 
					
						
							|  |  |  | 	    var2] = | 
					
						
							|  |  |  | 		Func() | 
					
						
							|  |  |  | - No line break is allowed in between arguments of an `:echo`, `:execute` and | 
					
						
							|  |  |  |   similar commands.  This is OK: > | 
					
						
							|  |  |  |   	echo [1, | 
					
						
							|  |  |  | 		2] [3, | 
					
						
							|  |  |  | 			4] | 
					
						
							|  |  |  | <  This does not work: > | 
					
						
							|  |  |  |   	echo [1, 2] | 
					
						
							|  |  |  | 		[3, 4] | 
					
						
							|  |  |  | - No line break is allowed in the arguments of a lambda, between the "{" and | 
					
						
							|  |  |  |   "->".  This is OK: > | 
					
						
							|  |  |  |   	filter(list, {k, v -> | 
					
						
							|  |  |  | 			v > 0}) | 
					
						
							|  |  |  | <  This does not work: > | 
					
						
							|  |  |  |   	filter(list, {k, | 
					
						
							|  |  |  | 			v -> v > 0}) | 
					
						
							| 
									
										
										
										
											2020-06-22 23:02:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-12 16:38:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | No curly braces expansion ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | |curly-braces-names| cannot be used. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 22:53:05 +01:00
										 |  |  | No :append, :change or :insert ~ | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 22:53:05 +01:00
										 |  |  | These commands are too quickly confused with local variable names. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Comparators ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The 'ignorecase' option is not used for comparators that use strings. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | White space ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vim9 script enforces proper use of white space.  This is no longer allowed: > | 
					
						
							|  |  |  | 	let var=234	" Error! | 
					
						
							|  |  |  | 	let var= 234	" Error! | 
					
						
							|  |  |  | 	let var =234	" Error! | 
					
						
							|  |  |  | There must be white space before and after the "=": > | 
					
						
							|  |  |  | 	let var = 234	" OK | 
					
						
							| 
									
										
										
										
											2020-07-10 22:00:53 +02:00
										 |  |  | White space must also be put before the # that starts a comment after a | 
					
						
							|  |  |  | command: > | 
					
						
							| 
									
										
										
										
											2020-04-13 14:41:35 +02:00
										 |  |  | 	let var = 234# Error! | 
					
						
							|  |  |  | 	let var = 234 # OK | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | White space is required around most operators. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | White space is not allowed: | 
					
						
							|  |  |  | - Between a function name and the "(": > | 
					
						
							|  |  |  |   	call Func (arg)	   " Error! | 
					
						
							|  |  |  |   	call Func | 
					
						
							|  |  |  | 	     \ (arg)	   " Error! | 
					
						
							|  |  |  |   	call Func(arg)	   " OK | 
					
						
							|  |  |  |   	call Func( | 
					
						
							|  |  |  | 	     \ arg)	   " OK | 
					
						
							| 
									
										
										
										
											2020-02-21 18:42:43 +01:00
										 |  |  |   	call Func( | 
					
						
							|  |  |  | 	     \ arg	   " OK | 
					
						
							|  |  |  | 	     \ ) | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Conditions and expressions ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Conditions and expression are mostly working like they do in JavaScript.  A | 
					
						
							|  |  |  | difference is made where JavaScript does not work like most people expect. | 
					
						
							|  |  |  | Specifically, an empty list is falsey. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Any type of variable can be used as a condition, there is no error, not even | 
					
						
							|  |  |  | for using a list or job.  This is very much like JavaScript, but there are a | 
					
						
							|  |  |  | few exceptions. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	type		TRUE when ~ | 
					
						
							|  |  |  | 	bool		v:true | 
					
						
							|  |  |  | 	number		non-zero | 
					
						
							|  |  |  | 	float		non-zero | 
					
						
							|  |  |  | 	string		non-empty | 
					
						
							|  |  |  | 	blob		non-empty | 
					
						
							|  |  |  | 	list		non-empty (different from JavaScript) | 
					
						
							|  |  |  | 	dictionary	non-empty (different from JavaScript) | 
					
						
							| 
									
										
										
										
											2020-04-10 22:10:56 +02:00
										 |  |  | 	func		when there is a function name | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 	special		v:true | 
					
						
							|  |  |  | 	job		when not NULL | 
					
						
							|  |  |  | 	channel		when not NULL | 
					
						
							|  |  |  | 	class		when not NULL | 
					
						
							|  |  |  | 	object		when not NULL (TODO: when isTrue() returns v:true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The boolean operators "||" and "&&" do not change the value: > | 
					
						
							|  |  |  | 	8 || 2   == 8 | 
					
						
							|  |  |  | 	0 || 2   == 2 | 
					
						
							|  |  |  | 	0 || ''  == '' | 
					
						
							|  |  |  | 	8 && 2   == 2 | 
					
						
							|  |  |  | 	0 && 2   == 0 | 
					
						
							| 
									
										
										
										
											2020-07-17 20:36:00 +02:00
										 |  |  | 	2 && 0   == 0 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 	[] && 2  == [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When using `..` for string concatenation the arguments are always converted to | 
					
						
							|  |  |  | string. > | 
					
						
							|  |  |  | 	'hello ' .. 123  == 'hello 123' | 
					
						
							|  |  |  | 	'hello ' .. v:true  == 'hello true' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In Vim9 script one can use "true" for v:true and "false" for v:false. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-30 20:38:27 +02:00
										 |  |  | What to watch out for ~ | 
					
						
							|  |  |  | 							*vim9-gotchas* | 
					
						
							|  |  |  | Vim9 was designed to be closer to often used programming languages, but at the | 
					
						
							|  |  |  | same time tries to support the legacy Vim commands.  Some compromises had to | 
					
						
							|  |  |  | be made.  Here is a summary of what might be unexpected. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ex command ranges need to be prefixed with a colon. > | 
					
						
							|  |  |  |   	->		" legacy Vim: shifts the previous line to the right | 
					
						
							| 
									
										
										
										
											2020-07-17 20:36:00 +02:00
										 |  |  | 	->func()	" Vim9: method call in continuation line | 
					
						
							| 
									
										
										
										
											2020-06-30 20:38:27 +02:00
										 |  |  | 	:->		" Vim9: shifts the previous line to the right | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	%s/a/b		" legacy Vim: substitute on all lines | 
					
						
							|  |  |  | 	x = alongname | 
					
						
							|  |  |  | 	     % another	" Vim9: line continuation without a backslash | 
					
						
							|  |  |  | 	:%s/a/b		" Vim9: substitute on all lines | 
					
						
							| 
									
										
										
										
											2020-07-17 20:36:00 +02:00
										 |  |  | 	'text'->func()	" Vim9: method call | 
					
						
							|  |  |  | 	:'t		" legacy Vim: jump to mark m | 
					
						
							| 
									
										
										
										
											2020-06-30 20:38:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Functions defined with `:def` compile the whole function.  Legacy functions | 
					
						
							|  |  |  | can bail out, and the following lines are not parsed: > | 
					
						
							|  |  |  | 	func Maybe() | 
					
						
							|  |  |  | 	  if !has('feature') | 
					
						
							|  |  |  | 	    return | 
					
						
							|  |  |  | 	  endif | 
					
						
							|  |  |  | 	  use-feature | 
					
						
							|  |  |  | 	endfunc | 
					
						
							|  |  |  | Vim9 functions are compiled as a whole: > | 
					
						
							|  |  |  | 	def Maybe() | 
					
						
							|  |  |  | 	  if !has('feature') | 
					
						
							|  |  |  | 	    return | 
					
						
							|  |  |  | 	  endif | 
					
						
							|  |  |  | 	  use-feature  " May give compilation error | 
					
						
							|  |  |  | 	enddef | 
					
						
							|  |  |  | For a workaround, split it in two functions: > | 
					
						
							|  |  |  | 	func Maybe() | 
					
						
							|  |  |  | 	  if has('feature') | 
					
						
							|  |  |  | 	    call MaybyInner() | 
					
						
							|  |  |  | 	  endif | 
					
						
							|  |  |  | 	endfunc | 
					
						
							|  |  |  | 	if has('feature') | 
					
						
							|  |  |  | 	  def MaybeInner() | 
					
						
							|  |  |  | 	    use-feature | 
					
						
							|  |  |  | 	  enddef | 
					
						
							|  |  |  | 	endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | ============================================================================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 3. New style functions					*fast-functions* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							*:def* | 
					
						
							|  |  |  | :def[!] {name}([arguments])[: {return-type} | 
					
						
							|  |  |  | 			Define a new function by the name {name}.  The body of | 
					
						
							|  |  |  | 			the function follows in the next lines, until the | 
					
						
							|  |  |  | 			matching `:enddef`. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | 			When {return-type} is omitted or is "void" the | 
					
						
							|  |  |  | 			function is not expected to return anything. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			{arguments} is a sequence of zero or more argument | 
					
						
							|  |  |  | 			declarations.  There are three forms: | 
					
						
							|  |  |  | 				{name}: {type} | 
					
						
							|  |  |  | 				{name} = {value} | 
					
						
							|  |  |  | 				{name}: {type} = {value} | 
					
						
							|  |  |  | 			The first form is a mandatory argument, the caller | 
					
						
							|  |  |  | 			must always provide them. | 
					
						
							|  |  |  | 			The second and third form are optional arguments. | 
					
						
							|  |  |  | 			When the caller omits an argument the {value} is used. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | 			The function will be compiled into instructions when | 
					
						
							|  |  |  | 			called, or when `:defcompile` is used.  Syntax and | 
					
						
							|  |  |  | 			type errors will be produced at that time. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 22:53:05 +01:00
										 |  |  | 			NOTE: It is possible to nest `:def` inside another | 
					
						
							|  |  |  | 			`:def`, but it is not possible to nest `:def` inside | 
					
						
							|  |  |  | 			`:function`, for backwards compatibility. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 21:20:45 +02:00
										 |  |  | 			[!] is used as with `:function`.  Note that in Vim9 | 
					
						
							|  |  |  | 			script script-local functions cannot be deleted or | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | 			redefined later in the same script. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							*:enddef* | 
					
						
							|  |  |  | :enddef			End of a function defined with `:def`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 18:42:43 +01:00
										 |  |  | If the script the function is defined in is Vim9 script, then script-local | 
					
						
							|  |  |  | variables can be accessed without the "s:" prefix.  They must be defined | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | before the function is compiled.  If the script the function is defined in is | 
					
						
							|  |  |  | legacy script, then script-local variables must be accessed with the "s:" | 
					
						
							|  |  |  | prefix. | 
					
						
							| 
									
										
										
										
											2020-02-21 18:42:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 21:20:45 +02:00
										 |  |  | 						*:defc* *:defcompile* | 
					
						
							|  |  |  | :defc[ompile]		Compile functions defined in the current script that | 
					
						
							|  |  |  | 			were not compiled yet. | 
					
						
							|  |  |  | 			This will report errors found during the compilation. | 
					
						
							| 
									
										
										
										
											2020-02-21 18:42:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-15 21:41:42 +01:00
										 |  |  | 						*:disa* *:disassemble* | 
					
						
							|  |  |  | :disa[ssemble] {func}	Show the instructions generated for {func}. | 
					
						
							|  |  |  | 			This is for debugging and testing. | 
					
						
							| 
									
										
										
										
											2020-02-29 22:06:30 +01:00
										 |  |  | 			Note that for command line completion of {func} you | 
					
						
							|  |  |  | 			can prepend "s:" to find script-local functions. | 
					
						
							| 
									
										
										
										
											2020-02-15 21:41:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 22:00:53 +02:00
										 |  |  | Limitations ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Local variables will not be visible to string evaluation.  For example: > | 
					
						
							|  |  |  | 	def EvalString(): list<string> | 
					
						
							|  |  |  | 	  let list = ['aa', 'bb', 'cc', 'dd'] | 
					
						
							|  |  |  | 	  return range(1, 2)->map('list[v:val]') | 
					
						
							|  |  |  | 	enddef | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The map argument is a string expression, which is evaluated without the | 
					
						
							|  |  |  | function scope.  Instead, use a lambda: > | 
					
						
							|  |  |  | 	def EvalString(): list<string> | 
					
						
							|  |  |  | 	  let list = ['aa', 'bb', 'cc', 'dd'] | 
					
						
							|  |  |  | 	  return range(1, 2)->map({ _, v -> list[v] }) | 
					
						
							|  |  |  | 	enddef | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | ============================================================================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 4. Types					*vim9-types* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following builtin types are supported: | 
					
						
							|  |  |  | 	bool | 
					
						
							|  |  |  | 	number | 
					
						
							|  |  |  | 	float | 
					
						
							|  |  |  | 	string | 
					
						
							|  |  |  | 	blob | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | 	list<{type}> | 
					
						
							|  |  |  | 	dict<{type}> | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 	job | 
					
						
							|  |  |  | 	channel | 
					
						
							| 
									
										
										
										
											2020-03-14 08:19:51 +01:00
										 |  |  | 	func | 
					
						
							| 
									
										
										
										
											2020-04-10 22:10:56 +02:00
										 |  |  | 	func: {type} | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | 	func({type}, ...) | 
					
						
							|  |  |  | 	func({type}, ...): {type} | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Not supported yet: | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | 	tuple<a: {type}, b: {type}, ...> | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | These types can be used in declarations, but no value will have this type: | 
					
						
							|  |  |  | 	{type}|{type} | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 	void | 
					
						
							|  |  |  | 	any | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | There is no array type, use list<{type}> instead.  For a list constant an | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | efficient implementation is used that avoids allocating lot of small pieces of | 
					
						
							|  |  |  | memory. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | A partial and function can be declared in more or less specific ways: | 
					
						
							|  |  |  | func				any kind of function reference, no type | 
					
						
							| 
									
										
										
										
											2020-04-10 22:10:56 +02:00
										 |  |  | 				checking for arguments or return value | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | func: {type}			any number and type of arguments with specific | 
					
						
							|  |  |  | 				return type | 
					
						
							| 
									
										
										
										
											2020-04-10 22:10:56 +02:00
										 |  |  | func({type})			function with argument type, does not return | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | 				a value | 
					
						
							| 
									
										
										
										
											2020-04-10 22:10:56 +02:00
										 |  |  | func({type}): {type}		function with argument type and return type | 
					
						
							|  |  |  | func(?{type})			function with type of optional argument, does | 
					
						
							|  |  |  | 				not return a value | 
					
						
							|  |  |  | func(...{type})			function with type of variable number of | 
					
						
							|  |  |  | 				arguments, does not return a value | 
					
						
							|  |  |  | func({type}, ?{type}, ...{type}): {type} | 
					
						
							|  |  |  | 				function with: | 
					
						
							|  |  |  | 				- type of mandatory argument | 
					
						
							|  |  |  | 				- type of optional argument | 
					
						
							|  |  |  | 				- type of variable number of arguments | 
					
						
							|  |  |  | 				- return type | 
					
						
							| 
									
										
										
										
											2020-04-03 21:59:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | If the return type is "void" the function does not return a value. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The reference can also be a |Partial|, in which case it stores extra arguments | 
					
						
							|  |  |  | and/or a dictionary, which are not visible to the caller.  Since they are | 
					
						
							|  |  |  | called in the same way the declaration is the same. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Custom types can be defined with `:type`: > | 
					
						
							|  |  |  | 	:type MyList list<string> | 
					
						
							|  |  |  | {not implemented yet} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | And classes and interfaces can be used as types: > | 
					
						
							|  |  |  | 	:class MyClass | 
					
						
							|  |  |  | 	:let mine: MyClass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	:interface MyInterface | 
					
						
							|  |  |  | 	:let mine: MyInterface | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	:class MyTemplate<Targ> | 
					
						
							|  |  |  | 	:let mine: MyTemplate<number> | 
					
						
							|  |  |  | 	:let mine: MyTemplate<string> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	:class MyInterface<Targ> | 
					
						
							|  |  |  | 	:let mine: MyInterface<number> | 
					
						
							|  |  |  | 	:let mine: MyInterface<string> | 
					
						
							|  |  |  | {not implemented yet} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Type inference						*type-inference* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In general: Whenever the type is clear it can be omitted.  For example, when | 
					
						
							|  |  |  | declaring a variable and giving it a value: > | 
					
						
							|  |  |  | 	let var = 0		" infers number type | 
					
						
							|  |  |  | 	let var = 'hello'	" infers string type | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ============================================================================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 5.  Namespace, Import and Export | 
					
						
							|  |  |  | 					*vim9script* *vim9-export* *vim9-import* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A Vim9 script can be written to be imported.  This means that everything in | 
					
						
							|  |  |  | the script is local, unless exported.  Those exported items, and only those | 
					
						
							|  |  |  | items, can then be imported in another script. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Namespace ~ | 
					
						
							|  |  |  | 							*:vim9script* *:vim9* | 
					
						
							| 
									
										
										
										
											2020-02-04 22:53:05 +01:00
										 |  |  | To recognize a file that can be imported the `vim9script` statement must | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | appear as the first statement in the file.  It tells Vim to interpret the | 
					
						
							|  |  |  | script in its own namespace, instead of the global namespace.  If a file | 
					
						
							|  |  |  | starts with: > | 
					
						
							|  |  |  | 	vim9script | 
					
						
							|  |  |  | 	let myvar = 'yes' | 
					
						
							|  |  |  | Then "myvar" will only exist in this file.  While without `vim9script` it would | 
					
						
							|  |  |  | be available as `g:myvar` from any other script and function. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The variables at the file level are very much like the script-local "s:" | 
					
						
							| 
									
										
										
										
											2020-04-20 19:52:53 +02:00
										 |  |  | variables in legacy Vim script, but the "s:" is omitted.  And they cannot be | 
					
						
							|  |  |  | deleted. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-20 19:52:53 +02:00
										 |  |  | In Vim9 script the global "g:" namespace can still be used as before.  And the | 
					
						
							|  |  |  | "w:", "b:" and "t:" namespaces.  These have in common that variables are not | 
					
						
							|  |  |  | declared and they can be deleted. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | A side effect of `:vim9script` is that the 'cpoptions' option is set to the | 
					
						
							|  |  |  | Vim default value, like with: > | 
					
						
							|  |  |  | 	:set cpo&vim | 
					
						
							|  |  |  | One of the effects is that |line-continuation| is always enabled. | 
					
						
							|  |  |  | The original value of 'cpoptions' is restored at the end of the script. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Export ~ | 
					
						
							|  |  |  | 							*:export* *:exp* | 
					
						
							|  |  |  | Exporting one item can be written as: > | 
					
						
							|  |  |  | 	export const EXPORTED_CONST = 1234 | 
					
						
							|  |  |  | 	export let someValue = ... | 
					
						
							|  |  |  | 	export def MyFunc() ... | 
					
						
							|  |  |  | 	export class MyClass ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As this suggests, only constants, variables, `:def` functions and classes can | 
					
						
							|  |  |  | be exported. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Alternatively, an export statement can be used to export several already | 
					
						
							|  |  |  | defined (otherwise script-local) items: > | 
					
						
							|  |  |  | 	export {EXPORTED_CONST, someValue, MyFunc, MyClass} | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | < | 
					
						
							|  |  |  | 							*E1042* | 
					
						
							|  |  |  | `:export` can only be used in Vim9 script, at the script level. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Import ~ | 
					
						
							| 
									
										
										
										
											2020-06-21 22:12:03 +02:00
										 |  |  | 						*:import* *:imp* *E1094* | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | The exported items can be imported individually in another Vim9 script: > | 
					
						
							|  |  |  | 	import EXPORTED_CONST from "thatscript.vim" | 
					
						
							|  |  |  | 	import MyClass from "myclass.vim" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To import multiple items at the same time: > | 
					
						
							|  |  |  | 	import {someValue, MyClass} from "thatscript.vim" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 22:53:05 +01:00
										 |  |  | In case the name is ambiguous, another name can be specified: > | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 	import MyClass as ThatClass from "myclass.vim" | 
					
						
							|  |  |  | 	import {someValue, MyClass as ThatClass} from "myclass.vim" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To import all exported items under a specific identifier: > | 
					
						
							|  |  |  | 	import * as That from 'thatscript.vim' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Then you can use "That.EXPORTED_CONST", "That.someValue", etc.  You are free | 
					
						
							|  |  |  | to choose the name "That", but it is highly recommended to use the name of the | 
					
						
							|  |  |  | script file to avoid confusion. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The script name after `import` can be: | 
					
						
							|  |  |  | - A relative path, starting "." or "..".  This finds a file relative to the | 
					
						
							|  |  |  |   location of the script file itself.  This is useful to split up a large | 
					
						
							|  |  |  |   plugin into several files. | 
					
						
							|  |  |  | - An absolute path, starting with "/" on Unix or "D:/" on MS-Windows.  This | 
					
						
							|  |  |  |   will be rarely used. | 
					
						
							|  |  |  | - A path not being relative or absolute.  This will be found in the | 
					
						
							|  |  |  |   "import" subdirectories of 'runtimepath' entries.  The name will usually be | 
					
						
							|  |  |  |   longer and unique, to avoid loading the wrong file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Once a vim9 script file has been imported, the result is cached and used the | 
					
						
							|  |  |  | next time the same script is imported.  It will not be read again. | 
					
						
							|  |  |  | 							*:import-cycle* | 
					
						
							|  |  |  | The `import` commands are executed when encountered.  If that script (directly | 
					
						
							|  |  |  | or indirectly) imports the current script, then items defined after the | 
					
						
							|  |  |  | `import` won't be processed yet.  Therefore cyclic imports can exist, but may | 
					
						
							|  |  |  | result in undefined items. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Import in an autoload script ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For optimal startup speed, loading scripts should be postponed until they are | 
					
						
							| 
									
										
										
										
											2020-02-04 22:53:05 +01:00
										 |  |  | actually needed.  A recommended mechanism: | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 1. In the plugin define user commands, functions and/or mappings that refer to | 
					
						
							|  |  |  |    an autoload script. > | 
					
						
							|  |  |  |    	command -nargs=1 SearchForStuff call searchfor#Stuff(<f-args>) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <   This goes in .../plugin/anyname.vim.  "anyname.vim" can be freely chosen. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2. In the autocommand script do the actual work.  You can import items from | 
					
						
							|  |  |  |    other files to split up functionality in appropriate pieces. > | 
					
						
							|  |  |  | 	vim9script | 
					
						
							|  |  |  |         import FilterFunc from "../import/someother.vim" | 
					
						
							|  |  |  | 	def searchfor#Stuff(arg: string) | 
					
						
							|  |  |  | 	  let filtered = FilterFunc(arg) | 
					
						
							|  |  |  | 	  ... | 
					
						
							|  |  |  | <   This goes in .../autoload/searchfor.vim.  "searchfor" in the file name | 
					
						
							|  |  |  |    must be exactly the same as the prefix for the function name, that is how | 
					
						
							|  |  |  |    Vim finds the file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 3. Other functionality, possibly shared between plugins, contains the exported | 
					
						
							|  |  |  |    items and any private items. > | 
					
						
							|  |  |  | 	vim9script | 
					
						
							|  |  |  | 	let localVar = 'local' | 
					
						
							|  |  |  |    	export def FilterFunc(arg: string): string | 
					
						
							|  |  |  | 	   ... | 
					
						
							|  |  |  | <   This goes in .../import/someother.vim. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Import in legacy Vim script ~ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | If an `import` statement is used in legacy Vim script, the script-local "s:" | 
					
						
							|  |  |  | namespace will be used for the imported item, even when "s:" is not specified. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ============================================================================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 9. Rationale						*vim9-rationale* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The :def command ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Plugin writers have asked for a much faster Vim script.  Investigation have | 
					
						
							| 
									
										
										
										
											2020-02-04 22:53:05 +01:00
										 |  |  | shown that keeping the existing semantics of function calls make this close to | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | impossible, because of the overhead involved with calling a function, setting | 
					
						
							|  |  |  | up the local function scope and executing lines.  There are many details that | 
					
						
							|  |  |  | need to be handled, such as error messages and exceptions.  The need to create | 
					
						
							|  |  |  | a dictionary for a: and l: scopes, the a:000 list and several others add too | 
					
						
							|  |  |  | much overhead that cannot be avoided. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Therefore the `:def` method to define a new-style function had to be added, | 
					
						
							|  |  |  | which allows for a function with different semantics.  Most things still work | 
					
						
							|  |  |  | as before, but some parts do not.  A new way to define a function was | 
					
						
							|  |  |  | considered the best way to separate the old-style code from Vim9 script code. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Using "def" to define a function comes from Python. Other languages use | 
					
						
							|  |  |  | "function" which clashes with legacy Vim script. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Type checking ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When compiling lines of Vim commands into instructions as much as possible | 
					
						
							|  |  |  | should be done at compile time.  Postponing it to runtime makes the execution | 
					
						
							|  |  |  | slower and means mistakes are found only later.  For example, when | 
					
						
							|  |  |  | encountering the "+" character and compiling this into a generic add | 
					
						
							|  |  |  | instruction, at execution time the instruction would have to inspect the type | 
					
						
							|  |  |  | of the arguments and decide what kind of addition to do.  And when the | 
					
						
							|  |  |  | type is dictionary throw an error.  If the types are known to be numbers then | 
					
						
							|  |  |  | an "add number" instruction can be used, which is faster.  The error can be | 
					
						
							|  |  |  | given at compile time, no error handling is needed at runtime. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The syntax for types is similar to Java, since it is easy to understand and | 
					
						
							|  |  |  | widely used.  The type names are what was used in Vim before, with some | 
					
						
							|  |  |  | additions such as "void" and "bool". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | Compiling functions early ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Functions are compiled when called or when `:defcompile` is used.  Why not | 
					
						
							|  |  |  | compile them early, so that syntax and type errors are reported early? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The functions can't be compiled right away when encountered, because there may | 
					
						
							|  |  |  | be forward references to functions defined later.  Consider defining functions | 
					
						
							|  |  |  | A, B and C, where A calls B, B calls C, and C calls A again.  It's impossible | 
					
						
							|  |  |  | to reorder the functions to avoid forward references. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | An alternative would be to first scan through the file to locate items and | 
					
						
							| 
									
										
										
										
											2020-06-21 22:12:03 +02:00
										 |  |  | figure out their type, so that forward references are found, and only then | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | execute the script and compile the functions.  This means the script has to be | 
					
						
							|  |  |  | parsed twice, which is slower, and some conditions at the script level, such | 
					
						
							|  |  |  | as checking if a feature is supported, are hard to use.  An attempt was made | 
					
						
							|  |  |  | to see if it works, but it turned out to be impossible to make work nicely. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It would be possible to compile all the functions at the end of the script. | 
					
						
							|  |  |  | The drawback is that if a function never gets called, the overhead of | 
					
						
							|  |  |  | compiling it counts anyway.  Since startup speed is very important, in most | 
					
						
							|  |  |  | cases it's better to do it later and accept that syntax and type errors are | 
					
						
							|  |  |  | only reported then.  In case these errors should be found early, e.g. when | 
					
						
							|  |  |  | testing, the `:defcompile` command will help out. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TypeScript syntax and semantics ~ | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Script writers have complained that the Vim script syntax is unexpectedly | 
					
						
							|  |  |  | different from what they are used to.  To reduce this complaint popular | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | languages are used as an example.  At the same time, we do not want to abandon | 
					
						
							|  |  |  | the well-known parts of legacy Vim script. | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Since Vim already uses `:let` and `:const` and optional type checking is | 
					
						
							|  |  |  | desirable, the JavaScript/TypeScript syntax fits best for variable | 
					
						
							|  |  |  | declarations. > | 
					
						
							|  |  |  | 	const greeting = 'hello'  " string type is inferred | 
					
						
							|  |  |  | 	let name: string | 
					
						
							|  |  |  | 	... | 
					
						
							|  |  |  | 	name = 'John' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Expression evaluation was already close to what JavaScript and other languages | 
					
						
							|  |  |  | are doing.  Some details are unexpected and can be fixed.  For example how the | 
					
						
							|  |  |  | || and && operators work.  Legacy Vim script: > | 
					
						
							|  |  |  | 	let result = 44 | 
					
						
							|  |  |  | 	... | 
					
						
							|  |  |  | 	return result || 0	" returns 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | Vim9 script works like JavaScript/Typescript, keep the value: > | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 	let result = 44 | 
					
						
							|  |  |  | 	... | 
					
						
							|  |  |  | 	return result || 0	" returns 44 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | On the other hand, overloading "+" to use both for addition and string | 
					
						
							|  |  |  | concatenation goes against legacy Vim script and often leads to mistakes. | 
					
						
							|  |  |  | For that reason we will keep using ".." for string concatenation.  Lua also | 
					
						
							|  |  |  | uses ".." this way. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Import and Export ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A problem of legacy Vim script is that by default all functions and variables | 
					
						
							|  |  |  | are global.  It is possible to make them script-local, but then they are not | 
					
						
							|  |  |  | available in other scripts. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In Vim9 script a mechanism very similar to the Javascript import and export | 
					
						
							|  |  |  | mechanism is supported.  It is a variant to the existing `:source` command | 
					
						
							|  |  |  | that works like one would expect: | 
					
						
							|  |  |  | - Instead of making everything global by default, everything is script-local, | 
					
						
							|  |  |  |   unless exported. | 
					
						
							|  |  |  | - When importing a script the symbols that are imported are listed, avoiding | 
					
						
							|  |  |  |   name conflicts and failures if later functionality is added. | 
					
						
							|  |  |  | - The mechanism allows for writing a big, long script with a very clear API: | 
					
						
							|  |  |  |   the exported function(s) and class(es). | 
					
						
							|  |  |  | - By using relative paths loading can be much faster for an import inside of a | 
					
						
							|  |  |  |   package, no need to search many directories. | 
					
						
							|  |  |  | - Once an import has been used, it can be cached and loading it again can be | 
					
						
							|  |  |  |   avoided. | 
					
						
							|  |  |  | - The Vim-specific use of "s:" to make things script-local can be dropped. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 17:29:55 +02:00
										 |  |  | When sourcing a Vim9 script from a legacy script, only the items defined | 
					
						
							|  |  |  | globally can be used, not the exported items.  Alternatives considered: | 
					
						
							|  |  |  | - All the exported items become available as script-local items.  This makes | 
					
						
							|  |  |  |   it uncontrollable what items get defined. | 
					
						
							|  |  |  | - Use the exported items and make them global.  Disadvantage is that it's then | 
					
						
							|  |  |  |   not possible to avoid name clashes in the global namespace. | 
					
						
							|  |  |  | - Completely disallow sourcing a Vim9 script, require using `:import`.  That | 
					
						
							|  |  |  |   makes it difficult to use scripts for testing, or sourcing them from the | 
					
						
							|  |  |  |   command line to try them out. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:56:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Classes ~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vim supports interfaces to Perl, Python, Lua, Tcl and a few others.  But | 
					
						
							|  |  |  | these have never become widespread.  When Vim 9 was designed a decision was | 
					
						
							|  |  |  | made to phase out these interfaces and concentrate on Vim script, while | 
					
						
							|  |  |  | encouraging plugin authors to write code in any language and run it as an | 
					
						
							|  |  |  | external tool, using jobs and channels. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Still, using an external tool has disadvantages.  An alternative is to convert | 
					
						
							|  |  |  | the tool into Vim script.  For that to be possible without too much | 
					
						
							|  |  |  | translation, and keeping the code fast at the same time, the constructs of the | 
					
						
							|  |  |  | tool need to be supported.  Since most languages support classes the lack of | 
					
						
							|  |  |  | class support in Vim is then a problem. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Previously Vim supported a kind-of object oriented programming by adding | 
					
						
							|  |  |  | methods to a dictionary.  With some care this could be made to work, but it | 
					
						
							|  |  |  | does not look like real classes.  On top of that, it's very slow, because of | 
					
						
							|  |  |  | the use of dictionaries. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The support of classes in Vim9 script is a "minimal common functionality" of | 
					
						
							|  |  |  | class support in most languages.  It works mostly like Java, which is the most | 
					
						
							|  |  |  | popular programming language. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  vim:tw=78:ts=8:noet:ft=help:norl: |