1 use clap::{arg, Arg, ArgAction, Command};
2
3 #[test]
issue_1076()4 fn issue_1076() {
5 let mut cmd = Command::new("myprog")
6 .arg(
7 Arg::new("GLOBAL_ARG")
8 .long("global-arg")
9 .help("Specifies something needed by the subcommands")
10 .global(true)
11 .action(ArgAction::Set)
12 .default_value("default_value"),
13 )
14 .arg(
15 Arg::new("GLOBAL_FLAG")
16 .long("global-flag")
17 .help("Specifies something needed by the subcommands")
18 .global(true)
19 .action(ArgAction::Set),
20 )
21 .subcommand(Command::new("outer").subcommand(Command::new("inner")));
22 let _ = cmd.try_get_matches_from_mut(vec!["myprog"]);
23 let _ = cmd.try_get_matches_from_mut(vec!["myprog"]);
24 let _ = cmd.try_get_matches_from_mut(vec!["myprog"]);
25 }
26
27 #[test]
propagate_global_arg_in_subcommand_to_subsubcommand_1385()28 fn propagate_global_arg_in_subcommand_to_subsubcommand_1385() {
29 let m1 = Command::new("foo")
30 .subcommand(
31 Command::new("sub1")
32 .arg(
33 Arg::new("arg1")
34 .long("arg1")
35 .action(ArgAction::Set)
36 .global(true),
37 )
38 .subcommand(Command::new("sub1a")),
39 )
40 .try_get_matches_from(["foo", "sub1", "--arg1", "v1", "sub1a"])
41 .unwrap();
42 assert_eq!(
43 "v1",
44 m1.subcommand_matches("sub1")
45 .unwrap()
46 .subcommand_matches("sub1a")
47 .unwrap()
48 .get_one::<String>("arg1")
49 .map(|v| v.as_str())
50 .unwrap()
51 );
52 }
53
54 #[test]
propagate_global_arg_to_subcommand_in_subsubcommand_2053()55 fn propagate_global_arg_to_subcommand_in_subsubcommand_2053() {
56 let m = Command::new("opts")
57 .arg(arg!(--"global-flag").global(true))
58 .arg(arg!(--"global-str" <str>).global(true))
59 .subcommand(
60 Command::new("test")
61 .arg(arg!(--"sub-flag").global(true))
62 .arg(arg!(--"sub-str" <str>).global(true))
63 .subcommand(Command::new("test")),
64 )
65 .try_get_matches_from([
66 "cmd",
67 "test",
68 "test",
69 "--global-flag",
70 "--global-str",
71 "hello",
72 "--sub-flag",
73 "--sub-str",
74 "world",
75 ])
76 .unwrap();
77 assert_eq!(
78 Some("world"),
79 m.subcommand_matches("test")
80 .unwrap()
81 .get_one::<String>("sub-str")
82 .map(|v| v.as_str())
83 );
84 }
85
86 #[test]
global_arg_available_in_subcommand()87 fn global_arg_available_in_subcommand() {
88 let m = Command::new("opt")
89 .args([
90 Arg::new("global")
91 .global(true)
92 .long("global")
93 .action(ArgAction::SetTrue),
94 Arg::new("not")
95 .global(false)
96 .long("not")
97 .action(ArgAction::SetTrue),
98 ])
99 .subcommand(Command::new("ping"))
100 .try_get_matches_from(["opt", "ping", "--global"])
101 .unwrap();
102
103 assert!(*m.get_one::<bool>("global").expect("defaulted by clap"));
104 assert!(*m
105 .subcommand_matches("ping")
106 .unwrap()
107 .get_one::<bool>("global")
108 .expect("defaulted by clap"));
109 }
110
111 #[test]
deeply_nested_discovery()112 fn deeply_nested_discovery() {
113 let cmd = Command::new("a")
114 .arg(arg!(--"long-a").global(true).action(ArgAction::SetTrue))
115 .subcommand(
116 Command::new("b")
117 .arg(arg!(--"long-b").global(true).action(ArgAction::SetTrue))
118 .subcommand(
119 Command::new("c")
120 .arg(arg!(--"long-c").global(true).action(ArgAction::SetTrue))
121 .subcommand(Command::new("d")),
122 ),
123 );
124
125 let m = cmd
126 .try_get_matches_from(["a", "b", "c", "d", "--long-a", "--long-b", "--long-c"])
127 .unwrap();
128 assert!(*m.get_one::<bool>("long-a").expect("defaulted by clap"));
129 let m = m.subcommand_matches("b").unwrap();
130 assert!(*m.get_one::<bool>("long-b").expect("defaulted by clap"));
131 let m = m.subcommand_matches("c").unwrap();
132 assert!(*m.get_one::<bool>("long-c").expect("defaulted by clap"));
133 }
134
135 #[test]
global_overrides_default()136 fn global_overrides_default() {
137 let cmd = Command::new("test")
138 .arg(
139 Arg::new("name")
140 .long("name")
141 .global(true)
142 .action(ArgAction::Set)
143 .default_value("from_default"),
144 )
145 .subcommand(Command::new("sub"));
146
147 let m = cmd.clone().try_get_matches_from(["test"]).unwrap();
148 assert_eq!(
149 m.get_one::<String>("name").unwrap().as_str(),
150 "from_default"
151 );
152
153 let m = cmd
154 .clone()
155 .try_get_matches_from(["test", "--name", "from_arg"])
156 .unwrap();
157 assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
158
159 let m = cmd
160 .clone()
161 .try_get_matches_from(["test", "--name", "from_arg", "sub"])
162 .unwrap();
163 assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
164
165 let m = cmd
166 .clone()
167 .try_get_matches_from(["test", "sub", "--name", "from_arg"])
168 .unwrap();
169 assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
170 }
171
172 #[test]
173 #[cfg(feature = "env")]
global_overrides_env()174 fn global_overrides_env() {
175 std::env::set_var("GLOBAL_OVERRIDES_ENV", "from_env");
176
177 let cmd = Command::new("test")
178 .arg(
179 Arg::new("name")
180 .long("name")
181 .global(true)
182 .action(ArgAction::Set)
183 .env("GLOBAL_OVERRIDES_ENV"),
184 )
185 .subcommand(Command::new("sub"));
186
187 let m = cmd.clone().try_get_matches_from(["test"]).unwrap();
188 assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_env");
189
190 let m = cmd
191 .clone()
192 .try_get_matches_from(["test", "--name", "from_arg"])
193 .unwrap();
194 assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
195
196 let m = cmd
197 .clone()
198 .try_get_matches_from(["test", "--name", "from_arg", "sub"])
199 .unwrap();
200 assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
201
202 let m = cmd
203 .clone()
204 .try_get_matches_from(["test", "sub", "--name", "from_arg"])
205 .unwrap();
206 assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
207 }
208