-
-
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
Using index_of()/indices_of() with optional arguments that take optional values #2419
Comments
Currently, we only support indices for values, not arguments. This will require some design work for what the API / behavior should be.
Could you elaborate on your use case for why the order they are set matters? Its helpful to have the wider context on these types of things.
How are you getting the index with structopt? |
I'm trying to match the behavior of a C program where the order matters. That isn't terribly uncommon for C programs; e.g.
Something like this (see docs):
|
I'm running into a related issue (#4908). In my use case there are multiple configuration layers that override each other (e.g.
Is this still true? The docs say:
FWIW, this would be the behaviour I'd expect: use clap;
fn main() {
use clap::{Arg, Command};
let app = Command::new("Basic Test")
.arg(Arg::new("optional")
.short('o')
.num_args(0..=1))
.arg(Arg::new("flag")
.short('f')
.num_args(0))
.arg(Arg::new("value")
.short('v')
.num_args(1));
let matches = app.clone().get_matches_from(&["", "-f"]);
assert_eq!(matches.index_of("flag"), Some(1));
let matches = app.clone().get_matches_from(&["", "-v", "42"]);
assert_eq!(matches.index_of("value"), Some(2));
let matches = app.clone().get_matches_from(&["", "-o", "42"]);
assert_eq!(matches.index_of("optional"), Some(2));
let matches = app.clone().get_matches_from(&["", "-o"]);
assert_eq!(matches.index_of("optional"), Some(1)); // Fails, returns None.
} I've drafted up PR #4909 to implement this. |
When an argument takes an optional value (e.g. `.num_args(0..=1)`), make sure an index is pushed: * when a value is specified, for each value * when no value is specified, for the option, similar to a flag. Note: this means that a MatchedArg's `num_vals` no longer necessarily matches the number of indices. Fixes clap-rs#2419
When an argument takes an optional value (e.g. `.num_args(0..=1)`), make sure an index is pushed: * when a value is specified, for each value * when no value is specified, for the option, similar to a flag. Note: this means that a MatchedArg's `num_vals` no longer necessarily matches the number of indices. Fixes clap-rs#2419
Perhaps opening a PR was the wrong thing to do here -- what would be the best way to help move this forward? |
Nuance: it is true for When you do
That works for you, but what about others? Users are relying on a mapping between values and indices.
Examine the relevant use cases for indices and come up with a proposal that meets them. If its a breaking change, evaluate if there is a way to opt into it now or whether we have to wait on clap v5.0.0 for this. |
Right, so, use cases. There seem to be two disjunct use cases here:
I currently see the following ways forward:
A mixture of these approaches could also be possible, e.g. going with 1.) for clap v4 and implementing 3.) for clap v5 and feature-gating it for clap v4, then deprecating 1.) in clap v5. I'd be curious to see what aspects I missed, because I'm sure there are some. |
For some extra context, we did not expose grouping-by-occurrence until clap v4.1.0 (see #2924), so index per occurrence was not possible until then. An extra challenge in all of this is #3846. Would occurrence indexes (whether replacing value indexes or parallel to it) make that issue harder, easier, or no difference? |
TL;DR: Long form: Current value indices form a subset of the proposed occurrence indices, every value is part of an ocurrence, but not all ocurrences have values:
Therefore, using ocurrence indices instead of value indices definitely don't make it harder to find an index for every value (i.e. #3846). Now consider (since I'm not sure how to do #[derive(Args)]
struct MyArgs {
// --arg1 --arg1=42 -> vec![None, Some(42)]
#[clap(short, long, value_source)]
pub arg1: Vec<Value<Option<u8>>>,
// --arg2 --arg2 foo --arg2 foo bar -> vec![vec![], vec!["foo"], vec!["foo", "bar"]]
#[clap(short, long, value_source)]
pub arg1: Vec<Value<Vec<String>>>,
} In these cases, finding an index to assign to the empty values would be possible using occurrence indices, but not possible using value indices. (i.e. making #3864 easier) However, since args taking a variable number of values seem to not be supported like that using derive (unless I'm mistaken?) at the moment, I'd say at the moment it doesn't make a difference. |
Please complete the following tasks
Describe your use case
I have multiple optional arguments with optional values. If several of them were specified without passing a value, I want to determine the indices of the arguments so I can find out which one was specified first. However, it seems that this is one of the few cases where
Arg::index_of()
/Arg::indices_of()
doesn't work.A simple example can be found below.
Describe the solution you'd like
Ideally,
Arg::index_of()
would work for arguments with optional values.Alternatives, if applicable
Perhaps a new method, say
Args::index_of_opt()
(which would return the index of the flag like-a
or --all`, instead of the value) could be added?Additional Context
I'm using
structopt
, but I've translated this toclap
code.Example with clap 2.33:
This produces the following output:
Updated for clap 3 (produces the same output as the above version when run against the latest master):
The text was updated successfully, but these errors were encountered: