blob: d06c250a3f564731c5f369c2a471b5449abb4e28 [file] [log] [blame]
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001*vim9.txt* For Vim version 9.1. Last change: 2025 Mar 23
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002
3
4 VIM REFERENCE MANUAL by Bram Moolenaar
5
6
Bram Moolenaardcc58e02020-12-28 20:53:21 +01007Vim9 script commands and expressions. *Vim9* *vim9*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008
9Most expression help is in |eval.txt|. This file is about the new syntax and
10features in Vim9 script.
11
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010012
13
Bram Moolenaar7e6a5152021-01-02 16:39:53 +0100141. What is Vim9 script? |Vim9-script|
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100152. Differences |vim9-differences|
163. New style functions |fast-functions|
174. Types |vim9-types|
185. Namespace, Import and Export |vim9script|
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000196. Classes and interfaces |vim9-classes|
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010020
219. Rationale |vim9-rationale|
22
23==============================================================================
24
Bram Moolenaar2b327002020-12-26 15:39:31 +0100251. What is Vim9 script? *Vim9-script*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010026
Bram Moolenaar7ceefb32020-05-01 16:07:38 +020027Vim script has been growing over time, while preserving backwards
28compatibility. That means bad choices from the past often can't be changed
Bram Moolenaar73fef332020-06-21 22:12:03 +020029and compatibility with Vi restricts possible solutions. Execution is quite
Bram Moolenaar7ceefb32020-05-01 16:07:38 +020030slow, each line is parsed every time it is executed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010031
Bram Moolenaar7ceefb32020-05-01 16:07:38 +020032The main goal of Vim9 script is to drastically improve performance. This is
33accomplished by compiling commands into instructions that can be efficiently
34executed. An increase in execution speed of 10 to 100 times can be expected.
35
36A secondary goal is to avoid Vim-specific constructs and get closer to
37commonly used programming languages, such as JavaScript, TypeScript and Java.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010038
39The performance improvements can only be achieved by not being 100% backwards
Bram Moolenaar8a3b8052022-06-26 12:21:15 +010040compatible. For example, making function arguments available in the "a:"
41dictionary adds quite a lot of overhead. In a Vim9 function this dictionary
42is not available. Other differences are more subtle, such as how errors are
43handled.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010044
45The Vim9 script syntax and semantics are used in:
46- a function defined with the `:def` command
47- a script file where the first command is `vim9script`
Bram Moolenaar1d59aa12020-09-19 18:50:13 +020048- an autocommand defined in the context of the above
Bram Moolenaar39f3b142021-02-14 12:57:36 +010049- a command prefixed with the `vim9cmd` command modifier
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010050
Bram Moolenaar82be4842021-01-11 19:40:15 +010051When using `:function` in a Vim9 script file the legacy syntax is used, with
52the highest |scriptversion|. However, this can be confusing and is therefore
53discouraged.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010054
Bram Moolenaar7ceefb32020-05-01 16:07:38 +020055Vim9 script and legacy Vim script can be mixed. There is no requirement to
Bram Moolenaar1d59aa12020-09-19 18:50:13 +020056rewrite old scripts, they keep working as before. You may want to use a few
57`:def` functions for code that needs to be fast.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010058
Bram Moolenaara2baa732022-02-04 16:09:54 +000059:vim9[cmd] {cmd} *:vim9* *:vim9cmd* *E1164*
Bram Moolenaar5b1d6e92022-02-11 20:33:48 +000060 Evaluate and execute {cmd} using Vim9 script syntax and
61 semantics. Useful when typing a command and in a legacy
62 script or function.
Bram Moolenaar39f3b142021-02-14 12:57:36 +010063
Bram Moolenaara2baa732022-02-04 16:09:54 +000064:leg[acy] {cmd} *:leg* *:legacy* *E1189* *E1234*
Bram Moolenaar5b1d6e92022-02-11 20:33:48 +000065 Evaluate and execute {cmd} using legacy script syntax and
66 semantics. Only useful in a Vim9 script or a :def function.
Bram Moolenaar96cf4ba2021-04-24 14:15:41 +020067 Note that {cmd} cannot use local variables, since it is parsed
68 with legacy expression syntax.
69
Christian Brabandtbad95772024-05-31 14:58:26 +020070See some examples of Vim9 script at |52.6|.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010071==============================================================================
72
732. Differences from legacy Vim script *vim9-differences*
74
Bram Moolenaard58a3bf2020-09-28 21:48:16 +020075Overview ~
Bram Moolenaara2baa732022-02-04 16:09:54 +000076 *E1146*
Bram Moolenaard58a3bf2020-09-28 21:48:16 +020077Brief summary of the differences you will most often encounter when using Vim9
78script and `:def` functions; details are below:
79- Comments start with #, not ": >
Bram Moolenaar82be4842021-01-11 19:40:15 +010080 echo "hello" # comment
Bram Moolenaard58a3bf2020-09-28 21:48:16 +020081- Using a backslash for line continuation is hardly ever needed: >
Bram Moolenaar82be4842021-01-11 19:40:15 +010082 echo "hello "
Bram Moolenaard58a3bf2020-09-28 21:48:16 +020083 .. yourName
84 .. ", how are you?"
Bram Moolenaar5da36052021-12-27 15:39:57 +000085- White space is required in many places to improve readability.
Bram Moolenaarf10911e2022-01-29 22:20:48 +000086- Assign values without `:let` *E1126* , declare variables with `:var`: >
Bram Moolenaar82be4842021-01-11 19:40:15 +010087 var count = 0
Bram Moolenaard58a3bf2020-09-28 21:48:16 +020088 count += 3
89- Constants can be declared with `:final` and `:const`: >
Bram Moolenaar63f32602022-06-09 20:45:54 +010090 final matches = [] # add to the list later
Bram Moolenaard58a3bf2020-09-28 21:48:16 +020091 const names = ['Betty', 'Peter'] # cannot be changed
92- `:final` cannot be used as an abbreviation of `:finally`.
93- Variables and functions are script-local by default.
94- Functions are declared with argument types and return type: >
95 def CallMe(count: number, message: string): bool
96- Call functions without `:call`: >
Bram Moolenaar82be4842021-01-11 19:40:15 +010097 writefile(['done'], 'file.txt')
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +000098- You cannot use old Ex commands:
99 `:Print`
100 `:append`
101 `:change`
102 `:d` directly followed by 'd' or 'p'.
103 `:insert`
104 `:k`
105 `:mode`
106 `:open`
107 `:s` with only flags
108 `:t`
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000109 `:xit`
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +0000110- Some commands, especially those used for flow control, cannot be shortened.
Bram Moolenaar9712ff12022-09-18 13:04:22 +0100111 E.g., `:throw` cannot be written as `:th`. *vim9-no-shorten*
Bram Moolenaar22863042021-10-16 15:23:36 +0100112- You cannot use curly-braces names.
Bram Moolenaard58a3bf2020-09-28 21:48:16 +0200113- A range before a command must be prefixed with a colon: >
Bram Moolenaar82be4842021-01-11 19:40:15 +0100114 :%s/this/that
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200115- Executing a register with "@r" does not work, you can prepend a colon or use
116 `:exe`: >
Bram Moolenaar938ae282023-02-20 20:44:55 +0000117 :exe @a
Bram Moolenaar82be4842021-01-11 19:40:15 +0100118- Unless mentioned specifically, the highest |scriptversion| is used.
Bram Moolenaarfd31be22022-01-16 14:46:06 +0000119- When defining an expression mapping, the expression will be evaluated in the
120 context of the script where it was defined.
Bram Moolenaar10e8ff92023-06-10 21:40:39 +0100121- When indexing a string the index is counted in characters, not bytes:
122 |vim9-string-index|
123- Some possibly unexpected differences: |vim9-gotchas|.
Bram Moolenaard58a3bf2020-09-28 21:48:16 +0200124
125
Bram Moolenaar2c330432020-04-13 14:41:35 +0200126Comments starting with # ~
127
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +0200128In legacy Vim script comments start with double quote. In Vim9 script
129comments start with #. >
130 # declarations
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200131 var count = 0 # number of occurrences
Bram Moolenaar2c330432020-04-13 14:41:35 +0200132
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +0200133The reason is that a double quote can also be the start of a string. In many
Bram Moolenaar3d1cde82020-08-15 18:55:18 +0200134places, especially halfway through an expression with a line break, it's hard
135to tell what the meaning is, since both a string and a comment can be followed
136by arbitrary text. To avoid confusion only # comments are recognized. This
137is the same as in shell scripts and Python programs.
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +0200138
139In Vi # is a command to list text with numbers. In Vim9 script you can use
140`:number` for that. >
Bram Moolenaar2f0936c2022-01-08 21:51:59 +0000141 :101 number
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +0200142
143To improve readability there must be a space between a command and the #
Bram Moolenaar2b327002020-12-26 15:39:31 +0100144that starts a comment: >
Bram Moolenaardcc58e02020-12-28 20:53:21 +0100145 var name = value # comment
146 var name = value# error!
Bram Moolenaara2baa732022-02-04 16:09:54 +0000147< *E1170*
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200148Do not start a comment with #{, it looks like the legacy dictionary literal
149and produces an error where this might be confusing. #{{ or #{{{ are OK,
150these can be used to start a fold.
151
Bram Moolenaar5ed11532022-07-06 13:18:11 +0100152When starting to read a script file Vim doesn't know it is |Vim9| script until
153the `vim9script` command is found. Until that point you would need to use
154legacy comments: >
155 " legacy comment
156 vim9script
157 # Vim9 comment
158
159That looks ugly, better put `vim9script` in the very first line: >
160 vim9script
161 # Vim9 comment
162
Bram Moolenaardcc58e02020-12-28 20:53:21 +0100163In legacy Vim script # is also used for the alternate file name. In Vim9
164script you need to use %% instead. Instead of ## use %%% (stands for all
165arguments).
Bram Moolenaar2c7f8c52020-04-20 19:52:53 +0200166
Bram Moolenaar2c330432020-04-13 14:41:35 +0200167
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100168Vim9 functions ~
Bram Moolenaarf10911e2022-01-29 22:20:48 +0000169 *E1099*
Bram Moolenaar7ceefb32020-05-01 16:07:38 +0200170A function defined with `:def` is compiled. Execution is many times faster,
Bram Moolenaar962c43b2021-04-10 17:18:09 +0200171often 10 to 100 times.
Bram Moolenaar7ceefb32020-05-01 16:07:38 +0200172
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200173Many errors are already found when compiling, before the function is executed.
Bram Moolenaar7ceefb32020-05-01 16:07:38 +0200174The syntax is strict, to enforce code that is easy to read and understand.
175
Bram Moolenaar962c43b2021-04-10 17:18:09 +0200176Compilation is done when any of these is encountered:
Bram Moolenaar1b884a02020-12-10 21:11:27 +0100177- the first time the function is called
Bram Moolenaar962c43b2021-04-10 17:18:09 +0200178- when the `:defcompile` command is encountered in the script after the
Bram Moolenaar207f0092020-08-30 17:20:20 +0200179 function was defined
180- `:disassemble` is used for the function.
181- a function that is compiled calls the function or uses it as a function
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200182 reference (so that the argument and return types can be checked)
Bram Moolenaara2baa732022-02-04 16:09:54 +0000183 *E1091* *E1191*
Bram Moolenaar962c43b2021-04-10 17:18:09 +0200184If compilation fails it is not tried again on the next call, instead this
185error is given: "E1091: Function is not compiled: {name}".
Bram Moolenaar4c295022021-05-02 17:19:11 +0200186Compilation will fail when encountering a user command that has not been
187created yet. In this case you can call `execute()` to invoke it at runtime. >
188 def MyFunc()
189 execute('DefinedLater')
190 enddef
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200191
192`:def` has no options like `:function` does: "range", "abort", "dict" or
Bram Moolenaar1b884a02020-12-10 21:11:27 +0100193"closure". A `:def` function always aborts on an error (unless `:silent!` was
Bram Moolenaarfa3b7232021-12-24 13:18:38 +0000194used for the command or the error was caught a `:try` block), does not get a
Bram Moolenaar63f32602022-06-09 20:45:54 +0100195range passed, cannot be a "dict" function, and can always be a closure.
h-east08be9dd2024-12-23 10:11:25 +0100196 *vim9-no-dict-function* *E1182*
Bram Moolenaar10e8ff92023-06-10 21:40:39 +0100197You can use a Vim9 Class (|Vim9-class|) instead of a "dict function".
198You can also pass the dictionary explicitly: >
Bram Moolenaar63f32602022-06-09 20:45:54 +0100199 def DictFunc(self: dict<any>, arg: string)
200 echo self[arg]
Bram Moolenaar74235772021-06-12 14:53:05 +0200201 enddef
Bram Moolenaar46eea442022-03-30 10:51:39 +0100202 var ad = {item: 'value', func: DictFunc}
Bram Moolenaarcbaff5e2022-04-08 17:45:08 +0100203 ad.func(ad, 'item')
Bram Moolenaar74235772021-06-12 14:53:05 +0200204
Bram Moolenaar34cc7d82021-09-21 20:09:51 +0200205You can call a legacy dict function though: >
206 func Legacy() dict
207 echo self.value
208 endfunc
209 def CallLegacy()
210 var d = {func: Legacy, value: 'text'}
211 d.func()
212 enddef
Bram Moolenaara2baa732022-02-04 16:09:54 +0000213< *E1096* *E1174* *E1175*
Bram Moolenaar7ceefb32020-05-01 16:07:38 +0200214The argument types and return type need to be specified. The "any" type can
215be used, type checking will then be done at runtime, like with legacy
216functions.
Bram Moolenaarf10911e2022-01-29 22:20:48 +0000217 *E1106*
Bram Moolenaar3d1cde82020-08-15 18:55:18 +0200218Arguments are accessed by name, without "a:", just like any other language.
219There is no "a:" dictionary or "a:000" list.
Bram Moolenaara2baa732022-02-04 16:09:54 +0000220 *vim9-variable-arguments* *E1055* *E1160* *E1180*
Bram Moolenaar7ceefb32020-05-01 16:07:38 +0200221Variable arguments are defined as the last argument, with a name and have a
Bram Moolenaar3d1cde82020-08-15 18:55:18 +0200222list type, similar to TypeScript. For example, a list of numbers: >
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200223 def MyFunc(...itemlist: list<number>)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100224 for item in itemlist
225 ...
226
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200227When a function argument is optional (it has a default value) passing `v:none`
228as the argument results in using the default value. This is useful when you
229want to specify a value for an argument that comes after an argument that
230should use its default value. Example: >
Bram Moolenaar22863042021-10-16 15:23:36 +0100231 def MyFunc(one = 'one', last = 'last')
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200232 ...
233 enddef
234 MyFunc(v:none, 'LAST') # first argument uses default value 'one'
Bram Moolenaar962c43b2021-04-10 17:18:09 +0200235<
Bram Moolenaara2baa732022-02-04 16:09:54 +0000236 *vim9-ignored-argument* *E1181*
Bram Moolenaar962c43b2021-04-10 17:18:09 +0200237The argument "_" (an underscore) can be used to ignore the argument. This is
238most useful in callbacks where you don't need it, but do need to give an
239argument to match the call. E.g. when using map() two arguments are passed,
240the key and the value, to ignore the key: >
Bram Moolenaar63f32602022-06-09 20:45:54 +0100241 map(numberList, (_, v) => v * 2)
Bram Moolenaar962c43b2021-04-10 17:18:09 +0200242There is no error for using the "_" argument multiple times. No type needs to
243be given.
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200244
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100245
Bram Moolenaar7ceefb32020-05-01 16:07:38 +0200246Functions and variables are script-local by default ~
Bram Moolenaar65e0d772020-06-14 17:29:55 +0200247 *vim9-scopes*
Bram Moolenaar2c7f8c52020-04-20 19:52:53 +0200248When using `:function` or `:def` to specify a new function at the script level
Bram Moolenaar92f645b2022-02-11 13:29:40 +0000249in a Vim9 script, the function is local to the script. Like prefixing "s:" in
250legacy script. To define a global function or variable the "g:" prefix must
251be used. For functions in a script that is to be imported and in an autoload
Bram Moolenaar63f32602022-06-09 20:45:54 +0100252script "export" needs to be used for those to be used elsewhere. >
Bram Moolenaarea2d8d22020-07-29 22:11:05 +0200253 def ThisFunction() # script-local
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200254 def g:ThatFunction() # global
Bram Moolenaar9da17d72022-02-09 21:50:44 +0000255 export def Function() # for import and import autoload
Bram Moolenaar6f4754b2022-01-23 12:07:04 +0000256< *E1058* *E1075*
Bram Moolenaar2bb26582020-10-03 22:52:39 +0200257When using `:function` or `:def` to specify a nested function inside a `:def`
Bram Moolenaar47003982021-12-05 21:54:04 +0000258function and no namespace was given, this nested function is local to the code
Bram Moolenaarc51cf032022-02-26 12:25:45 +0000259block it is defined in. It cannot be used in `function()` with a string
260argument, pass the function reference itself: >
261 def Outer()
262 def Inner()
263 echo 'inner'
264 enddef
265 var Fok = function(Inner) # OK
266 var Fbad = function('Inner') # does not work
267
Bram Moolenaar63f32602022-06-09 20:45:54 +0100268Detail: this is because "Inner" will actually become a function reference to a
269function with a generated name.
270
271It is not possible to define a script-local function in a function. You can
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000272define a local function and assign it to a script-local Funcref (it must have
Bram Moolenaar63f32602022-06-09 20:45:54 +0100273been declared at the script level). It is possible to define a global
274function by using the "g:" prefix.
Bram Moolenaar2c7f8c52020-04-20 19:52:53 +0200275
276When referring to a function and no "s:" or "g:" prefix is used, Vim will
Bram Moolenaar13106602020-10-04 16:06:05 +0200277search for the function:
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +0200278- in the function scope, in block scopes
Bram Moolenaar63f32602022-06-09 20:45:54 +0100279- in the script scope
280
281Imported functions are found with the prefix from the `:import` command.
Bram Moolenaar13106602020-10-04 16:06:05 +0200282
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200283Since a script-local function reference can be used without "s:" the name must
Bram Moolenaardad44732021-03-31 20:07:33 +0200284start with an upper case letter even when using the "s:" prefix. In legacy
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200285script "s:funcref" could be used, because it could not be referred to with
286"funcref". In Vim9 script it can, therefore "s:Funcref" must be used to avoid
287that the name interferes with builtin functions.
Bram Moolenaar2ecbe532022-07-29 21:36:21 +0100288 *vim9-s-namespace* *E1268*
Bram Moolenaar92f645b2022-02-11 13:29:40 +0000289The use of the "s:" prefix is not supported at the Vim9 script level. All
290functions and variables without a prefix are script-local.
Bram Moolenaarafa048f2022-02-22 20:43:36 +0000291
292In :def functions the use of "s:" depends on the script: Script-local
293variables and functions in a legacy script do use "s:", while in a Vim9 script
294they do not use "s:". This matches what you see in the rest of the file.
295
Bram Moolenaar92f645b2022-02-11 13:29:40 +0000296In legacy functions the use of "s:" for script items is required, as before.
Bram Moolenaar63f32602022-06-09 20:45:54 +0100297No matter if the script is Vim9 or legacy.
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200298
Bram Moolenaar13106602020-10-04 16:06:05 +0200299In all cases the function must be defined before used. That is when it is
Bram Moolenaarcb80aa22020-10-26 21:12:46 +0100300called, when `:defcompile` causes it to be compiled, or when code that calls
301it is being compiled (to figure out the return type).
Bram Moolenaar7ceefb32020-05-01 16:07:38 +0200302
Bram Moolenaare7b1ea02020-08-07 19:54:59 +0200303The result is that functions and variables without a namespace can usually be
Bram Moolenaar7ceefb32020-05-01 16:07:38 +0200304found in the script, either defined there or imported. Global functions and
Bram Moolenaar63f32602022-06-09 20:45:54 +0100305variables could be defined anywhere (good luck finding out where! You can
306often see where it was last set using |:verbose|).
Bram Moolenaarf10911e2022-01-29 22:20:48 +0000307 *E1102*
Bram Moolenaar3d1cde82020-08-15 18:55:18 +0200308Global functions can still be defined and deleted at nearly any time. In
Bram Moolenaar2cfb4a22020-05-07 18:56:00 +0200309Vim9 script script-local functions are defined once when the script is sourced
Bram Moolenaar63f32602022-06-09 20:45:54 +0100310and cannot be deleted or replaced by itself (it can be by reloading the
311script).
Bram Moolenaar2c7f8c52020-04-20 19:52:53 +0200312
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100313When compiling a function and a function call is encountered for a function
314that is not (yet) defined, the |FuncUndefined| autocommand is not triggered.
315You can use an autoload function if needed, or call a legacy function and have
316|FuncUndefined| triggered there.
317
Bram Moolenaar2c7f8c52020-04-20 19:52:53 +0200318
Bram Moolenaar2b327002020-12-26 15:39:31 +0100319Reloading a Vim9 script clears functions and variables by default ~
Bram Moolenaara2baa732022-02-04 16:09:54 +0000320 *vim9-reload* *E1149* *E1150*
Bram Moolenaar2b327002020-12-26 15:39:31 +0100321When loading a legacy Vim script a second time nothing is removed, the
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100322commands will replace existing variables and functions, create new ones, and
323leave removed things hanging around.
Bram Moolenaar2b327002020-12-26 15:39:31 +0100324
325When loading a Vim9 script a second time all existing script-local functions
326and variables are deleted, thus you start with a clean slate. This is useful
327if you are developing a plugin and want to try a new version. If you renamed
328something you don't have to worry about the old name still hanging around.
329
330If you do want to keep items, use: >
Bram Moolenaardcc58e02020-12-28 20:53:21 +0100331 vim9script noclear
Bram Moolenaar2b327002020-12-26 15:39:31 +0100332
333You want to use this in scripts that use a `finish` command to bail out at
Bram Moolenaar944697a2022-02-20 19:48:20 +0000334some point when loaded again. E.g. when a buffer local option is set to a
335function, the function does not need to be defined more than once: >
Bram Moolenaardcc58e02020-12-28 20:53:21 +0100336 vim9script noclear
Bram Moolenaar2b327002020-12-26 15:39:31 +0100337 setlocal completefunc=SomeFunc
Bram Moolenaar944697a2022-02-20 19:48:20 +0000338 if exists('*SomeFunc')
Bram Moolenaar9da17d72022-02-09 21:50:44 +0000339 finish
340 endif
Bram Moolenaar944697a2022-02-20 19:48:20 +0000341 def SomeFunc()
Bram Moolenaar2b327002020-12-26 15:39:31 +0100342 ....
343
Bram Moolenaar2b327002020-12-26 15:39:31 +0100344
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200345Variable declarations with :var, :final and :const ~
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +0000346 *vim9-declaration* *:var* *E1079*
Dominique Pellee764d1b2023-03-12 21:20:59 +0000347 *E1017* *E1020* *E1054* *E1087* *E1124*
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200348Local variables need to be declared with `:var`. Local constants need to be
349declared with `:final` or `:const`. We refer to both as "variables" in this
350section.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100351
352Variables can be local to a script, function or code block: >
353 vim9script
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200354 var script_var = 123
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100355 def SomeFunc()
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200356 var func_var = script_var
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100357 if cond
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200358 var block_var = func_var
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100359 ...
360
361The variables are only visible in the block where they are defined and nested
362blocks. Once the block ends the variable is no longer accessible: >
363 if cond
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200364 var inner = 5
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100365 else
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200366 var inner = 0
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100367 endif
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200368 echo inner # Error!
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100369
370The declaration must be done earlier: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200371 var inner: number
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100372 if cond
373 inner = 5
374 else
375 inner = 0
376 endif
377 echo inner
Bram Moolenaar63f32602022-06-09 20:45:54 +0100378
379Although this is shorter and faster for simple values: >
380 var inner = 0
381 if cond
382 inner = 5
383 endif
384 echo inner
Bram Moolenaarf10911e2022-01-29 22:20:48 +0000385< *E1025* *E1128*
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200386To intentionally hide a variable from code that follows, a block can be
387used: >
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100388 {
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200389 var temp = 'temp'
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100390 ...
391 }
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200392 echo temp # Error!
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100393
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +0200394This is especially useful in a user command: >
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +0200395 command -range Rename {
Bram Moolenaar6aa57292021-08-14 21:25:52 +0200396 var save = @a
397 @a = 'some expression'
398 echo 'do something with ' .. @a
399 @a = save
400 }
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +0200401
402And with autocommands: >
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +0200403 au BufWritePre *.go {
Bram Moolenaar6aa57292021-08-14 21:25:52 +0200404 var save = winsaveview()
405 silent! exe ':%! some formatting command'
406 winrestview(save)
407 }
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +0200408
409Although using a :def function probably works better.
Bram Moolenaar46eea442022-03-30 10:51:39 +0100410
Bram Moolenaara2baa732022-02-04 16:09:54 +0000411 *E1022* *E1103* *E1130* *E1131* *E1133*
Dominique Pelle7765f5c2022-04-10 11:26:53 +0100412 *E1134*
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +0200413Declaring a variable with a type but without an initializer will initialize to
Bram Moolenaar1f318c62021-12-26 18:09:31 +0000414false (for bool), empty (for string, list, dict, etc.) or zero (for number,
415any, etc.). This matters especially when using the "any" type, the value will
Bram Moolenaar46eea442022-03-30 10:51:39 +0100416default to the number zero. For example, when declaring a list, items can be
417added: >
418 var myList: list<number>
419 myList->add(7)
420
421Initializing a variable to a null value, e.g. `null_list`, differs from not
422initializing the variable. This throws an error: >
423 var myList = null_list
424 myList->add(7) # E1130: Cannot add to null list
425
426< *E1016* *E1052* *E1066*
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200427In Vim9 script `:let` cannot be used. An existing variable is assigned to
428without any command. The same for global, window, tab, buffer and Vim
Bram Moolenaar5da36052021-12-27 15:39:57 +0000429variables, because they are not really declared. Those can also be deleted
Bram Moolenaarf5a48012020-08-01 17:00:03 +0200430with `:unlet`.
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +0000431 *E1065*
432You cannot use `:va` to declare a variable, it must be written with the full
433name `:var`. Just to make sure it is easy to read.
Bram Moolenaara2baa732022-02-04 16:09:54 +0000434 *E1178*
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200435`:lockvar` does not work on local variables. Use `:const` and `:final`
436instead.
437
Bram Moolenaar6aa57292021-08-14 21:25:52 +0200438The `exists()` and `exists_compiled()` functions do not work on local variables
439or arguments.
Bram Moolenaara2baa732022-02-04 16:09:54 +0000440 *E1006* *E1041* *E1167* *E1168* *E1213*
Bram Moolenaar9faec4e2021-02-27 16:38:07 +0100441Variables, functions and function arguments cannot shadow previously defined
442or imported variables and functions in the same script file.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100443Variables may shadow Ex commands, rename the variable if needed.
444
Bram Moolenaar130cbfc2021-04-07 21:07:20 +0200445Global variables must be prefixed with "g:", also at the script level. >
Bram Moolenaard1caa942020-04-10 22:10:56 +0200446 vim9script
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200447 var script_local = 'text'
Bram Moolenaar2547aa92020-07-26 17:00:44 +0200448 g:global = 'value'
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200449 var Funcref = g:ThatFunction
Bram Moolenaard1caa942020-04-10 22:10:56 +0200450
Bram Moolenaarc4573eb2022-01-31 15:40:56 +0000451Global functions must be prefixed with "g:": >
Bram Moolenaar130cbfc2021-04-07 21:07:20 +0200452 vim9script
453 def g:GlobalFunc(): string
454 return 'text'
455 enddef
Bram Moolenaarc4573eb2022-01-31 15:40:56 +0000456 echo g:GlobalFunc()
Bram Moolenaar130cbfc2021-04-07 21:07:20 +0200457The "g:" prefix is not needed for auto-load functions.
458
Bram Moolenaar6aa57292021-08-14 21:25:52 +0200459 *vim9-function-defined-later*
460Although global functions can be called without the "g:" prefix, they must
461exist when compiled. By adding the "g:" prefix the function can be defined
462later. Example: >
463 def CallPluginFunc()
464 if exists('g:loaded_plugin')
465 g:PluginFunc()
466 endif
467 enddef
468
Bram Moolenaarb79ee0c2022-01-01 12:17:00 +0000469If you do it like this, you get an error at compile time that "PluginFunc"
470does not exist, even when "g:loaded_plugin" does not exist: >
Bram Moolenaar6aa57292021-08-14 21:25:52 +0200471 def CallPluginFunc()
472 if exists('g:loaded_plugin')
473 PluginFunc() # Error - function not found
474 endif
475 enddef
476
477You can use exists_compiled() to avoid the error, but then the function would
478not be called, even when "g:loaded_plugin" is defined later: >
479 def CallPluginFunc()
480 if exists_compiled('g:loaded_plugin')
481 PluginFunc() # Function may never be called
482 endif
483 enddef
484
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200485Since `&opt = value` is now assigning a value to option "opt", ":&" cannot be
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100486used to repeat a `:substitute` command.
Bram Moolenaar56994d22021-04-17 16:31:09 +0200487 *vim9-unpack-ignore*
Bram Moolenaarf93bbd02021-04-10 22:35:43 +0200488For an unpack assignment the underscore can be used to ignore a list item,
489similar to how a function argument can be ignored: >
490 [a, _, c] = theList
Bram Moolenaar56994d22021-04-17 16:31:09 +0200491To ignore any remaining items: >
Bram Moolenaarf93bbd02021-04-10 22:35:43 +0200492 [a, b; _] = longList
Bram Moolenaar944697a2022-02-20 19:48:20 +0000493< *E1163* *E1080*
Bram Moolenaarf93bbd02021-04-10 22:35:43 +0200494Declaring more than one variable at a time, using the unpack notation, is
Bram Moolenaarab36e6a2021-11-30 16:14:49 +0000495possible. Each variable can have a type or infer it from the value: >
496 var [v1: number, v2] = GetValues()
497Use this only when there is a list with values, declaring one variable per
498line is much easier to read and change later.
Bram Moolenaarf93bbd02021-04-10 22:35:43 +0200499
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200500
501Constants ~
502 *vim9-const* *vim9-final*
503How constants work varies between languages. Some consider a variable that
504can't be assigned another value a constant. JavaScript is an example. Others
505also make the value immutable, thus when a constant uses a list, the list
506cannot be changed. In Vim9 we can use both.
Bram Moolenaarf269eab2022-10-03 18:04:35 +0100507 *E1021* *E1307*
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200508`:const` is used for making both the variable and the value a constant. Use
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +0200509this for composite structures that you want to make sure will not be modified.
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200510Example: >
511 const myList = [1, 2]
512 myList = [3, 4] # Error!
513 myList[0] = 9 # Error!
Bram Moolenaar9faec4e2021-02-27 16:38:07 +0100514 myList->add(3) # Error!
Bram Moolenaarf10911e2022-01-29 22:20:48 +0000515< *:final* *E1125*
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200516`:final` is used for making only the variable a constant, the value can be
517changed. This is well known from Java. Example: >
518 final myList = [1, 2]
519 myList = [3, 4] # Error!
520 myList[0] = 9 # OK
Bram Moolenaar9faec4e2021-02-27 16:38:07 +0100521 myList->add(3) # OK
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +0200522
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +0200523It is common to write constants as ALL_CAPS, but you don't have to.
524
525The constant only applies to the value itself, not what it refers to. >
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200526 final females = ["Mary"]
527 const NAMES = [["John", "Peter"], females]
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +0200528 NAMES[0] = ["Jack"] # Error!
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200529 NAMES[0][0] = "Jack" # Error!
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +0200530 NAMES[1] = ["Emma"] # Error!
Bram Moolenaar82be4842021-01-11 19:40:15 +0100531 NAMES[1][0] = "Emma" # OK, now females[0] == "Emma"
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +0200532
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100533
534Omitting :call and :eval ~
Bram Moolenaara2baa732022-02-04 16:09:54 +0000535 *E1190*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100536Functions can be called without `:call`: >
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200537 writefile(lines, 'file')
Bram Moolenaar560979e2020-02-04 22:53:05 +0100538Using `:call` is still possible, but this is discouraged.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100539
540A method call without `eval` is possible, so long as the start is an
Bram Moolenaar0289a092021-03-14 18:40:19 +0100541identifier or can't be an Ex command. For a function either "(" or "->" must
542be following, without a line break. Examples: >
Bram Moolenaarae616492020-07-28 20:07:27 +0200543 myList->add(123)
544 g:myList->add(123)
545 [1, 2, 3]->Process()
Bram Moolenaar2bede172020-11-19 18:53:18 +0100546 {a: 1, b: 2}->Process()
Bram Moolenaarae616492020-07-28 20:07:27 +0200547 "foobar"->Process()
548 ("foobar")->Process()
549 'foobar'->Process()
550 ('foobar')->Process()
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100551
Bram Moolenaar3d1cde82020-08-15 18:55:18 +0200552In the rare case there is ambiguity between a function name and an Ex command,
Bram Moolenaare7b1ea02020-08-07 19:54:59 +0200553prepend ":" to make clear you want to use the Ex command. For example, there
554is both the `:substitute` command and the `substitute()` function. When the
555line starts with `substitute(` this will use the function. Prepend a colon to
556use the command instead: >
Bram Moolenaar0c6ceaf2020-02-22 18:36:32 +0100557 :substitute(pattern (replacement (
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +0100558
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +0200559If the expression starts with "!" this is interpreted as a shell command, not
560negation of a condition. Thus this is a shell command: >
561 !shellCommand->something
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200562Put the expression in parentheses to use the "!" for negation: >
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +0200563 (!expression)->Method()
564
Bram Moolenaarcc390ff2020-02-29 22:06:30 +0100565Note that while variables need to be defined before they can be used,
Bram Moolenaar3d1cde82020-08-15 18:55:18 +0200566functions can be called before being defined. This is required to allow
567for cyclic dependencies between functions. It is slightly less efficient,
Bram Moolenaarcc390ff2020-02-29 22:06:30 +0100568since the function has to be looked up by name. And a typo in the function
Bram Moolenaarae616492020-07-28 20:07:27 +0200569name will only be found when the function is called.
Bram Moolenaarcc390ff2020-02-29 22:06:30 +0100570
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100571
Bram Moolenaard1caa942020-04-10 22:10:56 +0200572Omitting function() ~
573
574A user defined function can be used as a function reference in an expression
575without `function()`. The argument types and return type will then be checked.
576The function must already have been defined. >
577
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200578 var Funcref = MyFunction
Bram Moolenaard1caa942020-04-10 22:10:56 +0200579
580When using `function()` the resulting type is "func", a function with any
Bram Moolenaar90df4b92021-07-07 20:26:08 +0200581number of arguments and any return type (including void). The function can be
Bram Moolenaarfa3b7232021-12-24 13:18:38 +0000582defined later if the argument is in quotes.
Bram Moolenaard1caa942020-04-10 22:10:56 +0200583
584
Bram Moolenaar2b327002020-12-26 15:39:31 +0100585Lambda using => instead of -> ~
Bram Moolenaar130cbfc2021-04-07 21:07:20 +0200586 *vim9-lambda*
Bram Moolenaar65c44152020-12-24 15:14:01 +0100587In legacy script there can be confusion between using "->" for a method call
588and for a lambda. Also, when a "{" is found the parser needs to figure out if
589it is the start of a lambda or a dictionary, which is now more complicated
590because of the use of argument types.
591
592To avoid these problems Vim9 script uses a different syntax for a lambda,
Bram Moolenaar74235772021-06-12 14:53:05 +0200593which is similar to JavaScript: >
Bram Moolenaar65c44152020-12-24 15:14:01 +0100594 var Lambda = (arg) => expression
Bram Moolenaara2baa732022-02-04 16:09:54 +0000595 var Lambda = (arg): type => expression
596< *E1157*
Bram Moolenaar2b327002020-12-26 15:39:31 +0100597No line break is allowed in the arguments of a lambda up to and including the
Bram Moolenaar4d8f4762021-06-27 15:18:56 +0200598"=>" (so that Vim can tell the difference between an expression in parentheses
Bram Moolenaar2346a632021-06-13 19:02:49 +0200599and lambda arguments). This is OK: >
Bram Moolenaar65c44152020-12-24 15:14:01 +0100600 filter(list, (k, v) =>
601 v > 0)
602This does not work: >
603 filter(list, (k, v)
604 => v > 0)
Bram Moolenaardcc58e02020-12-28 20:53:21 +0100605This also does not work: >
Bram Moolenaar65c44152020-12-24 15:14:01 +0100606 filter(list, (k,
607 v) => v > 0)
Bram Moolenaardcc58e02020-12-28 20:53:21 +0100608But you can use a backslash to concatenate the lines before parsing: >
609 filter(list, (k,
610 \ v)
611 \ => v > 0)
Bram Moolenaara2baa732022-02-04 16:09:54 +0000612< *vim9-lambda-arguments* *E1172*
Bram Moolenaar962c43b2021-04-10 17:18:09 +0200613In legacy script a lambda could be called with any number of extra arguments,
614there was no way to warn for not using them. In Vim9 script the number of
615arguments must match. If you do want to accept any arguments, or any further
616arguments, use "..._", which makes the function accept
617|vim9-variable-arguments|. Example: >
618 var Callback = (..._) => 'anything'
619 echo Callback(1, 2, 3) # displays "anything"
620
Bram Moolenaara2baa732022-02-04 16:09:54 +0000621< *inline-function* *E1171*
Bram Moolenaar65c44152020-12-24 15:14:01 +0100622Additionally, a lambda can contain statements in {}: >
623 var Lambda = (arg) => {
624 g:was_called = 'yes'
625 return expression
626 }
Bram Moolenaar130cbfc2021-04-07 21:07:20 +0200627This can be useful for a timer, for example: >
628 var count = 0
Bram Moolenaar938ae282023-02-20 20:44:55 +0000629 var timer = timer_start(500, (_) => {
Bram Moolenaar130cbfc2021-04-07 21:07:20 +0200630 count += 1
631 echom 'Handler called ' .. count
632 }, {repeat: 3})
633
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200634The ending "}" must be at the start of a line. It can be followed by other
635characters, e.g.: >
636 var d = mapnew(dict, (k, v): string => {
637 return 'value'
638 })
639No command can follow the "{", only a comment can be used there.
640
Bram Moolenaar6f4754b2022-01-23 12:07:04 +0000641 *command-block* *E1026*
Bram Moolenaar259f4432021-12-17 12:45:22 +0000642The block can also be used for defining a user command. Inside the block Vim9
643syntax will be used.
644
Yegappan Lakshmanane74cad32024-04-12 18:48:35 +0200645This is an example of using here-docs: >
646 com SomeCommand {
647 g:someVar =<< trim eval END
648 ccc
649 ddd
650 END
651 }
652
Bram Moolenaar0e6adf82021-12-16 14:41:10 +0000653If the statements include a dictionary, its closing bracket must not be
654written at the start of a line. Otherwise, it would be parsed as the end of
655the block. This does not work: >
656 command NewCommand {
Bram Moolenaar259f4432021-12-17 12:45:22 +0000657 g:mydict = {
Bram Moolenaar0e6adf82021-12-16 14:41:10 +0000658 'key': 'value',
659 } # ERROR: will be recognized as the end of the block
660 }
661Put the '}' after the last item to avoid this: >
662 command NewCommand {
Bram Moolenaar259f4432021-12-17 12:45:22 +0000663 g:mydict = {
Bram Moolenaar0e6adf82021-12-16 14:41:10 +0000664 'key': 'value' }
665 }
666
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200667Rationale: The "}" cannot be after a command because it would require parsing
668the commands to find it. For consistency with that no command can follow the
669"{". Unfortunately this means using "() => { command }" does not work, line
670breaks are always required.
Bram Moolenaar65c44152020-12-24 15:14:01 +0100671
Bram Moolenaare0e39172021-01-25 21:14:57 +0100672 *vim9-curly*
Bram Moolenaar2b327002020-12-26 15:39:31 +0100673To avoid the "{" of a dictionary literal to be recognized as a statement block
Bram Moolenaar9faec4e2021-02-27 16:38:07 +0100674wrap it in parentheses: >
Bram Moolenaar2b327002020-12-26 15:39:31 +0100675 var Lambda = (arg) => ({key: 42})
Bram Moolenaar65c44152020-12-24 15:14:01 +0100676
Bram Moolenaare0e39172021-01-25 21:14:57 +0100677Also when confused with the start of a command block: >
678 ({
679 key: value
680 })->method()
681
Bram Moolenaar65c44152020-12-24 15:14:01 +0100682
Bram Moolenaar4fdae992020-04-12 16:38:57 +0200683Automatic line continuation ~
Bram Moolenaarf10911e2022-01-29 22:20:48 +0000684 *vim9-line-continuation* *E1097*
Bram Moolenaar4fdae992020-04-12 16:38:57 +0200685In many cases it is obvious that an expression continues on the next line. In
Bram Moolenaardcc58e02020-12-28 20:53:21 +0100686those cases there is no need to prefix the line with a backslash (see
687|line-continuation|). For example, when a list spans multiple lines: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200688 var mylist = [
Bram Moolenaar4fdae992020-04-12 16:38:57 +0200689 'one',
690 'two',
691 ]
Bram Moolenaare6085c52020-04-12 20:19:16 +0200692And when a dict spans multiple lines: >
Bram Moolenaar2bede172020-11-19 18:53:18 +0100693 var mydict = {
Bram Moolenaare6085c52020-04-12 20:19:16 +0200694 one: 1,
695 two: 2,
696 }
Bram Moolenaar74235772021-06-12 14:53:05 +0200697With a function call: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200698 var result = Func(
Bram Moolenaare6085c52020-04-12 20:19:16 +0200699 arg1,
700 arg2
701 )
702
Bram Moolenaardf069ee2020-06-22 23:02:51 +0200703For binary operators in expressions not in [], {} or () a line break is
704possible just before or after the operator. For example: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200705 var text = lead
Bram Moolenaardf069ee2020-06-22 23:02:51 +0200706 .. middle
707 .. end
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200708 var total = start +
Bram Moolenaar82be4842021-01-11 19:40:15 +0100709 end -
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +0200710 correction
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200711 var result = positive
Bram Moolenaardf069ee2020-06-22 23:02:51 +0200712 ? PosFunc(arg)
713 : NegFunc(arg)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +0200714
Bram Moolenaar2547aa92020-07-26 17:00:44 +0200715For a method call using "->" and a member using a dot, a line break is allowed
716before it: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200717 var result = GetBuilder()
Bram Moolenaar73fef332020-06-21 22:12:03 +0200718 ->BuilderSetWidth(333)
719 ->BuilderSetHeight(777)
720 ->BuilderBuild()
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200721 var result = MyDict
Bram Moolenaar2547aa92020-07-26 17:00:44 +0200722 .member
Bram Moolenaar73fef332020-06-21 22:12:03 +0200723
Bram Moolenaardcc58e02020-12-28 20:53:21 +0100724For commands that have an argument that is a list of commands, the | character
725at the start of the line indicates line continuation: >
726 autocmd BufNewFile *.match if condition
727 | echo 'match'
728 | endif
729
Bram Moolenaar22863042021-10-16 15:23:36 +0100730Note that this means that in heredoc the first line cannot start with a bar: >
Bram Moolenaar74235772021-06-12 14:53:05 +0200731 var lines =<< trim END
732 | this doesn't work
733 END
734Either use an empty line at the start or do not use heredoc. Or temporarily
735add the "C" flag to 'cpoptions': >
736 set cpo+=C
737 var lines =<< trim END
Bram Moolenaar22863042021-10-16 15:23:36 +0100738 | this works
Bram Moolenaar74235772021-06-12 14:53:05 +0200739 END
740 set cpo-=C
741If the heredoc is inside a function 'cpoptions' must be set before :def and
742restored after the :enddef.
743
744In places where line continuation with a backslash is still needed, such as
Bram Moolenaar90df4b92021-07-07 20:26:08 +0200745splitting up a long Ex command, comments can start with '#\ ': >
746 syn region Text
Bram Moolenaar74235772021-06-12 14:53:05 +0200747 \ start='foo'
748 #\ comment
749 \ end='bar'
Bram Moolenaar90df4b92021-07-07 20:26:08 +0200750Like with legacy script '"\ ' is used. This is also needed when line
751continuation is used without a backslash and a line starts with a bar: >
752 au CursorHold * echom 'BEFORE bar'
753 #\ some comment
754 | echom 'AFTER bar'
755<
756 *E1050*
Bram Moolenaardf069ee2020-06-22 23:02:51 +0200757To make it possible for the operator at the start of the line to be
Bram Moolenaar74235772021-06-12 14:53:05 +0200758recognized, it is required to put a colon before a range. This example will
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000759add "start" and "print": >
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200760 var result = start
Bram Moolenaardf069ee2020-06-22 23:02:51 +0200761 + print
Bram Moolenaar7ff78462020-07-10 22:00:53 +0200762Like this: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200763 var result = start + print
Bram Moolenaar7ff78462020-07-10 22:00:53 +0200764
Bram Moolenaardf069ee2020-06-22 23:02:51 +0200765This will assign "start" and print a line: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +0200766 var result = start
Bram Moolenaardf069ee2020-06-22 23:02:51 +0200767 :+ print
Bram Moolenaar4fdae992020-04-12 16:38:57 +0200768
Bram Moolenaar6f4754b2022-01-23 12:07:04 +0000769After the range an Ex command must follow. Without the colon you can call a
770function without `:call`, but after a range you do need it: >
771 MyFunc()
772 :% call MyFunc()
773
Bram Moolenaar23515b42020-11-29 14:36:24 +0100774Note that the colon is not required for the |+cmd| argument: >
775 edit +6 fname
776
Bram Moolenaar5e774c72020-04-12 21:53:00 +0200777It is also possible to split a function header over multiple lines, in between
778arguments: >
779 def MyFunc(
780 text: string,
781 separator = '-'
782 ): string
783
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100784Since a continuation line cannot be easily recognized the parsing of commands
Bram Moolenaar65c44152020-12-24 15:14:01 +0100785has been made stricter. E.g., because of the error in the first line, the
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100786second line is seen as a separate command: >
787 popup_create(some invalid expression, {
788 exit_cb: Func})
789Now "exit_cb: Func})" is actually a valid command: save any changes to the
790file "_cb: Func})" and exit. To avoid this kind of mistake in Vim9 script
791there must be white space between most command names and the argument.
Bram Moolenaarf10911e2022-01-29 22:20:48 +0000792*E1144*
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100793
Bram Moolenaar98a29d02021-01-18 19:55:44 +0100794However, the argument of a command that is a command won't be recognized. For
795example, after "windo echo expr" a line break inside "expr" will not be seen.
796
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100797
Bram Moolenaar7ff78462020-07-10 22:00:53 +0200798Notes:
799- "enddef" cannot be used at the start of a continuation line, it ends the
800 current function.
801- No line break is allowed in the LHS of an assignment. Specifically when
802 unpacking a list |:let-unpack|. This is OK: >
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200803 [var1, var2] =
Bram Moolenaar7ff78462020-07-10 22:00:53 +0200804 Func()
805< This does not work: >
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200806 [var1,
Bram Moolenaar7ff78462020-07-10 22:00:53 +0200807 var2] =
808 Func()
809- No line break is allowed in between arguments of an `:echo`, `:execute` and
810 similar commands. This is OK: >
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200811 echo [1,
Bram Moolenaar7ff78462020-07-10 22:00:53 +0200812 2] [3,
813 4]
814< This does not work: >
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200815 echo [1, 2]
Bram Moolenaar7ff78462020-07-10 22:00:53 +0200816 [3, 4]
Bram Moolenaar74235772021-06-12 14:53:05 +0200817- In some cases it is difficult for Vim to parse a command, especially when
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000818 commands are used as an argument to another command, such as `:windo`. In
Bram Moolenaar74235772021-06-12 14:53:05 +0200819 those cases the line continuation with a backslash has to be used.
Bram Moolenaar4fdae992020-04-12 16:38:57 +0200820
Bram Moolenaar4c295022021-05-02 17:19:11 +0200821
822White space ~
Bram Moolenaara2baa732022-02-04 16:09:54 +0000823 *E1004* *E1068* *E1069* *E1074* *E1127* *E1202*
Bram Moolenaar4c295022021-05-02 17:19:11 +0200824Vim9 script enforces proper use of white space. This is no longer allowed: >
825 var name=234 # Error!
826 var name= 234 # Error!
827 var name =234 # Error!
828There must be white space before and after the "=": >
829 var name = 234 # OK
830White space must also be put before the # that starts a comment after a
831command: >
832 var name = 234# Error!
833 var name = 234 # OK
834
835White space is required around most operators.
836
837White space is required in a sublist (list slice) around the ":", except at
838the start and end: >
Bram Moolenaar938ae282023-02-20 20:44:55 +0000839 otherlist = mylist[v : count] # v:count has a different meaning
Bram Moolenaar4c295022021-05-02 17:19:11 +0200840 otherlist = mylist[:] # make a copy of the List
841 otherlist = mylist[v :]
842 otherlist = mylist[: v]
843
844White space is not allowed:
845- Between a function name and the "(": >
846 Func (arg) # Error!
847 Func
848 \ (arg) # Error!
849 Func
850 (arg) # Error!
851 Func(arg) # OK
852 Func(
853 arg) # OK
854 Func(
855 arg # OK
856 )
Bram Moolenaara2baa732022-02-04 16:09:54 +0000857< *E1205*
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200858White space is not allowed in a `:set` command between the option name and a
859following "&", "!", "<", "=", "+=", "-=" or "^=".
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +0200860
Bram Moolenaar4c295022021-05-02 17:19:11 +0200861
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100862No curly braces expansion ~
863
864|curly-braces-names| cannot be used.
865
866
Bram Moolenaara2baa732022-02-04 16:09:54 +0000867Command modifiers are not ignored ~
868 *E1176*
869Using a command modifier for a command that does not use it gives an error.
Bram Moolenaar2ecbe532022-07-29 21:36:21 +0100870 *E1082*
871Also, using a command modifier without a following command is now an error.
Bram Moolenaara2baa732022-02-04 16:09:54 +0000872
873
Bram Moolenaar2bede172020-11-19 18:53:18 +0100874Dictionary literals ~
Bram Moolenaar6f4754b2022-01-23 12:07:04 +0000875 *vim9-literal-dict* *E1014*
Bram Moolenaar2bede172020-11-19 18:53:18 +0100876Traditionally Vim has supported dictionary literals with a {} syntax: >
877 let dict = {'key': value}
878
Bram Moolenaarc5e6a712020-12-04 19:12:14 +0100879Later it became clear that using a simple text key is very common, thus
880literal dictionaries were introduced in a backwards compatible way: >
Bram Moolenaar2bede172020-11-19 18:53:18 +0100881 let dict = #{key: value}
882
Bram Moolenaarc5e6a712020-12-04 19:12:14 +0100883However, this #{} syntax is unlike any existing language. As it turns out
884that using a literal key is much more common than using an expression, and
Bram Moolenaar2bede172020-11-19 18:53:18 +0100885considering that JavaScript uses this syntax, using the {} form for dictionary
Bram Moolenaarc5e6a712020-12-04 19:12:14 +0100886literals is considered a much more useful syntax. In Vim9 script the {} form
Bram Moolenaar2bede172020-11-19 18:53:18 +0100887uses literal keys: >
Bram Moolenaar98a29d02021-01-18 19:55:44 +0100888 var dict = {key: value}
Bram Moolenaar2bede172020-11-19 18:53:18 +0100889
Bram Moolenaarc5e6a712020-12-04 19:12:14 +0100890This works for alphanumeric characters, underscore and dash. If you want to
891use another character, use a single or double quoted string: >
Bram Moolenaar98a29d02021-01-18 19:55:44 +0100892 var dict = {'key with space': value}
893 var dict = {"key\twith\ttabs": value}
Bram Moolenaar938ae282023-02-20 20:44:55 +0000894 var dict = {'': value} # empty key
Bram Moolenaarf10911e2022-01-29 22:20:48 +0000895< *E1139*
Bram Moolenaarc5e6a712020-12-04 19:12:14 +0100896In case the key needs to be an expression, square brackets can be used, just
897like in JavaScript: >
Bram Moolenaar98a29d02021-01-18 19:55:44 +0100898 var dict = {["key" .. nr]: value}
Bram Moolenaar2bede172020-11-19 18:53:18 +0100899
Bram Moolenaar2e5910b2021-02-03 17:41:24 +0100900The key type can be string, number, bool or float. Other types result in an
Bram Moolenaard899e512022-05-07 21:54:03 +0100901error. Without using [] the value is used as a string, keeping leading zeros.
902An expression given with [] is evaluated and then converted to a string.
903Leading zeros will then be dropped: >
904 var dict = {000123: 'without', [000456]: 'with'}
Bram Moolenaar2e5910b2021-02-03 17:41:24 +0100905 echo dict
Bram Moolenaard899e512022-05-07 21:54:03 +0100906 {'456': 'with', '000123': 'without'}
907A float only works inside [] because the dot is not accepted otherwise: >
908 var dict = {[00.013]: 'float'}
909 echo dict
910 {'0.013': 'float'}
Bram Moolenaar2e5910b2021-02-03 17:41:24 +0100911
Bram Moolenaar2bede172020-11-19 18:53:18 +0100912
Bram Moolenaar10b94212021-02-19 21:42:57 +0100913No :xit, :t, :k, :append, :change or :insert ~
Bram Moolenaarf10911e2022-01-29 22:20:48 +0000914 *E1100*
Bram Moolenaarf5a48012020-08-01 17:00:03 +0200915These commands are too easily confused with local variable names.
916Instead of `:x` or `:xit` you can use `:exit`.
917Instead of `:t` you can use `:copy`.
Bram Moolenaar10b94212021-02-19 21:42:57 +0100918Instead of `:k` you can use `:mark`.
Bram Moolenaar560979e2020-02-04 22:53:05 +0100919
920
921Comparators ~
922
923The 'ignorecase' option is not used for comparators that use strings.
Bram Moolenaar944697a2022-02-20 19:48:20 +0000924Thus "=~" works like "=~#".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100925
Bram Moolenaare1f3fd12022-08-15 18:51:32 +0100926"is" and "isnot" (|expr-is| and |expr-isnot|) when used on strings now return
927false. In legacy script they just compare the strings, in |Vim9| script they
928check identity, and strings are copied when used, thus two strings are never
Bram Moolenaar71badf92023-04-22 22:40:14 +0100929the same (this might change someday if strings are not copied but reference
Bram Moolenaare1f3fd12022-08-15 18:51:32 +0100930counted).
931
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100932
Bram Moolenaar4c295022021-05-02 17:19:11 +0200933Abort after error ~
934
935In legacy script, when an error is encountered, Vim continues to execute
936following lines. This can lead to a long sequence of errors and need to type
937CTRL-C to stop it. In Vim9 script execution of commands stops at the first
938error. Example: >
939 vim9script
940 var x = does-not-exist
941 echo 'not executed'
942
943
Bram Moolenaar98a29d02021-01-18 19:55:44 +0100944For loop ~
Bram Moolenaara2baa732022-02-04 16:09:54 +0000945 *E1254*
Bram Moolenaar47003982021-12-05 21:54:04 +0000946The loop variable must not be declared yet: >
Bram Moolenaar6304be62021-11-27 10:57:26 +0000947 var i = 1
948 for i in [1, 2, 3] # Error!
949
Bram Moolenaar47003982021-12-05 21:54:04 +0000950It is possible to use a global variable though: >
951 g:i = 1
952 for g:i in [1, 2, 3]
953 echo g:i
954 endfor
955
Bram Moolenaar98a29d02021-01-18 19:55:44 +0100956Legacy Vim script has some tricks to make a for loop over a list handle
957deleting items at the current or previous item. In Vim9 script it just uses
958the index, if items are deleted then items in the list will be skipped.
959Example legacy script: >
960 let l = [1, 2, 3, 4]
961 for i in l
962 echo i
963 call remove(l, index(l, i))
964 endfor
965Would echo:
966 1
967 2
968 3
969 4
970In compiled Vim9 script you get:
971 1
972 3
973Generally, you should not change the list that is iterated over. Make a copy
974first if needed.
Bram Moolenaar7c6cd442022-10-11 21:54:04 +0100975When looping over a list of lists, the nested lists can be changed. The loop
976variable is "final", it cannot be changed but what its value can be changed.
Bram Moolenaar9fbdbb82022-09-27 17:30:34 +0100977 *E1306*
978The depth of loops, :for and :while loops added together, cannot exceed 10.
Bram Moolenaar98a29d02021-01-18 19:55:44 +0100979
980
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100981Conditions and expressions ~
Bram Moolenaar6f4754b2022-01-23 12:07:04 +0000982 *vim9-boolean*
Bram Moolenaar13106602020-10-04 16:06:05 +0200983Conditions and expressions are mostly working like they do in other languages.
984Some values are different from legacy Vim script:
985 value legacy Vim script Vim9 script ~
986 0 falsy falsy
987 1 truthy truthy
988 99 truthy Error!
989 "0" falsy Error!
990 "99" truthy Error!
991 "text" falsy Error!
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100992
Bram Moolenaar13106602020-10-04 16:06:05 +0200993For the "??" operator and when using "!" then there is no error, every value
994is either falsy or truthy. This is mostly like JavaScript, except that an
995empty list and dict is falsy:
996
997 type truthy when ~
Bram Moolenaar7e6a5152021-01-02 16:39:53 +0100998 bool true, v:true or 1
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100999 number non-zero
1000 float non-zero
1001 string non-empty
1002 blob non-empty
1003 list non-empty (different from JavaScript)
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001004 tuple non-empty (different from JavaScript)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001005 dictionary non-empty (different from JavaScript)
Bram Moolenaard1caa942020-04-10 22:10:56 +02001006 func when there is a function name
Bram Moolenaar7e6a5152021-01-02 16:39:53 +01001007 special true or v:true
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001008 job when not NULL
1009 channel when not NULL
1010 class when not NULL
Bram Moolenaar7e6a5152021-01-02 16:39:53 +01001011 object when not NULL (TODO: when isTrue() returns true)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001012
Bram Moolenaar2bb26582020-10-03 22:52:39 +02001013The boolean operators "||" and "&&" expect the values to be boolean, zero or
1014one: >
1015 1 || false == true
1016 0 || 1 == true
1017 0 || false == false
1018 1 && true == true
1019 0 && 1 == false
1020 8 || 0 Error!
1021 'yes' && 0 Error!
1022 [] || 99 Error!
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001023
Bram Moolenaar2bb26582020-10-03 22:52:39 +02001024When using "!" for inverting, there is no error for using any type and the
Bram Moolenaar13106602020-10-04 16:06:05 +02001025result is a boolean. "!!" can be used to turn any value into boolean: >
Bram Moolenaar82be4842021-01-11 19:40:15 +01001026 !'yes' == false
Bram Moolenaar13106602020-10-04 16:06:05 +02001027 !![] == false
Bram Moolenaar82be4842021-01-11 19:40:15 +01001028 !![1, 2, 3] == true
Bram Moolenaar2bb26582020-10-03 22:52:39 +02001029
1030When using "`.."` for string concatenation arguments of simple types are
Bram Moolenaar13106602020-10-04 16:06:05 +02001031always converted to string: >
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001032 'hello ' .. 123 == 'hello 123'
Bram Moolenaar7e6a5152021-01-02 16:39:53 +01001033 'hello ' .. v:true == 'hello true'
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001034
Bram Moolenaar5da36052021-12-27 15:39:57 +00001035Simple types are Number, Float, Special and Bool. For other types |string()|
1036should be used.
Bram Moolenaar7db29e42022-12-11 15:53:04 +00001037 *false* *true* *null* *null_blob* *null_channel*
dkearns521fb7e2023-11-11 19:33:43 +11001038 *null_class* *null_dict* *null_function* *null_job*
1039 *null_list* *null_object* *null_partial* *null_string*
1040 *E1034*
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001041In Vim9 script one can use the following predefined values: >
1042 true
1043 false
1044 null
1045 null_blob
1046 null_channel
Yegappan Lakshmanane750f8c2023-08-24 07:07:05 -07001047 null_class
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001048 null_dict
1049 null_function
1050 null_job
1051 null_list
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001052 null_tuple
Yegappan Lakshmanane750f8c2023-08-24 07:07:05 -07001053 null_object
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001054 null_partial
1055 null_string
1056`true` is the same as `v:true`, `false` the same as `v:false`, `null` the same
1057as `v:null`.
1058
Bram Moolenaar76db9e02022-11-09 21:21:04 +00001059While `null` has the type "special", the other "null_" values have the type
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001060indicated by their name. Quite often a null value is handled the same as an
1061empty value, but not always. The values can be useful to clear a script-local
1062variable, since they cannot be deleted with `:unlet`. E.g.: >
1063 var theJob = job_start(...)
1064 # let the job do its work
1065 theJob = null_job
1066
1067The values can also be useful as the default value for an argument: >
1068 def MyFunc(b: blob = null_blob)
erraelcea3dac2023-12-25 01:31:23 -08001069 # Note: compare against null, not null_blob,
1070 # to distinguish the default value from an empty blob.
1071 if b == null
1072 # b argument was not given
1073See |null-compare| for more information about testing against null.
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001074
Bram Moolenaar47c532e2022-03-19 15:18:53 +00001075It is possible to compare `null` with any value, this will not give a type
1076error. However, comparing `null` with a number, float or bool will always
1077result in `false`. This is different from legacy script, where comparing
1078`null` with zero or `false` would return `true`.
Bram Moolenaar10e8ff92023-06-10 21:40:39 +01001079 *vim9-false-true*
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001080When converting a boolean to a string `false` and `true` are used, not
1081`v:false` and `v:true` like in legacy script. `v:none` has no `none`
1082replacement, it has no equivalent in other languages.
Bram Moolenaar10e8ff92023-06-10 21:40:39 +01001083 *vim9-string-index*
Bram Moolenaar0289a092021-03-14 18:40:19 +01001084Indexing a string with [idx] or taking a slice with [idx : idx] uses character
1085indexes instead of byte indexes. Composing characters are included.
1086Example: >
Bram Moolenaar3d1cde82020-08-15 18:55:18 +02001087 echo 'bár'[1]
1088In legacy script this results in the character 0xc3 (an illegal byte), in Vim9
1089script this results in the string 'á'.
Bram Moolenaar82be4842021-01-11 19:40:15 +01001090A negative index is counting from the end, "[-1]" is the last character.
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001091To exclude the last character use |slice()|.
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02001092To count composing characters separately use |strcharpart()|.
Bram Moolenaar82be4842021-01-11 19:40:15 +01001093If the index is out of range then an empty string results.
1094
1095In legacy script "++var" and "--var" would be silently accepted and have no
1096effect. This is an error in Vim9 script.
1097
1098Numbers starting with zero are not considered to be octal, only numbers
1099starting with "0o" are octal: "0o744". |scriptversion-4|
Bram Moolenaar3d1cde82020-08-15 18:55:18 +02001100
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001101
Bram Moolenaare46a4402020-06-30 20:38:27 +02001102What to watch out for ~
1103 *vim9-gotchas*
1104Vim9 was designed to be closer to often used programming languages, but at the
1105same time tries to support the legacy Vim commands. Some compromises had to
1106be made. Here is a summary of what might be unexpected.
1107
1108Ex command ranges need to be prefixed with a colon. >
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001109 -> legacy Vim: shifts the previous line to the right
1110 ->func() Vim9: method call in a continuation line
1111 :-> Vim9: shifts the previous line to the right
Bram Moolenaare46a4402020-06-30 20:38:27 +02001112
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001113 %s/a/b legacy Vim: substitute on all lines
Bram Moolenaare46a4402020-06-30 20:38:27 +02001114 x = alongname
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001115 % another Vim9: modulo operator in a continuation line
1116 :%s/a/b Vim9: substitute on all lines
1117 't legacy Vim: jump to mark t
1118 'text'->func() Vim9: method call
1119 :'t Vim9: jump to mark t
Bram Moolenaare46a4402020-06-30 20:38:27 +02001120
Bram Moolenaare7b1ea02020-08-07 19:54:59 +02001121Some Ex commands can be confused with assignments in Vim9 script: >
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001122 g:name = value # assignment
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001123 :g:pattern:cmd # :global command
Bram Moolenaare7b1ea02020-08-07 19:54:59 +02001124
Bram Moolenaar7b829262021-10-13 15:04:34 +01001125To avoid confusion between a `:global` or `:substitute` command and an
1126expression or assignment, a few separators cannot be used when these commands
1127are abbreviated to a single character: ':', '-' and '.'. >
1128 g:pattern:cmd # invalid command - ERROR
1129 s:pattern:repl # invalid command - ERROR
1130 g-pattern-cmd # invalid command - ERROR
1131 s-pattern-repl # invalid command - ERROR
1132 g.pattern.cmd # invalid command - ERROR
1133 s.pattern.repl # invalid command - ERROR
1134
1135Also, there cannot be a space between the command and the separator: >
1136 g /pattern/cmd # invalid command - ERROR
1137 s /pattern/repl # invalid command - ERROR
1138
Bram Moolenaare46a4402020-06-30 20:38:27 +02001139Functions defined with `:def` compile the whole function. Legacy functions
1140can bail out, and the following lines are not parsed: >
1141 func Maybe()
1142 if !has('feature')
1143 return
1144 endif
1145 use-feature
1146 endfunc
1147Vim9 functions are compiled as a whole: >
1148 def Maybe()
1149 if !has('feature')
1150 return
1151 endif
Bram Moolenaar82be4842021-01-11 19:40:15 +01001152 use-feature # May give a compilation error
Bram Moolenaare46a4402020-06-30 20:38:27 +02001153 enddef
1154For a workaround, split it in two functions: >
1155 func Maybe()
1156 if has('feature')
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001157 call MaybeInner()
Bram Moolenaare46a4402020-06-30 20:38:27 +02001158 endif
1159 endfunc
1160 if has('feature')
1161 def MaybeInner()
1162 use-feature
1163 enddef
1164 endif
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02001165Or put the unsupported code inside an `if` with a constant expression that
Bram Moolenaar207f0092020-08-30 17:20:20 +02001166evaluates to false: >
1167 def Maybe()
1168 if has('feature')
1169 use-feature
1170 endif
1171 enddef
Bram Moolenaar6aa57292021-08-14 21:25:52 +02001172The `exists_compiled()` function can also be used for this.
1173 *vim9-user-command*
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001174Another side effect of compiling a function is that the presence of a user
Bram Moolenaar82be4842021-01-11 19:40:15 +01001175command is checked at compile time. If the user command is defined later an
1176error will result. This works: >
1177 command -nargs=1 MyCommand echom <q-args>
1178 def Works()
1179 MyCommand 123
1180 enddef
1181This will give an error for "MyCommand" not being defined: >
1182 def Works()
1183 command -nargs=1 MyCommand echom <q-args>
1184 MyCommand 123
1185 enddef
1186A workaround is to invoke the command indirectly with `:execute`: >
1187 def Works()
1188 command -nargs=1 MyCommand echom <q-args>
1189 execute 'MyCommand 123'
1190 enddef
1191
Bram Moolenaar207f0092020-08-30 17:20:20 +02001192Note that for unrecognized commands there is no check for "|" and a following
1193command. This will give an error for missing `endif`: >
1194 def Maybe()
1195 if has('feature') | use-feature | endif
1196 enddef
Bram Moolenaare46a4402020-06-30 20:38:27 +02001197
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001198Other differences ~
1199
1200Patterns are used like 'magic' is set, unless explicitly overruled.
1201The 'edcompatible' option value is not used.
1202The 'gdefault' option value is not used.
1203
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001204You may also find this wiki useful. It was written by an early adopter of
Bram Moolenaarc8cdf0f2021-03-13 13:28:13 +01001205Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001206
Bram Moolenaar4d8f4762021-06-27 15:18:56 +02001207 *:++* *:--*
1208The ++ and -- commands have been added. They are very similar to adding or
1209subtracting one: >
1210 ++var
1211 var += 1
1212 --var
1213 var -= 1
1214
1215Using ++var or --var in an expression is not supported yet.
1216
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001217==============================================================================
1218
12193. New style functions *fast-functions*
1220
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001221 *:def* *E1028*
Bram Moolenaar3d1cde82020-08-15 18:55:18 +02001222:def[!] {name}([arguments])[: {return-type}]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001223 Define a new function by the name {name}. The body of
1224 the function follows in the next lines, until the
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001225 matching `:enddef`. *E1073*
1226 *E1011*
1227 The {name} must be less than 100 bytes long.
1228 *E1003* *E1027* *E1056* *E1059*
1229 The type of value used with `:return` must match
1230 {return-type}. When {return-type} is omitted or is
1231 "void" the function is not expected to return
1232 anything.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001233 *E1077* *E1123*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001234 {arguments} is a sequence of zero or more argument
1235 declarations. There are three forms:
1236 {name}: {type}
1237 {name} = {value}
1238 {name}: {type} = {value}
1239 The first form is a mandatory argument, the caller
1240 must always provide them.
1241 The second and third form are optional arguments.
1242 When the caller omits an argument the {value} is used.
1243
Bram Moolenaar65e0d772020-06-14 17:29:55 +02001244 The function will be compiled into instructions when
Bram Moolenaar2547aa92020-07-26 17:00:44 +02001245 called, or when `:disassemble` or `:defcompile` is
1246 used. Syntax and type errors will be produced at that
1247 time.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02001248
Bram Moolenaar2547aa92020-07-26 17:00:44 +02001249 It is possible to nest `:def` inside another `:def` or
1250 `:function` up to about 50 levels deep.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001251 *E1117*
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001252 [!] is used as with `:function`. Note that
1253 script-local functions cannot be deleted or redefined
1254 later in Vim9 script. They can only be removed by
1255 reloading the same script.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001256
Bram Moolenaara2baa732022-02-04 16:09:54 +00001257 *:enddef* *E1057* *E1152* *E1173*
Bram Moolenaar2547aa92020-07-26 17:00:44 +02001258:enddef End of a function defined with `:def`. It should be on
1259 a line by its own.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001260
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001261You may also find this wiki useful. It was written by an early adopter of
Bram Moolenaar0289a092021-03-14 18:40:19 +01001262Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001263
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01001264If the script the function is defined in is Vim9 script, then script-local
1265variables can be accessed without the "s:" prefix. They must be defined
Bram Moolenaar65e0d772020-06-14 17:29:55 +02001266before the function is compiled. If the script the function is defined in is
1267legacy script, then script-local variables must be accessed with the "s:"
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001268prefix if they do not exist at the time of compiling.
Bram Moolenaar2ecbe532022-07-29 21:36:21 +01001269 *E1269*
1270Script-local variables in a |Vim9| script must be declared at the script
1271level. They cannot be created in a function, also not in a legacy function.
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01001272
Bram Moolenaar388a5d42020-05-26 21:20:45 +02001273 *:defc* *:defcompile*
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +01001274:defc[ompile] Compile functions and classes (|class-compile|)
1275 defined in the current script that were not compiled
1276 yet. This will report any errors found during
1277 compilation.
1278
h_east4d496432024-01-27 19:22:28 +09001279:defc[ompile] MyClass Compile all methods in a class. |class-compile|
Bram Moolenaarf79d9dd2022-05-21 15:39:02 +01001280
1281:defc[ompile] {func}
1282:defc[ompile] debug {func}
1283:defc[ompile] profile {func}
1284 Compile function {func}, if needed. Use "debug" and
1285 "profile" to specify the compilation mode.
1286 This will report any errors found during compilation.
Bram Moolenaardd60c362023-02-27 15:49:53 +00001287 {func} call also be "ClassName.functionName" to
1288 compile a function or method in a class.
1289 {func} call also be "ClassName" to compile all
1290 functions and methods in a class.
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01001291
Bram Moolenaarebdf3c92020-02-15 21:41:42 +01001292 *:disa* *:disassemble*
1293:disa[ssemble] {func} Show the instructions generated for {func}.
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001294 This is for debugging and testing. *E1061*
Bram Moolenaarcc390ff2020-02-29 22:06:30 +01001295 Note that for command line completion of {func} you
1296 can prepend "s:" to find script-local functions.
Bram Moolenaarebdf3c92020-02-15 21:41:42 +01001297
Bram Moolenaar2346a632021-06-13 19:02:49 +02001298:disa[ssemble] profile {func}
1299 Like `:disassemble` but with the instructions used for
Bram Moolenaare0e39172021-01-25 21:14:57 +01001300 profiling.
1301
Bram Moolenaar2346a632021-06-13 19:02:49 +02001302:disa[ssemble] debug {func}
1303 Like `:disassemble` but with the instructions used for
1304 debugging.
1305
Bram Moolenaar7ff78462020-07-10 22:00:53 +02001306Limitations ~
1307
1308Local variables will not be visible to string evaluation. For example: >
Bram Moolenaar2b327002020-12-26 15:39:31 +01001309 def MapList(): list<string>
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001310 var list = ['aa', 'bb', 'cc', 'dd']
Bram Moolenaar7ff78462020-07-10 22:00:53 +02001311 return range(1, 2)->map('list[v:val]')
1312 enddef
1313
1314The map argument is a string expression, which is evaluated without the
1315function scope. Instead, use a lambda: >
Bram Moolenaar2b327002020-12-26 15:39:31 +01001316 def MapList(): list<string>
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001317 var list = ['aa', 'bb', 'cc', 'dd']
Bram Moolenaar22863042021-10-16 15:23:36 +01001318 return range(1, 2)->map((_, v) => list[v])
Bram Moolenaar7ff78462020-07-10 22:00:53 +02001319 enddef
1320
Bram Moolenaar3d2e0312021-12-01 09:27:20 +00001321For commands that are not compiled, such as `:edit`, backtick expansion can be
1322used and it can use the local scope. Example: >
Bram Moolenaar2b327002020-12-26 15:39:31 +01001323 def Replace()
Bram Moolenaar3d2e0312021-12-01 09:27:20 +00001324 var fname = 'blah.txt'
1325 edit `=fname`
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001326 enddef
1327
Bram Moolenaardad44732021-03-31 20:07:33 +02001328Closures defined in a loop will share the same context. For example: >
1329 var flist: list<func>
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001330 for i in range(5)
Bram Moolenaardad44732021-03-31 20:07:33 +02001331 var inloop = i
1332 flist[i] = () => inloop
1333 endfor
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001334 echo range(5)->map((i, _) => flist[i]())
1335 # Result: [4, 4, 4, 4, 4]
Bram Moolenaar47c532e2022-03-19 15:18:53 +00001336< *E1271*
1337A closure must be compiled in the context that it is defined in, so that
1338variables in that context can be found. This mostly happens correctly, except
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00001339when a function is marked for debugging with `:breakadd` after it was compiled.
Bram Moolenaar46eea442022-03-30 10:51:39 +01001340Make sure to define the breakpoint before compiling the outer function.
Bram Moolenaardad44732021-03-31 20:07:33 +02001341
1342The "inloop" variable will exist only once, all closures put in the list refer
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001343to the same instance, which in the end will have the value 4. This is
1344efficient, also when looping many times. If you do want a separate context
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001345for each closure, call a function to define it: >
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001346 def GetClosure(i: number): func
1347 var infunc = i
1348 return () => infunc
Bram Moolenaardad44732021-03-31 20:07:33 +02001349 enddef
1350
1351 var flist: list<func>
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001352 for i in range(5)
1353 flist[i] = GetClosure(i)
Bram Moolenaardad44732021-03-31 20:07:33 +02001354 endfor
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001355 echo range(5)->map((i, _) => flist[i]())
1356 # Result: [0, 1, 2, 3, 4]
Bram Moolenaardad44732021-03-31 20:07:33 +02001357
Bram Moolenaara2baa732022-02-04 16:09:54 +00001358In some situations, especially when calling a Vim9 closure from legacy
1359context, the evaluation will fail. *E1248*
1360
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001361Note that at the script level the loop variable will be invalid after the
1362loop, also when used in a closure that is called later, e.g. with a timer.
1363This will generate error |E1302|: >
1364 for n in range(4)
1365 timer_start(500 * n, (_) => {
1366 echowin n
1367 })
1368 endfor
1369
Bram Moolenaar9712ff12022-09-18 13:04:22 +01001370You need to use a block and define a variable there, and use that one in the
1371closure: >
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001372 for n in range(4)
Bram Moolenaar9712ff12022-09-18 13:04:22 +01001373 {
1374 var nr = n
1375 timer_start(500 * n, (_) => {
1376 echowin nr
1377 })
1378 }
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001379 endfor
1380
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00001381Using `:echowindow` is useful in a timer, the messages go into a popup and will
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001382not interfere with what the user is doing when it triggers.
1383
Bram Moolenaara2baa732022-02-04 16:09:54 +00001384
1385Converting a function from legacy to Vim9 ~
1386 *convert_legacy_function_to_vim9*
1387These are the most changes that need to be made to convert a legacy function
1388to a Vim9 function:
1389
1390- Change `func` or `function` to `def`.
1391- Change `endfunc` or `endfunction` to `enddef`.
1392- Add types to the function arguments.
1393- If the function returns something, add the return type.
1394- Change comments to start with # instead of ".
1395
1396 For example, a legacy function: >
1397 func MyFunc(text)
1398 " function body
1399 endfunc
1400< Becomes: >
1401 def MyFunc(text: string): number
1402 # function body
1403 enddef
1404
1405- Remove "a:" used for arguments. E.g.: >
1406 return len(a:text)
1407< Becomes: >
1408 return len(text)
1409
1410- Change `let` used to declare a variable to `var`.
1411- Remove `let` used to assign a value to a variable. This is for local
1412 variables already declared and b: w: g: and t: variables.
1413
1414 For example, legacy function: >
1415 let lnum = 1
1416 let lnum += 3
1417 let b:result = 42
1418< Becomes: >
1419 var lnum = 1
1420 lnum += 3
1421 b:result = 42
1422
1423- Insert white space in expressions where needed.
1424- Change "." used for concatenation to "..".
1425
1426 For example, legacy function: >
1427 echo line(1).line(2)
1428< Becomes: >
1429 echo line(1) .. line(2)
1430
1431- line continuation does not always require a backslash: >
Bram Moolenaar938ae282023-02-20 20:44:55 +00001432 echo ['one',
Bram Moolenaara2baa732022-02-04 16:09:54 +00001433 \ 'two',
1434 \ 'three'
1435 \ ]
1436< Becomes: >
1437 echo ['one',
1438 'two',
1439 'three'
1440 ]
1441
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +01001442
1443Calling a function in an expr option ~
1444 *expr-option-function*
Bram Moolenaarf269eab2022-10-03 18:04:35 +01001445The value of a few options, such as 'foldexpr', is an expression that is
1446evaluated to get a value. The evaluation can have quite a bit of overhead.
1447One way to minimize the overhead, and also to keep the option value very
1448simple, is to define a compiled function and set the option to call it
1449without arguments. Example: >
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +01001450 vim9script
1451 def MyFoldFunc(): any
1452 ... compute fold level for line v:lnum
1453 return level
1454 enddef
1455 set foldexpr=s:MyFoldFunc()
1456
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001457==============================================================================
1458
14594. Types *vim9-types*
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001460 *E1008* *E1009* *E1010* *E1012*
1461 *E1013* *E1029* *E1030*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001462The following builtin types are supported:
1463 bool
1464 number
1465 float
1466 string
1467 blob
Bram Moolenaard77a8522020-04-03 21:59:57 +02001468 list<{type}>
1469 dict<{type}>
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001470 job
1471 channel
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001472 tuple<{type}>
1473 tuple<{type}, {type}, ...>
1474 tuple<...list<{type}>>
1475 tuple<{type}, ...list<{type}>>
Bram Moolenaarb17893a2020-03-14 08:19:51 +01001476 func
Bram Moolenaard1caa942020-04-10 22:10:56 +02001477 func: {type}
Bram Moolenaard77a8522020-04-03 21:59:57 +02001478 func({type}, ...)
1479 func({type}, ...): {type}
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001480 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001481
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001482These types can be used in declarations, but no simple value will actually
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001483have the "void" type. Trying to use a void (e.g. a function without a
Bram Moolenaara2baa732022-02-04 16:09:54 +00001484return value) results in error *E1031* *E1186* .
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001485
Bram Moolenaard77a8522020-04-03 21:59:57 +02001486There is no array type, use list<{type}> instead. For a list constant an
Bram Moolenaar71badf92023-04-22 22:40:14 +01001487efficient implementation is used that avoids allocating a lot of small pieces
1488of memory.
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001489 *tuple-type*
1490A tuple type can be declared in more or less specific ways:
1491tuple<number> a tuple with a single item of type |Number|
1492tuple<number, string> a tuple with two items of type |Number| and
1493 |String|
1494tuple<number, float, bool> a tuple with three items of type |Number|,
1495 |Float| and |Boolean|.
1496tuple<...list<number>> a variadic tuple with zero or more items of
1497 type |Number|.
1498tuple<number, ...list<string>> a tuple with an item of type |Number| followed
1499 by zero or more items of type |String|.
1500
1501Examples: >
1502 var myTuple: tuple<number> = (20,)
1503 var myTuple: tuple<number, string> = (30, 'vim')
1504 var myTuple: tuple<number, float, bool> = (40, 1.1, true)
1505 var myTuple: tuple<...list<string>> = ('a', 'b', 'c')
1506 var myTuple: tuple<number, ...list<string>> = (3, 'a', 'b', 'c')
1507<
1508 *variadic-tuple* *E1539*
1509A variadic tuple has zero or more items of the same type. The type of a
1510variadic tuple must end with a list type. Examples: >
1511 var myTuple: tuple<...list<number>> = (1, 2, 3)
1512 var myTuple: tuple<...list<string>> = ('a', 'b', 'c')
1513 var myTuple: tuple<...list<bool>> = ()
1514<
Ernie Rael3ec6c1f2023-10-21 11:45:38 +02001515 *vim9-func-declaration* *E1005* *E1007*
Bram Moolenaard77a8522020-04-03 21:59:57 +02001516A partial and function can be declared in more or less specific ways:
1517func any kind of function reference, no type
Bram Moolenaard1caa942020-04-10 22:10:56 +02001518 checking for arguments or return value
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001519func: void any number and type of arguments, no return
1520 value
Bram Moolenaard77a8522020-04-03 21:59:57 +02001521func: {type} any number and type of arguments with specific
1522 return type
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001523
1524func() function with no argument, does not return a
1525 value
1526func(): void same
1527func(): {type} function with no argument and return type
1528
Bram Moolenaard1caa942020-04-10 22:10:56 +02001529func({type}) function with argument type, does not return
Bram Moolenaard77a8522020-04-03 21:59:57 +02001530 a value
Bram Moolenaard1caa942020-04-10 22:10:56 +02001531func({type}): {type} function with argument type and return type
1532func(?{type}) function with type of optional argument, does
1533 not return a value
Ernie Raela5a15342023-10-23 19:08:38 +02001534func(...list<{type}>) function with type of list for variable number
1535 of arguments, does not return a value
1536func({type}, ?{type}, ...list<{type}>): {type}
Bram Moolenaard1caa942020-04-10 22:10:56 +02001537 function with:
1538 - type of mandatory argument
1539 - type of optional argument
Ernie Raela5a15342023-10-23 19:08:38 +02001540 - type of list for variable number of
1541 arguments
Bram Moolenaard1caa942020-04-10 22:10:56 +02001542 - return type
Bram Moolenaard77a8522020-04-03 21:59:57 +02001543
1544If the return type is "void" the function does not return a value.
1545
1546The reference can also be a |Partial|, in which case it stores extra arguments
1547and/or a dictionary, which are not visible to the caller. Since they are
1548called in the same way the declaration is the same.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001549
1550Custom types can be defined with `:type`: >
1551 :type MyList list<string>
Bram Moolenaar127542b2020-08-09 17:22:04 +02001552Custom types must start with a capital letter, to avoid name clashes with
1553builtin types added later, similarly to user functions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001554
1555And classes and interfaces can be used as types: >
1556 :class MyClass
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001557 :var mine: MyClass
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001558
1559 :interface MyInterface
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001560 :var mine: MyInterface
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001561
1562 :class MyTemplate<Targ>
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001563 :var mine: MyTemplate<number>
1564 :var mine: MyTemplate<string>
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001565
1566 :class MyInterface<Targ>
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001567 :var mine: MyInterface<number>
1568 :var mine: MyInterface<string>
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001569{not implemented yet}
1570
1571
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001572Variable types and type casting ~
1573 *variable-types*
Bram Moolenaar64d662d2020-08-09 19:02:50 +02001574Variables declared in Vim9 script or in a `:def` function have a type, either
1575specified explicitly or inferred from the initialization.
1576
1577Global, buffer, window and tab page variables do not have a specific type, the
1578value can be changed at any time, possibly changing the type. Therefore, in
1579compiled code the "any" type is assumed.
1580
1581This can be a problem when the "any" type is undesired and the actual type is
1582expected to always be the same. For example, when declaring a list: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001583 var l: list<number> = [1, g:two]
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001584At compile time Vim doesn't know the type of "g:two" and the expression type
1585becomes list<any>. An instruction is generated to check the list type before
1586doing the assignment, which is a bit inefficient.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001587 *type-casting* *E1104*
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001588To avoid this, use a type cast: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001589 var l: list<number> = [1, <number>g:two]
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001590The compiled code will then only check that "g:two" is a number and give an
1591error if it isn't. This is called type casting.
Bram Moolenaar64d662d2020-08-09 19:02:50 +02001592
1593The syntax of a type cast is: "<" {type} ">". There cannot be white space
1594after the "<" or before the ">" (to avoid them being confused with
1595smaller-than and bigger-than operators).
1596
1597The semantics is that, if needed, a runtime type check is performed. The
1598value is not actually changed. If you need to change the type, e.g. to change
1599it to a string, use the |string()| function. Or use |str2nr()| to convert a
1600string to a number.
1601
Bram Moolenaar2ecbe532022-07-29 21:36:21 +01001602If a type is given where it is not expected you can get *E1272* .
1603
h_eastba77bbb2023-10-03 04:47:13 +09001604If a type is incomplete you get *E1363* , e.g. when you have an object for
Bram Moolenaar71badf92023-04-22 22:40:14 +01001605which the class is not known (usually that is a null object).
Bram Moolenaar64d662d2020-08-09 19:02:50 +02001606
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001607Type inference ~
1608 *type-inference*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001609In general: Whenever the type is clear it can be omitted. For example, when
1610declaring a variable and giving it a value: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001611 var name = 0 # infers number type
1612 var name = 'hello' # infers string type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001613
Bram Moolenaar127542b2020-08-09 17:22:04 +02001614The type of a list and dictionary comes from the common type of the values.
1615If the values all have the same type, that type is used for the list or
1616dictionary. If there is a mix of types, the "any" type is used. >
1617 [1, 2, 3] list<number>
1618 ['a', 'b', 'c'] list<string>
1619 [1, 'x', 3] list<any>
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001620
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001621The common type of function references, if they do not all have the same
1622number of arguments, uses "(...)" to indicate the number of arguments is not
1623specified. For example: >
1624 def Foo(x: bool)
1625 enddef
1626 def Bar(x: bool, y: bool)
1627 enddef
1628 var funclist = [Foo, Bar]
1629 echo funclist->typename()
1630Results in:
1631 list<func(...)>
1632
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001633For script-local variables in Vim9 script the type is checked, also when the
1634variable was declared in a legacy function.
1635
Bram Moolenaar9da17d72022-02-09 21:50:44 +00001636When a type has been declared this is attached to a List or Dictionary. When
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001637later some expression attempts to change the type an error will be given: >
1638 var ll: list<number> = [1, 2, 3]
Bram Moolenaarc4573eb2022-01-31 15:40:56 +00001639 ll->extend(['x']) # Error, 'x' is not a number
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001640
Bram Moolenaar9da17d72022-02-09 21:50:44 +00001641If the type is not declared then it is allowed to change: >
Bram Moolenaarc4573eb2022-01-31 15:40:56 +00001642 [1, 2, 3]->extend(['x']) # result: [1, 2, 3, 'x']
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001643
Bram Moolenaar9da17d72022-02-09 21:50:44 +00001644For a variable declaration an inferred type matters: >
1645 var ll = [1, 2, 3]
1646 ll->extend(['x']) # Error, 'x' is not a number
1647That is because the declaration looks like a list of numbers, thus is
1648equivalent to: >
1649 var ll: list<number> = [1, 2, 3]
1650If you do want a more permissive list you need to declare the type: >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00001651 var ll: list<any> = [1, 2, 3]
Bram Moolenaar9da17d72022-02-09 21:50:44 +00001652 ll->extend(['x']) # OK
1653
Bram Moolenaar207f0092020-08-30 17:20:20 +02001654
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001655Stricter type checking ~
1656 *type-checking*
Bram Moolenaar207f0092020-08-30 17:20:20 +02001657In legacy Vim script, where a number was expected, a string would be
1658automatically converted to a number. This was convenient for an actual number
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001659such as "123", but leads to unexpected problems (and no error message) if the
Bram Moolenaar207f0092020-08-30 17:20:20 +02001660string doesn't start with a number. Quite often this leads to hard-to-find
Bram Moolenaar944697a2022-02-20 19:48:20 +00001661bugs. e.g.: >
1662 echo 123 == '123'
1663< 1 ~
1664With an accidental space: >
1665 echo 123 == ' 123'
1666< 0 ~
Bram Moolenaara2baa732022-02-04 16:09:54 +00001667 *E1206* *E1210* *E1212*
Bram Moolenaar207f0092020-08-30 17:20:20 +02001668In Vim9 script this has been made stricter. In most places it works just as
Bram Moolenaar944697a2022-02-20 19:48:20 +00001669before if the value used matches the expected type. There will sometimes be
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02001670an error, thus breaking backwards compatibility. For example:
Bram Moolenaar207f0092020-08-30 17:20:20 +02001671- Using a number other than 0 or 1 where a boolean is expected. *E1023*
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001672- Using a string value when setting a number option.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001673- Using a number where a string is expected. *E1024* *E1105*
Bram Moolenaar207f0092020-08-30 17:20:20 +02001674
Bram Moolenaar22863042021-10-16 15:23:36 +01001675One consequence is that the item type of a list or dict given to |map()| must
Bram Moolenaar944697a2022-02-20 19:48:20 +00001676not change, if the type was declared. This will give an error in Vim9
1677script: >
1678 var mylist: list<number> = [1, 2, 3]
1679 echo map(mylist, (i, v) => 'item ' .. i)
1680< E1012: Type mismatch; expected number but got string in map() ~
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001681
Bram Moolenaar944697a2022-02-20 19:48:20 +00001682Instead use |mapnew()|, it creates a new list: >
1683 var mylist: list<number> = [1, 2, 3]
1684 echo mapnew(mylist, (i, v) => 'item ' .. i)
1685< ['item 0', 'item 1', 'item 2'] ~
1686
1687If the item type was not declared or determined to be "any" it can change to a
1688more specific type. E.g. when a list of mixed types gets changed to a list of
1689strings: >
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001690 var mylist = [1, 2.0, '3']
1691 # typename(mylist) == "list<any>"
1692 map(mylist, (i, v) => 'item ' .. i)
1693 # typename(mylist) == "list<string>", no error
Bram Moolenaar944697a2022-02-20 19:48:20 +00001694
1695There is a subtle difference between using a list constant directly and
Bram Moolenaarafa048f2022-02-22 20:43:36 +00001696through a variable declaration. Because of type inference, when using a list
Bram Moolenaar944697a2022-02-20 19:48:20 +00001697constant to initialize a variable, this also sets the declared type: >
1698 var mylist = [1, 2, 3]
1699 # typename(mylist) == "list<number>"
1700 echo map(mylist, (i, v) => 'item ' .. i) # Error!
1701
1702When using the list constant directly, the type is not declared and is allowed
1703to change: >
1704 echo map([1, 2, 3], (i, v) => 'item ' .. i) # OK
1705
1706The reasoning behind this is that when a type is declared and the list is
1707passed around and changed, the declaration must always hold. So that you can
1708rely on the type to match the declared type. For a constant this is not
1709needed.
1710
1711 *E1158*
Bram Moolenaar9faec4e2021-02-27 16:38:07 +01001712Same for |extend()|, use |extendnew()| instead, and for |flatten()|, use
Bram Moolenaar944697a2022-02-20 19:48:20 +00001713|flattennew()| instead. Since |flatten()| is intended to always change the
1714type, it can not be used in Vim9 script.
1715
Ernie Rael3ec6c1f2023-10-21 11:45:38 +02001716Assigning to a funcref with specified arguments (see |vim9-func-declaration|)
1717does strict type checking of the arguments. For variable number of arguments
1718the type must match: >
1719 var FuncRef: func(string, number, bool): number
1720 FuncRef = (v1: string, v2: number, v3: bool) => 777 # OK
1721 FuncRef = (v1: string, v2: number, v3: number) => 777 # Error!
1722 # variable number of arguments must have same type
1723 var FuncVA: func(...list<string>): number
1724 FuncVA = (...v: list<number>): number => v # Error!
1725 FuncVA = (...v: list<any>): number => v # OK, `any` runtime check
1726 FuncVA = (v1: string, v: string2): number => 333 # Error!
1727 FuncVA = (v: list<string>): number => 3 # Error!
1728
zeertzjq61e984e2023-12-09 15:18:33 +08001729If the destination funcref has no specified arguments, then there is no
Ernie Rael3ec6c1f2023-10-21 11:45:38 +02001730argument type checking: >
1731 var FuncUnknownArgs: func: number
1732 FuncUnknownArgs = (v): number => v # OK
1733 FuncUnknownArgs = (v1: string, v2: string): number => 3 # OK
Ernie Raela5a15342023-10-23 19:08:38 +02001734 FuncUnknownArgs = (...v1: list<string>): number => 333 # OK
1735<
Bram Moolenaara2baa732022-02-04 16:09:54 +00001736 *E1211* *E1217* *E1218* *E1219* *E1220* *E1221*
1737 *E1222* *E1223* *E1224* *E1225* *E1226* *E1227*
Dominique Pellee764d1b2023-03-12 21:20:59 +00001738 *E1228* *E1238* *E1250* *E1251* *E1252* *E1256*
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001739 *E1297* *E1298* *E1301* *E1528* *E1529* *E1530*
1740 *E1531* *E1534*
Bram Moolenaara2baa732022-02-04 16:09:54 +00001741Types are checked for most builtin functions to make it easier to spot
1742mistakes.
Bram Moolenaar82be4842021-01-11 19:40:15 +01001743
erraelcea3dac2023-12-25 01:31:23 -08001744Categories of variables, defaults and null handling ~
1745 *variable-categories* *null-variables*
1746There are categories of variables:
1747 primitive number, float, boolean
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001748 container string, blob, list, tuple, dict
erraelcea3dac2023-12-25 01:31:23 -08001749 specialized function, job, channel, user-defined-object
1750
1751When declaring a variable without an initializer, an explicit type must be
1752provided. Each category has different default initialization semantics. Here's
1753an example for each category: >
1754 var num: number # primitives default to a 0 equivalent
1755 var cont: list<string> # containers default to an empty container
1756 var spec: job # specialized variables default to null
1757<
1758Vim does not have a familiar null value; it has various null_<type> predefined
1759values, for example |null_string|, |null_list|, |null_job|. Primitives do not
1760have a null_<type>. The typical use cases for null_<type> are:
h_east4d496432024-01-27 19:22:28 +09001761- to clear a variable and release its resources;
1762- as a default for a parameter in a function definition, see |null-compare|.
erraelcea3dac2023-12-25 01:31:23 -08001763
1764For a specialized variable, like `job`, null_<type> is used to clear the
1765resources. For a container variable, resources can also be cleared by
1766assigning an empty container to the variable. For example: >
1767 var j: job = job_start(...)
1768 # ... job does its work
1769 j = null_job # clear the variable and release the job's resources
1770
1771 var l: list<any>
1772 # ... add lots of stuff to list
1773 l = [] # clear the variable and release container resources
1774Using the empty container, rather than null_<type>, to clear a container
1775variable may avoid null complications as described in |null-anomalies|.
1776
1777The initialization semantics of container variables and specialized variables
1778differ. An uninitialized container defaults to an empty container: >
1779 var l1: list<string> # empty container
1780 var l2: list<string> = [] # empty container
1781 var l3: list<string> = null_list # null container
1782"l1" and "l2" are equivalent and indistinguishable initializations; but "l3"
1783is a null container. A null container is similar to, but different from, an
1784empty container, see |null-anomalies|.
1785
1786Specialized variables default to null. These job initializations are
1787equivalent and indistinguishable: >
1788 var j1: job
1789 var j2: job = null_job
1790 var j3 = null_job
1791
1792When a list or dict is declared, if the item type is not specified and can not
1793be inferred, then the type is "any": >
1794 var d1 = {} # type is "dict<any>"
1795 var d2 = null_dict # type is "dict<any>"
1796
1797Declaring a function, see |vim9-func-declaration|, is particularly unique.
1798
1799 *null-compare*
1800For familiar null compare semantics, where a null container is not equal to
1801an empty container, do not use null_<type> in a comparison: >
1802 vim9script
1803 def F(arg: list<string> = null_list)
1804 if arg == null
1805 echo "null"
1806 else
1807 echo printf("not null, %sempty", empty(arg) ? '' : 'not ')
1808 endif
1809 enddef
1810 F() # output: "null"
1811 F(null_list) # output: "null"
1812 F([]) # output: "not null, empty"
1813 F(['']) # output: "not null, not empty"
h_east4d496432024-01-27 19:22:28 +09001814The above function takes a list of strings and reports on it.
erraelcea3dac2023-12-25 01:31:23 -08001815Change the above function signature to accept different types of arguments: >
1816 def F(arg: list<any> = null_list) # any type of list
1817 def F(arg: any = null) # any type
1818<
1819In the above example, where the goal is to distinguish a null list from an
1820empty list, comparing against `null` instead of `null_list` is the correct
1821choice. The basic reason is because "null_list == null" and "[] != null".
1822Comparing to `null_list` fails since "[] == null_list". In the following section
1823there are details about comparison results.
1824
1825 *null-details* *null-anomalies*
1826This section describes issues about using null and null_<type>; included below
1827are the enumerated results of null comparisons. In some cases, if familiar
1828with vim9 null semantics, the programmer may chose to use null_<type> in
1829comparisons and/or other situations.
1830
1831Elsewhere in the documentation it says:
h_east4d496432024-01-27 19:22:28 +09001832 Quite often a null value is handled the same as an empty value, but
1833 not always
erraelcea3dac2023-12-25 01:31:23 -08001834Here's an example: >
1835 vim9script
1836 var s1: list<string>
1837 var s2: list<string> = null_list
1838 echo s1 # output: "[]"
1839 echo s2 # output: "[]"
h_east4d496432024-01-27 19:22:28 +09001840
erraelcea3dac2023-12-25 01:31:23 -08001841 echo s1 + ['a'] # output: "['a']"
1842 echo s2 + ['a'] # output: "['a']"
h_east4d496432024-01-27 19:22:28 +09001843
erraelcea3dac2023-12-25 01:31:23 -08001844 echo s1->add('a') # output: "['a']"
1845 echo s2->add('a') # E1130: Can not add to null list
1846<
1847Two values equal to a null_<type> are not necessarily equal to each other: >
1848 vim9script
1849 echo {} == null_dict # true
1850 echo null_dict == null # true
1851 echo {} == null # false
1852<
1853Unlike the other containers, an uninitialized string is equal to null. The
1854'is' operator can be used to determine if it is a null_string: >
1855 vim9script
1856 var s1: string
1857 var s2 = null_string
1858 echo s1 == null # true - this is unexpected
1859 echo s2 == null # true
1860 echo s2 is null_string # true
1861
1862 var b1: blob
1863 var b2 = null_blob
1864 echo b1 == null # false
1865 echo b2 == null # true
1866<
1867Any variable initialized to the null_<type> is equal to the null_<type> and is
1868also equal to null. For example: >
1869 vim9script
1870 var x = null_blob
1871 echo x == null_blob # true
1872 echo x == null # true
1873<
1874An uninitialized variable is usually equal to null; it depends on its type:
1875 var s: string s == null
1876 var b: blob b != null ***
1877 var l: list<any> l != null ***
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001878 var t: tuple<any> t != null ***
erraelcea3dac2023-12-25 01:31:23 -08001879 var d: dict<any> d != null ***
1880 var f: func f == null
1881 var j: job j == null
1882 var c: channel c == null
1883 var o: Class o == null
1884
1885A variable initialized to empty equals null_<type>; but not null:
1886 var s2: string = "" == null_string != null
1887 var b2: blob = 0z == null_blob != null
1888 var l2: list<any> = [] == null_list != null
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001889 var t2: tuple<any> = () == null_tuple != null
erraelcea3dac2023-12-25 01:31:23 -08001890 var d2: dict<any> = {} == null_dict != null
1891
1892NOTE: the specialized variables, like job, default to null value and have no
1893corresponding empty value.
1894
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001895==============================================================================
1896
Bram Moolenaar30fd8202020-09-26 15:09:30 +020018975. Namespace, Import and Export
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001898 *vim9script* *vim9-export* *vim9-import*
1899
Bram Moolenaarfd31be22022-01-16 14:46:06 +00001900A Vim9 script can be written to be imported. This means that some items are
1901intentionally exported, made available to other scripts. When the exporting
1902script is imported in another script, these exported items can then be used in
1903that script. All the other items remain script-local in the exporting script
1904and cannot be accessed by the importing script.
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00001905
1906This mechanism exists for writing a script that can be sourced (imported) by
1907other scripts, while making sure these other scripts only have access to what
1908you want them to. This also avoids using the global namespace, which has a
Bram Moolenaar6ba83ba2022-06-12 22:15:57 +01001909risk of name collisions. For example when you have two plugins with similar
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00001910functionality.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001911
Bram Moolenaarfd31be22022-01-16 14:46:06 +00001912You can cheat by using the global namespace explicitly. That should be done
1913only for things that really are global.
Bram Moolenaar207f0092020-08-30 17:20:20 +02001914
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001915
1916Namespace ~
Bram Moolenaardcc58e02020-12-28 20:53:21 +01001917 *vim9-namespace*
Bram Moolenaar560979e2020-02-04 22:53:05 +01001918To recognize a file that can be imported the `vim9script` statement must
Bram Moolenaard3f8a9e2021-02-17 21:57:03 +01001919appear as the first statement in the file (see |vim9-mix| for an exception).
1920It tells Vim to interpret the script in its own namespace, instead of the
1921global namespace. If a file starts with: >
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001922 vim9script
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001923 var myvar = 'yes'
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001924Then "myvar" will only exist in this file. While without `vim9script` it would
1925be available as `g:myvar` from any other script and function.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001926 *E1101*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001927The variables at the file level are very much like the script-local "s:"
Bram Moolenaar2c7f8c52020-04-20 19:52:53 +02001928variables in legacy Vim script, but the "s:" is omitted. And they cannot be
1929deleted.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001930
Bram Moolenaar2c7f8c52020-04-20 19:52:53 +02001931In Vim9 script the global "g:" namespace can still be used as before. And the
1932"w:", "b:" and "t:" namespaces. These have in common that variables are not
Bram Moolenaar9712ff12022-09-18 13:04:22 +01001933declared, have no specific type and they can be deleted. *E1304*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001934
1935A side effect of `:vim9script` is that the 'cpoptions' option is set to the
1936Vim default value, like with: >
1937 :set cpo&vim
1938One of the effects is that |line-continuation| is always enabled.
Bram Moolenaar3e191692021-03-17 17:46:00 +01001939The original value of 'cpoptions' is restored at the end of the script, while
1940flags added or removed in the script are also added to or removed from the
1941original value to get the same effect. The order of flags may change.
Bram Moolenaar71eb3ad2021-12-26 12:07:30 +00001942In the |vimrc| file sourced on startup this does not happen.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001943
Bram Moolenaard3f8a9e2021-02-17 21:57:03 +01001944 *vim9-mix*
1945There is one way to use both legacy and Vim9 syntax in one script file: >
1946 " comments may go here
1947 if !has('vim9script')
1948 " legacy script commands go here
1949 finish
1950 endif
1951 vim9script
1952 # Vim9 script commands go here
1953This allows for writing a script that takes advantage of the Vim9 script
Bram Moolenaar9faec4e2021-02-27 16:38:07 +01001954syntax if possible, but will also work on a Vim version without it.
Bram Moolenaard3f8a9e2021-02-17 21:57:03 +01001955
Konfektde4b2442025-03-05 21:03:21 +01001956Note that Vim9 syntax changed before Vim 9 so that scripts using the current
1957syntax (such as "import from" instead of "import") might throw errors.
1958To prevent these, a safer check could be for |v:version| >= 900 instead.
1959
Bram Moolenaard3f8a9e2021-02-17 21:57:03 +01001960This can only work in two ways:
19611. The "if" statement evaluates to false, the commands up to `endif` are
1962 skipped and `vim9script` is then the first command actually executed.
19632. The "if" statement evaluates to true, the commands up to `endif` are
1964 executed and `finish` bails out before reaching `vim9script`.
1965
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001966
1967Export ~
1968 *:export* *:exp*
Bram Moolenaar2547aa92020-07-26 17:00:44 +02001969Exporting an item can be written as: >
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001970 export const EXPORTED_CONST = 1234
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001971 export var someValue = ...
1972 export final someValue = ...
1973 export const someValue = ...
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001974 export def MyFunc() ...
1975 export class MyClass ...
Bram Moolenaar74235772021-06-12 14:53:05 +02001976 export interface MyClass ...
Yegappan Lakshmanana81cf8b2025-01-19 22:20:34 +01001977 export enum MyEnum ...
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001978< *E1043* *E1044*
Yegappan Lakshmanana81cf8b2025-01-19 22:20:34 +01001979As this suggests, only constants, variables, `:def` functions, classes,
1980interfaces and enums can be exported.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001981
Bram Moolenaar65e0d772020-06-14 17:29:55 +02001982 *E1042*
1983`:export` can only be used in Vim9 script, at the script level.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001984
1985
1986Import ~
Bram Moolenaar2ecbe532022-07-29 21:36:21 +01001987 *:import* *:imp* *E1094* *E1047* *E1262*
1988 *E1048* *E1049* *E1053* *E1071* *E1088* *E1236*
Bram Moolenaar5ed11532022-07-06 13:18:11 +01001989The exported items can be imported in another script. The import syntax has
1990two forms. The simple form: >
1991 import {filename}
1992<
1993Where {filename} is an expression that must evaluate to a string. In this
1994form the filename should end in ".vim" and the portion before ".vim" will
1995become the script local name of the namespace. For example: >
Bram Moolenaard5f400c2022-01-06 21:10:28 +00001996 import "myscript.vim"
Bram Moolenaar5ed11532022-07-06 13:18:11 +01001997<
1998This makes each exported item in "myscript.vim" available as "myscript.item".
Bram Moolenaara2baa732022-02-04 16:09:54 +00001999 *:import-as* *E1257* *E1261*
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002000In case the name is long or ambiguous, this form can be used to specify
2001another name: >
2002 import {longfilename} as {name}
2003<
2004In this form {name} becomes a specific script local name for the imported
2005namespace. Therefore {name} must consist of letters, digits and '_', like
2006|internal-variables|. The {longfilename} expression must evaluate to any
2007filename. For example: >
2008 import "thatscript.vim.v2" as that
Bram Moolenaara2baa732022-02-04 16:09:54 +00002009< *E1060* *E1258* *E1259* *E1260*
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002010Then you can use "that.item", etc. You are free to choose the name "that".
2011Use something that will be recognized as referring to the imported script.
2012Avoid command names, command modifiers and builtin function names, because the
Aliaksei Budaveib043ff32023-10-03 17:39:53 +03002013name will shadow them. It's better not to start the name with a capital
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002014letter, since it can then also shadow global user commands and functions.
2015Also, you cannot use the name for something else in the script, such as a
2016function or variable name.
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002017
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00002018In case the dot in the name is undesired, a local reference can be made for a
2019function: >
2020 var LongFunc = that.LongFuncName
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002021
2022This also works for constants: >
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00002023 const MAXLEN = that.MAX_LEN_OF_NAME
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002024
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00002025This does not work for variables, since the value would be copied once and
2026when changing the variable the copy will change, not the original variable.
2027You will need to use the full name, with the dot.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002028
Bram Moolenaar4db572e2021-07-18 18:21:38 +02002029`:import` can not be used in a function. Imported items are intended to exist
2030at the script level and only imported once.
2031
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002032The script name after `import` can be:
2033- A relative path, starting "." or "..". This finds a file relative to the
2034 location of the script file itself. This is useful to split up a large
2035 plugin into several files.
2036- An absolute path, starting with "/" on Unix or "D:/" on MS-Windows. This
Bram Moolenaarcb80aa22020-10-26 21:12:46 +01002037 will rarely be used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002038- A path not being relative or absolute. This will be found in the
2039 "import" subdirectories of 'runtimepath' entries. The name will usually be
2040 longer and unique, to avoid loading the wrong file.
Bram Moolenaar6aa57292021-08-14 21:25:52 +02002041 Note that "after/import" is not used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002042
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00002043If the name does not end in ".vim" then the use of "as name" is required.
2044
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002045Once a vim9 script file has been imported, the result is cached and used the
2046next time the same script is imported. It will not be read again.
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002047
2048It is not allowed to import the same script twice, also when using two
2049different "as" names.
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00002050
2051When using the imported name the dot and the item name must be in the same
2052line, there can be no line break: >
2053 echo that.
2054 name # Error!
2055 echo that
2056 .name # Error!
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +01002057< *import-map*
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002058When you've imported a function from one script into a vim9 script you can
2059refer to the imported function in a mapping by prefixing it with |<SID>|: >
Bram Moolenaar89445512022-04-14 12:58:23 +01002060 noremap <silent> ,a :call <SID>name.Function()<CR>
2061
2062When the mapping is defined "<SID>name." will be replaced with <SNR> and the
2063script ID of the imported script.
Bram Moolenaar6ba83ba2022-06-12 22:15:57 +01002064An even simpler solution is using |<ScriptCmd>|: >
2065 noremap ,a <ScriptCmd>name.Function()<CR>
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002066
2067Note that this does not work for variables, only for functions.
2068
2069 *import-legacy* *legacy-import*
2070`:import` can also be used in legacy Vim script. The imported namespace still
2071becomes script-local, even when the "s:" prefix is not given. For example: >
zeertzjqd086b8f2024-02-25 15:42:52 +08002072 import "myfile.vim"
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002073 call s:myfile.MyFunc()
2074
2075And using the "as name" form: >
2076 import "otherfile.vim9script" as that
2077 call s:that.OtherFunc()
2078
Bram Moolenaar9712ff12022-09-18 13:04:22 +01002079However, the namespace cannot be resolved on its own: >
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002080 import "that.vim"
2081 echo s:that
2082 " ERROR: E1060: Expected dot after name: s:that
2083<
2084This also affects the use of |<SID>| in the legacy mapping context. Since
2085|<SID>| is only a valid prefix for a function and NOT for a namespace, you
h_eastba77bbb2023-10-03 04:47:13 +09002086cannot use it to scope a function in a script local namespace. Instead of
2087prefixing the function with |<SID>| you should use|<ScriptCmd>|. For example:
2088>
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002089 noremap ,a <ScriptCmd>:call s:that.OtherFunc()<CR>
Bram Moolenaar6ba83ba2022-06-12 22:15:57 +01002090<
Christian Brabandtd9a1f262025-01-21 22:17:50 +01002091 *:import-cycle*
2092The `import` commands are executed when encountered. If script A imports
2093script B, and B (directly or indirectly) imports A, this will be skipped over.
2094At this point items in A after "import B" will not have been processed and
2095defined yet. Therefore cyclic imports can exist and not result in an error
2096directly, but may result in an error for items in A after "import B" not being
2097defined. This does not apply to autoload imports, see the next section.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002098
2099
Bram Moolenaarfd31be22022-01-16 14:46:06 +00002100Importing an autoload script ~
Bram Moolenaarfd999452022-08-24 18:30:14 +01002101 *vim9-autoload* *import-autoload*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002102For optimal startup speed, loading scripts should be postponed until they are
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002103actually needed. Using the autoload mechanism is recommended:
Bram Moolenaara2baa732022-02-04 16:09:54 +00002104 *E1264*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010021051. In the plugin define user commands, functions and/or mappings that refer to
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002106 items imported from an autoload script. >
2107 import autoload 'for/search.vim'
2108 command -nargs=1 SearchForStuff search.Stuff(<f-args>)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002109
2110< This goes in .../plugin/anyname.vim. "anyname.vim" can be freely chosen.
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002111 The "SearchForStuff" command is now available to the user.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002112
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002113 The "autoload" argument to `:import` means that the script is not loaded
2114 until one of the items is actually used. The script will be found under
2115 the "autoload" directory in 'runtimepath' instead of the "import"
Bram Moolenaarcbaff5e2022-04-08 17:45:08 +01002116 directory. Alternatively a relative or absolute name can be used, see
2117 below.
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002118
21192. In the autoload script put the bulk of the code. >
Bram Moolenaarfd218c82022-01-18 16:26:24 +00002120 vim9script
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002121 export def Stuff(arg: string)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002122 ...
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002123
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002124< This goes in .../autoload/for/search.vim.
2125
Bram Moolenaarfd218c82022-01-18 16:26:24 +00002126 Putting the "search.vim" script under the "/autoload/for/" directory has
2127 the effect that "for#search#" will be prefixed to every exported item. The
2128 prefix is obtained from the file name, as you would to manually in a
2129 legacy autoload script. Thus the exported function can be found with
2130 "for#search#Stuff", but you would normally use `import autoload` and not
Bram Moolenaar47c532e2022-03-19 15:18:53 +00002131 use the prefix (which has the side effect of loading the autoload script
2132 when compiling a function that encounters this name).
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002133
2134 You can split up the functionality and import other scripts from the
2135 autoload script as you like. This way you can share code between plugins.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002136
Bram Moolenaarcbaff5e2022-04-08 17:45:08 +01002137Searching for the autoload script in all entries in 'runtimepath' can be a bit
2138slow. If the plugin knows where the script is located, quite often a relative
2139path can be used. This avoids the search and should be quite a bit faster.
2140Another advantage is that the script name does not need to be unique. An
2141absolute path is also possible. Examples: >
2142 import autoload '../lib/implement.vim'
2143 import autoload MyScriptsDir .. '/lib/implement.vim'
2144
Bram Moolenaarfd31be22022-01-16 14:46:06 +00002145For defining a mapping that uses the imported autoload script the special key
2146|<ScriptCmd>| is useful. It allows for a command in a mapping to use the
2147script context of where the mapping was defined.
2148
Bram Moolenaar418f1df2020-08-12 21:34:49 +02002149When compiling a `:def` function and a function in an autoload script is
2150encountered, the script is not loaded until the `:def` function is called.
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002151This also means you get any errors only at runtime, since the argument and
Bram Moolenaar47c532e2022-03-19 15:18:53 +00002152return types are not known yet. If you would use the name with '#' characters
2153then the autoload script IS loaded.
2154
2155Be careful to not refer to an item in an autoload script that does trigger
2156loading it unintentionally. For example, when setting an option that takes a
2157function name, make sure to use a string, not a function reference: >
2158 import autoload 'qftf.vim'
2159 &quickfixtextfunc = 'qftf.Func' # autoload script NOT loaded
2160 &quickfixtextfunc = qftf.Func # autoload script IS loaded
2161On the other hand, it can be useful to load the script early, at a time when
2162any errors should be given.
Bram Moolenaar418f1df2020-08-12 21:34:49 +02002163
Bram Moolenaarfd31be22022-01-16 14:46:06 +00002164For testing the |test_override()| function can be used to have the
2165`import autoload` load the script right away, so that the items and types can
2166be checked without waiting for them to be actually used: >
2167 test_override('autoload', 1)
2168Reset it later with: >
2169 test_override('autoload', 0)
2170Or: >
2171 test_override('ALL', 0)
2172
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002173
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002174==============================================================================
2175
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000021766. Classes and interfaces *vim9-classes*
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002177
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002178In legacy script a Dictionary could be used as a kind-of object, by adding
2179members that are functions. However, this is quite inefficient and requires
2180the writer to do the work of making sure all the objects have the right
2181members. See |Dictionary-function|.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002182
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002183In |Vim9| script you can have classes, objects and interfaces like in most
2184popular object-oriented programming languages. Since this is a lot of
2185functionality it is located in a separate help file: |vim9class.txt|.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002186
Bram Moolenaar74235772021-06-12 14:53:05 +02002187
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002188==============================================================================
2189
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010021909. Rationale *vim9-rationale*
2191
2192The :def command ~
2193
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002194Plugin writers have asked for much faster Vim script. Investigations have
Bram Moolenaar560979e2020-02-04 22:53:05 +01002195shown that keeping the existing semantics of function calls make this close to
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002196impossible, because of the overhead involved with calling a function, setting
2197up the local function scope and executing lines. There are many details that
2198need to be handled, such as error messages and exceptions. The need to create
2199a dictionary for a: and l: scopes, the a:000 list and several others add too
2200much overhead that cannot be avoided.
2201
2202Therefore the `:def` method to define a new-style function had to be added,
2203which allows for a function with different semantics. Most things still work
2204as before, but some parts do not. A new way to define a function was
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002205considered the best way to separate the legacy style code from Vim9 style code.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002206
2207Using "def" to define a function comes from Python. Other languages use
2208"function" which clashes with legacy Vim script.
2209
2210
2211Type checking ~
2212
2213When compiling lines of Vim commands into instructions as much as possible
2214should be done at compile time. Postponing it to runtime makes the execution
2215slower and means mistakes are found only later. For example, when
2216encountering the "+" character and compiling this into a generic add
Bram Moolenaar98a29d02021-01-18 19:55:44 +01002217instruction, at runtime the instruction would have to inspect the type of the
2218arguments and decide what kind of addition to do. And when the type is
2219dictionary throw an error. If the types are known to be numbers then an "add
2220number" instruction can be used, which is faster. The error can be given at
2221compile time, no error handling is needed at runtime, since adding two numbers
2222cannot fail.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002223
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002224The syntax for types, using <type> for compound types, is similar to Java. It
2225is easy to understand and widely used. The type names are what were used in
2226Vim before, with some additions such as "void" and "bool".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002227
2228
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002229Removing clutter and weirdness ~
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002230
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002231Once decided that `:def` functions have different syntax than legacy functions,
2232we are free to add improvements to make the code more familiar for users who
2233know popular programming languages. In other words: remove weird things that
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002234only Vim does.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002235
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002236We can also remove clutter, mainly things that were done to make Vim script
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002237backwards compatible with the good old Vi commands.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002238
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002239Examples:
Bram Moolenaar63f32602022-06-09 20:45:54 +01002240- Drop `:call` for calling a function and `:eval` for evaluating an
2241 expression.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002242- Drop using a leading backslash for line continuation, automatically figure
2243 out where an expression ends.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002244
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002245However, this does require that some things need to change:
2246- Comments start with # instead of ", to avoid confusing them with strings.
Bram Moolenaar63f32602022-06-09 20:45:54 +01002247 This is good anyway, it is also used by several popular languages.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002248- Ex command ranges need to be prefixed with a colon, to avoid confusion with
2249 expressions (single quote can be a string or a mark, "/" can be divide or a
2250 search command, etc.).
2251
2252Goal is to limit the differences. A good criteria is that when the old syntax
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002253is accidentally used you are very likely to get an error message.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002254
2255
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002256Syntax and semantics from popular languages ~
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002257
2258Script writers have complained that the Vim script syntax is unexpectedly
2259different from what they are used to. To reduce this complaint popular
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002260languages are used as an example. At the same time, we do not want to abandon
2261the well-known parts of legacy Vim script.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002262
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002263For many things TypeScript is followed. It's a recent language that is
2264gaining popularity and has similarities with Vim script. It also has a
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002265mix of static typing (a variable always has a known value type) and dynamic
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002266typing (a variable can have different types, this changes at runtime). Since
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002267legacy Vim script is dynamically typed and a lot of existing functionality
2268(esp. builtin functions) depends on that, while static typing allows for much
2269faster execution, we need to have this mix in Vim9 script.
2270
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002271There is no intention to completely match TypeScript syntax and semantics. We
2272just want to take those parts that we can use for Vim and we expect Vim users
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002273will be happy with. TypeScript is a complex language with its own history,
2274advantages and disadvantages. To get an idea of the disadvantages read the
2275book: "JavaScript: The Good Parts". Or find the article "TypeScript: the good
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02002276parts" and read the "Things to avoid" section.
2277
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002278People familiar with other languages (Java, Python, etc.) will also find
2279things in TypeScript that they do not like or do not understand. We'll try to
2280avoid those things.
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02002281
2282Specific items from TypeScript we avoid:
2283- Overloading "+", using it both for addition and string concatenation. This
2284 goes against legacy Vim script and often leads to mistakes. For that reason
2285 we will keep using ".." for string concatenation. Lua also uses ".." this
2286 way. And it allows for conversion to string for more values.
2287- TypeScript can use an expression like "99 || 'yes'" in a condition, but
2288 cannot assign the value to a boolean. That is inconsistent and can be
2289 annoying. Vim recognizes an expression with && or || and allows using the
Bram Moolenaar1f318c62021-12-26 18:09:31 +00002290 result as a bool. The |falsy-operator| was added for the mechanism to use a
2291 default value.
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02002292- TypeScript considers an empty string as Falsy, but an empty list or dict as
2293 Truthy. That is inconsistent. In Vim an empty list and dict are also
2294 Falsy.
2295- TypeScript has various "Readonly" types, which have limited usefulness,
2296 since a type cast can remove the immutable nature. Vim locks the value,
2297 which is more flexible, but is only checked at runtime.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00002298- TypeScript has a complicated "import" statement that does not match how the
2299 Vim import mechanism works. A much simpler mechanism is used instead, which
2300 matches that the imported script is only sourced once.
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002301
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002302
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002303Declarations ~
2304
2305Legacy Vim script uses `:let` for every assignment, while in Vim9 declarations
2306are used. That is different, thus it's good to use a different command:
2307`:var`. This is used in many languages. The semantics might be slightly
2308different, but it's easily recognized as a declaration.
2309
Bram Moolenaar23515b42020-11-29 14:36:24 +01002310Using `:const` for constants is common, but the semantics varies. Some
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002311languages only make the variable immutable, others also make the value
2312immutable. Since "final" is well known from Java for only making the variable
2313immutable we decided to use that. And then `:const` can be used for making
2314both immutable. This was also used in legacy Vim script and the meaning is
2315almost the same.
2316
2317What we end up with is very similar to Dart: >
2318 :var name # mutable variable and value
2319 :final name # immutable variable, mutable value
2320 :const name # immutable variable and value
2321
2322Since legacy and Vim9 script will be mixed and global variables will be
2323shared, optional type checking is desirable. Also, type inference will avoid
2324the need for specifying the type in many cases. The TypeScript syntax fits
2325best for adding types to declarations: >
2326 var name: string # string type is specified
2327 ...
2328 name = 'John'
2329 const greeting = 'hello' # string type is inferred
2330
2331This is how we put types in a declaration: >
2332 var mylist: list<string>
2333 final mylist: list<string> = ['foo']
2334 def Func(arg1: number, arg2: string): bool
2335
2336Two alternatives were considered:
23371. Put the type before the name, like Dart: >
2338 var list<string> mylist
2339 final list<string> mylist = ['foo']
2340 def Func(number arg1, string arg2) bool
23412. Put the type after the variable name, but do not use a colon, like Go: >
2342 var mylist list<string>
2343 final mylist list<string> = ['foo']
2344 def Func(arg1 number, arg2 string) bool
2345
2346The first is more familiar for anyone used to C or Java. The second one
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002347doesn't really have an advantage over the first, so let's discard the second.
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002348
2349Since we use type inference the type can be left out when it can be inferred
2350from the value. This means that after `var` we don't know if a type or a name
2351follows. That makes parsing harder, not only for Vim but also for humans.
2352Also, it will not be allowed to use a variable name that could be a type name,
2353using `var string string` is too confusing.
2354
2355The chosen syntax, using a colon to separate the name from the type, adds
2356punctuation, but it actually makes it easier to recognize the parts of a
2357declaration.
2358
2359
2360Expressions ~
2361
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002362Expression evaluation was already close to what other languages are doing.
2363Some details are unexpected and can be improved. For example a boolean
2364condition would accept a string, convert it to a number and check if the
2365number is non-zero. This is unexpected and often leads to mistakes, since
2366text not starting with a number would be converted to zero, which is
Bram Moolenaarcb80aa22020-10-26 21:12:46 +01002367considered false. Thus using a string for a condition would often not give an
2368error and be considered false. That is confusing.
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002369
Bram Moolenaar23515b42020-11-29 14:36:24 +01002370In Vim9 type checking is stricter to avoid mistakes. Where a condition is
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002371used, e.g. with the `:if` command and the `||` operator, only boolean-like
2372values are accepted:
2373 true: `true`, `v:true`, `1`, `0 < 9`
2374 false: `false`, `v:false`, `0`, `0 > 9`
2375Note that the number zero is false and the number one is true. This is more
Bram Moolenaarcb80aa22020-10-26 21:12:46 +01002376permissive than most other languages. It was done because many builtin
Bram Moolenaar63f32602022-06-09 20:45:54 +01002377functions return these values, and changing that causes more problems than it
2378solves. After using this for a while it turned out to work well.
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002379
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002380If you have any type of value and want to use it as a boolean, use the `!!`
2381operator:
Bram Moolenaar63f32602022-06-09 20:45:54 +01002382 true: `!!'text'` `!![99]` `!!{'x': 1}` `!!99`
2383 false: `!!''` `!![]` `!!{}`
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002384
2385From a language like JavaScript we have this handy construct: >
2386 GetName() || 'unknown'
2387However, this conflicts with only allowing a boolean for a condition.
2388Therefore the "??" operator was added: >
2389 GetName() ?? 'unknown'
2390Here you can explicitly express your intention to use the value as-is and not
2391result in a boolean. This is called the |falsy-operator|.
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002392
2393
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002394Import and Export ~
2395
2396A problem of legacy Vim script is that by default all functions and variables
2397are global. It is possible to make them script-local, but then they are not
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002398available in other scripts. This defies the concept of a package that only
2399exports selected items and keeps the rest local.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002400
Bram Moolenaar3d1cde82020-08-15 18:55:18 +02002401In Vim9 script a mechanism very similar to the JavaScript import and export
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002402mechanism is supported. It is a variant to the existing `:source` command
2403that works like one would expect:
2404- Instead of making everything global by default, everything is script-local,
Bram Moolenaar63f32602022-06-09 20:45:54 +01002405 some of these are exported.
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002406- When importing a script the symbols that are imported are explicitly listed,
2407 avoiding name conflicts and failures if functionality is added later.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002408- The mechanism allows for writing a big, long script with a very clear API:
Bram Moolenaar63f32602022-06-09 20:45:54 +01002409 the exported functions, variables and classes.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002410- By using relative paths loading can be much faster for an import inside of a
2411 package, no need to search many directories.
Bram Moolenaar63f32602022-06-09 20:45:54 +01002412- Once an import has been used, its items are cached and loading it again is
2413 not needed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002414- The Vim-specific use of "s:" to make things script-local can be dropped.
2415
Bram Moolenaar63f32602022-06-09 20:45:54 +01002416When sourcing a Vim9 script (from a Vim9 or legacy script), only the items
2417defined globally can be used, not the exported items. Alternatives
2418considered:
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002419- All the exported items become available as script-local items. This makes
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002420 it uncontrollable what items get defined and likely soon leads to trouble.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002421- Use the exported items and make them global. Disadvantage is that it's then
2422 not possible to avoid name clashes in the global namespace.
2423- Completely disallow sourcing a Vim9 script, require using `:import`. That
2424 makes it difficult to use scripts for testing, or sourcing them from the
2425 command line to try them out.
Bram Moolenaar63f32602022-06-09 20:45:54 +01002426Note that you CAN also use `:import` in legacy Vim script, see above.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002427
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002428
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002429Compiling functions early ~
2430
2431Functions are compiled when called or when `:defcompile` is used. Why not
2432compile them early, so that syntax and type errors are reported early?
2433
2434The functions can't be compiled right away when encountered, because there may
2435be forward references to functions defined later. Consider defining functions
2436A, B and C, where A calls B, B calls C, and C calls A again. It's impossible
2437to reorder the functions to avoid forward references.
2438
2439An alternative would be to first scan through the file to locate items and
2440figure out their type, so that forward references are found, and only then
2441execute the script and compile the functions. This means the script has to be
2442parsed twice, which is slower, and some conditions at the script level, such
2443as checking if a feature is supported, are hard to use. An attempt was made
Bram Moolenaar63f32602022-06-09 20:45:54 +01002444to see if it works, but it turned out to be impossible to make work well.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002445
2446It would be possible to compile all the functions at the end of the script.
2447The drawback is that if a function never gets called, the overhead of
2448compiling it counts anyway. Since startup speed is very important, in most
2449cases it's better to do it later and accept that syntax and type errors are
2450only reported then. In case these errors should be found early, e.g. when
Bram Moolenaar63f32602022-06-09 20:45:54 +01002451testing, a `:defcompile` command at the end of the script will help out.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002452
2453
Bram Moolenaar63f32602022-06-09 20:45:54 +01002454Why not use an existing embedded language? ~
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002455
2456Vim supports interfaces to Perl, Python, Lua, Tcl and a few others. But
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002457these interfaces have never become widely used, for various reasons. When
2458Vim9 was designed a decision was made to make these interfaces lower priority
2459and concentrate on Vim script.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002460
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002461Still, plugin writers may find other languages more familiar, want to use
2462existing libraries or see a performance benefit. We encourage plugin authors
Bram Moolenaar63f32602022-06-09 20:45:54 +01002463to write code in any language and run it as an external process, using jobs
2464and channels. We can try to make this easier somehow.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002465
2466Using an external tool also has disadvantages. An alternative is to convert
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002467the tool into Vim script. For that to be possible without too much
2468translation, and keeping the code fast at the same time, the constructs of the
2469tool need to be supported. Since most languages support classes the lack of
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002470support for classes in Vim is then a problem.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002471
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002472
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002473
Christian Brabandtec6e82a2025-03-06 21:01:26 +01002474 vim:tw=78:ts=8:noet:ft=help:norl: