1 use clap::{Arg, ArgAction, ArgMatches, Command};
2
occurrences_as_vec_vec<'a>(m: &'a ArgMatches, name: &str) -> Vec<Vec<&'a String>>3 fn occurrences_as_vec_vec<'a>(m: &'a ArgMatches, name: &str) -> Vec<Vec<&'a String>> {
4 m.get_occurrences(name)
5 .unwrap()
6 .map(Iterator::collect)
7 .collect()
8 }
9
10 #[test]
grouped_value_works()11 fn grouped_value_works() {
12 let m = Command::new("cli")
13 .arg(
14 Arg::new("option")
15 .long("option")
16 .action(ArgAction::Set)
17 .num_args(1..)
18 .action(ArgAction::Append),
19 )
20 .try_get_matches_from([
21 "cli",
22 "--option",
23 "fr_FR:mon option 1",
24 "en_US:my option 1",
25 "--option",
26 "fr_FR:mon option 2",
27 "en_US:my option 2",
28 ])
29 .unwrap();
30 let grouped_vals = occurrences_as_vec_vec(&m, "option");
31 assert_eq!(
32 grouped_vals,
33 vec![
34 vec!["fr_FR:mon option 1", "en_US:my option 1",],
35 vec!["fr_FR:mon option 2", "en_US:my option 2",],
36 ]
37 );
38 }
39
40 #[test]
issue_1026()41 fn issue_1026() {
42 let m = Command::new("cli")
43 .arg(Arg::new("server").short('s').action(ArgAction::Set))
44 .arg(Arg::new("user").short('u').action(ArgAction::Set))
45 .arg(
46 Arg::new("target")
47 .long("target")
48 .action(ArgAction::Set)
49 .num_args(1..)
50 .action(ArgAction::Append),
51 )
52 .try_get_matches_from([
53 "backup", "-s", "server", "-u", "user", "--target", "target1", "file1", "file2",
54 "file3", "--target", "target2", "file4", "file5", "file6", "file7", "--target",
55 "target3", "file8",
56 ])
57 .unwrap();
58 let grouped_vals = occurrences_as_vec_vec(&m, "target");
59 assert_eq!(
60 grouped_vals,
61 vec![
62 vec!["target1", "file1", "file2", "file3"],
63 vec!["target2", "file4", "file5", "file6", "file7",],
64 vec!["target3", "file8"]
65 ]
66 );
67 }
68
69 #[test]
grouped_value_long_flag_delimiter()70 fn grouped_value_long_flag_delimiter() {
71 let m = Command::new("myapp")
72 .arg(
73 Arg::new("option")
74 .long("option")
75 .action(ArgAction::Set)
76 .value_delimiter(',')
77 .num_args(1..)
78 .action(ArgAction::Append),
79 )
80 .try_get_matches_from(vec![
81 "myapp",
82 "--option=hmm",
83 "--option=val1,val2,val3",
84 "--option",
85 "alice,bob",
86 ])
87 .unwrap();
88 let grouped_vals = occurrences_as_vec_vec(&m, "option");
89 assert_eq!(
90 grouped_vals,
91 vec![
92 vec!["hmm"],
93 vec!["val1", "val2", "val3"],
94 vec!["alice", "bob"]
95 ]
96 );
97 }
98
99 #[test]
grouped_value_short_flag_delimiter()100 fn grouped_value_short_flag_delimiter() {
101 let m = Command::new("myapp")
102 .arg(
103 Arg::new("option")
104 .short('o')
105 .action(ArgAction::Set)
106 .value_delimiter(',')
107 .num_args(1..)
108 .action(ArgAction::Append),
109 )
110 .try_get_matches_from(vec!["myapp", "-o=foo", "-o=val1,val2,val3", "-o=bar"])
111 .unwrap();
112 let grouped_vals = occurrences_as_vec_vec(&m, "option");
113 assert_eq!(
114 grouped_vals,
115 vec![vec!["foo"], vec!["val1", "val2", "val3"], vec!["bar"]]
116 );
117 }
118
119 #[test]
grouped_value_positional_arg()120 fn grouped_value_positional_arg() {
121 let m = Command::new("multiple_values")
122 .arg(
123 Arg::new("pos")
124 .help("multiple positionals")
125 .action(ArgAction::Set)
126 .num_args(1..),
127 )
128 .try_get_matches_from(vec![
129 "myprog", "val1", "val2", "val3", "val4", "val5", "val6",
130 ])
131 .unwrap();
132 let grouped_vals = occurrences_as_vec_vec(&m, "pos");
133 assert_eq!(
134 grouped_vals,
135 vec![vec!["val1", "val2", "val3", "val4", "val5", "val6"]]
136 );
137 }
138
139 #[test]
grouped_value_multiple_positional_arg()140 fn grouped_value_multiple_positional_arg() {
141 let m = Command::new("multiple_values")
142 .arg(Arg::new("pos1").help("multiple positionals"))
143 .arg(
144 Arg::new("pos2")
145 .help("multiple positionals")
146 .action(ArgAction::Set)
147 .num_args(1..),
148 )
149 .try_get_matches_from(vec![
150 "myprog", "val1", "val2", "val3", "val4", "val5", "val6",
151 ])
152 .unwrap();
153 let grouped_vals = occurrences_as_vec_vec(&m, "pos2");
154 assert_eq!(
155 grouped_vals,
156 vec![vec!["val2", "val3", "val4", "val5", "val6"]]
157 );
158 }
159
160 #[test]
grouped_value_multiple_positional_arg_last_multiple()161 fn grouped_value_multiple_positional_arg_last_multiple() {
162 let m = Command::new("multiple_values")
163 .arg(Arg::new("pos1").help("multiple positionals"))
164 .arg(
165 Arg::new("pos2")
166 .help("multiple positionals")
167 .action(ArgAction::Set)
168 .num_args(1..)
169 .last(true),
170 )
171 .try_get_matches_from(vec![
172 "myprog", "val1", "--", "val2", "val3", "val4", "val5", "val6",
173 ])
174 .unwrap();
175 let grouped_vals = occurrences_as_vec_vec(&m, "pos2");
176 assert_eq!(
177 grouped_vals,
178 vec![vec!["val2", "val3", "val4", "val5", "val6"]]
179 );
180 }
181
182 #[test]
grouped_interleaved_positional_values()183 fn grouped_interleaved_positional_values() {
184 let cmd = clap::Command::new("foo")
185 .arg(clap::Arg::new("pos").num_args(1..))
186 .arg(
187 clap::Arg::new("flag")
188 .short('f')
189 .long("flag")
190 .action(ArgAction::Set)
191 .action(ArgAction::Append),
192 );
193
194 let m = cmd
195 .try_get_matches_from(["foo", "1", "2", "-f", "a", "3", "-f", "b", "4"])
196 .unwrap();
197
198 let pos = occurrences_as_vec_vec(&m, "pos");
199 assert_eq!(pos, vec![vec!["1", "2"], vec!["3"], vec!["4"]]);
200
201 let flag = occurrences_as_vec_vec(&m, "flag");
202 assert_eq!(flag, vec![vec!["a"], vec!["b"]]);
203 }
204
205 #[test]
grouped_interleaved_positional_occurrences()206 fn grouped_interleaved_positional_occurrences() {
207 let cmd = clap::Command::new("foo")
208 .arg(clap::Arg::new("pos").num_args(1..))
209 .arg(
210 clap::Arg::new("flag")
211 .short('f')
212 .long("flag")
213 .action(ArgAction::Set)
214 .action(ArgAction::Append),
215 );
216
217 let m = cmd
218 .try_get_matches_from(["foo", "1", "2", "-f", "a", "3", "-f", "b", "4"])
219 .unwrap();
220
221 let pos = occurrences_as_vec_vec(&m, "pos");
222 assert_eq!(pos, vec![vec!["1", "2"], vec!["3"], vec!["4"]]);
223
224 let flag = occurrences_as_vec_vec(&m, "flag");
225 assert_eq!(flag, vec![vec!["a"], vec!["b"]]);
226 }
227
228 #[test]
issue_2171()229 fn issue_2171() {
230 let schema = Command::new("ripgrep#1701 reproducer")
231 .args_override_self(true)
232 .arg(
233 Arg::new("pretty")
234 .short('p')
235 .long("pretty")
236 .action(ArgAction::SetTrue),
237 )
238 .arg(
239 Arg::new("search_zip")
240 .short('z')
241 .long("search-zip")
242 .action(ArgAction::SetTrue),
243 );
244
245 let test_args = [
246 vec!["reproducer", "-pz", "-p"],
247 vec!["reproducer", "-pzp"],
248 vec!["reproducer", "-zpp"],
249 vec!["reproducer", "-pp", "-z"],
250 vec!["reproducer", "-p", "-p", "-z"],
251 vec!["reproducer", "-p", "-pz"],
252 vec!["reproducer", "-ppz"],
253 ];
254
255 for argv in test_args {
256 let _ = schema.clone().try_get_matches_from(argv).unwrap();
257 }
258 }
259