-
-
Notifications
You must be signed in to change notification settings - Fork 1.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
Tracking issue CustomDerive #146
Comments
RustcSerialize/Deserialize? Serde2? |
I'm thinking more about creating a i.e. imagine all valid options are set the same as they are now, but instead of using As a secondary feature, it would be nice to actually serialize basic types using any of the above listed methods. |
I think @james-darkfox is asking what kind of library we would use if we are going to do this. I don't think it is possible without library and without syntax extension because of the custom fields. |
No syntax extension required. We have macros for this already. I could modify my builder macro to build a Note: This also makes the default value accessible to the builder macro. 😉 For decoding into types. This depends on what types we want to support? I don't think we'd need RustcSerialize/deser, or serde2 as they are for more generic purposes. Currently we only have strings; I'd expect integers (u8 i8 u16 i16 u32 i32 u64 i64 f32 f64...), booleans (1/0, true/false, yes/no), paths, ???, Note: Inherit validation ensures that "foo" is not a number and as such not a valid value for an argument accepting a number. |
@james-darkfox Actually, that works quite nice, besides forcing user to use macro if they want the custom struct (which I think is somewhat trivial because the builder macro is simple enough). |
Doesn't force the user to use it. As they can always use the current behavior or manually construct their own struct and |
I'm actually thinking about how clap could be refactored down... It is REALLY quite a large implementation for what everyone would like to call a simple task. Docopt was initially created to be simple, quick, and easy. I have a number of ideas that would refactor clap down heavily but this would be a VERY breaking change. |
@james-darkfox I see what you are getting at now. On the other hand, you can always open up issues with RFC tag. |
@sru Maybe when I have the basic concepts working. I'm currently throwing together some ideas for a minimal clap implementation. Tackling the problem much the same way as I have for my own builder & macro which constructs a dummy registry of crates. Notably: Once I have this quick hack ready. We will see which of the following is better: porting the ideas over to the current clap (preferable); or extending the minimal implementation (much more work). |
Thanks to @kamalmarhubi at RustBelt, but thanks to macros 1.1 this may be a possibility. I need to look into this further! |
@kbknapp Macros 1.1 are no better for this job than normal macros. Feel free to jump on IRC |
So I was playing round with something like this over the last week, basically a macros 1.1 builder that generates a #[derive(StompCommand)]
pub struct MyApp {
/// Sets a custom config file
#[stomp(short = 'c', value_name = "FILE")]
config: Option<String>,
}
fn main() {
let app = MyApp::parse();
if let Some(c) = app.config {
println!("Value for config: {}", c);
}
} There's a full rewrite of the main clap example at https://github.com/Nemo157/stomp-rs/blob/master/examples/01b_quick_example.rs along with a rewrite of the app I'm currently using clap in at Nemo157/ipfsdc-rs@41e5d5f One of the nice things about this is how much can be inferred from just the types given; if something is a
|
@Nemo157 yes! That's what I had in mind. Awesome that you put together a proof of concept. |
These are all really cool ideas. :-) |
(Since 1.15 and macros 1.1 is landing soon, I'd love if we can make the CLI story in Rust beautiful!) |
@Nemo157 I can't believe I missed these comments somehow! Apologies to both you and @kamalmarhubi! This is a very cool proof of concept that's super exciting! I think this could either be continued in There are, however, two parts that could have potential issues
This is amazing work, and I'm really excited by it! |
That explains a lot! I'd be willing to help with merging this into clap and looking over the API for other changes like you suggested. |
I'd love for this to land within the 1.15 cycle! |
Absolutely, me too! If we can resolve those outstanding questions above (values in order, ensuring The subcommand enum not being inlined I'm fine with. I forgot to mention in the last post the example above merges two distinct ideas into one, but I'd also want the ability to do one or the other and not be forced to use both. I haven't dug into the source yet, so if it's already possible ignore this comment 😜 What I mean is, I view both of these as distinct ideas (also, I'm using
Being able to do these two things separatly would greatly increase adoptability. i.e. "I've already got an Likewise, if for some unknown reason they don't want to use the |
😃 I would definitely be happy to make this a part of
At the moment, definitely not. I was basically using my application and the primary
Yeah, again because of the test cases I was using I did not consider that at all. Hopefully, at least for the case where the user both generates the
Depends which way you mean, an anonymous enum in the parent command would be cool, but probably not really doable without proper anonymous enum support in Rust. An enum with struct variants definitely should be possible, it would result in some massive generated code blocks, but that shouldn't be too bad, and could be fixed in the future with types for enum variants allowing delegating variant specific parsing.
The trait doesn't allow it, but the macro is basically following two distinct paths for each so would be simple to split the trait for it. Also, one thought I had soon after I implemented this was that the macro is doing too much. It should be possible to split a lot of what the macro is doing based on types (which is actually based on type names, so could very easily be broken with type aliases etc.) out to trait implementations. For example something like I think I should have some time this week I could spend on this, I can definitely try and do a quick port into the |
Just pushed a branch with a quick port of the changes into the Currently it fails to build the example, and I'm not sure exactly why. There was some changes to
|
That's definitely off the table now that procedural macros can't modify the item at all. |
I think the |
It's currently allowed in master (and beta): https://github.com/rust-lang/rust/blob/master/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs |
Looks like it might be related to some of the features I was still using, removed them all and |
The part that people have been really asking for is the Either way this will eventually merge as |
Excellent!!! I'm going to be looking through this over the next few days, feel free to continue working on it, and if I get some time I'll probably push some commits as well. Full disclosure, I'll be traveling pretty heavily for the next two weeks so my replies may not be instant 😉 My initial bikeshed thoughts are to move the traits into a For UX, I think So the example would go to: /// Does awesome things.
#[derive(App, FromArgMatches)]
#[clap(name = "MyApp", version = "1.0")]
#[clap(author = "Nemo157 <[email protected]>")]
pub struct MyApp {
/// Sets a custom config file
#[clap(short = "c", value_name = "FILE")]
config: Option<String>,
/// Sets an optional output file
#[clap(index = "1")]
output: Option<String>,
/// Turn debugging information on
#[clap(counted, short = "d", long = "debug")]
debug_level: u64,
#[clap(subcommand)]
subcommand: Option<Commands>,
}
#[derive(SubCommands)]
pub enum Commands {
Test(Test),
}
/// does testing things
#[derive(App, FromArgMatches)]
pub struct Test {
/// lists test values
#[clap(short = "l")]
list: bool,
} I'm going to go ahead and submit a PR so we can use it for tracking purposes and as a standard place for easily seeing the diffs. |
#835 is open. Feel free to discuss exact implementation details in that PR, but also know that I'll be keeping that PR quite clean and deleting old comments and such as well as updating the OP to keep track of current discussion. If talk around abstract implementation details need to continue to happen, I'd prefer to use this issue for historical data reasons. |
This issue was moved to kbknapp/clap-derives#4 |
To Do
Derive FromArgMatches
#[derive(FromArgMatches)]
Default
where possible and document such)Derive App
#[derive(App)]
Derive Subcommands
#[derive(SubCommands)]
Derive SubcommandFromArgMatches
#[derive(DefineSubCommands)]
Derive TryFromArgMatches
#[derive(FromArgMatches)]
The text was updated successfully, but these errors were encountered: