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

Bash completion for git diff git suggests only top-level completions #4273

Closed
2 tasks done
martinvonz opened this issue Sep 28, 2022 · 0 comments · Fixed by #4289
Closed
2 tasks done

Bash completion for git diff git suggests only top-level completions #4273

martinvonz opened this issue Sep 28, 2022 · 0 comments · Fixed by #4289
Labels
A-completion Area: completion generator C-bug Category: Updating dependencies E-hard Call for participation: Experience needed to fix: Hard / a lot

Comments

@martinvonz
Copy link
Contributor

Please complete the following tasks

Rust Version

1.63.0

Clap Version

3.2.22

Minimal reproducible code

use std::io::{stdout, Write};
use clap;
use clap::CommandFactory;

#[derive(clap::Parser, Clone, Debug)]
enum App {
    Diff,
}

fn main() {
    let mut app = App::command();
    let mut buf = vec![];
    clap_complete::generate(clap_complete::Shell::Bash, &mut app, "git", &mut buf);
    stdout().write_all(&mut buf).unwrap();
}

Steps to reproduce the bug with the above code

Run the command and source the generated script. Then enter git diff git <TAB>

Actual Behaviour

The suggestions include diff.

Expected Behaviour

The suggestions should not include diff.

Additional Context

This is a bug in the Bash completion script I noticed while working on #4265. The issue is that the initial processing loop in the generated Bash script resets the "command so far" variable ($cmd) to git whenever git appears in the list, so it provides suggestions for the top-level command.

Debug Output

No response

@martinvonz martinvonz added the C-bug Category: Updating dependencies label Sep 28, 2022
@epage epage added E-hard Call for participation: Experience needed to fix: Hard / a lot A-completion Area: completion generator labels Sep 28, 2022
martinvonz added a commit to martinvonz/clap that referenced this issue Sep 29, 2022
Early in the Bash-completion script, we build up a string that
identifies the command or subcommand. When we see the top-level
command's name (e.g. `git`) we set the command so far to that
value. We do that regardless of where in the argument list it
appears. For example, if the argument list is `git diff git`, we set
the current command to `git` when run into it the second time. We
therefore suggest arguments to the top-level command afterwards, which
is not correct.

This patch fixes that by also considering the string that identifies
the command so far, so we only set the overall command to `git` if the
command so far is the empty string.

This is actually just a step on the way to getting completion to work
for aliases of subcommands.

Closes clap-rs#4273
martinvonz added a commit to martinvonz/clap that referenced this issue Sep 29, 2022
This continues the work started with the fix for clap-rs#4273. There was
another bug caused by using the subcommand names without considering
their position in the argument list. If the user enters `git diff log
<TAB>`, we build up a string that identifies the subcommand. We ended
up making the string `git__diff__log` in this case because we appended
`__log` without considering the current state. Since `git__diff__log`
does not correspond to an actual command, we wouldn't provide any
suggestions.

This commit restructures the code so we walk subcommands and
subsubcommands in `bash.rs`. While walking those, we build up a list
containing triples of the parent `$cmd` name (e.g. `git__diff`), the
current command's name (e.g. `log`), and the `$cmd` for the current
command. We then build the shell script's case arms based on that
information.

We could instead have fixed clap-rs#4280 by using the second element in the
pair returned from `utils::all_subcommands()` (a stringified list of
the subcommand path) instead of the first one. However, that would not
have helped us solve clap-rs#4265.

Closes clap-rs#4280
martinvonz added a commit to martinvonz/clap that referenced this issue Sep 29, 2022
With the previous fixes for clap-rs#4273 and clap-rs#4280 in place, it's now easy to
add support for subcommand aliases, which this commit does. This
addresses clap-rs#4265 for Bash.
martinvonz added a commit to martinvonz/clap that referenced this issue Sep 29, 2022
Early in the Bash-completion script, we build up a string that
identifies the command or subcommand. When we see the top-level
command's name (e.g. `git`) we set the command so far to that
value. We do that regardless of where in the argument list it
appears. For example, if the argument list is `git diff git`, we set
the current command to `git` when run into it the second time. We
therefore suggest arguments to the top-level command afterwards, which
is not correct.

This patch fixes that by also considering the string that identifies
the command so far, so we only set the overall command to `git` if the
command so far is the empty string.

This is actually just a step on the way to getting completion to work
for aliases of subcommands.

Closes clap-rs#4273
martinvonz added a commit to martinvonz/clap that referenced this issue Sep 29, 2022
This continues the work started with the fix for clap-rs#4273. There was
another bug caused by using the subcommand names without considering
their position in the argument list. If the user enters `git diff log
<TAB>`, we build up a string that identifies the subcommand. We ended
up making the string `git__diff__log` in this case because we appended
`__log` without considering the current state. Since `git__diff__log`
does not correspond to an actual command, we wouldn't provide any
suggestions.

This commit restructures the code so we walk subcommands and
subsubcommands in `bash.rs`. While walking those, we build up a list
containing triples of the parent `$cmd` name (e.g. `git__diff`), the
current command's name (e.g. `log`), and the `$cmd` for the current
command. We then build the shell script's case arms based on that
information.

We could instead have fixed clap-rs#4280 by using the second element in the
pair returned from `utils::all_subcommands()` (a stringified list of
the subcommand path) instead of the first one. However, that would not
have helped us solve clap-rs#4265.

Closes clap-rs#4280
martinvonz added a commit to martinvonz/clap that referenced this issue Sep 29, 2022
With the previous fixes for clap-rs#4273 and clap-rs#4280 in place, it's now easy to
add support for subcommand aliases, which this commit does. This
addresses clap-rs#4265 for Bash.
martinvonz added a commit to martinvonz/clap that referenced this issue Sep 29, 2022
Early in the Bash-completion script, we build up a string that
identifies the command or subcommand. When we see the top-level
command's name (e.g. `git`) we set the command so far to that
value. We do that regardless of where in the argument list it
appears. For example, if the argument list is `git diff git`, we set
the current command to `git` when run into it the second time. We
therefore suggest arguments to the top-level command afterwards, which
is not correct.

This patch fixes that by also considering the string that identifies
the command so far, so we only set the overall command to `git` if the
command so far is the empty string.

This is actually just a step on the way to getting completion to work
for aliases of subcommands.

Closes clap-rs#4273
martinvonz added a commit to martinvonz/clap that referenced this issue Sep 29, 2022
This continues the work started with the fix for clap-rs#4273. There was
another bug caused by using the subcommand names without considering
their position in the argument list. If the user enters `git diff log
<TAB>`, we build up a string that identifies the subcommand. We ended
up making the string `git__diff__log` in this case because we appended
`__log` without considering the current state. Since `git__diff__log`
does not correspond to an actual command, we wouldn't provide any
suggestions.

This commit restructures the code so we walk subcommands and
subsubcommands in `bash.rs`. While walking those, we build up a list
containing triples of the parent `$cmd` name (e.g. `git__diff`), the
current command's name (e.g. `log`), and the `$cmd` for the current
command. We then build the shell script's case arms based on that
information.

We could instead have fixed clap-rs#4280 by using the second element in the
pair returned from `utils::all_subcommands()` (a stringified list of
the subcommand path) instead of the first one. However, that would not
have helped us solve clap-rs#4265.

Closes clap-rs#4280
martinvonz added a commit to martinvonz/clap that referenced this issue Sep 29, 2022
With the previous fixes for clap-rs#4273 and clap-rs#4280 in place, it's now easy to
add support for subcommand aliases, which this commit does. This
addresses clap-rs#4265 for Bash.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-completion Area: completion generator C-bug Category: Updating dependencies E-hard Call for participation: Experience needed to fix: Hard / a lot
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants