1#[cfg(feature = "cargo")]
15#[macro_export]
16macro_rules! crate_version {
17 () => {
18 env!("CARGO_PKG_VERSION")
19 };
20}
21
22#[cfg(feature = "cargo")]
42#[macro_export]
43macro_rules! crate_authors {
44 ($sep:expr) => {{
45 static AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
46 if AUTHORS.contains(':') {
47 static CACHED: std::sync::OnceLock<String> = std::sync::OnceLock::new();
48 let s = CACHED.get_or_init(|| AUTHORS.replace(':', $sep));
49 let s: &'static str = &*s;
50 s
51 } else {
52 AUTHORS
53 }
54 }};
55 () => {
56 env!("CARGO_PKG_AUTHORS")
57 };
58}
59
60#[cfg(feature = "cargo")]
73#[macro_export]
74macro_rules! crate_description {
75 () => {
76 env!("CARGO_PKG_DESCRIPTION")
77 };
78}
79
80#[cfg(feature = "cargo")]
102#[macro_export]
103macro_rules! crate_name {
104 () => {
105 env!("CARGO_PKG_NAME")
106 };
107}
108
109#[cfg(feature = "cargo")]
130#[macro_export]
131macro_rules! command {
132 () => {{
133 $crate::command!($crate::crate_name!())
134 }};
135 ($name:expr) => {{
136 let mut cmd = $crate::Command::new($name).version($crate::crate_version!());
137
138 let author = $crate::crate_authors!();
139 if !author.is_empty() {
140 cmd = cmd.author(author)
141 }
142
143 let about = $crate::crate_description!();
144 if !about.is_empty() {
145 cmd = cmd.about(about)
146 }
147
148 cmd
149 }};
150}
151
152#[cfg(not(feature = "cargo"))]
154#[macro_export]
155macro_rules! command {
156 () => {{
157 compile_error!("`cargo` feature flag is required");
158 }};
159 ($name:expr) => {{
160 compile_error!("`cargo` feature flag is required");
161 }};
162}
163
164#[doc(hidden)]
165#[macro_export]
166macro_rules! arg_impl {
167 ( @string $val:ident ) => {
168 stringify!($val)
169 };
170 ( @string $val:literal ) => {{
171 let ident_or_string_literal: &str = $val;
172 ident_or_string_literal
173 }};
174 ( @string $val:tt ) => {
175 ::std::compile_error!("Only identifiers or string literals supported");
176 };
177 ( @string ) => {
178 None
179 };
180
181 ( @char $val:ident ) => {{
182 let ident_or_char_literal = stringify!($val);
183 debug_assert_eq!(
184 ident_or_char_literal.len(),
185 1,
186 "Single-letter identifier expected, got {ident_or_char_literal}",
187 );
188 ident_or_char_literal.chars().next().unwrap()
189 }};
190 ( @char $val:literal ) => {{
191 let ident_or_char_literal: char = $val;
192 ident_or_char_literal
193 }};
194 ( @char ) => {{
195 None
196 }};
197
198 (
199 @arg
200 ($arg:expr)
201 --$long:ident
202 $($tail:tt)*
203 ) => {{
204 debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
205 debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
206
207 let mut arg = $arg;
208 let long = $crate::arg_impl! { @string $long };
209 if arg.get_id() == "" {
210 arg = arg.id(long);
211 }
212 let action = $crate::ArgAction::SetTrue;
213 let arg = arg
214 .long(long)
215 .action(action);
216 let arg = $crate::arg_impl! {
217 @arg (arg) $($tail)*
218 };
219 arg
220 }};
221 (
222 @arg
223 ($arg:expr)
224 --$long:literal
225 $($tail:tt)*
226 ) => {{
227 debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
228 debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
229
230 let mut arg = $arg;
231 let long = $crate::arg_impl! { @string $long };
232 if arg.get_id() == "" {
233 arg = arg.id(long);
234 }
235 let action = $crate::ArgAction::SetTrue;
236 let arg = arg
237 .long(long)
238 .action(action);
239 let arg = $crate::arg_impl! {
240 @arg (arg) $($tail)*
241 };
242 arg
243 }};
244 (
245 @arg
246 ($arg:expr)
247 -$short:ident
248 $($tail:tt)*
249 ) => {{
250 debug_assert_eq!($arg.get_long(), None, "Short flags should precede long flags");
251 debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
252 debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
253
254 let action = $crate::ArgAction::SetTrue;
255 let arg = $arg
256 .short($crate::arg_impl! { @char $short })
257 .action(action);
258 let arg = $crate::arg_impl! {
259 @arg (arg) $($tail)*
260 };
261 arg
262 }};
263 (
264 @arg
265 ($arg:expr)
266 -$short:literal
267 $($tail:tt)*
268 ) => {{
269 debug_assert_eq!($arg.get_long(), None, "Short flags should precede long flags");
270 debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
271 debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
272
273 let action = $crate::ArgAction::SetTrue;
274 let arg = $arg
275 .short($crate::arg_impl! { @char $short })
276 .action(action);
277 let arg = $crate::arg_impl! {
278 @arg (arg) $($tail)*
279 };
280 arg
281 }};
282 (
283 @arg
284 ($arg:expr)
285 <$value_name:ident>
286 $($tail:tt)*
287 ) => {{
288 debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
289 debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
290
291 let mut arg = $arg;
292
293 if arg.get_long().is_none() && arg.get_short().is_none() {
294 arg = arg.required(true);
295 }
296
297 let value_name = $crate::arg_impl! { @string $value_name };
298 if arg.get_id() == "" {
299 arg = arg.id(value_name);
300 }
301 let arg = arg
302 .value_name(value_name)
303 .action($crate::ArgAction::Set);
304 let arg = $crate::arg_impl! {
305 @arg (arg) $($tail)*
306 };
307 arg
308 }};
309 (
310 @arg
311 ($arg:expr)
312 <$value_name:literal>
313 $($tail:tt)*
314 ) => {{
315 debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
316 debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
317
318 let mut arg = $arg;
319
320 if arg.get_long().is_none() && arg.get_short().is_none() {
321 arg = arg.required(true);
322 }
323
324 let value_name = $crate::arg_impl! { @string $value_name };
325 if arg.get_id() == "" {
326 arg = arg.id(value_name);
327 }
328 let arg = arg
329 .value_name(value_name)
330 .action($crate::ArgAction::Set);
331 let arg = $crate::arg_impl! {
332 @arg (arg) $($tail)*
333 };
334 arg
335 }};
336 (
337 @arg
338 ($arg:expr)
339 [$value_name:ident]
340 $($tail:tt)*
341 ) => {{
342 debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
343 debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
344
345 let mut arg = $arg;
346
347 if arg.get_long().is_none() && arg.get_short().is_none() {
348 arg = arg.required(false);
349 } else {
350 arg = arg.num_args(0..=1);
351 }
352
353 let value_name = $crate::arg_impl! { @string $value_name };
354 if arg.get_id() == "" {
355 arg = arg.id(value_name);
356 }
357 let arg = arg
358 .value_name(value_name)
359 .action($crate::ArgAction::Set);
360 let arg = $crate::arg_impl! {
361 @arg (arg) $($tail)*
362 };
363 arg
364 }};
365 (
366 @arg
367 ($arg:expr)
368 [$value_name:literal]
369 $($tail:tt)*
370 ) => {{
371 debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
372 debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
373
374 let mut arg = $arg;
375
376 if arg.get_long().is_none() && arg.get_short().is_none() {
377 arg = arg.required(false);
378 } else {
379 arg = arg.num_args(0..=1);
380 }
381
382 let value_name = $crate::arg_impl! { @string $value_name };
383 if arg.get_id() == "" {
384 arg = arg.id(value_name);
385 }
386 let arg = arg
387 .value_name(value_name)
388 .action($crate::ArgAction::Set);
389 let arg = $crate::arg_impl! {
390 @arg (arg) $($tail)*
391 };
392 arg
393 }};
394 (
395 @arg
396 ($arg:expr)
397 ...
398 $($tail:tt)*
399 ) => {{
400 let arg = match $arg.get_action() {
401 $crate::ArgAction::Set => {
402 if $arg.get_long().is_none() && $arg.get_short().is_none() {
403 $arg.num_args(1..)
404 .action($crate::ArgAction::Append)
406 } else {
407 $arg.action($crate::ArgAction::Append)
408 }
409 },
410 $crate::ArgAction::SetTrue | $crate::ArgAction::Help | $crate::ArgAction::Version => {
411 $arg.action($crate::ArgAction::Count)
412 }
413 action => {
414 panic!("Unexpected action {action:?}")
415 }
416 };
417 let arg = $crate::arg_impl! {
418 @arg (arg) $($tail)*
419 };
420 arg
421 }};
422 (
423 @arg
424 ($arg:expr)
425 $help:literal
426 ) => {{
427 $arg.help($help)
428 }};
429 (
430 @arg
431 ($arg:expr)
432 ) => {{
433 $arg
434 }};
435}
436
437#[macro_export]
532macro_rules! arg {
533 ( $name:ident: $($tail:tt)+ ) => {{
534 let arg = $crate::Arg::new($crate::arg_impl! { @string $name });
535 let arg = $crate::arg_impl! {
536 @arg (arg) $($tail)+
537 };
538 arg
539 }};
540 ( $($tail:tt)+ ) => {{
541 let arg = $crate::Arg::default();
542 let arg = $crate::arg_impl! {
543 @arg (arg) $($tail)+
544 };
545 debug_assert_ne!(arg.get_id(), "", "Without a value or long flag, the `name:` prefix is required");
546 arg
547 }};
548}
549
550#[cfg(feature = "debug")]
551macro_rules! debug {
552 ($($arg:tt)*) => ({
553 use std::fmt::Write as _;
554 let hint = anstyle::Style::new().dimmed();
555
556 let module_path = module_path!();
557 let body = format!($($arg)*);
558 let mut styled = $crate::builder::StyledStr::new();
559 let _ = write!(styled, "{hint}[{module_path:>28}]{body}{hint:#}\n");
560 let color = $crate::output::fmt::Colorizer::new($crate::output::fmt::Stream::Stderr, $crate::ColorChoice::Auto).with_content(styled);
561 let _ = color.print();
562 })
563}
564
565#[cfg(not(feature = "debug"))]
566macro_rules! debug {
567 ($($arg:tt)*) => {};
568}
569
570macro_rules! ok {
571 ($expr:expr) => {
572 match $expr {
573 Ok(val) => val,
574 Err(err) => {
575 return Err(err);
576 }
577 }
578 };
579}
580
581macro_rules! some {
582 ($expr:expr) => {
583 match $expr {
584 Some(val) => val,
585 None => {
586 return None;
587 }
588 }
589 };
590}