wilder.nvim
wilder.nvim copied to clipboard
Candidates for second and subsequent user command arguments are not shown
Hey :wave:
I have been using this plugin for quite some time and found out there may be something wrong with the way the plugin handles candidates for user command arguments.
When trying to get completions at the end of the following command from https://github.com/sindrets/diffview.nvim:
:DiffviewOpen sway --imp
wilder.nvim does not show any candidates for the second argument (--imp).
It does show the candidates when I am typing the first argument (i.e. does suggest sway when the cmdline is :DiffviewOpen sw).
Investigation notes
Here are some debug logs from my investigation from some of the values used in wilder.nvim for the ctx and the arg:
sway --im
['s', 'w', 'a', 'y', ' ', '-', '-', 'i', 'm']
{'cmd': 'DiffviewOpen', 'expand': 'nothing', 'cmdline': 'DiffviewOpen sway --imp', 'pos': 13, 'force': 0}
{'cmd': 'DiffviewOpen', 'expand': 'nothing', 'cmdline': 'DiffviewOpen sway --imp', 'arg': 'sway --imp', 'pos': 13, 'force': 0}
{'cmd': 'DiffviewOpen', 'expand': 'nothing', 'cmdline': 'DiffviewOpen sway --imp', 'arg': 'sway --imp', 'pos': 13, 'force': 0}
The suggestions returned from the DiffviewOpen user command at that point are:
{ "--imply-local" }
It looks like wilder.nvim assumes that the argument is sway --imp and not just --imp. Thus, later, when it tries to match the completion candidates (--imply-local) against the arg, it does not find the match, because sway --imp does not match --imply-local. If it only used the last argument (--imp), it would correctly find the match between --imp and --imply-local.
I suspect the problem is somewhere in https://github.com/gelguy/wilder.nvim/blob/679f348dc90d80ff9ba0e7c470c40a4d038dcecf/autoload/wilder/cmdline/main.vim#L36
The function is quite complex and I didn't end up finding the problem, unfortunately.
Native wildmenu behavior
To check whether this is a wrong assumption of wilder.nvim or a problem in diffview.nvim completion candidates, I checked how the native wildmenu behaves. It correctly offers completions for the second argument:

After pressing Tab for :DiffviewOpen sway --imp, the argument is correctly completed to :DiffviewOpen sway --imply-local. Completing subsequent arguments works in the native wildmenu as well:

Other problematic plugins
The problem can be reproduced with other plugins that have completions for more than one user command argument. For example, with :Telescope live_grep | (| is the cursor position), there are no completions shown by wilder.nvim, but there are many completions shown in the native wildmenu.
Thanks for the detailed info and the screenshots!
I've narrowed this down to command DiffviewOpen setting a Lua function for the complete option. I don't see a way to call that Lua function since its stringified into <Lua function NUM>, but I have a workaround in mind.
I'm dubious whether this is the problem with the complete option of user commands. I thought the issue is in the code parsing the current cmdline and incorrectly assuming there is just one argument for user commands. That is what I gathered after seeing 'cmdline': 'DiffviewOpen sway --imp', 'arg': 'sway --imp', 'pos': 13 in the ctx in wilder#cmdline#main#do, if I recall correctly.
I'm curious, what am I missing?
wilder gets the candidates from the command completion manually:
https://github.com/gelguy/wilder.nvim/blob/777b163e394ba658ef288292efb533b25610ef9d/autoload/wilder/cmdline.vim#L681-L682
It doesn't handle Lua functions sincce complete=lua was (relatively) newly added. Furthermore, Lua functions are stringified to <Lua function>, and so cannot be de-referenced into the actual function.
The ctx doesn't contain the completions as no completions are returned.
The fallback will be to call getcompletion(cmdline, 'cmdline') and get the completions from there.
Interesting, thanks for sharing these details. Why did it work for the first argument, though?
I get correct completions for the first argument of DiffviewOpen and I guess these completions are also returned from a Lua function:

You're saying that getting the completions for the first argument works fine when using a Lua function for complete, but breaks for 2nd and subsequent arguments?
I'm asking out of my curiosity, so I can better understand the Vim <-> Lua user command completions interop
Hmm, looks like I'm wrong - wilder is already using the getcompletion(..., 'cmdline') fallback, but is setting the wrong argument for the fuzzy filter. (wilder basically doesn't handle complete=<lua function> correctly.)
You can confirm this by setting fuzzy_filter: {ctx, xs -> xs} in the options to wilder#cmdline_pipeline() (or fuzzy_filter = function(ctx, xs) return xs end for Lua).
Yup, I confirm I can see the correct completion candidates in the xs list in the fuzzy filter.
function FuzzyFilter(ctx, xs, c)
echomsg "ctx" a:ctx
echomsg "xs" a:xs
return a:xs
endfunction
\ 'fuzzy_filter': function("FuzzyFilter"),
Yields
ctx {'session_id': 3, 'handler_id': 90, 'input': 'DiffviewOpen abc --', 'run_id': 20}
xs ['--untracked-files', '--cached', '--staged', '--imply-local', '--selected-file']
The candidates are there.
At first glance, it seems to me the input/cmdline parsing logic that determines the arg to be completed seems incorrect, as I pointed out at the beginning of the Investigation notes ('cmdline': 'DiffviewOpen sway --imp', 'arg': 'sway --imp' instead of 'arg': '--imp').
@gelguy Is there any way I can help out more here? Should I try to adjust the cmdline parsing logic so it only takes one argument into account instead of everything but the command name?
Thanks for offering!
If you're ok with waiting, I'll have a fix done over the weekend.
That sounds great! Take your time, there's no rush, and it's just an inconvenience, not a showstopper.
I'm sorry to bring it up, but this bug keeps annoying me. Could I help fix it?
I found a possible fix and raised #166