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