-
Notifications
You must be signed in to change notification settings - Fork 532
completion: fix bash and zsh shell completion when completing aliases of multiple arguments #6407
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally LGTM, but I'm not familiar with completion details so it might be worth having an expert review.
277e965
to
42cab3f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation looks good, thanks.
42cab3f
to
c7b33f4
Compare
c7b33f4
to
fadb0c6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
The completion mechanism works differently in different shells: For example, when the command line `jj aaa bb ccc` is completed at the end of the `bb` token, bash and zsh pass the completer the whole line `-- jj aaa bb ccc` and an index of 2 which refers to the `bb` token; they are then expected to complete `bb`. Meanwhile, fish and Powershell only pass the command up to the completion point, so `-- jj aaa bb`; the completer is always expected to complete the last token. In all cases, the shell ultimately decides what to do with the completions, e.g. to complete up to a common prefix (bash), to show an interactive picker (zsh, fish), or to insert the completion if it is the only one (all shells). Remaining tokens (`ccc`) are also always appended by the shell and not part of the completion. While this is mostly handled by the clap_complete crate, we do expand aliases and present clap_complete with a fake view of the real command line, thereby reaching into its internals by wrapping the interface between the completion shell script that is provided by clap_complete and its Rust code in `CommandEnv::try_complete()`. If we get this wrong, completion might yield unexpected results, so it is worth testing completion for both flavors of shells whenever aliases are potentially in the mix. To avoid redundancy, the shell-specific invocation of `jj` is factored into a `complete_at()` function of the test fixture. The `test-case` crate is then used to instantiate each test case for different values of clap_complete's `Shell` enum. filter bash/zsh specific behavior move impl
…n bash and zsh This also adds a test case for the completion of arguments following multi-argument aliases, to cover the bug reported in issue #5377. The default command is like a special kind of alias, one which is expanded from zero tokens. Consequently, it also triggers the bug #5377 on bash/zsh, even if the `default-command` is just a single token. The fix is along the lines sketched out by the "TODO" comment. Bash and Zsh don't behave identical, so the padding ([""]) still needs to be applied (and removed) conditionally in a disciplined manner.
fadb0c6
to
2b85bd1
Compare
Fixes #5377.
The fix ended up as exactly like @yuja mentioned in the issue and what the
TODO
comment in the code was already proposing. Still, it took a fair bit of fiddling around with the different shells to understand where they are differing in behavior exactly.I've gotten a wee bit carried away refactoring the existing tests to cover multiple shells (where sensible) without duplicating too much of the test code. Even so, insta needs a
match
over the different shell flavors to snapshot their output individually. For a while, I've entertained the idea of adding a.normalize_shell_completions(shell)
function on the test output to basically strip away the comment (because bash doesn't have that) such that it would produce the same (normalized) output for each shell and we could do away with thematch
es. Obviously, that would lose the comment snapshots, so I decided against it for now. Let me know if that's something you want me to revisit.Checklist
If applicable:
CHANGELOG.md