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

Candidates for second and subsequent user command arguments are not shown #159

Open
Gelio opened this issue Oct 2, 2022 · 11 comments · May be fixed by #166
Open

Candidates for second and subsequent user command arguments are not shown #159

Gelio opened this issue Oct 2, 2022 · 11 comments · May be fixed by #166
Labels
bug Something isn't working neovim

Comments

@Gelio
Copy link

Gelio commented Oct 2, 2022

Hey 👋

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

function! wilder#cmdline#main#do(ctx) abort

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:

image

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:

image

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.

@Gelio Gelio changed the title Candidates for second and subsequent arguments are not shown Candidates for second and subsequent user command arguments are not shown Oct 2, 2022
@gelguy gelguy added bug Something isn't working neovim labels Oct 3, 2022
@gelguy
Copy link
Owner

gelguy commented Oct 3, 2022

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.

@Gelio
Copy link
Author

Gelio commented Oct 3, 2022

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?

@gelguy
Copy link
Owner

gelguy commented Oct 3, 2022

wilder gets the candidates from the command completion manually:

let l:Completion_func = function(l:function_name)
let l:result = l:Completion_func(l:arg, a:res.cmdline, len(a:res.cmdline))

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.

@Gelio
Copy link
Author

Gelio commented Oct 3, 2022

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:

image

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

@gelguy
Copy link
Owner

gelguy commented Oct 4, 2022

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).

@Gelio
Copy link
Author

Gelio commented Oct 4, 2022

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').

@Gelio
Copy link
Author

Gelio commented Oct 7, 2022

@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?

@gelguy
Copy link
Owner

gelguy commented Oct 7, 2022

Thanks for offering!

If you're ok with waiting, I'll have a fix done over the weekend.

@Gelio
Copy link
Author

Gelio commented Oct 7, 2022

That sounds great! Take your time, there's no rush, and it's just an inconvenience, not a showstopper.

@Gelio
Copy link
Author

Gelio commented Nov 17, 2022

I'm sorry to bring it up, but this bug keeps annoying me. Could I help fix it?

Gelio added a commit to Gelio/wilder.nvim that referenced this issue Nov 18, 2022
For user commands, the parsed `arg` was everything in the cmdline after
the command name. This meant that for `:DiffviewOpen origin/master --i`,
the `arg` was `origin/master --i`. The completions returned by
`getcompletion(cmdline, 'cmdline')` returned the completions that are
prefixed by the last argument (`--i`, for example `--imply-local`).
Then, the filtering code attempted to filter the completions
(`["--imply-local"]`) using `origin/master --i`, which did not match.
For the `arg`, only the last argument (`--i`) should be used in this
case for the filtering to return the correct completions.

The consequence was that completions for the 2nd and subsequent were not
shown for user commands with `complete` functions in Lua.

This commit changes the cmdline parsing logic so that for user commands,
only the last argument in the cmdline is parsed as the `arg`. This way
the filtering logic correctly matches `--imply-local` as a valid
completion for `--i`.

The following commands now show completions, whereas they did not show
any completions before:

* :DiffviewOpen origin/master --i
* :Telescope live_grep pre

Fixes gelguy#159
@Gelio Gelio linked a pull request Nov 18, 2022 that will close this issue
@Gelio
Copy link
Author

Gelio commented Nov 18, 2022

I found a possible fix and raised #166

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working neovim
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants