1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
use crate::{
matcher_needed::*,
parselib::{build_possible_flags, get_seeked_first, multi_seek_eq, seek_end_of_options},
};
/// `FlagMatcher` is used to match flags in command-line arguments.
///
/// Flags typically start with `-` or `--` (e.g., `-h`, `--help`),
/// and do not carry additional values. This matcher is responsible for finding
/// these flags in the argument list, taking into account that flags after `--`
/// (end-of-options marker) should not be matched.
pub struct FlagMatcher;
impl Matcher for FlagMatcher {
fn on_match_one(
args: &[MaskedArg],
style: &ParserStyle,
arg_info: &PickerArgInfo,
) -> Option<usize> {
let possible_flags = build_possible_flags(style, arg_info);
let flag_refs: Vec<&str> = possible_flags.iter().map(|s| s.as_str()).collect();
let end_of_options = seek_end_of_options(args, style);
let result = get_seeked_first(multi_seek_eq(args, &flag_refs, style.case_sensitive));
match (end_of_options, result) {
(Some(end), Some(current)) if current > end => None,
_ => result,
}
}
fn on_match_all(
args: &[MaskedArg],
style: &ParserStyle,
arg_info: &PickerArgInfo,
) -> Vec<usize> {
let possible_flags = build_possible_flags(style, arg_info);
single_pass_match_all(args, style, &possible_flags)
}
}
/// Single-pass match: finds the `--` marker and matching flags in one iteration.
fn single_pass_match_all(
args: &[MaskedArg],
style: &ParserStyle,
possible_flags: &[String],
) -> Vec<usize> {
let flag_refs: Vec<&str> = possible_flags.iter().map(|s| s.as_str()).collect();
let eoo = style.end_of_options;
let case_sensitive = style.case_sensitive;
let mut end_pos: Option<usize> = None;
let mut matches: Vec<usize> = Vec::new();
for arg in args {
if end_pos.is_none() {
let is_eoo = if case_sensitive {
arg.raw == eoo
} else {
arg.raw.eq_ignore_ascii_case(eoo)
};
if is_eoo {
end_pos = Some(arg.raw_idx);
continue;
}
}
// Only match flags before the end-of-options marker.
if end_pos.is_none() {
let matched = if case_sensitive {
flag_refs.contains(&arg.raw)
} else {
flag_refs.iter().any(|s| arg.raw.eq_ignore_ascii_case(s))
};
if matched {
matches.push(arg.raw_idx);
}
}
}
matches
}
|