-
-
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
Custom collections #3114
Comments
Comment by TeXitoi You can do https://github.com/TeXitoi/structopt/blob/master/examples/keyvalue.rs It may be interesting to be able to choose to use a dedicated collection, but that's really not trivial to propose a great syntax. Maybe something like: fn parse_key_val(s: &str) -> Result<(String, String), String> {
unimplemented!()
}
struct Opt {
#[structopt(short = "D", collect(try_from_str = "parse_key_val"))]
defines: HashMap<String, String>,
} |
Comment by vorner I understand I can „force“ it to do what I want with custom functions and so on. My point was more about if structopt should be able to handle these out of the box. If there should be a way for it to recognize these other collections (sets could be easy) and do The Right Thing. But I admit I don't have a concrete idea how that should work exactly ‒ because I might want to specify how the separator looks like, or how to specify the parser for both left and right side. Maybe having a special-case of Anyway, that's mostly brainstorming. |
Comment by TeXitoi As structopt works at the macro level, there is no type information. You can't check if some type implement |
Comment by vorner I understand you can't check if the type implements I understand having many special cases isn't good for the code. So if that wouldn't look good, does it make sense to provide some common parser functions as part of the library, so one could reuse them instead of implementing (I'm talking about the one from the example). The |
Comment by pksunkara What about adding support for |
Comment by CreepySkeleton I'm not a big fun of specializing types that are not in |
Comment by TeXitoi I agree, and I'd prefere to support all the collections implementing FromIterator. |
Comment by CreepySkeleton Hey, @TeXitoi , care to join https://rust-lang.zulipchat.com/#narrow/stream/220302-wg-cli ? |
Comment by pickfire Any news on this? |
Comment by TeXitoi No, nothing new AFAIK. |
Comment by CreepySkeleton @pickfire Could you explain what you mean? A piece of pseudocode would help a lot |
Comment by pickfire #[derive(StructOpt)]
struct Opt {
#[structopt(..., try_from_str = parse_format_string)]
// without format: Format,
format: Vec<Token>,
}
// without fn parse_format_string(input: &str) -> Format {
fn parse_format_string(input: &str) -> Vec<Token> {
...
}
// without type Format = Vec<Token>; |
Comment by CreepySkeleton This is not how validators in clap work: they check arguments one by one. |
Comment by pickfire No, I mean the function needs to return |
Comment by rustonaut I believe a solution to "custom" collections should:
I think a good idea would be to first initialize a empty container (using some For example something like following rust sketch: use thiserror::Error;
use std::collections::HashMap;
[derive(Debug, StructOpt)[
struct Options {
#[structopt(
short="k",
// implies takes_value=true,multiple=true
try_fold(fold_kv_map),
)]
kv_map: HashMap<String, String>
}
fn fold_kv_map(
mut state: HashMap<String, String>,
raw: &str
) -> Result<HashMap<String, String>, Error> {
let (key, value) = parse_key_value(raw)?;
let old = state.insert(key.to_owned(), value.to_owned());
if old.is_some() {
Err(Error::DuplicateKey { key: key.to_owned() })
} else {
Ok(state)
}
}
#[derive(Debug, Error)]
enum Error {
#[error("...")]
MalformedKVPair,
#[error("...")]
DuplicateKey { key: String }
} By default Alternatively something like:
To not rely on EDIT: Shortened sketch example. I myself have run recently into this issue when I needed arguments like |
This is a pretty good feature, as we can use it for directly deriving set relations with multiple values. Right now I have iterate through the vector then collect them as HashSet/BTreeSet which incurs extra allocation cost, although some may argue I can just use into_iter to consume the vector, this is not ergonomic to manually do this all the time from my perspective. Also, having set support would let us have a nice little feature to preempt errors early about duplicated values, by first cloning the vector (or the iterator) and then cast it into a set data structure. Thanks to set theory, if the length of both container doesn't match, there must be duplicates. Based off this we can have more optimization opportunities such as saving the length of the original vector and then convert it into a set directly. |
I came up with the following solution for supporting a custom collection (even a little bit more advanced). |
The first step for general support is defining how users interact with it. Ideally, we'd just leverage Maybe #3912 or #4626 could help
You are welcome to create an API proposal for this
This would be more of an optimization than anything else. I think it would be great to do eventually but it will be a lot of work and can come at the risk (depending on the implementation) of losing support for things like |
It would be great if I could parse |
Is deciding on a specific collection type, or allowing for customization, even necessary? Are there performance constraints for command-line parsing that discourage the requirement to move values from say a Isn't As a user I still would probably want a simple string map value parser behind a feature flag to avoid copy and pasting the example in projects if validation isn't necessary or possible at command line argument parsing time. Longer term if the idea makes sense, it seems that some refactoring would be involved, but I don't have an idea nor opinion on how |
We have baked in
|
Issue by vorner
Friday Mar 09, 2018 at 11:20 GMT
Originally opened as TeXitoi/structopt#79
Hello
I discovered I'm missing one use case of command line parsing. Something like the
-D
parameter of GCC, where you can do-D NDEBUG=1
‒ basically way to parse key-value pairs.I'm not sure if there needs to be some support from clap, but AFAIK clap just returns bunch of strings for each parameter (if multiple are allowed) and type-conversion is up to structop.
So I was wondering, similar as structopt provides
Vec<T>
, it could be extended to eitherVec<(Key, Value)>
orHashMap/BTreeMap<Key, Value>
.Does that make sense? Or is a better place to add such feature?
The text was updated successfully, but these errors were encountered: