Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
vim9.txt3690 linesDownload Raw Back to doc
1*vim9.txt*	For Vim version 9.2.  Last change: 2026 Feb 142 3 4		  VIM REFERENCE MANUAL	  by Bram Moolenaar5 6 7Vim9 script commands and expressions.			*Vim9* *vim9*8 9Most expression help is in |eval.txt|.  This file is about the new syntax and10features in Vim9 script.11 12 13 141.  What is Vim9 script?		|Vim9-script|152.  Differences				|vim9-differences|163.  New style functions			|fast-functions|174.  Types				|vim9-types|185.  Generic functions			|generic-functions|196.  Namespace, Import and Export	|vim9script|207.  Classes and interfaces		|vim9-classes|218.  Rationale				|vim9-rationale|22 23 24------------------------------------------------------------------------------25 26  NOTE: In this vim9.txt help file, the Vim9 script code blocks beginning27	with `vim9script` (and individual lines starting with `vim9cmd`) are28	Vim9 script syntax highlighted.  Also, they are sourceable, meaning29	you can run them to see what they output.  To source them, use30	`:'<,'>source` (see |:source-range|), which is done by visually31	selecting the line(s) with |V| and typing `:so`.  For example, try it32	on the following Vim9 script: >vim933 34		vim9script35		echowindow "Welcome to Vim9 script!"36<37	There are also code examples that should not be sourced - they38	explain concepts that don't require a sourceable example.  Such code39	blocks appear in generic code syntax highlighting, like this: >40 41		def ThisFunction()          # script-local42		def g:ThatFunction()        # global43		export def Function()       # for import and import autoload44 45==============================================================================46 471. What is Vim9 script?					*Vim9-script*48 49Vim script has been growing over time, while preserving backwards50compatibility.  That means bad choices from the past often can't be changed51and compatibility with Vi restricts possible solutions.  Execution is quite52slow, each line is parsed every time it is executed.53 54The main goal of Vim9 script is to drastically improve performance.  This is55accomplished by compiling commands into instructions that can be efficiently56executed.  An increase in execution speed of 10 to 100 times can be expected.57 58A secondary goal is to avoid Vim-specific constructs and get closer to59commonly used programming languages, such as JavaScript, TypeScript and Java.60 61The performance improvements can only be achieved by not being 100% backwards62compatible.  For example, making function arguments available in the "a:"63dictionary adds quite a lot of overhead.  In a Vim9 function this dictionary64is not available.  Other differences are more subtle, such as how errors are65handled.66 67Vim9 script syntax, semantics, and behavior apply in:68- a function defined with the `:def` command69- a script file where the first command is `vim9script`70- an autocommand defined in the context of the above71- a command prefixed with the `vim9cmd` command modifier72 73When using `:function` in a Vim9 script file the legacy syntax is used, with74the highest |scriptversion|.  However, this can be confusing and is therefore75discouraged.76 77Vim9 script and legacy Vim script can be mixed.  There is no requirement to78rewrite old scripts, they keep working as before.  You may want to use a few79`:def` functions for code that needs to be fast.80 81:vim9[cmd] {cmd}				*:vim9* *:vim9cmd*82		Evaluate and execute {cmd} using Vim9 script syntax,83		semantics, and behavior.  Useful when typing a command,84		in a `:function`, or a legacy Vim script.85 86		The following short example shows how a legacy Vim script87		command and a :vim9cmd (so Vim9 script context) may appear88		similar, though may differ not just syntactically, but also89		semantically and behaviorally. >vim90 91		  call popup_notification('entrée'[5:]92		    \ ->str2list()->string(), #{time: 7000})93		  vim9cmd popup_notification('entrée'[5 :]94		      ->str2list()->string(), {time: 7000})95<96		 Notes: 1) The reason for the different output is Vim9 script97			   uses character indexing whereas legacy Vim script98			   uses byte indexing - see |vim9-string-index|.99			2) Syntax is different too.  In Vim9 script:100			  - The space in "[5 :]" is mandatory (see101			    |vim9-white-space|).102			  - Line continuation with "\" is not required.103			  - The "#" (to avoid putting quotes around dictionary104			    keys) is neither required nor allowed - see |#{}|.105 106						*E1164*107		`:vim9cmd` cannot stand alone; it must be followed by a command.108 109:leg[acy] {cmd}					*:leg* *:legacy*110		Evaluate and execute {cmd} using legacy Vim script syntax,111		semantics, and behavior.  It is only applicable in a Vim9112		script or a `:def` function.  Using an equivalent script to113		the one, above (see its notes for why the output differs): >vim9114 115		  vim9script116		  # Legacy context - so, this creates a popup with [769, 101]117		  legacy call popup_notification('entrée'[5:]118		    \ ->str2list()->string(), #{time: 7000})119		  # Vim9 script context - so, this creates a pop up with [101]120		  popup_notification('entrée'[5 :]121		      ->str2list()->string(), {time: 7000})122<123		Vim9 script script-local variables may be used by prefixing124		"s:", like in legacy Vim script.  This example shows the125		difference in syntax: "k" for the script-local variable in126		Vim9 script, "s:k" in the legacy Vim script context. >vim9127 128		  vim9script129		  var k: string = "Okay"130		  echo k131		  legacy echo s:k132<						*E1189*133		Using `:legacy` is not allowed in compiled Vim9 script134		control flow contexts. For example: >vim9135 136		  vim9script137		  def F_1189()138		    if v:version == 900139		    # E1189: Cannot use :legacy with this command: endif140		    legacy endif141		  enddef142		  F_1189()143<						*E1234*144		`:legacy` cannot stand alone; it must be followed by a command.145 146 147==============================================================================148 1492. Differences from legacy Vim script			*vim9-differences*150 151Overview ~152							*E1146*153Brief summary of the differences you will most often encounter when using Vim9154script and `:def` functions; details are below:155- Comments start with #, not ": >156	echo "hello"   # comment157- Using a backslash for line continuation is hardly ever needed: >158	echo "hello "159	     .. yourName160	     .. ", how are you?"161- White space is required in many places to improve readability,162  see |vim9-white-space|.163- Assign values without `:let` *E1126* , declare variables with `:var`: >164	var count = 0165	count += 3166- Constants can be declared with `:final` and `:const`: >167	final matches = []		  # add to the list later168	const names = ['Betty', 'Peter']  # cannot be changed169- `:final` cannot be used as an abbreviation of `:finally`.170- Variables and functions are script-local by default.171- Functions are declared with argument types and return type: >172	def CallMe(count: number, message: string): bool173- Call functions without `:call`: >174	writefile(['done'], 'file.txt')175- You cannot use old Ex commands:176	`:Print`177	`:append`178	`:change`179	`:d`  directly followed by 'd' or 'p'.180	`:insert`181	`:k`182	`:mode`183	`:open`184	`:s`  with only flags185	`:t`186	`:xit`187- Some commands, especially those used for flow control, cannot be shortened.188  E.g., `:throw` cannot be written as `:th`.  *vim9-no-shorten*189- You cannot use curly-braces names.190- A range before a command must be prefixed with a colon: >191	:%s/this/that192- Executing a register with "@r" does not work, you can prepend a colon or use193  `:exe`: >194	:exe @a195- Unless mentioned specifically, the highest |scriptversion| is used.196- When defining an expression mapping, the expression will be evaluated in the197  context of the script where it was defined.198- When indexing a string the index is counted in characters, not bytes:199  |vim9-string-index|200- Some possibly unexpected differences: |vim9-gotchas|.201 202 203Comments starting with # ~204 205In legacy Vim script comments start with double quote.  In Vim9 script206comments start with #. >207	# declarations208	var count = 0  # number of occurrences209 210The reason is that a double quote can also be the start of a string. In many211places, especially halfway through an expression with a line break, it's hard212to tell what the meaning is, since both a string and a comment can be followed213by arbitrary text.  To avoid confusion only # comments are recognized.  This214is the same as in shell scripts and Python programs.215 216In Vi # is a command to list text with numbers.  In Vim9 script you can use217`:number` for that. >218	:101 number219 220To improve readability there must be a space between a command and the #221that starts a comment: >222	var name = value # comment223	var name = value# error!224<							*E1170*225Do not start a comment with #{, it looks like the legacy dictionary literal226and produces an error where this might be confusing.  #{{ or #{{{ are OK,227these can be used to start a fold.228 229When starting to read a script file Vim doesn't know it is |Vim9| script until230the `vim9script` command is found.  Until that point you would need to use231legacy comments: >232	" legacy comment233	vim9script234	# Vim9 comment235 236That looks ugly, better put `vim9script` in the very first line: >237	vim9script238	# Vim9 comment239 240In legacy Vim script # is also used for the alternate file name.  In Vim9241script you need to use %% instead.  Instead of ## use %%% (stands for all242arguments).243 244 245Vim9 functions ~246							*E1099*247A function defined with `:def` is compiled.  Execution is many times faster,248often 10 to 100 times.249 250Many errors are already found when compiling, before the function is executed.251The syntax is strict, to enforce code that is easy to read and understand.252 253Compilation is done when any of these is encountered:254- the first time the function is called255- when the `:defcompile` command is encountered in the script after the256  function was defined257- `:disassemble` is used for the function.258- a function that is compiled calls the function or uses it as a function259  reference (so that the argument and return types can be checked)260						*E1091* *E1191*261If compilation fails it is not tried again on the next call, instead this262error is given: "E1091: Function is not compiled: {name}".263Compilation will fail when encountering a user command that has not been264created yet.  In this case you can call `execute()` to invoke it at runtime. >265	def MyFunc()266	  execute('DefinedLater')267	enddef268 269`:def` has no options like `:function` does: "range", "abort", "dict" or270"closure".  A `:def` function always aborts on an error (unless `:silent!` was271used for the command or the error was caught a `:try` block), does not get a272range passed, cannot be a "dict" function, and can always be a closure.273						*vim9-no-dict-function* *E1182*274You can use a Vim9 Class (|Vim9-class|) instead of a "dict function".275You can also pass the dictionary explicitly: >276	def DictFunc(self: dict<any>, arg: string)277	   echo self[arg]278	enddef279	var ad = {item: 'value', func: DictFunc}280	ad.func(ad, 'item')281 282You can call a legacy dict function though: >283	func Legacy() dict284	  echo self.value285	endfunc286	def CallLegacy()287	  var d = {func: Legacy, value: 'text'}288	  d.func()289	enddef290 291The argument types and return type need to be specified.  The "any" type can292be used, type checking will then be done at runtime, like with legacy293functions.294							*E1106*295Arguments are accessed by name, without "a:", just like any other language.296There is no "a:" dictionary or "a:000" list.297			*vim9-variable-arguments* *E1055* *E1160* *E1180*298Variable arguments are defined as the last argument, with a name and have a299list type, similar to TypeScript.  For example, a list of numbers: >300	def MyFunc(...itemlist: list<number>)301	   for item in itemlist302	     ...303 304When a function argument is optional (it has a default value) passing `v:none`305as the argument results in using the default value.  This is useful when you306want to specify a value for an argument that comes after an argument that307should use its default value.  Example: >308	def MyFunc(one = 'one', last = 'last')309	  ...310	enddef311	MyFunc(v:none, 'LAST')  # first argument uses default value 'one'312<313					*vim9-ignored-argument* *E1181*314The argument "_" (an underscore) can be used to ignore the argument.  This is315most useful in callbacks where you don't need it, but do need to give an316argument to match the call.  E.g. when using map() two arguments are passed,317the key and the value, to ignore the key: >318	map(numberList, (_, v) => v * 2)319There is no error for using the "_" argument multiple times.  No type needs to320be given.321 322 323Functions and variables are script-local by default ~324							*vim9-scopes*325When using `:function` or `:def` to specify a new function at the script level326in a Vim9 script, the function is local to the script.  Like prefixing "s:" in327legacy script.  To define a global function or variable the "g:" prefix must328be used.  For functions in a script that is to be imported and in an autoload329script "export" needs to be used for those to be used elsewhere. >330	def ThisFunction()          # script-local331	def g:ThatFunction()        # global332	export def Function()       # for import and import autoload333<						*E1075*334When using `:function` or `:def` to specify a nested function inside a `:def`335function and no namespace was given, this nested function is local to the code336block it is defined in.  It cannot be used in `function()` with a string337argument, pass the function reference itself: >338	def Outer()339	  def Inner()340	    echo 'inner'341	  enddef342	  var Fok = function(Inner)     # OK343	  var Fbad = function('Inner')  # does not work344 345Detail: this is because "Inner" will actually become a function reference to a346function with a generated name.347 348It is not possible to define a script-local function in a function.  You can349define a local function and assign it to a script-local Funcref (it must have350been declared at the script level).  It is possible to define a global351function by using the "g:" prefix.352 353When referring to a function and no "s:" or "g:" prefix is used, Vim will354search for the function:355- in the function scope, in block scopes356- in the script scope357 358Imported functions are found with the prefix from the `:import` command.359 360Since a script-local function reference can be used without "s:" the name must361start with an upper case letter even when using the "s:" prefix.  In legacy362script "s:funcref" could be used, because it could not be referred to with363"funcref".  In Vim9 script it can, therefore "s:Funcref" must be used to avoid364that the name interferes with builtin functions.365						*vim9-s-namespace* *E1268*366The use of the "s:" prefix is not supported at the Vim9 script level.  All367functions and variables without a prefix are script-local.368 369In :def functions the use of "s:" depends on the script: Script-local370variables and functions in a legacy script do use "s:", while in a Vim9 script371they do not use "s:".  This matches what you see in the rest of the file.372 373In legacy functions the use of "s:" for script items is required, as before.374No matter if the script is Vim9 or legacy.375 376In all cases the function must be defined before used.  That is when it is377called, when `:defcompile` causes it to be compiled, or when code that calls378it is being compiled (to figure out the return type).379 380The result is that functions and variables without a namespace can usually be381found in the script, either defined there or imported.  Global functions and382variables could be defined anywhere (good luck finding out where!  You can383often see where it was last set using |:verbose|).384							*E1102*385Global functions can still be defined and deleted at nearly any time.  In386Vim9 script script-local functions are defined once when the script is sourced387and cannot be deleted or replaced by itself (it can be by reloading the388script).389 390When compiling a function and a function call is encountered for a function391that is not (yet) defined, the |FuncUndefined| autocommand is not triggered.392You can use an autoload function if needed, or call a legacy function and have393|FuncUndefined| triggered there.394 395 396Reloading a Vim9 script clears functions and variables by default ~397						*vim9-reload* *E1149* *E1150*398When loading a legacy Vim script a second time nothing is removed, the399commands will replace existing variables and functions, create new ones, and400leave removed things hanging around.401 402When loading a Vim9 script a second time all existing script-local functions403and variables are deleted, thus you start with a clean slate.  This is useful404if you are developing a plugin and want to try a new version.  If you renamed405something you don't have to worry about the old name still hanging around.406 407If you do want to keep items, use: >408	vim9script noclear409 410You want to use this in scripts that use a `finish` command to bail out at411some point when loaded again.  E.g. when a buffer local option is set to a412function, the function does not need to be defined more than once: >413	vim9script noclear414	setlocal completefunc=SomeFunc415	if exists('*SomeFunc')416	  finish417	endif418	def SomeFunc()419	....420 421 422Variable declarations with :var, :final and :const ~423				*vim9-declaration* *:var* *E1079*424				*E1017* *E1020* *E1054* *E1087* *E1124*425Local variables need to be declared with `:var`.  Local constants need to be426declared with `:final` or `:const`.  We refer to both as "variables" in this427section.428 429Variables can be local to a script, function or code block: >430	vim9script431	var script_var = 123432	def SomeFunc()433	  var func_var = script_var434	  if cond435	    var block_var = func_var436	  ...437 438The variables are only visible in the block where they are defined and nested439blocks.  Once the block ends the variable is no longer accessible: >440	if cond441	   var inner = 5442	else443	   var inner = 0444	endif445	echo inner  # Error!446 447The declaration must be done earlier: >448	var inner: number449	if cond450	   inner = 5451	else452	   inner = 0453	endif454	echo inner455 456Although this is shorter and faster for simple values: >457	var inner = 0458	if cond459	   inner = 5460	endif461	echo inner462<							*E1025* *E1128*463To intentionally hide a variable from code that follows, a block can be464used: >465	{466	   var temp = 'temp'467	   ...468	}469	echo temp  # Error!470 471This is especially useful in a user command: >472	command -range Rename {473		 var save = @a474		 @a = 'some expression'475		 echo 'do something with ' .. @a476		 @a = save477	    }478 479And with autocommands: >480   au BufWritePre *.go {481		 var save = winsaveview()482		 silent! exe ':%! some formatting command'483		 winrestview(save)484	   }485 486Although using a :def function probably works better.487 488				*E1022* *E1103* *E1130* *E1131* *E1133*489				*E1134*490Declaring a variable with a type but without an initializer will initialize to491false (for bool), empty (for string, list, dict, etc.) or zero (for number,492any, etc.).  This matters especially when using the "any" type, the value will493default to the number zero.  For example, when declaring a list, items can be494added: >495	var myList: list<number>496	myList->add(7)497 498Initializing a variable to a null value, e.g. `null_list`, differs from not499initializing the variable.  This throws an error: >500	var myList = null_list501	myList->add(7)  # E1130: Cannot add to null list502 503<						*E1016* *E1052* *E1066*504In Vim9 script `:let` cannot be used.  An existing variable is assigned to505without any command.  The same for global, window, tab, buffer and Vim506variables, because they are not really declared.  Those can also be deleted507with `:unlet`.508							*E1065*509You cannot use `:va` to declare a variable, it must be written with the full510name `:var`.  Just to make sure it is easy to read.511							*E1178*512`:lockvar` does not work on local variables.  Use `:const` and `:final`513instead.514 515The `exists()` and `exists_compiled()` functions do not work on local variables516or arguments.517				*E1006* *E1041* *E1167* *E1168* *E1213*518Variables, functions and function arguments cannot shadow previously defined519or imported variables and functions in the same script file.520Variables may shadow Ex commands, rename the variable if needed.521 522Global variables must be prefixed with "g:", also at the script level. >523	vim9script524	var script_local = 'text'525	g:global = 'value'526	var Funcref = g:ThatFunction527 528Global functions must be prefixed with "g:": >529	vim9script530	def g:GlobalFunc(): string531	  return 'text'532	enddef533	echo g:GlobalFunc()534The "g:" prefix is not needed for auto-load functions.535 536					*vim9-function-defined-later*537Although global functions can be called without the "g:" prefix, they must538exist when compiled.  By adding the "g:" prefix the function can be defined539later.  Example: >540	def CallPluginFunc()541	  if exists('g:loaded_plugin')542	    g:PluginFunc()543	  endif544	enddef545 546If you do it like this, you get an error at compile time that "PluginFunc"547does not exist, even when "g:loaded_plugin" does not exist: >548	def CallPluginFunc()549	  if exists('g:loaded_plugin')550	    PluginFunc()   # Error - function not found551	  endif552	enddef553 554You can use exists_compiled() to avoid the error, but then the function would555not be called, even when "g:loaded_plugin" is defined later: >556	def CallPluginFunc()557	  if exists_compiled('g:loaded_plugin')558	    PluginFunc()   # Function may never be called559	  endif560	enddef561 562Since `&opt = value` is now assigning a value to option "opt", ":&" cannot be563used to repeat a `:substitute` command.564							*vim9-unpack-ignore*565For an unpack assignment the underscore can be used to ignore a list item,566similar to how a function argument can be ignored: >567	[a, _, c] = theList568To ignore any remaining items: >569	[a, b; _] = longList570<							*E1163* *E1080*571Declaring more than one variable at a time, using the unpack notation, is572possible.  Each variable can have a type or infer it from the value: >573	var [v1: number, v2] = GetValues()574Use this only when there is a list with values, declaring one variable per575line is much easier to read and change later.576 577 578Constants ~579						*vim9-const* *vim9-final*580How constants work varies between languages.  Some consider a variable that581can't be assigned another value a constant.  JavaScript is an example.  Others582also make the value immutable, thus when a constant uses a list, the list583cannot be changed.  In Vim9 we can use both.584							*E1021* *E1307*585`:const` is used for making both the variable and the value a constant.  Use586this for composite structures that you want to make sure will not be modified.587Example: >588	const myList = [1, 2]589	myList = [3, 4]		# Error!590	myList[0] = 9		# Error!591	myList->add(3)		# Error!592<							*:final* *E1125*593`:final` is used for making only the variable a constant, the value can be594changed.  This is well known from Java.  Example: >595	final myList = [1, 2]596	myList = [3, 4]		# Error!597	myList[0] = 9		# OK598	myList->add(3)		# OK599 600It is common to write constants as ALL_CAPS, but you don't have to.601 602The constant only applies to the value itself, not what it refers to. >603	final females = ["Mary"]604	const NAMES = [["John", "Peter"], females]605	NAMES[0] = ["Jack"]     # Error!606	NAMES[0][0] = "Jack"    # Error!607	NAMES[1] = ["Emma"]     # Error!608	NAMES[1][0] = "Emma"    # OK, now females[0] == "Emma"609 610 611Omitting :call and :eval ~612							*E1190*613Functions can be called without `:call`: >614	writefile(lines, 'file')615Using `:call` is still possible, but this is discouraged.616 617A method call without `eval` is possible, so long as the start is an618identifier or can't be an Ex command.  For a function either "(" or "->" must619be following, without a line break.  Examples: >620	myList->add(123)621	g:myList->add(123)622	[1, 2, 3]->Process()623	{a: 1, b: 2}->Process()624	"foobar"->Process()625	("foobar")->Process()626	'foobar'->Process()627	('foobar')->Process()628 629In the rare case there is ambiguity between a function name and an Ex command,630prepend ":" to make clear you want to use the Ex command.  For example, there631is both the `:substitute` command and the `substitute()` function.  When the632line starts with `substitute(` this will use the function. Prepend a colon to633use the command instead: >634	:substitute(pattern (replacement (635 636If the expression starts with "!" this is interpreted as a shell command, not637negation of a condition.  Thus this is a shell command: >638	!shellCommand->something639Put the expression in parentheses to use the "!" for negation: >640	(!expression)->Method()641 642Note that while variables need to be defined before they can be used,643functions can be called before being defined.  This is required to allow644for cyclic dependencies between functions.  It is slightly less efficient,645since the function has to be looked up by name.  And a typo in the function646name will only be found when the function is called.647 648 649Omitting function() ~650 651A user defined function can be used as a function reference in an expression652without `function()`. The argument types and return type will then be checked.653The function must already have been defined. >654 655	var Funcref = MyFunction656 657When using `function()` the resulting type is "func", a function with any658number of arguments and any return type (including void).  The function can be659defined later if the argument is in quotes.660 661 662Lambda using => instead of -> ~663							*vim9-lambda*664In legacy script there can be confusion between using "->" for a method call665and for a lambda.  Also, when a "{" is found the parser needs to figure out if666it is the start of a lambda or a dictionary, which is now more complicated667because of the use of argument types.668 669To avoid these problems Vim9 script uses a different syntax for a lambda,670which is similar to JavaScript: >671	var Lambda = (arg) => expression672	var Lambda = (arg): type => expression673<							*E1157*674No line break is allowed in the arguments of a lambda up to and including the675"=>" (so that Vim can tell the difference between an expression in parentheses676and lambda arguments).  This is OK: >677	filter(list, (k, v) =>678			v > 0)679This does not work: >680	filter(list, (k, v)681			=> v > 0)682This also does not work: >683	filter(list, (k,684			v) => v > 0)685But you can use a backslash to concatenate the lines before parsing: >686	filter(list, (k,687		\	v)688		\	=> v > 0)689<					*vim9-lambda-arguments* *E1172*690In legacy script a lambda could be called with any number of extra arguments,691there was no way to warn for not using them.  In Vim9 script the number of692arguments must match.  If you do want to accept any arguments, or any further693arguments, use "..._", which makes the function accept694|vim9-variable-arguments|.  Example: >695	var Callback = (..._) => 'anything'696	echo Callback(1, 2, 3)  # displays "anything"697 698<						*inline-function* *E1171*699Additionally, a lambda can contain statements in {}: >700	var Lambda = (arg) => {701		g:was_called = 'yes'702		return expression703	    }704This can be useful for a timer, for example: >705	var count = 0706	var timer = timer_start(500, (_) => {707		 count += 1708		 echom 'Handler called ' .. count709	     }, {repeat: 3})710 711The ending "}" must be at the start of a line.  It can be followed by other712characters, e.g.: >713	var d = mapnew(dict, (k, v): string => {714	     return 'value'715	   })716No command can follow the "{", only a comment can be used there.717 718						*command-block* *E1026*719The block can also be used for defining a user command.  Inside the block Vim9720syntax will be used.721 722This is an example of using here-docs: >723    com SomeCommand {724        g:someVar =<< trim eval END725          ccc726          ddd727        END728      }729 730If the statements include a dictionary, its closing bracket must not be731written at the start of a line.  Otherwise, it would be parsed as the end of732the block.  This does not work: >733	command NewCommand {734	     g:mydict = {735	       'key': 'value',736	       }  # ERROR: will be recognized as the end of the block737	   }738Put the '}' after the last item to avoid this: >739	command NewCommand {740	     g:mydict = {741	       'key': 'value' }742	   }743 744Rationale: The "}" cannot be after a command because it would require parsing745the commands to find it.  For consistency with that no command can follow the746"{".  Unfortunately this means using "() => {  command  }" does not work, line747breaks are always required.748 749							*vim9-curly*750To avoid the "{" of a dictionary literal to be recognized as a statement block751wrap it in parentheses: >752	var Lambda = (arg) => ({key: 42})753 754Also when confused with the start of a command block: >755	({756	    key: value757	 })->method()758 759 760Automatic line continuation ~761					*vim9-line-continuation* *E1097*762In many cases it is obvious that an expression continues on the next line.  In763those cases there is no need to prefix the line with a backslash (see764|line-continuation|).  For example, when a list spans multiple lines: >765	var mylist = [766		'one',767		'two',768		]769And when a dict spans multiple lines: >770	var mydict = {771		one: 1,772		two: 2,773		}774With a function call: >775	var result = Func(776			arg1,777			arg2778			)779 780For binary operators in expressions not in [], {} or () a line break is781possible just before or after the operator.  For example: >782	var text = lead783		   .. middle784		   .. end785	var total = start +786		    end -787		    correction788	var result = positive789			? PosFunc(arg)790			: NegFunc(arg)791 792For a method call using "->" and a member using a dot, a line break is allowed793before it: >794	var result = GetBuilder()795			->BuilderSetWidth(333)796			->BuilderSetHeight(777)797			->BuilderBuild()798	var result = MyDict799			.member800 801For commands that have an argument that is a list of commands, the | character802at the start of the line indicates line continuation: >803	autocmd BufNewFile *.match if condition804		|   echo 'match'805		| endif806 807Note that this means that in heredoc the first line cannot start with a bar: >808	var lines =<< trim END809	   | this doesn't work810	END811Either use an empty line at the start or do not use heredoc.  Or temporarily812add the "C" flag to 'cpoptions': >813	set cpo+=C814	var lines =<< trim END815	   | this works816	END817	set cpo-=C818If the heredoc is inside a function 'cpoptions' must be set before :def and819restored after the :enddef.820 821In places where line continuation with a backslash is still needed, such as822splitting up a long Ex command, comments can start with '#\ ': >823	syn region Text824	      \ start='foo'825	      #\ comment826	      \ end='bar'827Like with legacy script '"\ ' is used.  This is also needed when line828continuation is used without a backslash and a line starts with a bar: >829	au CursorHold * echom 'BEFORE bar'830	      #\ some comment831	      | echom 'AFTER bar'832<833							*E1050*834To make it possible for the operator at the start of the line to be835recognized, it is required to put a colon before a range.  This example will836add "start" and "print": >837	var result = start838	+ print839Like this: >840	var result = start + print841 842This will assign "start" and print a line: >843	var result = start844	:+ print845 846After the range an Ex command must follow.  Without the colon you can call a847function without `:call`, but after a range you do need it: >848	MyFunc()849	:% call MyFunc()850 851Note that the colon is not required for the |+cmd| argument: >852	edit +6 fname853 854It is also possible to split a function header over multiple lines, in between855arguments: >856	def MyFunc(857		text: string,858		separator = '-'859		): string860 861Since a continuation line cannot be easily recognized the parsing of commands862has been made stricter.  E.g., because of the error in the first line, the863second line is seen as a separate command: >864	popup_create(some invalid expression, {865	   exit_cb: Func})866Now "exit_cb: Func})" is actually a valid command: save any changes to the867file "_cb: Func})" and exit.  To avoid this kind of mistake in Vim9 script868there must be white space between most command names and the argument.869*E1144*870 871However, the argument of a command that is a command won't be recognized.  For872example, after "windo echo expr" a line break inside "expr" will not be seen.873 874 875Notes:876- "enddef" cannot be used at the start of a continuation line, it ends the877  current function.878- No line break is allowed in the LHS of an assignment.  Specifically when879  unpacking a list |:let-unpack|. This is OK: >880	[var1, var2] =881		Func()882<  This does not work: >883	[var1,884	    var2] =885		Func()886- No line break is allowed in between arguments of an `:echo`, `:execute` and887  similar commands.  This is OK: >888	echo [1,889		2] [3,890			4]891<  This does not work: >892	echo [1, 2]893		[3, 4]894- In some cases it is difficult for Vim to parse a command, especially when895  commands are used as an argument to another command, such as `:windo`.  In896  those cases the line continuation with a backslash has to be used.897 898 899White space ~900	*vim9-white-space* *E1004* *E1068* *E1069* *E1074* *E1127* *E1202*901Vim9 script enforces proper use of white space.  This is no longer allowed: >902	var name=234	# Error!903	var name= 234	# Error!904	var name =234	# Error!905There must be white space before and after the "=": >906	var name = 234	# OK907White space must also be put before the # that starts a comment after a908command: >909	var name = 234# Error!910	var name = 234 # OK911 912White space is required around most operators.913 914White space is required in a sublist (list slice) around the ":", except at915the start and end: >916	otherlist = mylist[v : count]	# v:count has a different meaning917	otherlist = mylist[:]		# make a copy of the List918	otherlist = mylist[v :]919	otherlist = mylist[: v]920 921White space is not allowed:922- Between a function name and the "(": >923	Func (arg)	   # Error!924	Func925	     \ (arg)	   # Error!926	Func927	      (arg)	   # Error!928	Func(arg)	   # OK929	Func(930	      arg)	   # OK931	Func(932	      arg	   # OK933	      )934<							*E1205*935White space is not allowed in a `:set` command between the option name and a936following "&", "!", "<", "=", "+=", "-=" or "^=".937 938 939No curly braces expansion ~940 941|curly-braces-names| cannot be used.942 943 944Command modifiers are not ignored ~945								*E1176*946Using a command modifier for a command that does not use it gives an error.947								*E1082*948Also, using a command modifier without a following command is now an error.949 950 951Dictionary literals ~952						*vim9-literal-dict* *E1014*953Traditionally Vim has supported dictionary literals with a {} syntax: >954	let dict = {'key': value}955 956Later it became clear that using a simple text key is very common, thus957literal dictionaries were introduced in a backwards compatible way: >958	let dict = #{key: value}959 960However, this #{} syntax is unlike any existing language.  As it turns out961that using a literal key is much more common than using an expression, and962considering that JavaScript uses this syntax, using the {} form for dictionary963literals is considered a much more useful syntax.  In Vim9 script the {} form964uses literal keys: >965	var dict = {key: value}966 967This works for alphanumeric characters, underscore and dash.  If you want to968use another character, use a single or double quoted string: >969	var dict = {'key with space': value}970	var dict = {"key\twith\ttabs": value}971	var dict = {'': value}			# empty key972<							*E1139*973In case the key needs to be an expression, square brackets can be used, just974like in JavaScript: >975	var dict = {["key" .. nr]: value}976 977The key type can be string, number, bool or float.  Other types result in an978error.  Without using [] the value is used as a string, keeping leading zeros.979An expression given with [] is evaluated and then converted to a string.980Leading zeros will then be dropped: >981	var dict = {000123: 'without', [000456]: 'with'}982	echo dict983	{'456': 'with', '000123': 'without'}984A float only works inside [] because the dot is not accepted otherwise: >985	var dict = {[00.013]: 'float'}986	echo dict987	{'0.013': 'float'}988 989 990No :xit, :t, :k, :append, :change or :insert ~991							*E1100*992These commands are too easily confused with local variable names.993Instead of `:x` or `:xit` you can use `:exit`.994Instead of `:t` you can use `:copy`.995Instead of `:k` you can use `:mark`.996 997 998Comparators ~999 1000The 'ignorecase' option is not used for comparators that use strings.1001Thus "=~" works like "=~#".1002 1003"is" and "isnot" (|expr-is| and |expr-isnot|) when used on strings now return1004false.  In legacy script they just compare the strings, in |Vim9| script they1005check identity, and strings are copied when used, thus two strings are never1006the same (this might change someday if strings are not copied but reference1007counted).1008 1009 1010Abort after error ~1011 1012In legacy script, when an error is encountered, Vim continues to execute1013following lines.  This can lead to a long sequence of errors and need to type1014CTRL-C to stop it.  In Vim9 script execution of commands stops at the first1015error.  Example: >1016	vim9script1017	var x = does-not-exist1018	echo 'not executed'1019 1020 1021For loop ~1022							*E1254*1023The loop variable must not be declared yet: >1024	var i = 11025	for i in [1, 2, 3]   # Error!1026 1027It is possible to use a global variable though: >1028	g:i = 11029	for g:i in [1, 2, 3]1030	  echo g:i1031	endfor1032 1033Legacy Vim script has some tricks to make a for loop over a list handle1034deleting items at the current or previous item.  In Vim9 script it just uses1035the index, if items are deleted then items in the list will be skipped.1036Example legacy script: >1037	let l = [1, 2, 3, 4]1038	for i in l1039	   echo i1040	   call remove(l, index(l, i))1041	endfor1042Would echo:1043	11044	21045	31046	41047In compiled Vim9 script you get:1048	11049	31050Generally, you should not change the list that is iterated over.  Make a copy1051first if needed.1052When looping over a list of lists, the nested lists can be changed.  The loop1053variable is "final", it cannot be changed but what its value can be changed.1054							*E1306*1055The depth of loops, :for and :while loops added together, cannot exceed 10.1056 1057 1058Conditions and expressions ~1059						*vim9-boolean*1060Conditions and expressions are mostly working like they do in other languages.1061Some values are different from legacy Vim script:1062	value		legacy Vim script	Vim9 script ~1063	0		falsy			falsy1064	1		truthy			truthy1065	99		truthy			Error!1066	"0"		falsy			Error!1067	"99"		truthy			Error!1068	"text"		falsy			Error!1069 1070For the "??" operator and when using "!" then there is no error, every value1071is either falsy or truthy.  This is mostly like JavaScript, except that an1072empty list and dict is falsy:1073 1074	type		truthy when ~1075	bool		true, v:true or 11076	number		non-zero1077	float		non-zero1078	string		non-empty1079	blob		non-empty1080	list		non-empty (different from JavaScript)1081	tuple		non-empty (different from JavaScript)1082	dictionary	non-empty (different from JavaScript)1083	func		when there is a function name1084	special		true or v:true1085	job		when not NULL1086	channel		when not NULL1087	class		not applicable1088	object		when not NULL1089	enum		not applicable1090	enum value	always1091	typealias	not applicable1092 1093The boolean operators "||" and "&&" expect the values to be boolean, zero or1094one: >1095	1 || false   == true1096	0 || 1       == true1097	0 || false   == false1098	1 && true    == true1099	0 && 1       == false1100	8 || 0	     Error!1101	'yes' && 0   Error!1102	[] || 99     Error!1103 1104When using "!" for inverting, there is no error for using any type and the1105result is a boolean.  "!!" can be used to turn any value into boolean: >1106	!'yes'			== false1107	!![]			== false1108	!![1, 2, 3]		== true1109 1110When using "`.."` for string concatenation arguments of simple types are1111always converted to string: >1112	'hello ' .. 123  == 'hello 123'1113	'hello ' .. v:true  == 'hello true'1114 1115Simple types are Number, Float, Special and Bool.  For other types |string()|1116should be used.1117			*false* *true* *null* *null_blob* *null_channel*1118			*null_class* *null_dict* *null_function* *null_job*1119			*null_list* *null_object* *null_partial* *null_string*1120			*E1034*1121In Vim9 script one can use the following predefined values: >1122	true1123	false1124	null1125	null_blob1126	null_channel1127	null_class1128	null_dict1129	null_function1130	null_job1131	null_list1132	null_tuple1133	null_object1134	null_partial1135	null_string1136`true` is the same as `v:true`, `false` the same as `v:false`, `null` the same1137as `v:null`.1138 1139While `null` has the type "special", the other "null_" values have the type1140indicated by their name.  Quite often a null value is handled the same as an1141empty value, but not always.  The values can be useful to clear a script-local1142variable, since they cannot be deleted with `:unlet`.  E.g.: >1143	var theJob = job_start(...)1144	# let the job do its work1145	theJob = null_job1146 1147The values can also be useful as the default value for an argument: >1148	def MyFunc(b: blob = null_blob)1149	    # Note: compare against null, not null_blob,1150	    #       to distinguish the default value from an empty blob.1151	    if b == null1152	        # b argument was not given1153See |null-compare| for more information about testing against null.1154 1155It is possible to compare `null`  with any value, this will not give a type1156error.  However, comparing `null` with a number, float or bool will always1157result in `false`.  This is different from legacy script, where comparing1158`null` with zero or `false` would return `true`.1159							*vim9-false-true*1160When converting a boolean to a string `false` and `true` are used, not1161`v:false` and `v:true` like in legacy script.  `v:none` has no `none`1162replacement, it has no equivalent in other languages.1163							*vim9-string-index*1164Indexing a string with [idx] or taking a slice with [idx : idx] uses character1165indexes instead of byte indexes.  Composing characters are included.1166Example: >1167	echo 'bár'[1]1168In legacy script this results in the character 0xc3 (an illegal byte), in Vim91169script this results in the string 'á'.1170A negative index is counting from the end, "[-1]" is the last character.1171To exclude the last character use |slice()|.1172To count composing characters separately use |strcharpart()|.1173If the index is out of range then an empty string results.1174 1175In legacy script "++var" and "--var" would be silently accepted and have no1176effect.  This is an error in Vim9 script.1177 1178Numbers starting with zero are not considered to be octal, only numbers1179starting with "0o" are octal: "0o744". |scriptversion-4|1180 1181 1182What to watch out for ~1183							*vim9-gotchas*1184Vim9 was designed to be closer to often used programming languages, but at the1185same time tries to support the legacy Vim commands.  Some compromises had to1186be made.  Here is a summary of what might be unexpected.1187 1188Ex command ranges need to be prefixed with a colon. >1189	->		  legacy Vim: shifts the previous line to the right1190	->func()	  Vim9: method call in a continuation line1191	:->		  Vim9: shifts the previous line to the right1192 1193	%s/a/b		  legacy Vim: substitute on all lines1194	x = alongname1195	     % another	  Vim9: modulo operator in a continuation line1196	:%s/a/b		  Vim9: substitute on all lines1197	't		  legacy Vim: jump to mark t1198	'text'->func()	  Vim9: method call1199	:'t		  Vim9: jump to mark t1200 

Showing the first 1,200 of 3690 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai