Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make command-line execute vim9script without typing vim9cmd #14785

Closed
girishji opened this issue May 16, 2024 · 36 comments
Closed

Make command-line execute vim9script without typing vim9cmd #14785

girishji opened this issue May 16, 2024 · 36 comments
Labels
enhancement vim9script Vim9 script related issues

Comments

@girishji
Copy link
Contributor

Is your feature request about something that is currently impossible or hard to do? Please describe the problem.

In order to execute vim9script in command-line it has to be prefixed with vim9cmd. Even then it does not allow declaring new variables in vim9script.

Describe the solution you'd like

Perhaps an option can be set such that command-line switches from interpreting legacy script to vim9script.

Describe alternatives you've considered

None exist, other than cumbersome vim9cmd.

It would be convenient to have command-line provide first-class support to vim9script.

@k-takata k-takata added the vim9script Vim9 script related issues label May 16, 2024
@chrisbra
Copy link
Member

Even then it does not allow declaring new variables in vim9script.

Well, I just tried :vim9cmd g:var='foobar' and this works, may be it works different for Dicts or Lists, not sure.

Describe alternatives you've considered

I am not so convinced that this is good suggestion. I think we should rather keep one consistent way for the commandline and not introduce a second method to enter commands (with different syntax and semantics). For command line use, I often don't even adhere to the recommended style guide like adding spaces around assignments, etc. I am rather sloppy there :/

In any case, have you tried the following workaround?

au CmdlineEnter : :call setcmdline('vim9cmd ')

@ubaldot
Copy link
Contributor

ubaldot commented May 16, 2024

I was victime of the same annoyance and this trick is very nice! :)

@lifepillar
Copy link
Contributor

lifepillar commented May 16, 2024

Let's say I have a function F() and a public var x: bool in an autoload script foo.vim. In legacy Vim the function and the variable can be accessed from the command line:

:call foo#F()
:let foo#x = 1

Is there a way to use Vim 9 script syntax for those? The obvious:

:vim9cmd foo.F()
:vim9cmd foo.x = true

fail with Undefined variable: foo.

@girishji
Copy link
Contributor Author

girishji commented May 17, 2024

I cannot declare a variable this way:

:vim9cmd var foo = 0

I get:

E1079: Cannot declare a variable on the command line

But this works:

:let foo = 0

Are variables declared inside the command-line automatically scoped as global variables? If so, a similar mechanism may apply to Vim9 script variables, allowing us to avoid prefixing each variable with g:.

I am not so convinced that this is good suggestion. I think we should rather keep one consistent way for the commandline and not introduce a second method to enter commands (with different syntax and semantics).

We already have a second method with different syntax and semantics when one types :vim9cmd. Legacy script users will not be affected if there is a :set vim9cmdline option that is unset by default.

In my view, Vim9 script is the last great gift Bram left us. It goes without saying that vim9script is more 'user-friendly' compared to the suboptimal legacy script. New users are more likely to adopt Vim9 script if they don’t have to type :vim9cmd in the command line. Workarounds (that insert :vim9cmd) do not weaken this argument.

@chrisbra
Copy link
Member

I cannot declare a variable this way:

:vim9cmd var foo = 0

I get:

E1079: Cannot declare a variable on the command line

But this works:

:let foo = 0

Yes, that's because :let foo=0 automatically assigns global scope. I think you have to prefix the (global) scope to the variable to make it work then.

Regarding the other stuff, I am unsure if we should change it. Let's see what other people think.

@ubaldot
Copy link
Contributor

ubaldot commented May 17, 2024

My opinion: the idea of having an option vim9cmdline which is unset by default is nice, robust and shouldn't break anything. Regarding setting script-scoped variables from the command line: does it make sense? What would be the script where they are visible if they are defined in the command line?

@girishji
Copy link
Contributor Author

Regarding setting script-scoped variables from the command line: does it make sense?

Are you referring to lifepillar's reply? If so, one application is to customize a plugin through command-line by directly manipulating its options (maybe for testing).

@girishji
Copy link
Contributor Author

girishji commented May 17, 2024

Regarding the other stuff, I am unsure if we should change it. Let's see what other people think.

There is only upside to my proposal. Introducing :set vim9cmdline ensures seamless integration for users of legacy script while providing a modern experience for new users. New users need not have to bother with legacy script if they've learned vim9 script, and would like to use it for non-trivial tasks in the command-line.

Aside: The au CmdlineEnter workaround is not ideal. For example, using <C-u> to clear the command line also removes the vim9cmd, so it has to be typed again. This shows the need for a more robust solution like :set vim9cmdline.

@chrisbra
Copy link
Member

chrisbra commented May 17, 2024

There is only upside to my proposal.

Not really, there are at least 2 issues I can see right now:

  • it's a UI/UX issue and
  • every option value brings maintenance burden. We have to test and ensure commandline features works correctly with and without :set vim9cmdline.

For the UI issue that means, people will ask questions or send bug report and we will have to check the vim9cmdline setting. Or they may ask why the comamnd line behaves differently after copying an option value from some random page on a website.

I am just trying to weight the benefits vs the costs and I have no opinion yet. That's why I am asking for more opinions.

Aside: The au CmdlineEnter workaround is not ideal. For example, using to clear the command line also removes the vim9cmd. This shows the need for a more robust solution like :set vim9cmdline.

Well, it's a workaround. I actually find it quite convenient, that it clears the vim9cmd as well, so I don't have to do it manually, different expectations I guess.

@yegappan
Copy link
Member

Vim9 simplified the language by not supporting the command-line use and supporting only the script level use. For example, in a legacy script the :let command is used for variable assignment and in the command-line, it is simple to detect these assignments as they start with the let command. In a Vim9script, variables and their types are declared using the :var command, but variable assignment don't have a command prefix. In a command-line, supporting this will be difficult as we need to differentiate between regular Vim commands and variable assignments. Also, in Vim9, the variables are script local by default. In a command-line, the variables need to be global.

Also, as Chrisitan mentioned in his comment, making this an option will confuse users (as some commands they saw in a forum will not work depending on the option setting).

@zzzyxwvut
Copy link
Contributor

If :set vim9cmdline were supported, how can a user know
which syntax is currently on? Is there additional room for
-- VIM9 -- or similar but a more compact label, after the
fashion of modal cues like -- INSERT --? I would very much
like to not remember what syntax context is valid when I try
things in a variety of Vim builds.

Why would global variables defined in Vim9 syntax enjoy the
privilege of not being prefixed with g: on the command
line?

In short, I don't mind typing :vim9cmd or :vim9c<TAB>.

@ubaldot
Copy link
Contributor

ubaldot commented May 17, 2024

I think I see both the points and I understand how annoying is to write :vim9cmd while developing plugins (I tend to use the command window when developing, if it may help :) )

But I have something else that is rolling behind my head right now: from a business perspective I have never seen any company (profit or non-profit) that come out with a new version of an existing product and then push for the old version because otherwise users could get confused. This has nothing to do with retro-compatibility which in-fact, is there, alive and kicking ;-).
I think we should push Vim9 more. People will get used to it. Certainly at the beginning we will have a burst of questions but they will gravitate around the root question: "Why this does not work?". All these questions belong to the same equivalence class, which means that the answer will be always the same. That is, one million of questions will get one million of times the same answer to the point that such an answer will become the "standard" answer, easily searchable and that everybody will know. This will also feed all these chat-gpt-ish-things that will learn to (somehow) convert scripts, or at least to give a trace. I honestly only foresee a chaotic yet well manageable transient in pushing Vim9script more. I noticed that I am unconsciously doing it already. From my side all the plugins I wrote are in Vim9 and therefore all the docs, snippet, config I give is Vim9. And I don't have any intention at all to write them in legacy vim. If someone bump into some problems, they ask and I will answer. Easy-peasy (yes, I know that the number of user is not even remotely comparable, but it won't change the approach). :) if someone download Vim9, then he/she gets Vim9. Period.

Otherwise, what is the plan to make Vim9 to takeoff if we don't push it? Or the plan is to make plugin developers to use Vim9 but users to stick to vim legacy? I am genuinely curious :)

Note that for my specific case is not a big deal one way or the other, but given that different opinions have been requested here are my 2 cents :)

@girishji
Copy link
Contributor Author

girishji commented May 17, 2024

Vim9 simplified the language by not supporting the command-line use and supporting only the script level use. For example, in a legacy script the :let command is used for variable assignment and in the command-line, it is simple to detect these assignments as they start with the let command. In a Vim9script, variables and their types are declared using the :var command, but variable assignment don't have a command prefix. In a command-line, supporting this will be difficult as we need to differentiate between regular Vim commands and variable assignments.

I was under the impression that supporting vim9script vs legacy script is a matter of switching the parser when parsing command line. At any time, only one language is supported. Does parsing text in command-line (before execution) follow a different mechanism than the parser used to parse script files?

Also, in Vim9, the variables are script local by default. In a command-line, the variables need to be global.

Requiring users to type g: each time they declare a variable adds some friction but is not a critical issue. It can be addressed at a later time since it needs some thought.

@girishji
Copy link
Contributor Author

girishji commented May 17, 2024

Otherwise, what is the plan to make Vim9 to takeoff if we don't push it? Or the plan is to make plugin developers to use Vim9 but users to stick to vim legacy? I am genuinely curious :)

I sympathize with this view. I use Vim9 script and have avoided learning the legacy script because it is not user-friendly. Typing let/call for variable declaration, assignment, and function call is cumbersome, and that's just the beginning of its complexities. There's a reason someone wrote a book titled Learn Vim Script the Hard Way, not the Easy Way. I wish there were more concerted efforts to encourage new users to learn Vim9 script and steer them away from the legacy script. The legacy script needs to slowly lose relevance and become truly legacy.

@lifepillar
Copy link
Contributor

Requiring users to type g: each time they declare a variable adds some friction but is not a critical issue

I'd say it's not an issue at all. In Vim 9 script, prependingg: to reference the global scope is mandatory. I'd expect Vim 9 script on the command line to follow the same rule.

And I now realize that autoloaded names are not resolved because afaik in VIm 9 script you need import [autoload] to make any name visible.

@lifepillar
Copy link
Contributor

Maybe, a plugin might cover this use case. Proto idea:

vim9script

var cmd = input('> ')
execute 'vim9cmd' cmd

If I run this script and type var x = 42, I don't get an error. Where does that value live, if anywhere?

@chrisbra
Copy link
Member

If I run this script and type var x = 42

Well, I guess it ends up as a script-local variable.

But yes, it sounds like a great project for a new plugin, you could even make it fancy with popup window or so.

In any case, I think nobody here wishes that vim9script does not become successful. I think it is a great scripting language for plugins. I just don't see it that much useful for the commandline, mainly because I am sloppy testing one-off commands and don't adhere to the style guide and the performance advantage is neglectable here.

But for any serious newly written plugins, I definitly would recommend to use vim9script.

@ubaldot
Copy link
Contributor

ubaldot commented May 18, 2024

The idea of developing a plugin with a command window popup could be nice!
That could be a sort of vim interpreter "shell" which I would really like!

Yet, I think there is some misunderstanding on the use-case.
I think the problem @girishji is facing is not related to running a command every once in a while from the command line.
The problem is when developing a plugin or a function. I don't know if @girishji follows the same approach, but what I tend to do is to develop plugins/functions incrementally.

That is, say that I am developing a function Foo() (or a plugin named myplugin.vim). What I do is to develop and test "chunks" of the function/plugin in the command window and once I am satisfied I integrate it in the body of Foo() or in myplugin.vim file and ultimately test them. While working, my command window would look like something like the following:

image

Once I have secured that my chunk of code is doing what I want, then I copy/paste it in Foo() or in myplugin.vim and I test the whole function/plugin. Of course, once copied from the command window to the editor, I shall remove all the vim9cmd and (perhaps) I have to replace that g:A with var myvar. At the end, my Foo() would look like something like the following:

image

The process of removing all those vim9cmd and converting g:A to myvar can be tedious. But defining var myvar in the command window does not make any sense (as long as there is not a hidden support buffer to define the scope of what is defined in the command window).

If it may help, I have the following in my .vimrc to keep the command window always opened:

# For plugin writing
augroup CommandWindowOpen
    autocmd!
    autocmd CmdwinEnter * map <buffer> <cr> <cr>q:
augroup END

That, along with the autocmd suggested by @chrisbra at the beginning, smooth things out quite a lot.
However, I am not sure if what I described is the use-case @girishji was referring though.

@Shane-XB-Qian
Copy link
Contributor

github.com//pull/13670#issuecomment-1857256030

@lifepillar
Copy link
Contributor

I rarely use the command-line during Vim9 script development. I'd rather have a scratch buffer where I type or paste some code, which then I source with :%so, or I can select some text and type :so to execute only that. I only have a mapping for vnew +setl buftype=nofile bufhidden=wipe noswapfile; I don't have streamlined this workflow any further (I could make it so that it automatically inserts vim9script at the top for example, add a mapping for sourcing, for sending code to the buffer, etc.). It seems to me that from this idea a simple plugin could go a long way.

Perhaps, Vim 9 script is an opportunity to start using the command line less. Who knows, maybe the command line will follow the fate of Ex mode eventually.

@ubaldot
Copy link
Contributor

ubaldot commented May 18, 2024

Perhaps I am missing something about the command line, but I use it quite a bit: :copen, :cnext, :3,15norm! $x, :%y, … are just examples. Is there any trend to use the command line less that I am not aware of?

Regarding the scratch buffer: what if you want to step? Shall you define buffer local mappings? Also, with a scratch buffer you lose everything when you close the window. In the command window you have all there… I am just trying to figure out what is the best approach.

@lifepillar
Copy link
Contributor

The comment about getting rid of the command line was a bit tongue in cheek. But the point is that the command line is pretty limited as a means to support script development. Some of the limitations wouldn't go away even if the command line provided better support for Vim 9 script (e.g., limited editing possibilities).

Regarding the scratch buffer: what if you want to step? Shall you define buffer local mappings?

You may certainly do that (you may even do it in your current Vim buffer):

nnoremap <buffer> <leader>x <scriptcmd>execute 'vim9cmd' getline('.')<cr>+

Vim may also be used in debug mode: see :h debug-mode, and :h vim9-debug in particular.

@errael
Copy link
Contributor

errael commented May 18, 2024

with a scratch buffer you lose everything when you close the window

There's :w ;-)

When I'm working on some new vim9 code, I usually have a named file with code and code snippets with a lot of little test cases and/or functions related to what I'm working on. This play file might be used for days, or be revisited after weeks if things don't go as planned or just to review what I've been working on, or what experiments I've tried, over the last...

@vim-ml
Copy link

vim-ml commented May 19, 2024 via email

@ubaldot
Copy link
Contributor

ubaldot commented May 19, 2024

There's :w ;-)

So why create a scratch buffer in first instance? But then, when you write/close and re-open such a buffer what one shall do? Set again the local mappings and the various options? Or shall write some sort of automatism that sets it automatically? If so how? What tradeoff we shall accept if we want that sort of automatism?

Sorry, I may be just aging badly, but just typing q: and having a readily available "vim interpreter" looks much simpler than implementing all the suggested tweaking which, by the way, only accommodate the use-cases that we identified. I am sure that there are other use-cases we didn't think yet whose accommodation would most likely require additional hops. I clearly see potential for a plugin to develop scripts/plugins, but since then, in my world typing q: and get a vim interpreter ready to use looks better in terms of cost-benefits, being the costs to prepend vim9cmd to each line and to use global variables. Another standing benefit that just pop up in my mind is that when I close vim and reopen in from any other location, by typing again q: I can access all the history readily. I don't have to carry around a "support" file or create one in some predefined location.

@lifepillar Still on the command line: thanks for clarifying that there isn't any sort of "phasing out" plan. But limitations of the command line have been also mentioned. I am perhaps missing something on this point as well. Could anyone elaborate a bit more about such limitations?

Other than that, if we go back one second to our initial issue and if I have to express my preference, I would vote for having the command line interpreter set to Vim9 rather than the legacy Vim by default for all the Vim versions > 9.0. :)
The error message if anyone is running a legacy language command may warn the user that this is Vim9 further pointing to some help page for clarifications.

@lifepillar
Copy link
Contributor

Could anyone elaborate a bit more about such limitations?

The command-line and the command-line window are line-oriented.

@errael
Copy link
Contributor

