Skip to content

Conversation

@WindSoilder
Copy link
Contributor

@WindSoilder WindSoilder commented Oct 14, 2025

Closes: #15766

It's similar to #16383, but allows to generate completion dynamically, which can be useful for plugin commands.

To implement this, I added a new get_dynamic_completion method to Command trait, so nushell gets the ability to ask plugins for a completion. Here is how it goes when I type plugin-cmd --flag1 <tab>.

  1. the completion logic detect it's behind a flag, and it should have a value, then it goes to ArgValueDynamicCompletion
  2. inside ArgValueDynamicCompletion it calls get_dynamic_completion(ArgType::Flag(flag1)) on the command, which can be plugin command, and it will issue a get_dynamic_completion(ArgType::Flag(flag1)) call to the plugin
  3. the plugin returns Some(Vec<DynamicSemanticSuggestion>) if there are available items.

It also supports dynamic completion for positional arguments, here is how it goes when I type plugin-cmd x<tab>.

  1. the completion logic detect it's behind a flag, and it should have a value, then it goes to ArgValueDynamicCompletion
  2. inside ArgValueDynamicCompletion it calls get_dynamic_completion(ArgType::Positional(0)) on the command, which can be plugin command, and it will issue a get_dynamic_completion(ArgType::Positional(0)) call to the plugin
  3. the plugin returns Some(Vec<DynamicSemanticSuggestion>) if there are available items.

Release notes summary - What our users need to know

Plugin developer: auto completion is available for plugin command arguments.

User can define auto completions for plugin commands, here is the way to define this:

impl PluginCommand for FlagCompletion {
    type Plugin = ExamplePlugin;
    ...

    fn get_dynamic_completion(
        &self,
        _plugin: &Self::Plugin,
        _engine: &EngineInterface,
        arg_type: ArgType,
    ) -> Option<Vec<DynamicSemanticSuggestion>> {
        match arg_type {
            // enable completion for flag.
            ArgType::Flag(flag_name) => match flag_name {
                "flag1" => Some(vec!["flag_val1".to_string().into(), "flag_val2".to_string().into()]),
                "flag2" => Some(vec!["flag_val3".to_string().into(), "flag_val4".to_string().into()]),
                // for other flags don't need to provide a completion
                _ => None,
            },
            // enable completion for positional arguments.
            ArgType::Positional(index) => None,
        }
    }
}

For the detailed example, you can refer to get_dynamic_completion in crates/nu_plugin_example/src/commands/arg_completion.rs.

Tasks after submitting

@github-actions github-actions bot added the A:plugins This issue is about plugins label Oct 14, 2025
@WindSoilder WindSoilder added the A:completions Issues related to tab completion label Oct 14, 2025
@WindSoilder WindSoilder marked this pull request as draft October 14, 2025 12:24
@WindSoilder WindSoilder force-pushed the command_completion branch 4 times, most recently from a3383bf to 9ec6250 Compare October 28, 2025 12:26
@WindSoilder WindSoilder marked this pull request as ready for review October 28, 2025 12:35
@blindFS
Copy link
Contributor

blindFS commented Nov 7, 2025

It would be nice to have some integration tests to make sure that it's actually working from nu-cli.

Sorry, I have no idea of how to do it. You can ignore this if you find it difficult to implement.

@WindSoilder
Copy link
Contributor Author

It would be nice to have some integration tests to make sure that it's actually working from nu-cli.

Sure, I added a FakeCmd struct during completion testing, and runs some tests against it.

@blindFS
Copy link
Contributor

blindFS commented Nov 8, 2025

It would be nice to have some integration tests to make sure that it's actually working from nu-cli.

Sure, I added a FakeCmd struct during completion testing, and runs some tests against it.

Smart move, thanks!

Copy link
Member

@ysthakur ysthakur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me on the completions side, just some minor comments. Do you want someone else from the core team to review the plugin side?

@WindSoilder
Copy link
Contributor Author

Looks good to me on the completions side, just some minor comments. Do you want someone else from the core team to review the plugin side?

Of course it's better if anyone is available, perhaps @devyn and @cptpiepmatz ?

@cptpiepmatz cptpiepmatz self-requested a review November 9, 2025 09:16
@cptpiepmatz
Copy link
Member

While reviewing this I wondered why this is even needed. We have custom completions for externals: https://www.nushell.sh/book/custom_completions.html#custom-completion-and-extern

I don't understand why we cannot use that in some smart way. Is it not dynamic or what is the issue here? Also even if we go with the direction of this PR (I like the impl so far, so I'm not against this PR itself), should we merge these two ideas?

I'm not sure if this was talked already in this PR in the comments somewhere, sorry if I overlooked that.

@WindSoilder WindSoilder marked this pull request as draft November 9, 2025 12:57
@WindSoilder
Copy link
Contributor Author

Is it not dynamic or what is the issue here?

The main issue is that it's hard to get the internal state of a plugin, it may take a lot of effort to expose commands to query internal state.

@cptpiepmatz
Copy link
Member

I see the issue. But how are the other completers implemented? Both feel to me as they try to solve very similar issues. Should we move the impl for them into this one, when this one lands?

@WindSoilder
Copy link
Contributor Author

Not really, it's mainly for plugins, the plugin authors can add completion easily for there commands once it's landed

@WindSoilder WindSoilder marked this pull request as ready for review November 10, 2025 01:17
@ysthakur
Copy link
Member

I don't understand why we cannot use that in some smart way. Is it not dynamic or what is the issue here?

The way custom completions work right now is, we parse a custom command whose parameters refer to some completers, and then we store the DeclId of the command for the custom completer with the parameter. But when defining a builtin command or a plugin command, there is no such DeclId available. So Commands can't use this existing mechanism to provide dynamic completions at the moment.

After this PR, builtins as well as plugin commands can provide dynamic completions, and then we can try having shared logic for this, the static completions added by Bahex (foo: string@[a b c]), and for custom completions.

Copy link
Member

@ysthakur ysthakur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excited for this! Thanks for sticking with this @WindSoilder

Copy link
Contributor

@blindFS blindFS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually @cptpiepmatz made me thinking that maybe it could/should be done at the Parameter level, instead of Command. If we need to call the command during dynamic completion, we can always resort to find_decl.

Anyways, I don't want to keep this PR on-hold for too long. We still get time to redesign it before the next release.

@WindSoilder
Copy link
Contributor Author

Thanks for reviewing! I'm going to land it. Regards to this:

Hmm, I just realized that get_dynamic_completion doesn't get the buffer. Sorry to keep holding up this PR, but I think it'd be better if it also accepted the buffer/text typed by the user.
We don't need to pass in a span. Later, we can give plugins the ability to return spans, and then we would translate the span to a Reedline span with the right offset.

Let's keep the diff smaller, I can try to implement it in another pr.

@WindSoilder WindSoilder merged commit 85b5e57 into nushell:main Nov 10, 2025
16 checks passed
@github-actions github-actions bot added this to the v0.109.0 milestone Nov 10, 2025
WindSoilder pushed a commit that referenced this pull request Nov 13, 2025
…letion results (#17006)

First step of
[this](#16859 (comment)),
mainly to reuse the type-based completions for flag values, as reported
in #16977 .

And some complement test cases.

@WindSoilder @ysthakur 

## Release notes summary - What our users need to know

Fixed a bug where path/glob/directory typed flags don't get completions.

## Tasks after submitting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A:completions Issues related to tab completion A:plugins This issue is about plugins

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support custom completions in plugin command parameters or flags

4 participants