[vim/vim] Vim9: functions assigned to commands are not visible (Issue #9907)

16 views
Skip to first unread message

Sergey Vlasov

unread,
Mar 8, 2022, 10:58:56 AM3/8/22
to vim/vim, Subscribed

Steps to reproduce

  1. Create test.vim:
vim9script

def MyFunc()
  echom "hello"
enddef

command! MyCmd MyFunc()
  1. vim -g --clean +'source test.vim'
  2. Execute the command:
:MyCmd
hello
  1. Print command definition:
:command MyCmd
    Name              Args Address Complete    Definition
    MyCmd             0                        MyFunc()
  1. Call the function assigned to the command:
call MyFunc()
E117: Unknown function: MyFunc                                                                                                                                  

Expected behaviour

Functions assigned to commands are globally visible.

Version of Vim

8.2.4394

Environment

GUI

Logs and stack traces

No response


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907@github.com>

lacygoill

unread,
Mar 8, 2022, 11:43:54 AM3/8/22
to vim/vim, Subscribed

Functions assigned to commands are globally visible.

Why should a function be made implicitly global, simply because it can be called from a user-defined command?


Note that if you want a function to be explicitly global, you can prefix its name with g: in its header:

def g:MyFunc()
    ^^

Test:

vim9script
def g:MyFunc()
    echomsg 'hello'
enddef
command MyCmd g:MyFunc()
MyCmd
feedkeys(":call MyFunc()\<Cr>")


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1061979369@github.com>

Sergey Vlasov

unread,
Mar 8, 2022, 11:48:44 AM3/8/22
to vim/vim, Subscribed

Why should a function be made implicitly global, simply because it can be called from a user-defined command?

For example I want to rename a command defined by a plugin. I can do that for legacy vim plugins but it's not possible for vim9 plugins.

Note that if you want a function to be explicitly global, you can prefix its name with g: in its header:

This will not work for commands/functions defined by 3rd party vim9 plugins.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1061984325@github.com>

lacygoill

unread,
Mar 8, 2022, 12:02:04 PM3/8/22
to vim/vim, Subscribed

For example I want to rename a command defined by a plugin

How about this:

command Renamed OldName

Test:

vim9script
def MyFunc()
    echomsg 'hello'
enddef
command MyCmd MyFunc()
MyCmd
command Renamed MyCmd
Renamed
hello
hello

I can do that for legacy vim plugins but it's not possible for vim9 plugins.

You can do that if the command calls a global function, but I don't think you can do that if it calls a script-local one.

For example, suppose a third-party plugin provides this :Cmd:

function s:Func()
    echomsg 'hello'
endfunction
command Cmd call s:Func()

How would you rename Cmd into Renamed from a different script?


This will not work for commands/functions defined by 3rd party vim9 plugins.

But by default, items are local to the script where they are defined; including functions. It wouldn't make sense to make an exception for a function which is called by a user-defined command.

Alternatively, maybe we would need a new cmdarg() function, similar to maparg(). It could return the rhs of an arbitrary user-defined command. You could use it like so:

execute printf('command Renamed %s', cmdarg('OldName'))

Would that help?


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1061998557@github.com>

Sergey Vlasov

unread,
Mar 8, 2022, 12:45:50 PM3/8/22
to vim/vim, Subscribed

How about this:

command Renamed OldName

It is a bit more complicated than this. I would not want an alias to a command, but to rename a command for real, so the old command disappears. There are plugins that define many similar commands, so using command completion becomes very difficult. So I would like to only keep some commands visible to completion and rename other commands (so that I could still use them in mappings).

With legacy vim, I could define a new command and delete the old command.

You can do that if the command calls a global function, but I don't think you can do that if it calls a script-local one.

I can do that for any commands defined in legacy script using script id. That's a bit difficult to do but still doable.

Alternatively, maybe we would need a new cmdarg() function, similar to maparg(). It could return the rhs of an arbitrary user-defined command.

I think that would be great solution. I could use the rhs in a new command and delete the old command.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1062038824@github.com>

Bram Moolenaar

unread,
Mar 8, 2022, 1:40:27 PM3/8/22
to vim/vim, Subscribed

So, you would load a plugin, and then delete commands it defined.
That's a bit nasty. I can imagine Plugins are not prepared for this kind of use.

Making the function global is not desired, it should be private to the plugin.

If you would get the argument of the command and define a new command with that, it won't work, since the command is not defined in the script where the function is located. Unlike mappings, the function name is not expanded to the form.

The best solution I see is that the plugin provides a way to specify the command names you like.
E.g. for the "foobar" plugin set "g:foobar_that_name" to "MyCmdName".
The plugin would then need to do something like:

if exists('g:foobar_tat_name')
  exe 'command ' .. g:foobar_that_name .. ' ThatFunction()'
else
  command ThatCommand ThatFunction()
endif

More generally, using a dictionary to specify the configuration for the plugin would be a generic solution.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1062087201@github.com>

Sergey Vlasov

unread,
Mar 8, 2022, 2:09:47 PM3/8/22
to vim/vim, Subscribed

I would not call it nasty. Commands were always for users, not for plugin internals. I'm sorry if I had a wrong picture.

The best solution I see is that the plugin provides a way to specify the command names you like.
E.g. for the "foobar" plugin set "g:foobar_that_name" to "MyCmdName".

That is a bit too much to ask from plugin developers.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1062110263@github.com>

Sergey Vlasov

unread,
Mar 8, 2022, 2:59:00 PM3/8/22
to vim/vim, Subscribed

I agree that deleting commands may still break some plugins.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1062154679@github.com>

Sergey Vlasov

unread,
Mar 8, 2022, 2:59:07 PM3/8/22
to vim/vim, Subscribed

Closed #9907.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issue/9907/issue_event/6205015105@github.com>

Bram Moolenaar

unread,
Mar 8, 2022, 4:38:21 PM3/8/22
to vim/vim, Subscribed


> I would not call it nasty. Commands were always for users, not for
> plugin internals. I'm sorry if I had a wrong picture.

One of the patterns used by plugins is to check if something was already
defined, e.g. with "exists(':PluginCommand')", and bail out if it was
already defined. If you delete the command, the plugin might do
something unpredictable.


> >The best solution I see is that the plugin provides a way to specify the command names you like.
> E.g. for the "foobar" plugin set "g:foobar_that_name" to "MyCmdName".
>
> That is a bit too much to ask from plugin developers.

I don't think it is complicated. Because plugins have to avoid using
the same name as other plugins, the command names may get a bit long or
hard to type. Allowing the user to pick their own name is a very nice
thing to have.

--
hundred-and-one symptoms of being an internet addict:
209. Your house stinks because you haven't cleaned it in a week.

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


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1062237459@github.com>

lacygoill

unread,
Mar 8, 2022, 5:51:42 PM3/8/22
to vim/vim, Subscribed

I know that introducing new options is frowned upon, considering that we already have a lot, but a new 'cmdignore' option would fix the real issue, which was described here:

There are plugins that define many similar commands, so using command completion becomes very difficult.

So, for example, if a user has 2 plugins installing a bunch of commands starting with the prefixes Foo and Bar, they could tell Vim that they don't want any of them to be suggested after pressing Tab while on the command-line:

set cmdignore=Foo*,Bar*


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1062310844@github.com>

Yegappan Lakshmanan

unread,
Mar 8, 2022, 7:40:04 PM3/8/22
to vim_dev, reply+ACY5DGCM4XQOU3IB2J...@reply.github.com, vim/vim, Subscribed
Hi,

On Tue, Mar 8, 2022 at 2:51 PM lacygoill <vim-dev...@256bit.org> wrote:

I know that introducing new options is frowned upon, considering that we already have a lot, but a new 'cmdignore' option would fix the real issue, which was described here:

There are plugins that define many similar commands, so using command completion becomes very difficult.

So, for example, if a user has 2 plugins installing a bunch of commands starting with the prefixes Foo and Bar, they could tell Vim that they don't want any of them to be suggested after pressing Tab while on the command-line:

set cmdignore=Foo*,Bar*



With the support for fuzzy completion of command names (set 'wildoptions' to 'fuzzy'),
it should be easy to complete command names ignoring case and to complete names
after typing a few characters anywhere in the name.

Regards,
Yegappan

vim-dev ML

unread,
Mar 8, 2022, 7:40:26 PM3/8/22
to vim/vim, vim-dev ML, Your activity

Hi,


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9907/1062434496@github.com>

lacygoill

unread,
Mar 9, 2022, 5:50:43 AM3/9/22
to vim/vim, vim-dev ML, Comment

With the support for fuzzy completion of command names (set 'wildoptions'
to 'fuzzy'), it should be easy to complete command names ignoring case and to complete
names after typing a few characters anywhere in the name.

While the new fuzzy value of the 'wildoptions' is great to increase the number of suggestions, I think the OP is looking for the opposite: a way to decrease the number of suggestions, by pruning arbitrary Ex commands.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you commented.Message ID: <vim/vim/issues/9907/1062793959@github.com>

Sergey Vlasov

unread,
Mar 9, 2022, 6:17:32 AM3/9/22
to vim/vim, vim-dev ML, Comment

Yes, hiding some commands from the completion would be a solution to my original problem.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you commented.Message ID: <vim/vim/issues/9907/1062815705@github.com>

Bram Moolenaar

unread,
Oct 11, 2022, 3:28:21 AM10/11/22
to vim/vim, vim-dev ML, Comment


> I know that introducing new options is frowned upon, considering that
> we already have a lot, but a new `'cmdignore'` option would fix the
> real issue, which was described here:
>
> > There are plugins that define many similar commands, so using command completion becomes very difficult.
>
> So, for example, if a user has 2 plugins installing a bunch of
> commands starting with the prefixes `Foo` and `Bar`, they could tell

> Vim that they don't want any of them to be suggested after pressing
> Tab while on the command-line:
>
> set cmdignore=Foo*,Bar*

I don't like doing it that way. One option for an unknown number of
plugins, with possibly hiding some that you do want to see.

It would be better to explicitly "alias" a command. So you would
install a new command that invokes an existing one, and then hides that
existing one.

commandalias MyCommand PluginLongNameCommand

It would add a flag to PluginLongNameCommand to not show it for
completion.


--
hundred-and-one symptoms of being an internet addict:
210. When you get a divorce, you don't care about who gets the children,
but discuss endlessly who can use the email address.


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


Reply to this email directly, view it on GitHub.

You are receiving this because you commented.Message ID: <vim/vim/issues/9907/1274212838@github.com>

Reply all
Reply to author
Forward
0 new messages