errael commented May 19, 2024

There's :w ;-)

So why create a scratch buffer in first instance? But then, when you write/close and re-open such a buffer what one shall do? Set again the local mappings and the various options? Or shall write some sort of automatism that sets it automatically? If so how? What tradeoff we shall accept if we want that sort of automatism?

Sorry, I may be just aging badly, but just typing q: and having a readily available "vim interpreter" looks much simpler than implementing all the suggested tweaking which, by the way, only accommodate the use-cases that we identified
...

I don't understand all the issues being discussed or exactly what people want to achieve. I never programed legacy vimscript (except a simple .vimrc). I'm not familiar with what may be the usual vim programmer development environment. And when I see a command line window it is a surprise and I wonder how I got there. (I probably won't forget now; and there's also c_CTRL-F, who would have guessed).

My point with the flippant :w comment is that using a play-scratch-file and the :source command is quite flexible. I may not fully grok the problems being discussed, or appreciate all the issues at hand.

when you write/close and re-open such a buffer what one shall do?
Set again the local mappings and the various options?

If the settings/mapping are specific to the development work, they can be in the file.

  • visually highlight the setting/mapping commands in the file
  • :vim9c so

and the highlighted command are executed, the environment should be ready to go. But I'll
typically have what I want at the moment at the top of the file, following by finish and just do
:so. Essentially what #14785 (comment) says.

There's #13156 and #13460 which have some discussion/wishes for vim9 development tools.

In the original post, there's

In order to execute vim9script in command-line it has to be prefixed with
vim9cmd. Even then it does not allow declaring new variables in vim9script.

Using a file, highlight var x = 123, do :vim9c so. I can read the value
back, along with other values similarly set. I can then do var x = 'foo'
which works and is a surprise to me.

I typically run the whole file and don't have much experience with piece wise
execution.

@girishji
Copy link
Contributor Author

girishji commented May 20, 2024

In any case, I think nobody here wishes that vim9script does not become successful. I think it is a great scripting language for plugins. I just don't see it that much useful for the commandline

On the contrary, I do see usefulness in using vim9script in commandline:

  1. Consistency with UTF-8 Handling: While developing a plugin, I encountered an issue where slicing UTF-8 characters worked differently in the command line compared to within a script. For example, evaluating 'aぬば'[1 : 2] yields different results in legacy script versus vim9script due to the use of byte indexing versus character indexing. The situation was a bit more complex and I was scratching my head for a while when uncovering a bug. If the command line always executed vim9script, such annoyances would not have happened. This is just an example, but I have run into similar situations a few times.

  2. Simplified Learning Curve for New Users: New users (I've been using Vim/Neovim for about two years) would benefit from not having to learn the legacy scripting language -- even for command line tasks. The legacy syntax, including the use of let, call, and # inside dictionaries, adds cognitive overload and general weirdness. It does not come naturally to new users, and I cannot impress this enough on veteran Vim users. Workarounds are just band-aid. As I pointed out earlier, <c-u>, <c-b>, or range inside commandline do not work in a useful/ideal manner when you prepend :vim9foo in front of every line. In a subtle way this compels new users to also learn legacy script unnecessarily. Please do not do this.

@girishji
Copy link
Contributor Author

Aside: Please refrain from discussing scratch buffer and other orthogonal stuff.

@zzzyxwvut
Copy link
Contributor

There is nothing special about :vim9cmd, there are other
language commands to boot: :python3, :perl, etc., which
are required for commands of that particular interface.

The proposed vim9cmdline option would be disruptive for it
should render :vim9cmd optional and make :legacy required
with one option setting, and impose the opposite optionality
with another option setting. But what recourse would poor
developers have that may prefer Vim9 and so would opt in,
but also tinker at legacy code now and then? Is the option
on/off? Plugin authors would still begin their files with
vim9script [noclear] when they write it in Vim9 syntax, so
why introducing an exception for command-line mode only?
Currently, you have to advertise it everywhere the kind of
syntax that follows for anything but legacy Vim code.

There is plenty of legacy Vim code under runtime/ that may
or may not be ever rewritten in Vim9 syntax. Who's going
to maintain it in the future if what new users/contributors
ever learn is Vim9?

@chrisbra
Copy link
Member

There was this comment, which was apparently deleted again:

For future readers:
I was happy to get this workaround in my .vimrc but then if you have functions that use filters, e.g. exe $":%!some_external_command bla bla " then you are in trouble. :)
I was getting mad why exe $":%!prettier ..." got stuck, then I found why.
Perhaps I should activate such an autocmd only when I am experimenting around (read: writing functions or plugins).

The fix to this is simple, stick in a <C-U> after the : so that the command line is cleared before running your prettier command.

@tonymec
Copy link

tonymec commented May 22, 2024

Disadvantage of having command-lines suddenly interpreted as Vim9 script language : old-timers will have to learn everything all over again (or learn to start every command-line with the word :legacy, or use the autocommand mentioned earlier, but in reverse).

I started using Vim when it was at version 6.1, did the vimtutor as it was back then, then followed the evolution into Vim 7 then Vim 8, as Floats, Lists and Dictionaries, among others, were added to the syntax. All the time it was no new language but just an evolution of the same. My vimrc and any plugins I wrote myself are still in Vim8 language and I have no problem with that, in particular no speed problem.

I'll learn Vim9 language all in my good time when (and if) I decide to do it, but since I know none of those newfangled programming languages which Vim 9 language is upposed to imitate, the replacement of :let by nothing, of :call by nothing, of "-comments by #-comments, of # by ## to mean the alternate file, etc., adds (for me) "cognitive overload, general weirdness and undesirable ambiguity". Please let me stay with classical Vim script, which I refuse to call a "legacy" as if it were something used by our great-grandparents but discarded long ago.

I believe that the weight of numbers is in favour of the old-timers because at any time there are a few newcomers (who will learn the ropes, or depart, $DEITY forbid, if they can't) and a lot of old-timers who already know the old ways and will probably learn the new ways, but all in their good time and not necessarily instantly.

Regards,
Tony.

@chrisbra
Copy link
Member

I am closing this, as I am not seeing this as a desired change and thus are against such a change. It also seems a bit controversial to other Vim old-timers.

@chrisbra chrisbra closed this as not planned Won't fix, can't repro, duplicate, stale May 25, 2024
@girishji
Copy link
Contributor Author

girishji commented May 28, 2024

I just got back to reading some of these comments, and many "old timers" never understood the proposal.

Disadvantage of having command-lines suddenly interpreted as Vim9 script language : old-timers will have to learn everything all over again

What does this even mean? Unless you set : set vim9cmdline in your .vimrc, the cmdline works exactly as before (in legacy script mode). No one is forced to learn vim9script.

The proposed vim9cmdline option would be disruptive for it
should render :vim9cmd optional and make :legacy required
with one option setting, and impose the opposite optionality
with another option setting. But what recourse would poor
developers have that may prefer Vim9 and so would opt in,
but also tinker at legacy code now and then? Is the option
on/off?

There is no need for any ":legacy" when vim9 is active. You are manufacturing complexity to discredit my proposal.

I am not seeing this as a desired change and thus are against such a change. It also seems a bit controversial to other Vim old-timers.

Survival bias. New users run to Neovim since Lua looks easier and legacy script is weird and complicated. Not many new users are invested in Vim9script, and thus will not comment. Older users have already learned legacy script out of necessity, or have written plugins and would like to keep them relevant. There is not a single argument against the proposal that passes smell test. I consider closing this proposal unwarranted.

@k-takata
Copy link
Member

I suppose what you want is a REPL environment for Vim9 script that can be used for plugin development.
How about using quickrun.vim (or a similar plugin)? (It is not a REPL, though.)

@nickspoons
Copy link

I like the idea of the proposal, and if it worked well, I would almost certainly use the :set vim9cmdline option personally.

However, as yegappan explained earlier, vim9script was not designed for command line use, and so it's hard to know how much work would be required to implement it well.

A nice way to handle the issue of global scoped variables might be to say that, as there is only global scope when commands are run from the command line, the g: becomes unnecessary. So instead of needing to do :vim9 g:foo = {} we could just do :foo = {}. I'm not sure how many other edge cases like this might be required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement vim9script Vim9 script related issues
Projects
None yet
Development

No branches or pull requests