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
cli: allow alias after global args #309
Conversation
8f5d913
to
c5a312b
Compare
4a10f5c
to
2f48cd6
Compare
c10b9d8
to
f3c4798
Compare
f3c4798
to
f77ab04
Compare
f77ab04
to
e939327
Compare
e939327
to
c3bb559
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.
Nit: description says "That make clap
", should be "makes"; also says 'suggestion on in' should just be 'suggestion in'.
Thoughts on implementation from offline discussion: Assuming that alias_args
is a subvec (the tail elements of string_args
), let's do something where each loop pass concatenates the first N arguments from string_args
, the arguments from the alias resolution, and all of the arguments from alias_args[1..]
(where N = string_args.length() - alias_args.length()
).
Our support for aliases is very naively implemented; it assumes the alias is the first argument in argv. It therefore fails to resolve aliases after global arguments such as `--at-op`. This patch fixes that by modifying the command defintion to have an "external subcommand" in the list of available commands. That makes `clap` give us the remainder of the arguments when it runs into an unknown command. The first in the list will then be an alias or simply an unknown command. Thanks to @epage for the suggestion on in clap-rs/clap#3672. With the new structure, it was easy to handle recursive alias definitions, so I added support for that too. Closes #292.
c3bb559
to
628677f
Compare
Done.
That turned out much simpler, and obviously more reliable because we don't need to manually merge earlier global arguments with later ones. @epage, can you confirm if that assumption is correct (i.e. that the list of strings passed to an |
clap does no post-processing on the external subcommand arguments; they are exactly what clap received. If I'm understanding the suggestion, its to manually extract the global args and subcommand and merge the global args in with the external subcommand arguments. I personally wouldn't do this as I'd be concerned about it being brittle; it having corner cases to deal with. |
Okay, that's good, and what we assumed.
Yes, that's correct. It actually seems much simpler and less brittle to me. See how much simpler it got. |
Fewer lines of code is not the sample thing as simplicity. There are more assumptions on behavior with the new approach which is where my concern with brittleness comes from. If it works for you, go for it. Like I said, for myself, I wouldn't but there are times when people come to different conclusions and that is fine. |
In what way do you think it's brittle? What should we watch out for if we do it this way? Is the concern that clap might do some parsing of the later arguments in the future (making that assertion I added fail)? My biggest concern with the way we did it before was that we had to replicate clap's override behavior. |
I'm more going more from gut feel and do not have the time or interest in litigating this. |
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.
I think new implementation is better.
It's clearer that alias expansion works at lower args: &[str]
layer (e.g. aliased_diff = ["diff", "-r"]
is valid even though -r
takes value), not at the layer where the structs parsed by clap should live (e.g. where the alias would be described as ["diff", "-r", "$1"]
.)
Our support for aliases is very naively implemented; it assumes the
alias is the first argument in argv. It therefore fails to resolve
aliases after global arguments such as
--at-op
.This patch fixes that by using doing an intial parse of the arguments
with a modified definition of the CLI passed to
clap
. The modifieddefinition has only global arguments, plus an "external
subcommand". That way we can convince
clap
to parse the globalarguments for us and give us the alias (or real command) and further
arguments back. Thanks to @epage for the suggestion on in
clap-rs/clap#3672. The only minor problem is that it doesn't seem
possible to tell
clap
to parse global arguments that come after theexternal subcommand. To work around that, we manually merge any parsed
global argument before the alias with any parsed global arguments
after it.
Closes #292.
Checklist
CHANGELOG.md