1use clap::{arg, Arg, ArgAction, Command}; 2 3#[test] 4fn 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] 28fn 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] 55fn 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] 87fn 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] 112fn 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] 136fn 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")] 174fn 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