blob: bf500944ed37e347f15af52b7611d445b777a4f8 [file] [log] [blame]
Christian Brabandtec6e82a2025-03-06 21:01:26 +01001*vim9.txt* For Vim version 9.1. Last change: 2025 Mar 06
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)
1004 dictionary non-empty (different from JavaScript)
Bram Moolenaard1caa942020-04-10 22:10:56 +02001005 func when there is a function name
Bram Moolenaar7e6a5152021-01-02 16:39:53 +01001006 special true or v:true
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001007 job when not NULL
1008 channel when not NULL
1009 class when not NULL
Bram Moolenaar7e6a5152021-01-02 16:39:53 +01001010 object when not NULL (TODO: when isTrue() returns true)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001011
Bram Moolenaar2bb26582020-10-03 22:52:39 +02001012The boolean operators "||" and "&&" expect the values to be boolean, zero or
1013one: >
1014 1 || false == true
1015 0 || 1 == true
1016 0 || false == false
1017 1 && true == true
1018 0 && 1 == false
1019 8 || 0 Error!
1020 'yes' && 0 Error!
1021 [] || 99 Error!
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001022
Bram Moolenaar2bb26582020-10-03 22:52:39 +02001023When using "!" for inverting, there is no error for using any type and the
Bram Moolenaar13106602020-10-04 16:06:05 +02001024result is a boolean. "!!" can be used to turn any value into boolean: >
Bram Moolenaar82be4842021-01-11 19:40:15 +01001025 !'yes' == false
Bram Moolenaar13106602020-10-04 16:06:05 +02001026 !![] == false
Bram Moolenaar82be4842021-01-11 19:40:15 +01001027 !![1, 2, 3] == true
Bram Moolenaar2bb26582020-10-03 22:52:39 +02001028
1029When using "`.."` for string concatenation arguments of simple types are
Bram Moolenaar13106602020-10-04 16:06:05 +02001030always converted to string: >
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001031 'hello ' .. 123 == 'hello 123'
Bram Moolenaar7e6a5152021-01-02 16:39:53 +01001032 'hello ' .. v:true == 'hello true'
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001033
Bram Moolenaar5da36052021-12-27 15:39:57 +00001034Simple types are Number, Float, Special and Bool. For other types |string()|
1035should be used.
Bram Moolenaar7db29e42022-12-11 15:53:04 +00001036 *false* *true* *null* *null_blob* *null_channel*
dkearns521fb7e2023-11-11 19:33:43 +11001037 *null_class* *null_dict* *null_function* *null_job*
1038 *null_list* *null_object* *null_partial* *null_string*
1039 *E1034*
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001040In Vim9 script one can use the following predefined values: >
1041 true
1042 false
1043 null
1044 null_blob
1045 null_channel
Yegappan Lakshmanane750f8c2023-08-24 07:07:05 -07001046 null_class
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001047 null_dict
1048 null_function
1049 null_job
1050 null_list
Yegappan Lakshmanane750f8c2023-08-24 07:07:05 -07001051 null_object
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001052 null_partial
1053 null_string
1054`true` is the same as `v:true`, `false` the same as `v:false`, `null` the same
1055as `v:null`.
1056
Bram Moolenaar76db9e02022-11-09 21:21:04 +00001057While `null` has the type "special", the other "null_" values have the type
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001058indicated by their name. Quite often a null value is handled the same as an
1059empty value, but not always. The values can be useful to clear a script-local
1060variable, since they cannot be deleted with `:unlet`. E.g.: >
1061 var theJob = job_start(...)
1062 # let the job do its work
1063 theJob = null_job
1064
1065The values can also be useful as the default value for an argument: >
1066 def MyFunc(b: blob = null_blob)
erraelcea3dac2023-12-25 01:31:23 -08001067 # Note: compare against null, not null_blob,
1068 # to distinguish the default value from an empty blob.
1069 if b == null
1070 # b argument was not given
1071See |null-compare| for more information about testing against null.
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001072
Bram Moolenaar47c532e2022-03-19 15:18:53 +00001073It is possible to compare `null` with any value, this will not give a type
1074error. However, comparing `null` with a number, float or bool will always
1075result in `false`. This is different from legacy script, where comparing
1076`null` with zero or `false` would return `true`.
Bram Moolenaar10e8ff92023-06-10 21:40:39 +01001077 *vim9-false-true*
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00001078When converting a boolean to a string `false` and `true` are used, not
1079`v:false` and `v:true` like in legacy script. `v:none` has no `none`
1080replacement, it has no equivalent in other languages.
Bram Moolenaar10e8ff92023-06-10 21:40:39 +01001081 *vim9-string-index*
Bram Moolenaar0289a092021-03-14 18:40:19 +01001082Indexing a string with [idx] or taking a slice with [idx : idx] uses character
1083indexes instead of byte indexes. Composing characters are included.
1084Example: >
Bram Moolenaar3d1cde82020-08-15 18:55:18 +02001085 echo 'bár'[1]
1086In legacy script this results in the character 0xc3 (an illegal byte), in Vim9
1087script this results in the string 'á'.
Bram Moolenaar82be4842021-01-11 19:40:15 +01001088A negative index is counting from the end, "[-1]" is the last character.
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001089To exclude the last character use |slice()|.
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02001090To count composing characters separately use |strcharpart()|.
Bram Moolenaar82be4842021-01-11 19:40:15 +01001091If the index is out of range then an empty string results.
1092
1093In legacy script "++var" and "--var" would be silently accepted and have no
1094effect. This is an error in Vim9 script.
1095
1096Numbers starting with zero are not considered to be octal, only numbers
1097starting with "0o" are octal: "0o744". |scriptversion-4|
Bram Moolenaar3d1cde82020-08-15 18:55:18 +02001098
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001099
Bram Moolenaare46a4402020-06-30 20:38:27 +02001100What to watch out for ~
1101 *vim9-gotchas*
1102Vim9 was designed to be closer to often used programming languages, but at the
1103same time tries to support the legacy Vim commands. Some compromises had to
1104be made. Here is a summary of what might be unexpected.
1105
1106Ex command ranges need to be prefixed with a colon. >
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001107 -> legacy Vim: shifts the previous line to the right
1108 ->func() Vim9: method call in a continuation line
1109 :-> Vim9: shifts the previous line to the right
Bram Moolenaare46a4402020-06-30 20:38:27 +02001110
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001111 %s/a/b legacy Vim: substitute on all lines
Bram Moolenaare46a4402020-06-30 20:38:27 +02001112 x = alongname
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001113 % another Vim9: modulo operator in a continuation line
1114 :%s/a/b Vim9: substitute on all lines
1115 't legacy Vim: jump to mark t
1116 'text'->func() Vim9: method call
1117 :'t Vim9: jump to mark t
Bram Moolenaare46a4402020-06-30 20:38:27 +02001118
Bram Moolenaare7b1ea02020-08-07 19:54:59 +02001119Some Ex commands can be confused with assignments in Vim9 script: >
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001120 g:name = value # assignment
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001121 :g:pattern:cmd # :global command
Bram Moolenaare7b1ea02020-08-07 19:54:59 +02001122
Bram Moolenaar7b829262021-10-13 15:04:34 +01001123To avoid confusion between a `:global` or `:substitute` command and an
1124expression or assignment, a few separators cannot be used when these commands
1125are abbreviated to a single character: ':', '-' and '.'. >
1126 g:pattern:cmd # invalid command - ERROR
1127 s:pattern:repl # invalid command - ERROR
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
1133Also, there cannot be a space between the command and the separator: >
1134 g /pattern/cmd # invalid command - ERROR
1135 s /pattern/repl # invalid command - ERROR
1136
Bram Moolenaare46a4402020-06-30 20:38:27 +02001137Functions defined with `:def` compile the whole function. Legacy functions
1138can bail out, and the following lines are not parsed: >
1139 func Maybe()
1140 if !has('feature')
1141 return
1142 endif
1143 use-feature
1144 endfunc
1145Vim9 functions are compiled as a whole: >
1146 def Maybe()
1147 if !has('feature')
1148 return
1149 endif
Bram Moolenaar82be4842021-01-11 19:40:15 +01001150 use-feature # May give a compilation error
Bram Moolenaare46a4402020-06-30 20:38:27 +02001151 enddef
1152For a workaround, split it in two functions: >
1153 func Maybe()
1154 if has('feature')
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001155 call MaybeInner()
Bram Moolenaare46a4402020-06-30 20:38:27 +02001156 endif
1157 endfunc
1158 if has('feature')
1159 def MaybeInner()
1160 use-feature
1161 enddef
1162 endif
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02001163Or put the unsupported code inside an `if` with a constant expression that
Bram Moolenaar207f0092020-08-30 17:20:20 +02001164evaluates to false: >
1165 def Maybe()
1166 if has('feature')
1167 use-feature
1168 endif
1169 enddef
Bram Moolenaar6aa57292021-08-14 21:25:52 +02001170The `exists_compiled()` function can also be used for this.
1171 *vim9-user-command*
Bram Moolenaar98a29d02021-01-18 19:55:44 +01001172Another side effect of compiling a function is that the presence of a user
Bram Moolenaar82be4842021-01-11 19:40:15 +01001173command is checked at compile time. If the user command is defined later an
1174error will result. This works: >
1175 command -nargs=1 MyCommand echom <q-args>
1176 def Works()
1177 MyCommand 123
1178 enddef
1179This will give an error for "MyCommand" not being defined: >
1180 def Works()
1181 command -nargs=1 MyCommand echom <q-args>
1182 MyCommand 123
1183 enddef
1184A workaround is to invoke the command indirectly with `:execute`: >
1185 def Works()
1186 command -nargs=1 MyCommand echom <q-args>
1187 execute 'MyCommand 123'
1188 enddef
1189
Bram Moolenaar207f0092020-08-30 17:20:20 +02001190Note that for unrecognized commands there is no check for "|" and a following
1191command. This will give an error for missing `endif`: >
1192 def Maybe()
1193 if has('feature') | use-feature | endif
1194 enddef
Bram Moolenaare46a4402020-06-30 20:38:27 +02001195
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001196Other differences ~
1197
1198Patterns are used like 'magic' is set, unless explicitly overruled.
1199The 'edcompatible' option value is not used.
1200The 'gdefault' option value is not used.
1201
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001202You may also find this wiki useful. It was written by an early adopter of
Bram Moolenaarc8cdf0f2021-03-13 13:28:13 +01001203Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001204
Bram Moolenaar4d8f4762021-06-27 15:18:56 +02001205 *:++* *:--*
1206The ++ and -- commands have been added. They are very similar to adding or
1207subtracting one: >
1208 ++var
1209 var += 1
1210 --var
1211 var -= 1
1212
1213Using ++var or --var in an expression is not supported yet.
1214
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001215==============================================================================
1216
12173. New style functions *fast-functions*
1218
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001219 *:def* *E1028*
Bram Moolenaar3d1cde82020-08-15 18:55:18 +02001220:def[!] {name}([arguments])[: {return-type}]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001221 Define a new function by the name {name}. The body of
1222 the function follows in the next lines, until the
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001223 matching `:enddef`. *E1073*
1224 *E1011*
1225 The {name} must be less than 100 bytes long.
1226 *E1003* *E1027* *E1056* *E1059*
1227 The type of value used with `:return` must match
1228 {return-type}. When {return-type} is omitted or is
1229 "void" the function is not expected to return
1230 anything.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001231 *E1077* *E1123*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001232 {arguments} is a sequence of zero or more argument
1233 declarations. There are three forms:
1234 {name}: {type}
1235 {name} = {value}
1236 {name}: {type} = {value}
1237 The first form is a mandatory argument, the caller
1238 must always provide them.
1239 The second and third form are optional arguments.
1240 When the caller omits an argument the {value} is used.
1241
Bram Moolenaar65e0d772020-06-14 17:29:55 +02001242 The function will be compiled into instructions when
Bram Moolenaar2547aa92020-07-26 17:00:44 +02001243 called, or when `:disassemble` or `:defcompile` is
1244 used. Syntax and type errors will be produced at that
1245 time.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02001246
Bram Moolenaar2547aa92020-07-26 17:00:44 +02001247 It is possible to nest `:def` inside another `:def` or
1248 `:function` up to about 50 levels deep.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001249 *E1117*
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001250 [!] is used as with `:function`. Note that
1251 script-local functions cannot be deleted or redefined
1252 later in Vim9 script. They can only be removed by
1253 reloading the same script.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001254
Bram Moolenaara2baa732022-02-04 16:09:54 +00001255 *:enddef* *E1057* *E1152* *E1173*
Bram Moolenaar2547aa92020-07-26 17:00:44 +02001256:enddef End of a function defined with `:def`. It should be on
1257 a line by its own.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001258
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001259You may also find this wiki useful. It was written by an early adopter of
Bram Moolenaar0289a092021-03-14 18:40:19 +01001260Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001261
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01001262If the script the function is defined in is Vim9 script, then script-local
1263variables can be accessed without the "s:" prefix. They must be defined
Bram Moolenaar65e0d772020-06-14 17:29:55 +02001264before the function is compiled. If the script the function is defined in is
1265legacy script, then script-local variables must be accessed with the "s:"
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001266prefix if they do not exist at the time of compiling.
Bram Moolenaar2ecbe532022-07-29 21:36:21 +01001267 *E1269*
1268Script-local variables in a |Vim9| script must be declared at the script
1269level. They cannot be created in a function, also not in a legacy function.
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01001270
Bram Moolenaar388a5d42020-05-26 21:20:45 +02001271 *:defc* *:defcompile*
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +01001272:defc[ompile] Compile functions and classes (|class-compile|)
1273 defined in the current script that were not compiled
1274 yet. This will report any errors found during
1275 compilation.
1276
h_east4d496432024-01-27 19:22:28 +09001277:defc[ompile] MyClass Compile all methods in a class. |class-compile|
Bram Moolenaarf79d9dd2022-05-21 15:39:02 +01001278
1279:defc[ompile] {func}
1280:defc[ompile] debug {func}
1281:defc[ompile] profile {func}
1282 Compile function {func}, if needed. Use "debug" and
1283 "profile" to specify the compilation mode.
1284 This will report any errors found during compilation.
Bram Moolenaardd60c362023-02-27 15:49:53 +00001285 {func} call also be "ClassName.functionName" to
1286 compile a function or method in a class.
1287 {func} call also be "ClassName" to compile all
1288 functions and methods in a class.
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01001289
Bram Moolenaarebdf3c92020-02-15 21:41:42 +01001290 *:disa* *:disassemble*
1291:disa[ssemble] {func} Show the instructions generated for {func}.
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001292 This is for debugging and testing. *E1061*
Bram Moolenaarcc390ff2020-02-29 22:06:30 +01001293 Note that for command line completion of {func} you
1294 can prepend "s:" to find script-local functions.
Bram Moolenaarebdf3c92020-02-15 21:41:42 +01001295
Bram Moolenaar2346a632021-06-13 19:02:49 +02001296:disa[ssemble] profile {func}
1297 Like `:disassemble` but with the instructions used for
Bram Moolenaare0e39172021-01-25 21:14:57 +01001298 profiling.
1299
Bram Moolenaar2346a632021-06-13 19:02:49 +02001300:disa[ssemble] debug {func}
1301 Like `:disassemble` but with the instructions used for
1302 debugging.
1303
Bram Moolenaar7ff78462020-07-10 22:00:53 +02001304Limitations ~
1305
1306Local variables will not be visible to string evaluation. For example: >
Bram Moolenaar2b327002020-12-26 15:39:31 +01001307 def MapList(): list<string>
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001308 var list = ['aa', 'bb', 'cc', 'dd']
Bram Moolenaar7ff78462020-07-10 22:00:53 +02001309 return range(1, 2)->map('list[v:val]')
1310 enddef
1311
1312The map argument is a string expression, which is evaluated without the
1313function scope. Instead, use a lambda: >
Bram Moolenaar2b327002020-12-26 15:39:31 +01001314 def MapList(): list<string>
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001315 var list = ['aa', 'bb', 'cc', 'dd']
Bram Moolenaar22863042021-10-16 15:23:36 +01001316 return range(1, 2)->map((_, v) => list[v])
Bram Moolenaar7ff78462020-07-10 22:00:53 +02001317 enddef
1318
Bram Moolenaar3d2e0312021-12-01 09:27:20 +00001319For commands that are not compiled, such as `:edit`, backtick expansion can be
1320used and it can use the local scope. Example: >
Bram Moolenaar2b327002020-12-26 15:39:31 +01001321 def Replace()
Bram Moolenaar3d2e0312021-12-01 09:27:20 +00001322 var fname = 'blah.txt'
1323 edit `=fname`
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001324 enddef
1325
Bram Moolenaardad44732021-03-31 20:07:33 +02001326Closures defined in a loop will share the same context. For example: >
1327 var flist: list<func>
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001328 for i in range(5)
Bram Moolenaardad44732021-03-31 20:07:33 +02001329 var inloop = i
1330 flist[i] = () => inloop
1331 endfor
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001332 echo range(5)->map((i, _) => flist[i]())
1333 # Result: [4, 4, 4, 4, 4]
Bram Moolenaar47c532e2022-03-19 15:18:53 +00001334< *E1271*
1335A closure must be compiled in the context that it is defined in, so that
1336variables in that context can be found. This mostly happens correctly, except
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00001337when a function is marked for debugging with `:breakadd` after it was compiled.
Bram Moolenaar46eea442022-03-30 10:51:39 +01001338Make sure to define the breakpoint before compiling the outer function.
Bram Moolenaardad44732021-03-31 20:07:33 +02001339
1340The "inloop" variable will exist only once, all closures put in the list refer
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001341to the same instance, which in the end will have the value 4. This is
1342efficient, also when looping many times. If you do want a separate context
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001343for each closure, call a function to define it: >
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001344 def GetClosure(i: number): func
1345 var infunc = i
1346 return () => infunc
Bram Moolenaardad44732021-03-31 20:07:33 +02001347 enddef
1348
1349 var flist: list<func>
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001350 for i in range(5)
1351 flist[i] = GetClosure(i)
Bram Moolenaardad44732021-03-31 20:07:33 +02001352 endfor
Bram Moolenaar53f7fcc2021-07-28 20:10:16 +02001353 echo range(5)->map((i, _) => flist[i]())
1354 # Result: [0, 1, 2, 3, 4]
Bram Moolenaardad44732021-03-31 20:07:33 +02001355
Bram Moolenaara2baa732022-02-04 16:09:54 +00001356In some situations, especially when calling a Vim9 closure from legacy
1357context, the evaluation will fail. *E1248*
1358
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001359Note that at the script level the loop variable will be invalid after the
1360loop, also when used in a closure that is called later, e.g. with a timer.
1361This will generate error |E1302|: >
1362 for n in range(4)
1363 timer_start(500 * n, (_) => {
1364 echowin n
1365 })
1366 endfor
1367
Bram Moolenaar9712ff12022-09-18 13:04:22 +01001368You need to use a block and define a variable there, and use that one in the
1369closure: >
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001370 for n in range(4)
Bram Moolenaar9712ff12022-09-18 13:04:22 +01001371 {
1372 var nr = n
1373 timer_start(500 * n, (_) => {
1374 echowin nr
1375 })
1376 }
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001377 endfor
1378
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00001379Using `:echowindow` is useful in a timer, the messages go into a popup and will
Bram Moolenaar71b6d332022-09-10 13:13:14 +01001380not interfere with what the user is doing when it triggers.
1381
Bram Moolenaara2baa732022-02-04 16:09:54 +00001382
1383Converting a function from legacy to Vim9 ~
1384 *convert_legacy_function_to_vim9*
1385These are the most changes that need to be made to convert a legacy function
1386to a Vim9 function:
1387
1388- Change `func` or `function` to `def`.
1389- Change `endfunc` or `endfunction` to `enddef`.
1390- Add types to the function arguments.
1391- If the function returns something, add the return type.
1392- Change comments to start with # instead of ".
1393
1394 For example, a legacy function: >
1395 func MyFunc(text)
1396 " function body
1397 endfunc
1398< Becomes: >
1399 def MyFunc(text: string): number
1400 # function body
1401 enddef
1402
1403- Remove "a:" used for arguments. E.g.: >
1404 return len(a:text)
1405< Becomes: >
1406 return len(text)
1407
1408- Change `let` used to declare a variable to `var`.
1409- Remove `let` used to assign a value to a variable. This is for local
1410 variables already declared and b: w: g: and t: variables.
1411
1412 For example, legacy function: >
1413 let lnum = 1
1414 let lnum += 3
1415 let b:result = 42
1416< Becomes: >
1417 var lnum = 1
1418 lnum += 3
1419 b:result = 42
1420
1421- Insert white space in expressions where needed.
1422- Change "." used for concatenation to "..".
1423
1424 For example, legacy function: >
1425 echo line(1).line(2)
1426< Becomes: >
1427 echo line(1) .. line(2)
1428
1429- line continuation does not always require a backslash: >
Bram Moolenaar938ae282023-02-20 20:44:55 +00001430 echo ['one',
Bram Moolenaara2baa732022-02-04 16:09:54 +00001431 \ 'two',
1432 \ 'three'
1433 \ ]
1434< Becomes: >
1435 echo ['one',
1436 'two',
1437 'three'
1438 ]
1439
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +01001440
1441Calling a function in an expr option ~
1442 *expr-option-function*
Bram Moolenaarf269eab2022-10-03 18:04:35 +01001443The value of a few options, such as 'foldexpr', is an expression that is
1444evaluated to get a value. The evaluation can have quite a bit of overhead.
1445One way to minimize the overhead, and also to keep the option value very
1446simple, is to define a compiled function and set the option to call it
1447without arguments. Example: >
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +01001448 vim9script
1449 def MyFoldFunc(): any
1450 ... compute fold level for line v:lnum
1451 return level
1452 enddef
1453 set foldexpr=s:MyFoldFunc()
1454
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001455==============================================================================
1456
14574. Types *vim9-types*
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001458 *E1008* *E1009* *E1010* *E1012*
1459 *E1013* *E1029* *E1030*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001460The following builtin types are supported:
1461 bool
1462 number
1463 float
1464 string
1465 blob
Bram Moolenaard77a8522020-04-03 21:59:57 +02001466 list<{type}>
1467 dict<{type}>
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001468 job
1469 channel
Bram Moolenaarb17893a2020-03-14 08:19:51 +01001470 func
Bram Moolenaard1caa942020-04-10 22:10:56 +02001471 func: {type}
Bram Moolenaard77a8522020-04-03 21:59:57 +02001472 func({type}, ...)
1473 func({type}, ...): {type}
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001474 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001475
1476Not supported yet:
Bram Moolenaard77a8522020-04-03 21:59:57 +02001477 tuple<a: {type}, b: {type}, ...>
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001478
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001479These types can be used in declarations, but no simple value will actually
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001480have the "void" type. Trying to use a void (e.g. a function without a
Bram Moolenaara2baa732022-02-04 16:09:54 +00001481return value) results in error *E1031* *E1186* .
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001482
Bram Moolenaard77a8522020-04-03 21:59:57 +02001483There is no array type, use list<{type}> instead. For a list constant an
Bram Moolenaar71badf92023-04-22 22:40:14 +01001484efficient implementation is used that avoids allocating a lot of small pieces
1485of memory.
Ernie Rael3ec6c1f2023-10-21 11:45:38 +02001486 *vim9-func-declaration* *E1005* *E1007*
Bram Moolenaard77a8522020-04-03 21:59:57 +02001487A partial and function can be declared in more or less specific ways:
1488func any kind of function reference, no type
Bram Moolenaard1caa942020-04-10 22:10:56 +02001489 checking for arguments or return value
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001490func: void any number and type of arguments, no return
1491 value
Bram Moolenaard77a8522020-04-03 21:59:57 +02001492func: {type} any number and type of arguments with specific
1493 return type
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001494
1495func() function with no argument, does not return a
1496 value
1497func(): void same
1498func(): {type} function with no argument and return type
1499
Bram Moolenaard1caa942020-04-10 22:10:56 +02001500func({type}) function with argument type, does not return
Bram Moolenaard77a8522020-04-03 21:59:57 +02001501 a value
Bram Moolenaard1caa942020-04-10 22:10:56 +02001502func({type}): {type} function with argument type and return type
1503func(?{type}) function with type of optional argument, does
1504 not return a value
Ernie Raela5a15342023-10-23 19:08:38 +02001505func(...list<{type}>) function with type of list for variable number
1506 of arguments, does not return a value
1507func({type}, ?{type}, ...list<{type}>): {type}
Bram Moolenaard1caa942020-04-10 22:10:56 +02001508 function with:
1509 - type of mandatory argument
1510 - type of optional argument
Ernie Raela5a15342023-10-23 19:08:38 +02001511 - type of list for variable number of
1512 arguments
Bram Moolenaard1caa942020-04-10 22:10:56 +02001513 - return type
Bram Moolenaard77a8522020-04-03 21:59:57 +02001514
1515If the return type is "void" the function does not return a value.
1516
1517The reference can also be a |Partial|, in which case it stores extra arguments
1518and/or a dictionary, which are not visible to the caller. Since they are
1519called in the same way the declaration is the same.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001520
1521Custom types can be defined with `:type`: >
1522 :type MyList list<string>
Bram Moolenaar127542b2020-08-09 17:22:04 +02001523Custom types must start with a capital letter, to avoid name clashes with
1524builtin types added later, similarly to user functions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001525
1526And classes and interfaces can be used as types: >
1527 :class MyClass
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001528 :var mine: MyClass
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001529
1530 :interface MyInterface
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001531 :var mine: MyInterface
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001532
1533 :class MyTemplate<Targ>
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001534 :var mine: MyTemplate<number>
1535 :var mine: MyTemplate<string>
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001536
1537 :class MyInterface<Targ>
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001538 :var mine: MyInterface<number>
1539 :var mine: MyInterface<string>
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001540{not implemented yet}
1541
1542
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001543Variable types and type casting ~
1544 *variable-types*
Bram Moolenaar64d662d2020-08-09 19:02:50 +02001545Variables declared in Vim9 script or in a `:def` function have a type, either
1546specified explicitly or inferred from the initialization.
1547
1548Global, buffer, window and tab page variables do not have a specific type, the
1549value can be changed at any time, possibly changing the type. Therefore, in
1550compiled code the "any" type is assumed.
1551
1552This can be a problem when the "any" type is undesired and the actual type is
1553expected to always be the same. For example, when declaring a list: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001554 var l: list<number> = [1, g:two]
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001555At compile time Vim doesn't know the type of "g:two" and the expression type
1556becomes list<any>. An instruction is generated to check the list type before
1557doing the assignment, which is a bit inefficient.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001558 *type-casting* *E1104*
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001559To avoid this, use a type cast: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001560 var l: list<number> = [1, <number>g:two]
Bram Moolenaar4072ba52020-12-23 13:56:35 +01001561The compiled code will then only check that "g:two" is a number and give an
1562error if it isn't. This is called type casting.
Bram Moolenaar64d662d2020-08-09 19:02:50 +02001563
1564The syntax of a type cast is: "<" {type} ">". There cannot be white space
1565after the "<" or before the ">" (to avoid them being confused with
1566smaller-than and bigger-than operators).
1567
1568The semantics is that, if needed, a runtime type check is performed. The
1569value is not actually changed. If you need to change the type, e.g. to change
1570it to a string, use the |string()| function. Or use |str2nr()| to convert a
1571string to a number.
1572
Bram Moolenaar2ecbe532022-07-29 21:36:21 +01001573If a type is given where it is not expected you can get *E1272* .
1574
h_eastba77bbb2023-10-03 04:47:13 +09001575If a type is incomplete you get *E1363* , e.g. when you have an object for
Bram Moolenaar71badf92023-04-22 22:40:14 +01001576which the class is not known (usually that is a null object).
Bram Moolenaar64d662d2020-08-09 19:02:50 +02001577
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001578Type inference ~
1579 *type-inference*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001580In general: Whenever the type is clear it can be omitted. For example, when
1581declaring a variable and giving it a value: >
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001582 var name = 0 # infers number type
1583 var name = 'hello' # infers string type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001584
Bram Moolenaar127542b2020-08-09 17:22:04 +02001585The type of a list and dictionary comes from the common type of the values.
1586If the values all have the same type, that type is used for the list or
1587dictionary. If there is a mix of types, the "any" type is used. >
1588 [1, 2, 3] list<number>
1589 ['a', 'b', 'c'] list<string>
1590 [1, 'x', 3] list<any>
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001591
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001592The common type of function references, if they do not all have the same
1593number of arguments, uses "(...)" to indicate the number of arguments is not
1594specified. For example: >
1595 def Foo(x: bool)
1596 enddef
1597 def Bar(x: bool, y: bool)
1598 enddef
1599 var funclist = [Foo, Bar]
1600 echo funclist->typename()
1601Results in:
1602 list<func(...)>
1603
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001604For script-local variables in Vim9 script the type is checked, also when the
1605variable was declared in a legacy function.
1606
Bram Moolenaar9da17d72022-02-09 21:50:44 +00001607When a type has been declared this is attached to a List or Dictionary. When
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001608later some expression attempts to change the type an error will be given: >
1609 var ll: list<number> = [1, 2, 3]
Bram Moolenaarc4573eb2022-01-31 15:40:56 +00001610 ll->extend(['x']) # Error, 'x' is not a number
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001611
Bram Moolenaar9da17d72022-02-09 21:50:44 +00001612If the type is not declared then it is allowed to change: >
Bram Moolenaarc4573eb2022-01-31 15:40:56 +00001613 [1, 2, 3]->extend(['x']) # result: [1, 2, 3, 'x']
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001614
Bram Moolenaar9da17d72022-02-09 21:50:44 +00001615For a variable declaration an inferred type matters: >
1616 var ll = [1, 2, 3]
1617 ll->extend(['x']) # Error, 'x' is not a number
1618That is because the declaration looks like a list of numbers, thus is
1619equivalent to: >
1620 var ll: list<number> = [1, 2, 3]
1621If you do want a more permissive list you need to declare the type: >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00001622 var ll: list<any> = [1, 2, 3]
Bram Moolenaar9da17d72022-02-09 21:50:44 +00001623 ll->extend(['x']) # OK
1624
Bram Moolenaar207f0092020-08-30 17:20:20 +02001625
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001626Stricter type checking ~
1627 *type-checking*
Bram Moolenaar207f0092020-08-30 17:20:20 +02001628In legacy Vim script, where a number was expected, a string would be
1629automatically converted to a number. This was convenient for an actual number
Bram Moolenaar130cbfc2021-04-07 21:07:20 +02001630such as "123", but leads to unexpected problems (and no error message) if the
Bram Moolenaar207f0092020-08-30 17:20:20 +02001631string doesn't start with a number. Quite often this leads to hard-to-find
Bram Moolenaar944697a2022-02-20 19:48:20 +00001632bugs. e.g.: >
1633 echo 123 == '123'
1634< 1 ~
1635With an accidental space: >
1636 echo 123 == ' 123'
1637< 0 ~
Bram Moolenaara2baa732022-02-04 16:09:54 +00001638 *E1206* *E1210* *E1212*
Bram Moolenaar207f0092020-08-30 17:20:20 +02001639In Vim9 script this has been made stricter. In most places it works just as
Bram Moolenaar944697a2022-02-20 19:48:20 +00001640before if the value used matches the expected type. There will sometimes be
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02001641an error, thus breaking backwards compatibility. For example:
Bram Moolenaar207f0092020-08-30 17:20:20 +02001642- Using a number other than 0 or 1 where a boolean is expected. *E1023*
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001643- Using a string value when setting a number option.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001644- Using a number where a string is expected. *E1024* *E1105*
Bram Moolenaar207f0092020-08-30 17:20:20 +02001645
Bram Moolenaar22863042021-10-16 15:23:36 +01001646One consequence is that the item type of a list or dict given to |map()| must
Bram Moolenaar944697a2022-02-20 19:48:20 +00001647not change, if the type was declared. This will give an error in Vim9
1648script: >
1649 var mylist: list<number> = [1, 2, 3]
1650 echo map(mylist, (i, v) => 'item ' .. i)
1651< E1012: Type mismatch; expected number but got string in map() ~
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001652
Bram Moolenaar944697a2022-02-20 19:48:20 +00001653Instead use |mapnew()|, it creates a new list: >
1654 var mylist: list<number> = [1, 2, 3]
1655 echo mapnew(mylist, (i, v) => 'item ' .. i)
1656< ['item 0', 'item 1', 'item 2'] ~
1657
1658If the item type was not declared or determined to be "any" it can change to a
1659more specific type. E.g. when a list of mixed types gets changed to a list of
1660strings: >
Bram Moolenaar90df4b92021-07-07 20:26:08 +02001661 var mylist = [1, 2.0, '3']
1662 # typename(mylist) == "list<any>"
1663 map(mylist, (i, v) => 'item ' .. i)
1664 # typename(mylist) == "list<string>", no error
Bram Moolenaar944697a2022-02-20 19:48:20 +00001665
1666There is a subtle difference between using a list constant directly and
Bram Moolenaarafa048f2022-02-22 20:43:36 +00001667through a variable declaration. Because of type inference, when using a list
Bram Moolenaar944697a2022-02-20 19:48:20 +00001668constant to initialize a variable, this also sets the declared type: >
1669 var mylist = [1, 2, 3]
1670 # typename(mylist) == "list<number>"
1671 echo map(mylist, (i, v) => 'item ' .. i) # Error!
1672
1673When using the list constant directly, the type is not declared and is allowed
1674to change: >
1675 echo map([1, 2, 3], (i, v) => 'item ' .. i) # OK
1676
1677The reasoning behind this is that when a type is declared and the list is
1678passed around and changed, the declaration must always hold. So that you can
1679rely on the type to match the declared type. For a constant this is not
1680needed.
1681
1682 *E1158*
Bram Moolenaar9faec4e2021-02-27 16:38:07 +01001683Same for |extend()|, use |extendnew()| instead, and for |flatten()|, use
Bram Moolenaar944697a2022-02-20 19:48:20 +00001684|flattennew()| instead. Since |flatten()| is intended to always change the
1685type, it can not be used in Vim9 script.
1686
Ernie Rael3ec6c1f2023-10-21 11:45:38 +02001687Assigning to a funcref with specified arguments (see |vim9-func-declaration|)
1688does strict type checking of the arguments. For variable number of arguments
1689the type must match: >
1690 var FuncRef: func(string, number, bool): number
1691 FuncRef = (v1: string, v2: number, v3: bool) => 777 # OK
1692 FuncRef = (v1: string, v2: number, v3: number) => 777 # Error!
1693 # variable number of arguments must have same type
1694 var FuncVA: func(...list<string>): number
1695 FuncVA = (...v: list<number>): number => v # Error!
1696 FuncVA = (...v: list<any>): number => v # OK, `any` runtime check
1697 FuncVA = (v1: string, v: string2): number => 333 # Error!
1698 FuncVA = (v: list<string>): number => 3 # Error!
1699
zeertzjq61e984e2023-12-09 15:18:33 +08001700If the destination funcref has no specified arguments, then there is no
Ernie Rael3ec6c1f2023-10-21 11:45:38 +02001701argument type checking: >
1702 var FuncUnknownArgs: func: number
1703 FuncUnknownArgs = (v): number => v # OK
1704 FuncUnknownArgs = (v1: string, v2: string): number => 3 # OK
Ernie Raela5a15342023-10-23 19:08:38 +02001705 FuncUnknownArgs = (...v1: list<string>): number => 333 # OK
1706<
Bram Moolenaara2baa732022-02-04 16:09:54 +00001707 *E1211* *E1217* *E1218* *E1219* *E1220* *E1221*
1708 *E1222* *E1223* *E1224* *E1225* *E1226* *E1227*
Dominique Pellee764d1b2023-03-12 21:20:59 +00001709 *E1228* *E1238* *E1250* *E1251* *E1252* *E1256*
1710 *E1297* *E1298* *E1301*
Bram Moolenaara2baa732022-02-04 16:09:54 +00001711Types are checked for most builtin functions to make it easier to spot
1712mistakes.
Bram Moolenaar82be4842021-01-11 19:40:15 +01001713
erraelcea3dac2023-12-25 01:31:23 -08001714Categories of variables, defaults and null handling ~
1715 *variable-categories* *null-variables*
1716There are categories of variables:
1717 primitive number, float, boolean
1718 container string, blob, list, dict
1719 specialized function, job, channel, user-defined-object
1720
1721When declaring a variable without an initializer, an explicit type must be
1722provided. Each category has different default initialization semantics. Here's
1723an example for each category: >
1724 var num: number # primitives default to a 0 equivalent
1725 var cont: list<string> # containers default to an empty container
1726 var spec: job # specialized variables default to null
1727<
1728Vim does not have a familiar null value; it has various null_<type> predefined
1729values, for example |null_string|, |null_list|, |null_job|. Primitives do not
1730have a null_<type>. The typical use cases for null_<type> are:
h_east4d496432024-01-27 19:22:28 +09001731- to clear a variable and release its resources;
1732- as a default for a parameter in a function definition, see |null-compare|.
erraelcea3dac2023-12-25 01:31:23 -08001733
1734For a specialized variable, like `job`, null_<type> is used to clear the
1735resources. For a container variable, resources can also be cleared by
1736assigning an empty container to the variable. For example: >
1737 var j: job = job_start(...)
1738 # ... job does its work
1739 j = null_job # clear the variable and release the job's resources
1740
1741 var l: list<any>
1742 # ... add lots of stuff to list
1743 l = [] # clear the variable and release container resources
1744Using the empty container, rather than null_<type>, to clear a container
1745variable may avoid null complications as described in |null-anomalies|.
1746
1747The initialization semantics of container variables and specialized variables
1748differ. An uninitialized container defaults to an empty container: >
1749 var l1: list<string> # empty container
1750 var l2: list<string> = [] # empty container
1751 var l3: list<string> = null_list # null container
1752"l1" and "l2" are equivalent and indistinguishable initializations; but "l3"
1753is a null container. A null container is similar to, but different from, an
1754empty container, see |null-anomalies|.
1755
1756Specialized variables default to null. These job initializations are
1757equivalent and indistinguishable: >
1758 var j1: job
1759 var j2: job = null_job
1760 var j3 = null_job
1761
1762When a list or dict is declared, if the item type is not specified and can not
1763be inferred, then the type is "any": >
1764 var d1 = {} # type is "dict<any>"
1765 var d2 = null_dict # type is "dict<any>"
1766
1767Declaring a function, see |vim9-func-declaration|, is particularly unique.
1768
1769 *null-compare*
1770For familiar null compare semantics, where a null container is not equal to
1771an empty container, do not use null_<type> in a comparison: >
1772 vim9script
1773 def F(arg: list<string> = null_list)
1774 if arg == null
1775 echo "null"
1776 else
1777 echo printf("not null, %sempty", empty(arg) ? '' : 'not ')
1778 endif
1779 enddef
1780 F() # output: "null"
1781 F(null_list) # output: "null"
1782 F([]) # output: "not null, empty"
1783 F(['']) # output: "not null, not empty"
h_east4d496432024-01-27 19:22:28 +09001784The above function takes a list of strings and reports on it.
erraelcea3dac2023-12-25 01:31:23 -08001785Change the above function signature to accept different types of arguments: >
1786 def F(arg: list<any> = null_list) # any type of list
1787 def F(arg: any = null) # any type
1788<
1789In the above example, where the goal is to distinguish a null list from an
1790empty list, comparing against `null` instead of `null_list` is the correct
1791choice. The basic reason is because "null_list == null" and "[] != null".
1792Comparing to `null_list` fails since "[] == null_list". In the following section
1793there are details about comparison results.
1794
1795 *null-details* *null-anomalies*
1796This section describes issues about using null and null_<type>; included below
1797are the enumerated results of null comparisons. In some cases, if familiar
1798with vim9 null semantics, the programmer may chose to use null_<type> in
1799comparisons and/or other situations.
1800
1801Elsewhere in the documentation it says:
h_east4d496432024-01-27 19:22:28 +09001802 Quite often a null value is handled the same as an empty value, but
1803 not always
erraelcea3dac2023-12-25 01:31:23 -08001804Here's an example: >
1805 vim9script
1806 var s1: list<string>
1807 var s2: list<string> = null_list
1808 echo s1 # output: "[]"
1809 echo s2 # output: "[]"
h_east4d496432024-01-27 19:22:28 +09001810
erraelcea3dac2023-12-25 01:31:23 -08001811 echo s1 + ['a'] # output: "['a']"
1812 echo s2 + ['a'] # output: "['a']"
h_east4d496432024-01-27 19:22:28 +09001813
erraelcea3dac2023-12-25 01:31:23 -08001814 echo s1->add('a') # output: "['a']"
1815 echo s2->add('a') # E1130: Can not add to null list
1816<
1817Two values equal to a null_<type> are not necessarily equal to each other: >
1818 vim9script
1819 echo {} == null_dict # true
1820 echo null_dict == null # true
1821 echo {} == null # false
1822<
1823Unlike the other containers, an uninitialized string is equal to null. The
1824'is' operator can be used to determine if it is a null_string: >
1825 vim9script
1826 var s1: string
1827 var s2 = null_string
1828 echo s1 == null # true - this is unexpected
1829 echo s2 == null # true
1830 echo s2 is null_string # true
1831
1832 var b1: blob
1833 var b2 = null_blob
1834 echo b1 == null # false
1835 echo b2 == null # true
1836<
1837Any variable initialized to the null_<type> is equal to the null_<type> and is
1838also equal to null. For example: >
1839 vim9script
1840 var x = null_blob
1841 echo x == null_blob # true
1842 echo x == null # true
1843<
1844An uninitialized variable is usually equal to null; it depends on its type:
1845 var s: string s == null
1846 var b: blob b != null ***
1847 var l: list<any> l != null ***
1848 var d: dict<any> d != null ***
1849 var f: func f == null
1850 var j: job j == null
1851 var c: channel c == null
1852 var o: Class o == null
1853
1854A variable initialized to empty equals null_<type>; but not null:
1855 var s2: string = "" == null_string != null
1856 var b2: blob = 0z == null_blob != null
1857 var l2: list<any> = [] == null_list != null
1858 var d2: dict<any> = {} == null_dict != null
1859
1860NOTE: the specialized variables, like job, default to null value and have no
1861corresponding empty value.
1862
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001863==============================================================================
1864
Bram Moolenaar30fd8202020-09-26 15:09:30 +020018655. Namespace, Import and Export
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001866 *vim9script* *vim9-export* *vim9-import*
1867
Bram Moolenaarfd31be22022-01-16 14:46:06 +00001868A Vim9 script can be written to be imported. This means that some items are
1869intentionally exported, made available to other scripts. When the exporting
1870script is imported in another script, these exported items can then be used in
1871that script. All the other items remain script-local in the exporting script
1872and cannot be accessed by the importing script.
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00001873
1874This mechanism exists for writing a script that can be sourced (imported) by
1875other scripts, while making sure these other scripts only have access to what
1876you want them to. This also avoids using the global namespace, which has a
Bram Moolenaar6ba83ba2022-06-12 22:15:57 +01001877risk of name collisions. For example when you have two plugins with similar
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00001878functionality.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001879
Bram Moolenaarfd31be22022-01-16 14:46:06 +00001880You can cheat by using the global namespace explicitly. That should be done
1881only for things that really are global.
Bram Moolenaar207f0092020-08-30 17:20:20 +02001882
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001883
1884Namespace ~
Bram Moolenaardcc58e02020-12-28 20:53:21 +01001885 *vim9-namespace*
Bram Moolenaar560979e2020-02-04 22:53:05 +01001886To recognize a file that can be imported the `vim9script` statement must
Bram Moolenaard3f8a9e2021-02-17 21:57:03 +01001887appear as the first statement in the file (see |vim9-mix| for an exception).
1888It tells Vim to interpret the script in its own namespace, instead of the
1889global namespace. If a file starts with: >
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001890 vim9script
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001891 var myvar = 'yes'
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001892Then "myvar" will only exist in this file. While without `vim9script` it would
1893be available as `g:myvar` from any other script and function.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00001894 *E1101*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001895The variables at the file level are very much like the script-local "s:"
Bram Moolenaar2c7f8c52020-04-20 19:52:53 +02001896variables in legacy Vim script, but the "s:" is omitted. And they cannot be
1897deleted.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001898
Bram Moolenaar2c7f8c52020-04-20 19:52:53 +02001899In Vim9 script the global "g:" namespace can still be used as before. And the
1900"w:", "b:" and "t:" namespaces. These have in common that variables are not
Bram Moolenaar9712ff12022-09-18 13:04:22 +01001901declared, have no specific type and they can be deleted. *E1304*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001902
1903A side effect of `:vim9script` is that the 'cpoptions' option is set to the
1904Vim default value, like with: >
1905 :set cpo&vim
1906One of the effects is that |line-continuation| is always enabled.
Bram Moolenaar3e191692021-03-17 17:46:00 +01001907The original value of 'cpoptions' is restored at the end of the script, while
1908flags added or removed in the script are also added to or removed from the
1909original value to get the same effect. The order of flags may change.
Bram Moolenaar71eb3ad2021-12-26 12:07:30 +00001910In the |vimrc| file sourced on startup this does not happen.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001911
Bram Moolenaard3f8a9e2021-02-17 21:57:03 +01001912 *vim9-mix*
1913There is one way to use both legacy and Vim9 syntax in one script file: >
1914 " comments may go here
1915 if !has('vim9script')
1916 " legacy script commands go here
1917 finish
1918 endif
1919 vim9script
1920 # Vim9 script commands go here
1921This allows for writing a script that takes advantage of the Vim9 script
Bram Moolenaar9faec4e2021-02-27 16:38:07 +01001922syntax if possible, but will also work on a Vim version without it.
Bram Moolenaard3f8a9e2021-02-17 21:57:03 +01001923
Konfektde4b2442025-03-05 21:03:21 +01001924Note that Vim9 syntax changed before Vim 9 so that scripts using the current
1925syntax (such as "import from" instead of "import") might throw errors.
1926To prevent these, a safer check could be for |v:version| >= 900 instead.
1927
Bram Moolenaard3f8a9e2021-02-17 21:57:03 +01001928This can only work in two ways:
19291. The "if" statement evaluates to false, the commands up to `endif` are
1930 skipped and `vim9script` is then the first command actually executed.
19312. The "if" statement evaluates to true, the commands up to `endif` are
1932 executed and `finish` bails out before reaching `vim9script`.
1933
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001934
1935Export ~
1936 *:export* *:exp*
Bram Moolenaar2547aa92020-07-26 17:00:44 +02001937Exporting an item can be written as: >
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001938 export const EXPORTED_CONST = 1234
Bram Moolenaar30fd8202020-09-26 15:09:30 +02001939 export var someValue = ...
1940 export final someValue = ...
1941 export const someValue = ...
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001942 export def MyFunc() ...
1943 export class MyClass ...
Bram Moolenaar74235772021-06-12 14:53:05 +02001944 export interface MyClass ...
Yegappan Lakshmanana81cf8b2025-01-19 22:20:34 +01001945 export enum MyEnum ...
Bram Moolenaar6f4754b2022-01-23 12:07:04 +00001946< *E1043* *E1044*
Yegappan Lakshmanana81cf8b2025-01-19 22:20:34 +01001947As this suggests, only constants, variables, `:def` functions, classes,
1948interfaces and enums can be exported.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001949
Bram Moolenaar65e0d772020-06-14 17:29:55 +02001950 *E1042*
1951`:export` can only be used in Vim9 script, at the script level.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001952
1953
1954Import ~
Bram Moolenaar2ecbe532022-07-29 21:36:21 +01001955 *:import* *:imp* *E1094* *E1047* *E1262*
1956 *E1048* *E1049* *E1053* *E1071* *E1088* *E1236*
Bram Moolenaar5ed11532022-07-06 13:18:11 +01001957The exported items can be imported in another script. The import syntax has
1958two forms. The simple form: >
1959 import {filename}
1960<
1961Where {filename} is an expression that must evaluate to a string. In this
1962form the filename should end in ".vim" and the portion before ".vim" will
1963become the script local name of the namespace. For example: >
Bram Moolenaard5f400c2022-01-06 21:10:28 +00001964 import "myscript.vim"
Bram Moolenaar5ed11532022-07-06 13:18:11 +01001965<
1966This makes each exported item in "myscript.vim" available as "myscript.item".
Bram Moolenaara2baa732022-02-04 16:09:54 +00001967 *:import-as* *E1257* *E1261*
Bram Moolenaar5ed11532022-07-06 13:18:11 +01001968In case the name is long or ambiguous, this form can be used to specify
1969another name: >
1970 import {longfilename} as {name}
1971<
1972In this form {name} becomes a specific script local name for the imported
1973namespace. Therefore {name} must consist of letters, digits and '_', like
1974|internal-variables|. The {longfilename} expression must evaluate to any
1975filename. For example: >
1976 import "thatscript.vim.v2" as that
Bram Moolenaara2baa732022-02-04 16:09:54 +00001977< *E1060* *E1258* *E1259* *E1260*
Bram Moolenaar5ed11532022-07-06 13:18:11 +01001978Then you can use "that.item", etc. You are free to choose the name "that".
1979Use something that will be recognized as referring to the imported script.
1980Avoid command names, command modifiers and builtin function names, because the
Aliaksei Budaveib043ff32023-10-03 17:39:53 +03001981name will shadow them. It's better not to start the name with a capital
Bram Moolenaar5ed11532022-07-06 13:18:11 +01001982letter, since it can then also shadow global user commands and functions.
1983Also, you cannot use the name for something else in the script, such as a
1984function or variable name.
Bram Moolenaard5f400c2022-01-06 21:10:28 +00001985
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00001986In case the dot in the name is undesired, a local reference can be made for a
1987function: >
1988 var LongFunc = that.LongFuncName
Bram Moolenaard5f400c2022-01-06 21:10:28 +00001989
1990This also works for constants: >
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00001991 const MAXLEN = that.MAX_LEN_OF_NAME
Bram Moolenaard5f400c2022-01-06 21:10:28 +00001992
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00001993This does not work for variables, since the value would be copied once and
1994when changing the variable the copy will change, not the original variable.
1995You will need to use the full name, with the dot.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001996
Bram Moolenaar4db572e2021-07-18 18:21:38 +02001997`:import` can not be used in a function. Imported items are intended to exist
1998at the script level and only imported once.
1999
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002000The script name after `import` can be:
2001- A relative path, starting "." or "..". This finds a file relative to the
2002 location of the script file itself. This is useful to split up a large
2003 plugin into several files.
2004- An absolute path, starting with "/" on Unix or "D:/" on MS-Windows. This
Bram Moolenaarcb80aa22020-10-26 21:12:46 +01002005 will rarely be used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002006- A path not being relative or absolute. This will be found in the
2007 "import" subdirectories of 'runtimepath' entries. The name will usually be
2008 longer and unique, to avoid loading the wrong file.
Bram Moolenaar6aa57292021-08-14 21:25:52 +02002009 Note that "after/import" is not used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002010
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00002011If the name does not end in ".vim" then the use of "as name" is required.
2012
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002013Once a vim9 script file has been imported, the result is cached and used the
2014next time the same script is imported. It will not be read again.
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002015
2016It is not allowed to import the same script twice, also when using two
2017different "as" names.
Bram Moolenaar2f0936c2022-01-08 21:51:59 +00002018
2019When using the imported name the dot and the item name must be in the same
2020line, there can be no line break: >
2021 echo that.
2022 name # Error!
2023 echo that
2024 .name # Error!
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +01002025< *import-map*
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002026When you've imported a function from one script into a vim9 script you can
2027refer to the imported function in a mapping by prefixing it with |<SID>|: >
Bram Moolenaar89445512022-04-14 12:58:23 +01002028 noremap <silent> ,a :call <SID>name.Function()<CR>
2029
2030When the mapping is defined "<SID>name." will be replaced with <SNR> and the
2031script ID of the imported script.
Bram Moolenaar6ba83ba2022-06-12 22:15:57 +01002032An even simpler solution is using |<ScriptCmd>|: >
2033 noremap ,a <ScriptCmd>name.Function()<CR>
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002034
2035Note that this does not work for variables, only for functions.
2036
2037 *import-legacy* *legacy-import*
2038`:import` can also be used in legacy Vim script. The imported namespace still
2039becomes script-local, even when the "s:" prefix is not given. For example: >
zeertzjqd086b8f2024-02-25 15:42:52 +08002040 import "myfile.vim"
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002041 call s:myfile.MyFunc()
2042
2043And using the "as name" form: >
2044 import "otherfile.vim9script" as that
2045 call s:that.OtherFunc()
2046
Bram Moolenaar9712ff12022-09-18 13:04:22 +01002047However, the namespace cannot be resolved on its own: >
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002048 import "that.vim"
2049 echo s:that
2050 " ERROR: E1060: Expected dot after name: s:that
2051<
2052This also affects the use of |<SID>| in the legacy mapping context. Since
2053|<SID>| is only a valid prefix for a function and NOT for a namespace, you
h_eastba77bbb2023-10-03 04:47:13 +09002054cannot use it to scope a function in a script local namespace. Instead of
2055prefixing the function with |<SID>| you should use|<ScriptCmd>|. For example:
2056>
Bram Moolenaar5ed11532022-07-06 13:18:11 +01002057 noremap ,a <ScriptCmd>:call s:that.OtherFunc()<CR>
Bram Moolenaar6ba83ba2022-06-12 22:15:57 +01002058<
Christian Brabandtd9a1f262025-01-21 22:17:50 +01002059 *:import-cycle*
2060The `import` commands are executed when encountered. If script A imports
2061script B, and B (directly or indirectly) imports A, this will be skipped over.
2062At this point items in A after "import B" will not have been processed and
2063defined yet. Therefore cyclic imports can exist and not result in an error
2064directly, but may result in an error for items in A after "import B" not being
2065defined. This does not apply to autoload imports, see the next section.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002066
2067
Bram Moolenaarfd31be22022-01-16 14:46:06 +00002068Importing an autoload script ~
Bram Moolenaarfd999452022-08-24 18:30:14 +01002069 *vim9-autoload* *import-autoload*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002070For optimal startup speed, loading scripts should be postponed until they are
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002071actually needed. Using the autoload mechanism is recommended:
Bram Moolenaara2baa732022-02-04 16:09:54 +00002072 *E1264*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010020731. In the plugin define user commands, functions and/or mappings that refer to
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002074 items imported from an autoload script. >
2075 import autoload 'for/search.vim'
2076 command -nargs=1 SearchForStuff search.Stuff(<f-args>)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002077
2078< This goes in .../plugin/anyname.vim. "anyname.vim" can be freely chosen.
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002079 The "SearchForStuff" command is now available to the user.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002080
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002081 The "autoload" argument to `:import` means that the script is not loaded
2082 until one of the items is actually used. The script will be found under
2083 the "autoload" directory in 'runtimepath' instead of the "import"
Bram Moolenaarcbaff5e2022-04-08 17:45:08 +01002084 directory. Alternatively a relative or absolute name can be used, see
2085 below.
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002086
20872. In the autoload script put the bulk of the code. >
Bram Moolenaarfd218c82022-01-18 16:26:24 +00002088 vim9script
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002089 export def Stuff(arg: string)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002090 ...
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002091
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002092< This goes in .../autoload/for/search.vim.
2093
Bram Moolenaarfd218c82022-01-18 16:26:24 +00002094 Putting the "search.vim" script under the "/autoload/for/" directory has
2095 the effect that "for#search#" will be prefixed to every exported item. The
2096 prefix is obtained from the file name, as you would to manually in a
2097 legacy autoload script. Thus the exported function can be found with
2098 "for#search#Stuff", but you would normally use `import autoload` and not
Bram Moolenaar47c532e2022-03-19 15:18:53 +00002099 use the prefix (which has the side effect of loading the autoload script
2100 when compiling a function that encounters this name).
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002101
2102 You can split up the functionality and import other scripts from the
2103 autoload script as you like. This way you can share code between plugins.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002104
Bram Moolenaarcbaff5e2022-04-08 17:45:08 +01002105Searching for the autoload script in all entries in 'runtimepath' can be a bit
2106slow. If the plugin knows where the script is located, quite often a relative
2107path can be used. This avoids the search and should be quite a bit faster.
2108Another advantage is that the script name does not need to be unique. An
2109absolute path is also possible. Examples: >
2110 import autoload '../lib/implement.vim'
2111 import autoload MyScriptsDir .. '/lib/implement.vim'
2112
Bram Moolenaarfd31be22022-01-16 14:46:06 +00002113For defining a mapping that uses the imported autoload script the special key
2114|<ScriptCmd>| is useful. It allows for a command in a mapping to use the
2115script context of where the mapping was defined.
2116
Bram Moolenaar418f1df2020-08-12 21:34:49 +02002117When compiling a `:def` function and a function in an autoload script is
2118encountered, the script is not loaded until the `:def` function is called.
Bram Moolenaardc4451d2022-01-09 21:36:37 +00002119This also means you get any errors only at runtime, since the argument and
Bram Moolenaar47c532e2022-03-19 15:18:53 +00002120return types are not known yet. If you would use the name with '#' characters
2121then the autoload script IS loaded.
2122
2123Be careful to not refer to an item in an autoload script that does trigger
2124loading it unintentionally. For example, when setting an option that takes a
2125function name, make sure to use a string, not a function reference: >
2126 import autoload 'qftf.vim'
2127 &quickfixtextfunc = 'qftf.Func' # autoload script NOT loaded
2128 &quickfixtextfunc = qftf.Func # autoload script IS loaded
2129On the other hand, it can be useful to load the script early, at a time when
2130any errors should be given.
Bram Moolenaar418f1df2020-08-12 21:34:49 +02002131
Bram Moolenaarfd31be22022-01-16 14:46:06 +00002132For testing the |test_override()| function can be used to have the
2133`import autoload` load the script right away, so that the items and types can
2134be checked without waiting for them to be actually used: >
2135 test_override('autoload', 1)
2136Reset it later with: >
2137 test_override('autoload', 0)
2138Or: >
2139 test_override('ALL', 0)
2140
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002141
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002142==============================================================================
2143
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000021446. Classes and interfaces *vim9-classes*
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002145
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002146In legacy script a Dictionary could be used as a kind-of object, by adding
2147members that are functions. However, this is quite inefficient and requires
2148the writer to do the work of making sure all the objects have the right
2149members. See |Dictionary-function|.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002150
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002151In |Vim9| script you can have classes, objects and interfaces like in most
2152popular object-oriented programming languages. Since this is a lot of
2153functionality it is located in a separate help file: |vim9class.txt|.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002154
Bram Moolenaar74235772021-06-12 14:53:05 +02002155
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002156==============================================================================
2157
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010021589. Rationale *vim9-rationale*
2159
2160The :def command ~
2161
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002162Plugin writers have asked for much faster Vim script. Investigations have
Bram Moolenaar560979e2020-02-04 22:53:05 +01002163shown that keeping the existing semantics of function calls make this close to
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002164impossible, because of the overhead involved with calling a function, setting
2165up the local function scope and executing lines. There are many details that
2166need to be handled, such as error messages and exceptions. The need to create
2167a dictionary for a: and l: scopes, the a:000 list and several others add too
2168much overhead that cannot be avoided.
2169
2170Therefore the `:def` method to define a new-style function had to be added,
2171which allows for a function with different semantics. Most things still work
2172as before, but some parts do not. A new way to define a function was
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002173considered the best way to separate the legacy style code from Vim9 style code.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002174
2175Using "def" to define a function comes from Python. Other languages use
2176"function" which clashes with legacy Vim script.
2177
2178
2179Type checking ~
2180
2181When compiling lines of Vim commands into instructions as much as possible
2182should be done at compile time. Postponing it to runtime makes the execution
2183slower and means mistakes are found only later. For example, when
2184encountering the "+" character and compiling this into a generic add
Bram Moolenaar98a29d02021-01-18 19:55:44 +01002185instruction, at runtime the instruction would have to inspect the type of the
2186arguments and decide what kind of addition to do. And when the type is
2187dictionary throw an error. If the types are known to be numbers then an "add
2188number" instruction can be used, which is faster. The error can be given at
2189compile time, no error handling is needed at runtime, since adding two numbers
2190cannot fail.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002191
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002192The syntax for types, using <type> for compound types, is similar to Java. It
2193is easy to understand and widely used. The type names are what were used in
2194Vim before, with some additions such as "void" and "bool".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002195
2196
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002197Removing clutter and weirdness ~
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002198
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002199Once decided that `:def` functions have different syntax than legacy functions,
2200we are free to add improvements to make the code more familiar for users who
2201know popular programming languages. In other words: remove weird things that
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002202only Vim does.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002203
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002204We can also remove clutter, mainly things that were done to make Vim script
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002205backwards compatible with the good old Vi commands.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002206
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002207Examples:
Bram Moolenaar63f32602022-06-09 20:45:54 +01002208- Drop `:call` for calling a function and `:eval` for evaluating an
2209 expression.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002210- Drop using a leading backslash for line continuation, automatically figure
2211 out where an expression ends.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002212
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002213However, this does require that some things need to change:
2214- Comments start with # instead of ", to avoid confusing them with strings.
Bram Moolenaar63f32602022-06-09 20:45:54 +01002215 This is good anyway, it is also used by several popular languages.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002216- Ex command ranges need to be prefixed with a colon, to avoid confusion with
2217 expressions (single quote can be a string or a mark, "/" can be divide or a
2218 search command, etc.).
2219
2220Goal is to limit the differences. A good criteria is that when the old syntax
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002221is accidentally used you are very likely to get an error message.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002222
2223
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002224Syntax and semantics from popular languages ~
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002225
2226Script writers have complained that the Vim script syntax is unexpectedly
2227different from what they are used to. To reduce this complaint popular
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002228languages are used as an example. At the same time, we do not want to abandon
2229the well-known parts of legacy Vim script.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002230
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002231For many things TypeScript is followed. It's a recent language that is
2232gaining popularity and has similarities with Vim script. It also has a
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002233mix of static typing (a variable always has a known value type) and dynamic
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002234typing (a variable can have different types, this changes at runtime). Since
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002235legacy Vim script is dynamically typed and a lot of existing functionality
2236(esp. builtin functions) depends on that, while static typing allows for much
2237faster execution, we need to have this mix in Vim9 script.
2238
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002239There is no intention to completely match TypeScript syntax and semantics. We
2240just want to take those parts that we can use for Vim and we expect Vim users
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002241will be happy with. TypeScript is a complex language with its own history,
2242advantages and disadvantages. To get an idea of the disadvantages read the
2243book: "JavaScript: The Good Parts". Or find the article "TypeScript: the good
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02002244parts" and read the "Things to avoid" section.
2245
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002246People familiar with other languages (Java, Python, etc.) will also find
2247things in TypeScript that they do not like or do not understand. We'll try to
2248avoid those things.
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02002249
2250Specific items from TypeScript we avoid:
2251- Overloading "+", using it both for addition and string concatenation. This
2252 goes against legacy Vim script and often leads to mistakes. For that reason
2253 we will keep using ".." for string concatenation. Lua also uses ".." this
2254 way. And it allows for conversion to string for more values.
2255- TypeScript can use an expression like "99 || 'yes'" in a condition, but
2256 cannot assign the value to a boolean. That is inconsistent and can be
2257 annoying. Vim recognizes an expression with && or || and allows using the
Bram Moolenaar1f318c62021-12-26 18:09:31 +00002258 result as a bool. The |falsy-operator| was added for the mechanism to use a
2259 default value.
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02002260- TypeScript considers an empty string as Falsy, but an empty list or dict as
2261 Truthy. That is inconsistent. In Vim an empty list and dict are also
2262 Falsy.
2263- TypeScript has various "Readonly" types, which have limited usefulness,
2264 since a type cast can remove the immutable nature. Vim locks the value,
2265 which is more flexible, but is only checked at runtime.
Bram Moolenaarf10911e2022-01-29 22:20:48 +00002266- TypeScript has a complicated "import" statement that does not match how the
2267 Vim import mechanism works. A much simpler mechanism is used instead, which
2268 matches that the imported script is only sourced once.
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002269
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002270
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002271Declarations ~
2272
2273Legacy Vim script uses `:let` for every assignment, while in Vim9 declarations
2274are used. That is different, thus it's good to use a different command:
2275`:var`. This is used in many languages. The semantics might be slightly
2276different, but it's easily recognized as a declaration.
2277
Bram Moolenaar23515b42020-11-29 14:36:24 +01002278Using `:const` for constants is common, but the semantics varies. Some
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002279languages only make the variable immutable, others also make the value
2280immutable. Since "final" is well known from Java for only making the variable
2281immutable we decided to use that. And then `:const` can be used for making
2282both immutable. This was also used in legacy Vim script and the meaning is
2283almost the same.
2284
2285What we end up with is very similar to Dart: >
2286 :var name # mutable variable and value
2287 :final name # immutable variable, mutable value
2288 :const name # immutable variable and value
2289
2290Since legacy and Vim9 script will be mixed and global variables will be
2291shared, optional type checking is desirable. Also, type inference will avoid
2292the need for specifying the type in many cases. The TypeScript syntax fits
2293best for adding types to declarations: >
2294 var name: string # string type is specified
2295 ...
2296 name = 'John'
2297 const greeting = 'hello' # string type is inferred
2298
2299This is how we put types in a declaration: >
2300 var mylist: list<string>
2301 final mylist: list<string> = ['foo']
2302 def Func(arg1: number, arg2: string): bool
2303
2304Two alternatives were considered:
23051. Put the type before the name, like Dart: >
2306 var list<string> mylist
2307 final list<string> mylist = ['foo']
2308 def Func(number arg1, string arg2) bool
23092. Put the type after the variable name, but do not use a colon, like Go: >
2310 var mylist list<string>
2311 final mylist list<string> = ['foo']
2312 def Func(arg1 number, arg2 string) bool
2313
2314The first is more familiar for anyone used to C or Java. The second one
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002315doesn't really have an advantage over the first, so let's discard the second.
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002316
2317Since we use type inference the type can be left out when it can be inferred
2318from the value. This means that after `var` we don't know if a type or a name
2319follows. That makes parsing harder, not only for Vim but also for humans.
2320Also, it will not be allowed to use a variable name that could be a type name,
2321using `var string string` is too confusing.
2322
2323The chosen syntax, using a colon to separate the name from the type, adds
2324punctuation, but it actually makes it easier to recognize the parts of a
2325declaration.
2326
2327
2328Expressions ~
2329
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002330Expression evaluation was already close to what other languages are doing.
2331Some details are unexpected and can be improved. For example a boolean
2332condition would accept a string, convert it to a number and check if the
2333number is non-zero. This is unexpected and often leads to mistakes, since
2334text not starting with a number would be converted to zero, which is
Bram Moolenaarcb80aa22020-10-26 21:12:46 +01002335considered false. Thus using a string for a condition would often not give an
2336error and be considered false. That is confusing.
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002337
Bram Moolenaar23515b42020-11-29 14:36:24 +01002338In Vim9 type checking is stricter to avoid mistakes. Where a condition is
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002339used, e.g. with the `:if` command and the `||` operator, only boolean-like
2340values are accepted:
2341 true: `true`, `v:true`, `1`, `0 < 9`
2342 false: `false`, `v:false`, `0`, `0 > 9`
2343Note that the number zero is false and the number one is true. This is more
Bram Moolenaarcb80aa22020-10-26 21:12:46 +01002344permissive than most other languages. It was done because many builtin
Bram Moolenaar63f32602022-06-09 20:45:54 +01002345functions return these values, and changing that causes more problems than it
2346solves. After using this for a while it turned out to work well.
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002347
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002348If you have any type of value and want to use it as a boolean, use the `!!`
2349operator:
Bram Moolenaar63f32602022-06-09 20:45:54 +01002350 true: `!!'text'` `!![99]` `!!{'x': 1}` `!!99`
2351 false: `!!''` `!![]` `!!{}`
Bram Moolenaar4f4d51a2020-10-11 13:57:40 +02002352
2353From a language like JavaScript we have this handy construct: >
2354 GetName() || 'unknown'
2355However, this conflicts with only allowing a boolean for a condition.
2356Therefore the "??" operator was added: >
2357 GetName() ?? 'unknown'
2358Here you can explicitly express your intention to use the value as-is and not
2359result in a boolean. This is called the |falsy-operator|.
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002360
2361
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002362Import and Export ~
2363
2364A problem of legacy Vim script is that by default all functions and variables
2365are global. It is possible to make them script-local, but then they are not
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002366available in other scripts. This defies the concept of a package that only
2367exports selected items and keeps the rest local.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002368
Bram Moolenaar3d1cde82020-08-15 18:55:18 +02002369In Vim9 script a mechanism very similar to the JavaScript import and export
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002370mechanism is supported. It is a variant to the existing `:source` command
2371that works like one would expect:
2372- Instead of making everything global by default, everything is script-local,
Bram Moolenaar63f32602022-06-09 20:45:54 +01002373 some of these are exported.
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002374- When importing a script the symbols that are imported are explicitly listed,
2375 avoiding name conflicts and failures if functionality is added later.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002376- The mechanism allows for writing a big, long script with a very clear API:
Bram Moolenaar63f32602022-06-09 20:45:54 +01002377 the exported functions, variables and classes.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002378- By using relative paths loading can be much faster for an import inside of a
2379 package, no need to search many directories.
Bram Moolenaar63f32602022-06-09 20:45:54 +01002380- Once an import has been used, its items are cached and loading it again is
2381 not needed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002382- The Vim-specific use of "s:" to make things script-local can be dropped.
2383
Bram Moolenaar63f32602022-06-09 20:45:54 +01002384When sourcing a Vim9 script (from a Vim9 or legacy script), only the items
2385defined globally can be used, not the exported items. Alternatives
2386considered:
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002387- All the exported items become available as script-local items. This makes
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002388 it uncontrollable what items get defined and likely soon leads to trouble.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002389- Use the exported items and make them global. Disadvantage is that it's then
2390 not possible to avoid name clashes in the global namespace.
2391- Completely disallow sourcing a Vim9 script, require using `:import`. That
2392 makes it difficult to use scripts for testing, or sourcing them from the
2393 command line to try them out.
Bram Moolenaar63f32602022-06-09 20:45:54 +01002394Note that you CAN also use `:import` in legacy Vim script, see above.
Bram Moolenaar65e0d772020-06-14 17:29:55 +02002395
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002396
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002397Compiling functions early ~
2398
2399Functions are compiled when called or when `:defcompile` is used. Why not
2400compile them early, so that syntax and type errors are reported early?
2401
2402The functions can't be compiled right away when encountered, because there may
2403be forward references to functions defined later. Consider defining functions
2404A, B and C, where A calls B, B calls C, and C calls A again. It's impossible
2405to reorder the functions to avoid forward references.
2406
2407An alternative would be to first scan through the file to locate items and
2408figure out their type, so that forward references are found, and only then
2409execute the script and compile the functions. This means the script has to be
2410parsed twice, which is slower, and some conditions at the script level, such
2411as checking if a feature is supported, are hard to use. An attempt was made
Bram Moolenaar63f32602022-06-09 20:45:54 +01002412to see if it works, but it turned out to be impossible to make work well.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002413
2414It would be possible to compile all the functions at the end of the script.
2415The drawback is that if a function never gets called, the overhead of
2416compiling it counts anyway. Since startup speed is very important, in most
2417cases it's better to do it later and accept that syntax and type errors are
2418only reported then. In case these errors should be found early, e.g. when
Bram Moolenaar63f32602022-06-09 20:45:54 +01002419testing, a `:defcompile` command at the end of the script will help out.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002420
2421
Bram Moolenaar63f32602022-06-09 20:45:54 +01002422Why not use an existing embedded language? ~
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002423
2424Vim supports interfaces to Perl, Python, Lua, Tcl and a few others. But
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002425these interfaces have never become widely used, for various reasons. When
2426Vim9 was designed a decision was made to make these interfaces lower priority
2427and concentrate on Vim script.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002428
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002429Still, plugin writers may find other languages more familiar, want to use
2430existing libraries or see a performance benefit. We encourage plugin authors
Bram Moolenaar63f32602022-06-09 20:45:54 +01002431to write code in any language and run it as an external process, using jobs
2432and channels. We can try to make this easier somehow.
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002433
2434Using an external tool also has disadvantages. An alternative is to convert
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002435the tool into Vim script. For that to be possible without too much
2436translation, and keeping the code fast at the same time, the constructs of the
2437tool need to be supported. Since most languages support classes the lack of
Bram Moolenaar1c6737b2020-09-07 22:18:52 +02002438support for classes in Vim is then a problem.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002439
Bram Moolenaar1d59aa12020-09-19 18:50:13 +02002440
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002441
Christian Brabandtec6e82a2025-03-06 21:01:26 +01002442 vim:tw=78:ts=8:noet:ft=help:norl: