You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am developing a GNU rm-like tool and need to support options like:
-i: prompt always
-I: prompt once
-f: force
--interactive[=WHEN]: prompt according to WHEN: never, once (-I), or always (-i); without WHEN, prompt always
I am following the GNU "last one wins" precedence rule. When two mutually exclusive options are provided (e.g., -i and -f), the last one specified on the command line should override the previous ones.
Additionally, I want to extend this behavior to support levels for interactive and force options. For example, -i -i would set the interactive level = 2, and -fff would set the force level = 3.
Clap handles the "last one wins" behavior using overrides_with_all, and I used ArgAction::Count for level counting.
.arg(Arg::new(ARG_FORCE).short('f').long(ARG_FORCE).help("Ignore nonexistent files and arguments, never prompt").overrides_with_all(&[ARG_PROMPT_ALWAYS,ARG_PROMPT_ONCE,ARG_INTERACTIVE]).action(ArgAction::Count),).arg(Arg::new(ARG_PROMPT_ALWAYS).short('i').help("Prompt before every removal").overrides_with_all(&[ARG_PROMPT_ONCE,ARG_FORCE]).action(ArgAction::Count),).arg(Arg::new(ARG_PROMPT_ONCE).short('I').help("Prompt once before removing more than three files, or when removing recursively").overrides_with_all(&[ARG_PROMPT_ALWAYS,ARG_FORCE]).action(ArgAction::Count),)
However, implementing the long option --interactive=WHEN alongside short options like -i and -I poses challenges. Specifically:
-i cannot be aliased to --interactive=always
-I cannot be aliased to --interactive=once
Currently, Clap does not allow for traversing ArgMatches in a way that can respect option order, which is crucial for determining precedence in cases like rm -I --interactive=always -I, where -I should win, but it's difficult to ensure this given the current API.
Arg::new("interactive").long("interactive").help("Prompt according to WHEN: never, once (-I), or always (-i). Without WHEN, prompts always").value_name("WHEN").value_parser(arg_interactive_parser).num_args(0..=1).require_equals(true).default_missing_value("always").overrides_with_all(&[ARG_FORCE]).action(ArgAction::Append),
Describe the solution you'd like
I propose two features:
Support for ArgMatches Traversal
Traversing ArgMatches would allow me to check the order in which options were provided, making it possible to implement the "last one wins" precedence rule accurately.
Option Value Binding
This would allow short options to be bound to specific values of long options. For example, -i would be treated as an alias for --interactive=always, and -I would map to --interactive=once. This would provide an elegant solution to handle the complexity of combining long and short options with the same meaning.
Example (pseudo-code):
Arg::new("interactive").long("interactive").value_name("WHEN").value_parser(["always","once","never"]).bind_to("-i","always")// Bind short option -i to --interactive=always.bind_to("-I","once")// Bind short option -I to --interactive=once.bind(Fn)// Bind by Closure
In addition to allowing option precedence, this feature could benefit other tools that rely on complex option parsing and precedence rules. It would also make it easier to support aliasing of options and reduce manual argument handling for developers.
Alternatives, if applicable
An alternative would be to manually parse the arguments in sequence and manage conflicts ourselves, but this would result in more complex code, reduce the benefits of using Clap, and potentially introduce bugs. Supporting these features natively in Clap would be much cleaner and more reliable.
Please keep issues focused on a single feature. It helps keep the conversation focused and makes the state clear as we have a single status (close, rejected) for an issue.
Support for ArgMatches Traversal
Traversing ArgMatches would allow me to check the order in which options were provided, making it possible to implement the "last one wins" precedence rule accurately.
fn position_sensitive_flag(arg:Arg) -> Arg{// Flags don't track the position of each occurrence, so we need to emulate flags with// value-less options to get the same result
Huh, that shouldn't be the case anymore and we should be able to drop that part from the example
Option Value Binding
This would allow short options to be bound to specific values of long options. For example, -i would be treated as an alias for --interactive=always, and -I would map to --interactive=once. This would provide an elegant solution to handle the complexity of combining long and short options with the same meaning.
We previously had Arg::replace which ran into issues, see #2836. We'll need this more fleshed out to evaluate how to move forward.
Please complete the following tasks
Clap Version
4.5.11
Describe your use case
I am developing a GNU
rm
-like tool and need to support options like:-i
: prompt always-I
: prompt once-f
: force--interactive[=WHEN]
: prompt according to WHEN: never, once (-I
), or always (-i
); without WHEN, prompt alwaysI am following the GNU "last one wins" precedence rule. When two mutually exclusive options are provided (e.g.,
-i
and-f
), the last one specified on the command line should override the previous ones.Additionally, I want to extend this behavior to support levels for
interactive
andforce
options. For example,-i -i
would set theinteractive level = 2
, and-fff
would set theforce level = 3
.Clap handles the "last one wins" behavior using
overrides_with_all
, and I usedArgAction::Count
for level counting.However, implementing the long option
--interactive=WHEN
alongside short options like-i
and-I
poses challenges. Specifically:-i
cannot be aliased to--interactive=always
-I
cannot be aliased to--interactive=once
ArgMatches
in a way that can respect option order, which is crucial for determining precedence in cases likerm -I --interactive=always -I
, where-I
should win, but it's difficult to ensure this given the current API.Describe the solution you'd like
I propose two features:
Support for
ArgMatches
TraversalTraversing
ArgMatches
would allow me to check the order in which options were provided, making it possible to implement the "last one wins" precedence rule accurately.Option Value Binding
This would allow short options to be bound to specific values of long options. For example,
-i
would be treated as an alias for--interactive=always
, and-I
would map to--interactive=once
. This would provide an elegant solution to handle the complexity of combining long and short options with the same meaning.Example (pseudo-code):
In addition to allowing option precedence, this feature could benefit other tools that rely on complex option parsing and precedence rules. It would also make it easier to support aliasing of options and reduce manual argument handling for developers.
Alternatives, if applicable
An alternative would be to manually parse the arguments in sequence and manage conflicts ourselves, but this would result in more complex code, reduce the benefits of using Clap, and potentially introduce bugs. Supporting these features natively in Clap would be much cleaner and more reliable.
Additional Context
Related issue: #1206
The text was updated successfully, but these errors were encountered: