-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
WIP: Extract subcommands into separate trait #1681
Conversation
Conflicts? And yeah, I think it will take me a bit of time to check this. I don't know about the other traits we were talking about, but I was pretty sure we didn't need subcommand trait. |
802ba1e
to
6dc44fd
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.
That's a bit long, I'll try to read it layer.
I've splited the PR into separate commits so it's hopefully easier to review :) A separate trait for subcommands was the whole point. It allows us to check that |
clap_derive/tests/subcommands.rs
Outdated
@@ -162,13 +162,14 @@ fn test_tuple_commands() { | |||
} | |||
|
|||
#[test] | |||
#[ignore] // FIXME (@CreepySkeleton) |
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.
This is not working yet. I know what this is all about, I know how to fix it, I'll get to it tomorrow.
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.
Upon further review, I'm totally convinced that this is an error in the test, see my comment below.
clap_derive/tests/subcommands.rs
Outdated
@@ -185,13 +186,14 @@ fn enum_in_enum_subsubcommand() { | |||
} | |||
|
|||
#[test] | |||
#[ignore] |
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.
Not working, I'm aware, will fix
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.
It tests an undocumented feature and I highly suspect that it wasn't intended to work that way, see my comment below.
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.
People, I think I've found a bug in the derive which has become yet another example of "this is not a bug anymore, but a feature". Two related bugs, actually. The Consider this code: #[derive(Clap)]
struct Foo {
// we should have used `subcommand` here
// this is an error
#[clap(flatten)]
sub: Sub
}
#[derive(Subcommand)]
enum Sub { /* whatev */ } Do you think it would fail to compile? Or, maybe panic with The second problem is more subtle. enum Foo {
// this is supposed to work as `flatten`
// https://docs.rs/structopt/0.3.9/structopt/#subcommands
Foo(Ext)
}
// This is supposed to be a struct
enum Ext {} This is how the snippet was supposed to be written, according to the docs: enum Foo {
// flattening struct, all good
Foo(Ext)
}
struct Ext {
#[clap(subcommand)]
sub: ExtSub
}
enum ExtSub {} But it works, miraculously. Instead of these "magical" solutions, I propose the alternative enum Foo {
// no attr = flatten, backcompat
Foo(Ext),
// tell derive that ExtFlat is struct and it must be flattened
#[clap(flatten)]
Bar(ExtFlat),
// tell derive that ExtSub is enum and it must be used as subcommands set
#[clap(subcommand)]
Bar(ExtSub),
// synonym for current #[structopt(flatten)]
// see https://github.com/TeXitoi/structopt/issues/327
#[clap(subcommand(flatten))]
Zog(ExtSubFlat)
} |
Could you please elaborate on that? I've got a strong feeling we're talking about different things here. |
It is related to #1681 (comment) |
@pksunkara Let's make sure we're talking about the same thing.
#[derive(Clap)]
enum Foo { }
let args = Foo::parse();
You're proposing to make |
Yes. What I am trying to aim for here is for the user to just simply do |
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.
So, I finally finished the review. Nothing wrong with the code much. I am just thinking about the API.
Can't we have #[clap(into_app)]
special for enums
that want to ::parse()
? Then, we can simply do #[derive(Clap)]
everywhere
2803fe5
to
17f9eca
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.
I still see #[derive(Subcommand)]
in the examples and tests, is that intentional?
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.
Just minor changes and I can merge this.
@@ -161,47 +161,52 @@ fn test_tuple_commands() { | |||
assert!(!output.contains("Not shown")); | |||
} | |||
|
|||
#[test] |
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.
Let's create an issue to rethink about Flatten and Composability.
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.
Mind explaining what you mean by "Composability"?
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 am thinking of the future. I actually started looking into Clap because I was working on a higher level CLI framework. In this, I wanted people to make plugins and CLI to use them. For example, I wanted to provide a plugin which provides a group of subcommands that I want a CLI to have at top-level, I would want to use flatten
. But this is not the only scenario.
What I am saying is we want to make sure we support all kinds of things people want to do if they can share Args and Apps.
690482d
to
ae574df
Compare
Let's discuss about the future later :p |
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.
bors r+
1681: WIP: Extract subcommands into separate trait r=pksunkara a=CreepySkeleton Not-yet-working-but-almost-there "multiple traits" approach. More or less done, what's left is to catch some bugs and adapt tests/examples. For the record: it took so long because of RL stuff (who would have thought?) and because [there was a detailed description of the experience I've had here, but it was deleted because it contained a lot of profanity and emotional notes]. As the only person alive that understands how the derive works (if you won't blow your own horn, nobody will do it for you, yeah), I'd like to made a statement: we Do need the refactoring. Co-authored-by: CreepySkeleton <[email protected]>
Build succeeded
|
`structopt` originally allowed ``` pub enum Opt { Daemon(DaemonCommand), } pub enum DaemonCommand { Start, Stop, } ``` This was partially broken in clap-rs#1681 where `$ cmd daemon start` works but `cmd daemon`, panics. Originally, `structopt` relied on exposing the implementation details of a derived type by providing a `is_subcommand` option, so we'd know whether to provide `SubcommandRequiredElseHelp` or not. This was removed in clap-rs#1681 Fixes clap-rs#2005
`structopt` originally allowed ``` pub enum Opt { Daemon(DaemonCommand), } pub enum DaemonCommand { Start, Stop, } ``` This was partially broken in clap-rs#1681 where `$ cmd daemon start` works but `cmd daemon`, panics. Originally, `structopt` relied on exposing the implementation details of a derived type by providing a `is_subcommand` option, so we'd know whether to provide `SubcommandRequiredElseHelp` or not. This was removed in clap-rs#1681 Fixes clap-rs#2005
`structopt` originally allowed ``` pub enum Opt { Daemon(DaemonCommand), } pub enum DaemonCommand { Start, Stop, } ``` This was partially broken in clap-rs#1681 where `$ cmd daemon start` works but `cmd daemon`, panics. Originally, `structopt` relied on exposing the implementation details of a derived type by providing a `is_subcommand` option, so we'd know whether to provide `SubcommandRequiredElseHelp` or not. This was removed in clap-rs#1681 Fixes clap-rs#2005
`structopt` originally allowed ``` pub enum Opt { Daemon(DaemonCommand), } pub enum DaemonCommand { Start, Stop, } ``` This was partially broken in clap-rs#1681 where `$ cmd daemon start` works but `cmd daemon`, panics. Originally, `structopt` relied on exposing the implementation details of a derived type by providing a `is_subcommand` option, so we'd know whether to provide `SubcommandRequiredElseHelp` or not. This was removed in clap-rs#1681 Fixes clap-rs#2005
`structopt` originally allowed ``` pub enum Opt { Daemon(DaemonCommand), } pub enum DaemonCommand { Start, Stop, } ``` This was partially broken in clap-rs#1681 where `$ cmd daemon start` works but `cmd daemon`, panics. Originally, `structopt` relied on exposing the implementation details of a derived type by providing a `is_subcommand` option, so we'd know whether to provide `SubcommandRequiredElseHelp` or not. This was removed in clap-rs#1681 Fixes clap-rs#2005
Not-yet-working-but-almost-there "multiple traits" approach. More or less done, what's left is to catch some bugs and adapt tests/examples.
For the record: it took so long because of RL stuff (who would have thought?) and because [there was a detailed description of the experience I've had here, but it was deleted because it contained a lot of profanity and emotional notes].
As the only person alive that understands how the derive works (if you won't blow your own horn, nobody will do it for you, yeah), I'd like to made a statement: we Do need the refactoring.