Vim9 script feature-complete

1,724 views
Skip to first unread message

Bram Moolenaar

unread,
Dec 30, 2021, 3:39:55 PM12/30/21
to vim_an...@googlegroups.com, vim...@googlegroups.com, vim...@googlegroups.com, vim...@googlegroups.com

[it appears this message did not reach the list, sending it again]

The work on Vim9 script is coming to a point where the syntax and
semantics are practially done. There might be some more tests
uncovering problems that need to be fixed and perhaps some tiny tweaks,
but otherwise it has been quite stable for the past months.

If you have remarks on something in Vim9 script that you think should be
different, speak up now! Soon we'll only make backwards compatible
changes to avoid breaking existing plugins.

The information about Vim9 script and many of the choices made can be
found in a recent build with ":help vim9". Or see it online (without
concealing): https://github.com/vim/vim/blob/master/runtime/doc/vim9.txt

In a few days I will add the "vim9script" feature, so that plugins can
check for Vim9 script being supported and rely on it working. From that
moment Vim9 script needs to be backwards compatible!

This is not the end, I plan to add more features later. But these will
be backwards compatible. That is why some commands such as "class" and
"interface" have been reserved for future use.

I will now work on including remarks about the Vim9 syntax throughout
the help text.

--
hundred-and-one symptoms of being an internet addict:
115. You are late picking up your kid from school and try to explain
to the teacher you were stuck in Web traffic.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Wei Zhang

unread,
Dec 31, 2021, 2:53:35 AM12/31/21
to vim_dev

any chance to remove the space compulsory in vim9 ??

Vim9 script enforces proper use of white space.  This is no longer allowed: >
        var name=234        # Error!
        var name= 234        # Error!
        var name =234        # Error!
There must be white space before and after the "=": >
        var name = 234        # OK

Bram Moolenaar

unread,
Dec 31, 2021, 6:35:37 AM12/31/21
to vim...@googlegroups.com, Wei Zhang

Wei Zhang wrote:

> any chance to remove the space compulsory in vim9 ??
>
> Vim9 script enforces proper use of white space. This is no longer allowed:
> >
> var name=234 # Error!
> var name= 234 # Error!
> var name =234 # Error!
> There must be white space before and after the "=": >
> var name = 234 # OK

This was an intentional choice. It may look a bit strict, but you will
eventually appreciate that scripts are easier to read. If the three
forms above would be allowed then you end up with a mix of them, making
scripts less uniform and taking a bit longer to spot the structure.

--
You're as much use as a condom machine at the Vatican.
-- Rimmer to Holly in Red Dwarf 'Queeg'

Wei Zhang

unread,
Dec 31, 2021, 7:03:50 AM12/31/21
to vim_dev
fair enough, thanks.

Bram Moolenaar

unread,
Jan 3, 2022, 6:04:36 AM1/3/22
to vim...@googlegroups.com, Lifepillar, vim...@googlegroups.com, vim...@googlegroups.com

> ["Followup-To:" header set to gmane.editors.vim.]
> On 2021-12-30, Bram Moolenaar <Br...@moolenaar.net> wrote:
> > The work on Vim9 script is coming to a point where the syntax and
> > semantics are practially done. There might be some more tests
> > uncovering problems that need to be fixed and perhaps some tiny tweaks,
> > but otherwise it has been quite stable for the past months.
> >
> > If you have remarks on something in Vim9 script that you think should be
> > different, speak up now! Soon we'll only make backwards compatible
> > changes to avoid breaking existing plugins.
>
> There was a thread about this on HN a few days ago, and one of the
> comments suggested to reverse the import syntax so that the imported
> script is named first and the imported entities next. A rationale for
> this is that it would help automatic completion.

Is there another language that works like this? The current syntax
resembles Javascript, which hopefully some users are familiar with.

> Personally, the thing I still miss is custom types. But that falls into
> the category of features to be added when Vim9 script is frozen,
> I guess. Other than that, I am really enjoying Vim9 script!

Defining types is planned to be added later. It can build on top of
what we have without changing it. I expect it to be quite a bit of work
to get right, which is why I want to do it later. Otherwise Vim9 will
never be launched.

--
hundred-and-one symptoms of being an internet addict:
198. You read all the quotes at Netaholics Anonymous and keep thinking
"What's wrong with that?"

Marvin Renich

unread,
Jan 3, 2022, 8:19:39 AM1/3/22
to vim...@googlegroups.com, vim...@googlegroups.com, Lifepillar, vim...@googlegroups.com
* Bram Moolenaar <Br...@moolenaar.net> [220103 07:07]:
>
> > On 2021-12-30, Bram Moolenaar <Br...@moolenaar.net> wrote:
> > > If you have remarks on something in Vim9 script that you think should be
> > > different, speak up now! Soon we'll only make backwards compatible
> > > changes to avoid breaking existing plugins.
> >
> > There was a thread about this on HN a few days ago, and one of the
> > comments suggested to reverse the import syntax so that the imported
> > script is named first and the imported entities next. A rationale for
> > this is that it would help automatic completion.
>
> Is there another language that works like this? The current syntax
> resembles Javascript, which hopefully some users are familiar with.

I have to agree that putting the file being imported first is much
better.

In Go, by default every imported identifier must be prefixed by the
package name, much like the current Vim9 "as" clause. Requiring an "as"
clause (or defaulting to some form of the script name for the value of
the "as" clause), and requiring that all imported identifiers be
prefixed by this identifier make the code _much_ clearer and easier to
follow.

I very much dislike the JavaScript style where importing, by default,
places the imported names in the current namespace rather than in a
separate namespace (identified by the "as" clause in Vim9).

Given that even when you are only importing one identifier from a
script, the whole script must be read and executed, I think the Go way
is better. Don't bother with the

import MyClass from "myclass.vim"
import {someValue, MyClass} from "thatscript.vim"

syntax, and only provide

import "myclass.vim"
import "myclass.vim" as Other

and require use of the namespace prefix:

Other.MyClass

The first case, without the "as" would default to the file name, with
leading directories and trailing ".vim" removed, and with the first
letter capitalized. Non-identifier characters and leading digits would
be removed as well. In the case without "as" above, you would reference
the imported MyClass identifier as

Myclass.MyClass

With this, every use of an imported identifier is clear and explicit.

...Marvin

Bram Moolenaar

unread,
Jan 3, 2022, 9:14:17 AM1/3/22
to vim...@googlegroups.com, Marvin Renich, vim...@googlegroups.com, Lifepillar, vim...@googlegroups.com
I have to agree that the Javascript way is a bit complicated and
verbose. Especially the "* as SomeName" part is not optimal:
import * as funcs from "./subdir/myfunctioncollection.vim"
Now "funcs" is somewhere in the middle of the line.
This form might actually be the most common use.

Not mentioning the items being imported has the disadvantage that it's
harder to find out what is used from the imported script. But that
might not be very important. You can always use "*" on the name to see
what's being used.

File names are often longer, thus the "import as" style can be expected
to be used quite a lot. Example:

import "./subdir/myfunctioncollection.vim" as funcs
funcs.DoSomething()

The main disadvantage is that the prefix must always be used, there is
no way to use an imported item without it. But as you mention, this can
also be seen as an advantage, that it's clear it is not defined in this
script file.

I hope others give there opinion, this is an important choice.

--
$ echo pizza > /dev/oven

Bram Moolenaar

unread,
Jan 3, 2022, 12:33:29 PM1/3/22
to vim...@googlegroups.com, Lifepillar, vim...@googlegroups.com, vim...@googlegroups.com

> On 2022-01-03, Marvin Renich <mr...@renich.org> wrote:
> > Don't bother with the
>
> > import MyClass from "myclass.vim"
> > import {someValue, MyClass} from "thatscript.vim"
> >
> > syntax, and only provide
> >
> > import "myclass.vim"
> > import "myclass.vim" as Other
> >
> > and require use of the namespace prefix:
> >
> > Other.MyClass
> >
> > The first case, without the "as" would default to the file name, with
> > leading directories and trailing ".vim" removed
>
> I do not think that using a filename as an identifier is a good idea.
> For instance, calling a script 1.vim would automatically make it
> non-importable (without "as").

Since a script needs to use "export" to be able to be imported, having
to use a nice name for the script is clearly needed. The only thing is
that it may be a long name to avoid name collisions, but then the "as
{name}" form can be used to shorten the name.

> I personally find that using an imported name without a prefix (as it is
> currently possible) makes my code terse, and I think that in the limited
> scope a plugin that works well. But I understand that Vim9 scripts might
> have a broader use, such as generic libraries of functions that can be
> used by many scripts. In that context, stricter scoping rules, such as
> in Go, are likely a cleaner approach.
>
> How about always requiring a prefix, but allowing explicit namespace
> pollution? As in
>
> import "myclass.vim" as Other
> use Other # Makes Other.F() available as just F()

Throwing everything from "Other" into the current namespace is going to
cause trouble, because someone may add an item to myclass.vim that
conflicts with what is in your script. Thus extending one script may
break another script, that is bad.

A kind of an alias mechanism would work. Since most of the items are
going to be functions, might as well use a function reference:

final Func = Other.Func

That's an existing mechanism, thus keeps things simple.

It also works for constants and read-only variables:

const MAX = Other.MAX_VALUE

This does not work for variables that can be set, but you should
probably use a setter function for that anyway.

I'm just pointing out what valid pro's and con's are, I'm not suggesting
this means the alternate import syntax is best.

--
hundred-and-one symptoms of being an internet addict:
208. Your goals for the future are obtaining a second Gbit connection
and upgrade your NAS to all SSD

Marvin Renich

unread,
Jan 4, 2022, 12:03:54 PM1/4/22
to vim...@googlegroups.com, vim...@googlegroups.com, vim...@googlegroups.com
* Bram Moolenaar <Br...@moolenaar.net> [220103 12:33]:
> > On 2022-01-03, Marvin Renich <mr...@renich.org> wrote:
> > > Don't bother with the
> >
> > > import MyClass from "myclass.vim"
> > > import {someValue, MyClass} from "thatscript.vim"
> > >
> > > syntax, and only provide
> > >
> > > import "myclass.vim"
> > > import "myclass.vim" as Other
> > >
> > > and require use of the namespace prefix:
> > >
> > > Other.MyClass
> > >
> > > The first case, without the "as" would default to the file name, with
> > > leading directories and trailing ".vim" removed
> >
> > I do not think that using a filename as an identifier is a good idea.
> > For instance, calling a script 1.vim would automatically make it
> > non-importable (without "as").

I agree that using the (cleansed) file name is suboptimal, but it was
the simplest choice. There are a couple other possibilities. One is to
require the "as" clause.

Another is to do something similar to Go (a language I like, if you
couldn't tell :-) ). Every Go source file has a package statement,
«package frob», and when importing, this package identifier, «frob», is
used as the prefix (if not overridden in the import statement).

Every vim9 script file already has a vim9script statement. You could
say that in order for the script to be imported the vim9script statement
must be of the form «vim9script ScriptId» where ScriptID must be a
capitalized identifier. If you import two different scripts with the
same script ID, you must use the "as" clause for at least one of them.

Alternatively, you could require either the script ID on the vim9script
statement or the "as" clause on the import statement.

> Since a script needs to use "export" to be able to be imported, having
> to use a nice name for the script is clearly needed. The only thing is
> that it may be a long name to avoid name collisions, but then the "as
> {name}" form can be used to shorten the name.
>
> > I personally find that using an imported name without a prefix (as it is
> > currently possible) makes my code terse, and I think that in the limited
> > scope a plugin that works well.

My opinion is the opposite, here. Even in small, simple scripts, the
prefix makes the code more readable; there is no question from where the
identifier came.

> > But I understand that Vim9 scripts might
> > have a broader use, such as generic libraries of functions that can be
> > used by many scripts. In that context, stricter scoping rules, such as
> > in Go, are likely a cleaner approach.
> >
> > How about always requiring a prefix, but allowing explicit namespace
> > pollution? As in
> >
> > import "myclass.vim" as Other
> > use Other # Makes Other.F() available as just F()

I like this very much; it works regardless of how the prefix gets
defined ("as" clause, vim9script statement, or cleansed filename).

I think if I had to pick, I would require the "as" clause. It is
simple, and doesn't depend on the script author keeping the same script
ID with newer versions of the script. The author of the script doing
the importing is required to be in control.

> Throwing everything from "Other" into the current namespace is going to
> cause trouble, because someone may add an item to myclass.vim that
> conflicts with what is in your script. Thus extending one script may
> break another script, that is bad.

This is probably the best reason to not allow blindly importing all
identifiers from one script into the local namespace of another.

...Marvin

Bram Moolenaar

unread,
Jan 4, 2022, 12:26:07 PM1/4/22
to vim...@googlegroups.com, Marvin Renich, vim...@googlegroups.com, vim...@googlegroups.com
Adding a script ID adds another mechanism and I don't see enough
advantage in it. It raises questions, such as what happens if two
completely unrelated plugins use the same ID?

Since the import can use a relative file name, a short file name can
work. It's only when using a file name in 'runtimepath' that we can
expect the name to be longer. Thus requiring the use of "as" up front
does not seem necessary.

> > Since a script needs to use "export" to be able to be imported, having
> > to use a nice name for the script is clearly needed. The only thing is
> > that it may be a long name to avoid name collisions, but then the "as
> > {name}" form can be used to shorten the name.
> >
> > > I personally find that using an imported name without a prefix (as it is
> > > currently possible) makes my code terse, and I think that in the limited
> > > scope a plugin that works well.
>
> My opinion is the opposite, here. Even in small, simple scripts, the
> prefix makes the code more readable; there is no question from where the
> identifier came.

Right. Somehow code writers can be very lazy typing things, and then
spend lots of time (possibly much later) figuring out what the code is
doing. Unfortunately I'm not aware of any studies being done on this
(it's more computer art than computer science).

> > > But I understand that Vim9 scripts might
> > > have a broader use, such as generic libraries of functions that can be
> > > used by many scripts. In that context, stricter scoping rules, such as
> > > in Go, are likely a cleaner approach.
> > >
> > > How about always requiring a prefix, but allowing explicit namespace
> > > pollution? As in
> > >
> > > import "myclass.vim" as Other
> > > use Other # Makes Other.F() available as just F()
>
> I like this very much; it works regardless of how the prefix gets
> defined ("as" clause, vim9script statement, or cleansed filename).
>
> I think if I had to pick, I would require the "as" clause. It is
> simple, and doesn't depend on the script author keeping the same script
> ID with newer versions of the script. The author of the script doing
> the importing is required to be in control.
>
> > Throwing everything from "Other" into the current namespace is going to
> > cause trouble, because someone may add an item to myclass.vim that
> > conflicts with what is in your script. Thus extending one script may
> > break another script, that is bad.
>
> This is probably the best reason to not allow blindly importing all
> identifiers from one script into the local namespace of another.

I'm starting to more and more like the idea of the simplistic import. The
main reason is that the Javascript way suggests that it is possible to
import individual items from a script, which in reality the whole script
is read, while some items can't be adressed.

Also since it's possible to do this:

import FuncOne from "thatscript.vim"
import FuncTwo from "thatscript.vim"
import FuncThree from "thatscript.vim"

This doesn't actually load the script three times, but you'll have to do
digging in the help to know that. Thus there is some hidden knowledge.
It can be written as:

import {FuncOne, FuncTwo, FuncThree} from "thatscript.vim"

Which turns it into a one-liner, but adds the need for a syntax that
isn't used anywhere else.

While using:

import "thatscript.vim"

Or:

import "thatscript.vim" as that

Is nice and short, no need for "from". The help for ":import" becomes
much shorter. The implementation will also be much simpler.

The discussion about the need for using the prefix, whether "as" should
be required and other things, seem less important.

--
A scientist is someone who knows exactly how an engine works, but
can't fix his car when it fails to start.
An engineer is someone who knows only some things about an engine, but
can fix his car when it's broken.

Marvin Renich

unread,
Jan 4, 2022, 12:54:51 PM1/4/22
to vim...@googlegroups.com, vim...@googlegroups.com
* Bram Moolenaar <Br...@moolenaar.net> [220104 12:26]:
> Marvin Renich wrote:
> > * Bram Moolenaar <Br...@moolenaar.net> [220103 12:33]:
[snip]
> > I agree that using the (cleansed) file name is suboptimal, but it was
> > the simplest choice. There are a couple other possibilities. One is to
> > require the "as" clause.
[snip]
> > Every vim9 script file already has a vim9script statement. You could
> > say that in order for the script to be imported the vim9script statement
> > must be of the form «vim9script ScriptId» where ScriptID must be a
> > capitalized identifier. If you import two different scripts with the
> > same script ID, you must use the "as" clause for at least one of them.
> >
> > Alternatively, you could require either the script ID on the vim9script
> > statement or the "as" clause on the import statement.
>
> Adding a script ID adds another mechanism and I don't see enough
> advantage in it. It raises questions, such as what happens if two
> completely unrelated plugins use the same ID?

Yes, the more I think about this, the more I like requiring "as" and
requiring using the prefix.

> Since the import can use a relative file name, a short file name can
> work. It's only when using a file name in 'runtimepath' that we can
> expect the name to be longer. Thus requiring the use of "as" up front
> does not seem necessary.

Then we would be back to cleansing the filename. I was the one who
originally suggested that, but I think that was not a great idea.
Require "as" (with Capitalized identifier), and require using that
identifier as prefix.

> > > > I personally find that using an imported name without a prefix (as it is
> > > > currently possible) makes my code terse, and I think that in the limited
> > > > scope a plugin that works well.
> >
> > My opinion is the opposite, here. Even in small, simple scripts, the
> > prefix makes the code more readable; there is no question from where the
> > identifier came.
>
> Right. Somehow code writers can be very lazy typing things, and then
> spend lots of time (possibly much later) figuring out what the code is
> doing. Unfortunately I'm not aware of any studies being done on this
> (it's more computer art than computer science).

I think this agrees with requiring both "as" and using the prefix.
Actually, I think the local namespace pollution is the more important
issue, and requiring "as" and the prefix gives the simpler import syntax
as an added benefit.

...Marvin

Devin Weaver

unread,
Jan 6, 2022, 9:43:49 AM1/6/22
to vim_dev
Bram, Thank you for all the hard work you do. I think the choices you’ve made have been good trade-offs. You are a superstar!

Manuel Ortega

unread,
Jan 7, 2022, 2:01:39 PM1/7/22
to vim_dev
I very much hope that one thing will be changed.  Currently '#' only starts a comment when it's followed by a space, if I understand correctly.  Please make it instead behave like almost every other language that uses '#' as a comment character, and *don't* require that it be followed by a space.

The choice of '"' as the comment character in vimscript of course proved a bit awkward, but forcing it to be '#<space>' rather than '#' is even worse IMO.

I note that if you look in the dictionary of comment characters found inside the popular NerdCommenter plugin, there are exactly ZERO entries for which '#<space>' is mandatory.  There are five entries that indicate a style preference for '#<space>' but allow '#'.  And there are 134 entries for which '#', with no following space, is a comment character.  (For 125 of these 134, that's the primary or sole comment character).

If one of the goals of vim9script is to be more like what a user expects, then '#' and not '#<space>' should be the comment-starter.

-Manny

Bram Moolenaar

unread,
Jan 7, 2022, 3:01:49 PM1/7/22
to vim...@googlegroups.com, Manuel Ortega
Where do you read that there must be a space after the #?

There is the requirement that there is space before it, or it is at the
start of the line.
Otherwise it could be confused with an autoload script item.

--
hundred-and-one symptoms of being an internet addict:
250. You've given up the search for the "perfect woman" and instead,
sit in front of the PC until you're just too tired to care.

Manuel Ortega

unread,
Jan 12, 2022, 12:55:41 PM1/12/22
to vim_dev
On Friday, January 7, 2022 at 2:01:49 PM UTC-6 Bram Moolenaar wrote:

Manuel Ortega wrote:

> I very much hope that one thing will be changed. Currently '#' only starts
> a comment when it's followed by a space, if I understand correctly. Please
> make it instead behave like almost every other language that uses '#' as a
> comment character, and *don't* require that it be followed by a space.
>
> The choice of '"' as the comment character in vimscript of course proved a
> bit awkward, but forcing it to be '#<space>' rather than '#' is even worse
> IMO.
>
> I note that if you look in the dictionary of comment characters found
> inside the popular NerdCommenter plugin, there are exactly ZERO entries for
> which '#<space>' is mandatory. There are five entries that indicate a
> style preference for '#<space>' but allow '#'. And there are 134 entries
> for which '#', with no following space, is a comment character. (For 125
> of these 134, that's the primary or sole comment character).
>
> If one of the goals of vim9script is to be more like what a user expects,
> then '#' and not '#<space>' should be the comment-starter.

Where do you read that there must be a space after the #?

Ah, it seems I misremembered the details.  But my point remains pretty much the same.  I'd said it was unexpected for the comment char of vim9script to be '#<space>'; it's at least as unexpected for it to be '<space>#', and even more unexpected for it to be "'<space>#', unless it's the start of the line".  That makes things worse than the old way, not better.

Otherwise it could be confused with an autoload script item.

Then the right thing to do would be to change the autoload syntax to not use '#'.  The main point of vim9script is to break backwards compatibility to "fix" stuff, right?  I would say having a normal and sensible comment-char, after all these years of an awkward one, it more important than keeping the autoload syntax the same.

And it definitely doesn't behave more like other langs (which seems to be one of vim9's goals).  '#' in bash, ruby, etc. don't require a space beforehand.  There are ZERO entries in the aforementioned NerdCommenter dictionary for '<space>#'.

-Manny

Bram Moolenaar

unread,
Jan 12, 2022, 3:27:55 PM1/12/22
to vim...@googlegroups.com, Manuel Ortega
Although the shell accepts "anything#comment", I have seen many style
guides that do require a space before the "#". And some companies
require it (presubmit check).

I can't think of an alternative for "#" that would work better.


--
GALAHAD: No. Look, I can tackle this lot single-handed!
GIRLS: Yes, yes, let him Tackle us single-handed!
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

Doug Kearns

unread,
Jan 15, 2022, 7:25:48 AM1/15/22
to vim...@googlegroups.com
On Thu, 13 Jan 2022 at 04:55, Manuel Ortega <manny...@gmail.com> wrote:

> Ah, it seems I misremembered the details. But my point remains pretty much the same. I'd said it was unexpected for the comment char of vim9script to be '#<space>'; it's at least as unexpected for it to be '<space>#', and even more unexpected for it to be "'<space>#', unless it's the start of the line". That makes things worse than the old way, not better.

Is this a practical problem?

A quick search of my system suggests that tail comments are very
rarely used without leading whitespace. The primary counter example
being the idiomatic use of ;# in Tcl.

Most, maybe all, of the other cases I came across are exceptions to
the predominant style of the file.

Doug

Niklas Lindström

unread,
Jan 15, 2022, 8:31:57 AM1/15/22
to vim...@googlegroups.com
I agree. Also, at least in bash [1] a leading space is required in
most if not all cases (apart from start of line), i.e. just as in
vim9script. As a practical example of why that is (or what that
enables), the cURL CLI has a progress bar option called -# [2]:

$ curl -# -O https://example.com/coolfile.tar.gz

All the best,
Niklas

[1]: https://tldp.org/LDP/abs/html/special-chars.html
[2]: https://daniel.haxx.se/blog/2018/01/22/a-flying-curl-progress-bar/
Reply all
Reply to author
Forward
0 new messages