Skip to content

Commit 3683e2c

Browse files
committed
fix(parser): Allow one-off self-overrides
bat needed this. See also #4261
1 parent 2d78749 commit 3683e2c

3 files changed

Lines changed: 32 additions & 11 deletions

File tree

src/builder/debug_asserts.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -686,11 +686,6 @@ fn assert_arg(arg: &Arg) {
686686
"Argument '{}' cannot conflict with itself",
687687
arg.get_id(),
688688
);
689-
assert!(
690-
!arg.overrides.iter().any(|x| *x == arg.id),
691-
"Argument '{}' cannot override itself, its the default",
692-
arg.get_id(),
693-
);
694689

695690
assert_eq!(
696691
arg.get_action().takes_values(),

src/parser/parser.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,9 @@ impl<'cmd> Parser<'cmd> {
11801180
self.cur_idx.set(self.cur_idx.get() + 1);
11811181
debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
11821182
}
1183-
if matcher.remove(&arg.id) && !self.cmd.is_args_override_self() {
1183+
if matcher.remove(&arg.id)
1184+
&& !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1185+
{
11841186
return Err(ClapError::argument_conflict(
11851187
self.cmd,
11861188
arg.to_string(),
@@ -1221,7 +1223,9 @@ impl<'cmd> Parser<'cmd> {
12211223
raw_vals
12221224
};
12231225

1224-
if matcher.remove(&arg.id) && !self.cmd.is_args_override_self() {
1226+
if matcher.remove(&arg.id)
1227+
&& !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1228+
{
12251229
return Err(ClapError::argument_conflict(
12261230
self.cmd,
12271231
arg.to_string(),
@@ -1240,7 +1244,9 @@ impl<'cmd> Parser<'cmd> {
12401244
raw_vals
12411245
};
12421246

1243-
if matcher.remove(&arg.id) && !self.cmd.is_args_override_self() {
1247+
if matcher.remove(&arg.id)
1248+
&& !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
1249+
{
12441250
return Err(ClapError::argument_conflict(
12451251
self.cmd,
12461252
arg.to_string(),

tests/builder/posix_compatible.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,36 @@
11
use clap::{arg, error::ErrorKind, Arg, ArgAction, Command};
22

33
#[test]
4-
#[should_panic = "Argument 'flag' cannot override itself"]
54
fn flag_overrides_itself() {
6-
Command::new("posix")
5+
let res = Command::new("posix")
76
.arg(
87
arg!(--flag "some flag"
98
)
109
.action(ArgAction::SetTrue)
1110
.overrides_with("flag"),
1211
)
13-
.build();
12+
.try_get_matches_from(vec!["", "--flag", "--flag"]);
13+
assert!(res.is_ok(), "{}", res.unwrap_err());
14+
let m = res.unwrap();
15+
assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
16+
}
17+
18+
#[test]
19+
fn option_overrides_itself() {
20+
let res = Command::new("posix")
21+
.arg(
22+
arg!(--opt <val> "some option")
23+
.required(false)
24+
.overrides_with("opt"),
25+
)
26+
.try_get_matches_from(vec!["", "--opt=some", "--opt=other"]);
27+
assert!(res.is_ok(), "{}", res.unwrap_err());
28+
let m = res.unwrap();
29+
assert!(m.contains_id("opt"));
30+
assert_eq!(
31+
m.get_one::<String>("opt").map(|v| v.as_str()),
32+
Some("other")
33+
);
1434
}
1535

1636
#[test]

0 commit comments

Comments
 (0)