Skip to main content

bpaf/
lib.rs

1#![warn(missing_docs)]
2#![allow(clippy::needless_doctest_main)]
3#![allow(clippy::redundant_else)] // not useful
4#![allow(rustdoc::redundant_explicit_links)] // two random markdown parsers I tried only supports explicit links
5
6//! Lightweight and flexible command line argument parser with derive and combinatoric style API
7
8//! # Quick links
9//! - [Introduction](_documentation::_0_intro) - features, design goals, restrictions
10//! - [Tutorials](_documentation::_1_tutorials) - practical learning oriented information and
11//!   examples to get you started
12//!   + [Types of arguments](_documentation::_1_tutorials::_0_types_of_arguments) -
13//!     common types of line options and conventions (optional)
14//!   + [Combinatoric API](_documentation::_1_tutorials::_1_combinatoric_api)  -
15//!     Parse arguments without using proc macros
16//!   + [Derive API](_documentation::_1_tutorials::_2_derive_api) -
17//!     Create a parser by defining a structure
18//! - [How-to and guides](_documentation::_2_howto) - assumes familiarity with the basics and
19//!   explains how to concrete tasks
20//! - [Explanations](_documentation::_4_explanation) - theoretical information about abstractions
21//!   used by the library, oriented for understanding
22//! - [FAQ](https://github.com/pacak/bpaf/discussions) - questions from library users
23
24//! # A quick start
25//!
26//! Add `bpaf`, optionally with derive enabled
27//!
28//! ```text
29//! $ cargo add bpaf -F derive,dull-color
30//! ```
31//!
32//! Use either derive or combinatoric API and try running it
33//!
34#![cfg_attr(not(doctest), doc = include_str!("docs2/intro.md"))]
35
36//!
37//! ## Consuming items - making `Parser`
38//!
39//! `bpaf` allows you to describe the parsers using a mix of two APIs: combinatoric and derive.
40//! Both APIs can achieve the same results, you can use one that better suits your needs. You can
41//! find documentation with more examples following those links.
42//!
43//! - For an argument with a name you define [`NamedArg`] using a combination of [`short`],
44//!   [`long`] and [`env`](crate::env()). At the same time you can attach
45//!   [`help`](NamedArg::help).
46//! - [`NamedArg::switch`] - simple switch that returns `true` if it's present on a command
47//!   line and `false` otherwise.
48//! - [`NamedArg::flag`] - a variant of `switch` that lets you return one of two custom
49//!   values, for example `Color::On` and `Color::Off`.
50//! - [`NamedArg::req_flag`] - a variant of `switch` that only only succeeds when it's name
51//!   is present on a command line
52//! - [`NamedArg::argument`] - named argument containing a value, you can further
53//!   customize it with [`adjacent`](crate::parsers::ParseArgument::adjacent)
54//! - [`positional`] - positional argument, you can further customize it with
55//!   [`strict`](ParsePositional::strict)
56//! - [`OptionParser::command`] - subcommand parser.
57//! - [`any`] and its specialized version [`literal`] are escape hatches that can parse anything
58//!   not fitting into usual classification.
59//! - [`pure`] and [`pure_with`] - a way to generate a value that can be composed without parsing
60//!   it from the command line.
61//!
62//! ## Transforming and changing parsers
63//!
64//! By default primitive parsers gives you back a single `bool`, a single `PathBuf` or a single
65//! value produced by [`FromStr`] trait, etc. You can further transform it by chaining methods from
66//! [`Parser`] trait, some of those methods are applied automagically if you are using derive API.
67//!
68//! `bpaf` distinguishes two types of parse failures - "value is absent" and
69//! "value is present but invalid", most parsers listed in this section only handle the first
70//! type of failure by default, but you can use their respective `catch` method to handle the later
71//! one.
72//!
73//! - [`fallback`](Parser::fallback) and [`fallback_with`](Parser::fallback_with) - return a
74//!   different value if parser fails to find what it is looking for. Generated help for former
75//!   can be updated to include default value using
76//!   [`display_fallback`](ParseFallback::display_fallback),
77//!   [`debug_fallback`](ParseFallback::debug_fallback), or
78//!   [`format_fallback`](ParseFallback::format_fallback).
79//! - [`optional`](Parser::optional) - return `None` if value is missing instead of failing, see
80//!   also [`catch`](ParseOptional::catch) .
81//! - [`many`](Parser::many), [`some`](Parser::some) and [`collect`](Parser::collect) - collect
82//!   multiple values into a collection, usually a vector, see their respective
83//!   [`catch`](ParseMany::catch), [`catch`](ParseSome::catch) and [`catch`](ParseCollect::catch).
84//! - [`map`](Parser::map), [`parse`](Parser::parse) and [`guard`](Parser::guard) - transform
85//!   and/or validate value produced by a parser
86//! - [`to_options`](Parser::to_options) - finalize the parser and prepare to run it
87//!
88//! ## Combining multiple parsers together
89//!
90//! Once you have parsers for all the primitive fields figured out you can start combining them
91//! together to produce a parser for a final result - data type you designed in the step one.
92//! For derive API you apply annotations to data types with `#[derive(Bpaf)`] and `#[bpaf(..)]`,
93//! with combinatoric API you use [`construct!`](crate::construct!) macro.
94//!
95//! All fields in a struct needs to be successfully parsed in order for the parser to succeed
96//! and only one variant from enum will consume its values at a time.
97//!
98//! You can use [`adjacent`](ParseCon::adjacent) annotation to parse multiple flags as an adjacent
99//! group allowing for more unusual scenarios such as multiple value arguments or chained commands.
100//!
101//! ## Improving user experience
102//!
103//! `bpaf` would use doc comments on fields and structures in derive mode and and values passed
104//! in various `help` methods to generate `--help` documentation, you can further improve it
105//! using those methods:
106//!
107//! - [`hide_usage`](Parser::hide_usage) and [`hide`](Parser::hide) - hide the parser from
108//!   generated *Usage* line or whole generated help
109//! - [`group_help`](Parser::group_help) and [`with_group_help`](Parser::with_group_help) -
110//!   add a common description shared by several parsers
111//! - [`custom_usage`](Parser::custom_usage) - customize usage for a primitive or composite parser
112//! - [`usage`](OptionParser::usage) and [`with_usage`](OptionParser::with_usage) lets you to
113//!   customize whole usage line as a whole either by completely overriding it or by building around it.
114//!
115//! By default with completion enabled `bpaf` would complete names for flags, arguments and
116//! commands. You can also generate completion for argument values, possible positionals, etc.
117//! This requires enabling **autocomplete** cargo feature.
118//!
119//! - [`complete`](Parser::complete) and [`complete_shell`](Parser::complete_shell)
120//!
121//! And finally you can generate documentation for command line in markdown, html and manpage
122//! formats using [`render_markdown`](OptionParser::render_markdown),
123//! [`render_html`](OptionParser::render_html) and [`render_manpage`](OptionParser::render_manpage),
124//! for more detailed info see [`doc`] module
125//!
126//! ## Testing your parsers and running them
127//! - You can [`OptionParser::run`] the parser on the arguments passed on the command line
128//! - [`check_invariants`](OptionParser::check_invariants) checks for a few invariants in the
129//!   parser `bpaf` relies on
130//! - [`run_inner`](OptionParser::run_inner) runs the parser with custom [`Args`] you can create
131//!   either explicitly or implicitly using one of the [`From`] implementations, `Args` can be
132//!   customized with [`set_comp`](Args::set_comp) and [`set_name`](Args::set_name).
133//! - [`ParseFailure`] contains the parse outcome, you can consume it either by hands or using one
134//!   of [`exit_code`](ParseFailure::exit_code), [`unwrap_stdout`](ParseFailure::unwrap_stdout) and
135//!   [`unwrap_stderr`](ParseFailure::unwrap_stderr)
136//!
137//! ## Cargo features
138//!
139//!  - `derive`: adds a dependency on `bpaf_derive` crate and reexport `Bpaf` derive macro. You
140//!     need to enable it to use derive API. Disabled by default.
141//!
142//!  - `batteries`: helpers implemented with public `bpaf` API. Disabled by default.
143//!
144//!  - `autocomplete`: enables support for shell autocompletion. Disabled by default.
145//!
146//!
147//! - `bright-color`, `dull-color`: use more colors when printing `--help` and such. Enabling
148//!   either color feature adds some extra dependencies and might raise MRSV. If you are planning
149//!   to use this feature in a published app - it’s best to expose them as feature flags:
150//!
151//!    ```toml
152//!    [features]
153//!    bright-color = ["bpaf/bright-color"]
154//!    dull-color = ["bpaf/dull-color"]
155//!    ```
156//!    Disabled by default.
157//!
158//!  - `docgen`: generate documentation from help declaration, see [`OptionParser::render_markdown`] and [`doc`](crate::doc). Disabled by default.
159
160
161
162#[cfg(feature = "extradocs")]
163#[rustfmt::skip]
164#[allow(unused_imports)]
165pub mod _documentation;
166
167mod arg;
168mod args;
169#[cfg(feature = "batteries")]
170pub mod batteries;
171mod buffer;
172#[cfg(feature = "autocomplete")]
173mod complete_gen;
174#[cfg(feature = "autocomplete")]
175mod complete_run;
176#[cfg(feature = "autocomplete")]
177mod complete_shell;
178pub mod doc;
179mod error;
180mod from_os_str;
181mod info;
182mod item;
183mod meta;
184mod meta_help;
185mod meta_youmean;
186pub mod params;
187mod structs;
188#[cfg(test)]
189mod tests;
190
191pub mod parsers {
192    //! This module exposes parsers that accept further configuration with builder pattern
193    //!
194    //! In most cases you won't be using those names directly, they're only listed here to provide
195    //! access to documentation
196    #[cfg(feature = "autocomplete")]
197    #[doc(inline)]
198    pub use crate::complete_shell::ParseCompShell;
199    #[doc(inline)]
200    pub use crate::params::{
201        NamedArg, ParseAny, ParseArgument, ParseCommand, ParseFlag, ParsePositional,
202    };
203    #[doc(inline)]
204    pub use crate::structs::{
205        ParseCollect, ParseCon, ParseCount, ParseFallback, ParseFallbackWith, ParseLast, ParseMany,
206        ParseOptional, ParseSome,
207    };
208}
209
210// -------------------------------------------------------------------
211
212#[doc(inline)]
213pub use crate::{args::Args, buffer::Doc, error::ParseFailure, info::OptionParser};
214
215#[doc(hidden)]
216// used by construct macro, not part of public API
217pub use crate::{args::State, error::Error, meta::Meta, structs::ParseCon};
218
219use std::{marker::PhantomData, str::FromStr};
220
221use crate::{
222    buffer::{MetaInfo, Style},
223    item::Item,
224    params::build_positional,
225    parsers::{NamedArg, ParseAny, ParseCommand, ParsePositional},
226    structs::{
227        ParseCollect, ParseCount, ParseFail, ParseFallback, ParseFallbackWith, ParseGroupHelp,
228        ParseGuard, ParseHide, ParseLast, ParseMany, ParseMap, ParseOptional, ParseOrElse,
229        ParsePure, ParsePureWith, ParseSome, ParseUsage, ParseWith, ParseWithGroupHelp,
230    },
231};
232
233#[cfg(feature = "autocomplete")]
234pub use crate::complete_shell::ShellComp;
235#[cfg(feature = "autocomplete")]
236use structs::ParseComp;
237
238#[doc(inline)]
239#[cfg(feature = "bpaf_derive")]
240pub use bpaf_derive::Bpaf;
241
242/// Compose several parsers to produce a single result
243///
244/// # Usage reference
245/// ```rust
246/// # use bpaf::*;
247/// # { struct Res(bool, bool, bool);
248/// # let a = short('a').switch(); let b = short('b').switch(); let c = short('c').switch();
249/// // structs with unnamed fields:
250/// construct!(Res(a, b, c));
251/// # }
252///
253/// # { struct Res { a: bool, b: bool, c: bool }
254/// # let a = short('a').switch(); let b = short('b').switch(); let c = short('c').switch();
255/// // structs with named fields:
256/// construct!(Res {a, b, c});
257/// # }
258///
259/// # { enum Ty { Res(bool, bool, bool) }
260/// # let a = short('a').switch(); let b = short('b').switch(); let c = short('c').switch();
261/// // enums with unnamed fields:
262/// construct!(Ty::Res(a, b, c));
263/// # }
264///
265/// # { enum Ty { Res { a: bool, b: bool, c: bool } }
266/// # let a = short('a').switch(); let b = short('b').switch(); let c = short('c').switch();
267/// // enums with named fields:
268/// construct!(Ty::Res {a, b, c});
269/// # }
270///
271/// # { let a = short('a').switch(); let b = short('b').switch(); let c = short('c').switch();
272/// // tuples:
273/// construct!(a, b, c);
274/// # }
275///
276/// # { let a = short('a').switch(); let b = short('b').switch(); let c = short('c').switch();
277/// // parallel composition, tries all parsers, picks one that consumes the left most value,
278/// // or if they consume the same (or not at all) - the left most in a list
279/// construct!([a, b, c]);
280/// # }
281///
282/// // defining primitive parsers inside construct macro :)
283/// construct!(a(short('a').switch()), b(long("arg").argument::<usize>("ARG")));
284///
285/// # { let a = short('a').switch();
286/// // defining a boxed parser
287/// construct!(a);
288/// # }
289/// ```
290///
291/// # Combinatoric usage
292/// `construct!` can compose parsers sequentially or in parallel.
293///
294/// Sequential composition runs each parser and if all of them succeed you get a parser object of a
295/// new type back. Placeholder names for values inside `construct!` macro must correspond to both
296/// struct/enum names and parser names present in scope. In examples below `a` corresponds to a
297/// function and `b` corresponds to a variable name. Note parens in `a()`, you must to use them to
298/// indicate function parsers.
299///
300/// Inside the parens you can put a whole expression to use instead of
301/// having to define them in advance: `a(positional::<String>("POS"))`. Probably a good idea to use this
302/// approach only for simple parsers.
303///
304/// ```rust
305/// # use bpaf::*;
306/// struct Res (u32, u32);
307/// enum Ul { T { a: u32, b: u32 } }
308///
309/// // You can share parameters across multiple construct invocations
310/// // if defined as functions
311/// fn a() -> impl Parser<u32> {
312///     short('a').argument::<u32>("N")
313/// }
314///
315/// // You can construct structs or enums with unnamed fields
316/// fn res() -> impl Parser<Res> {
317///     let b = short('b').argument::<u32>("n");
318///     construct!(Res ( a(), b ))
319/// }
320///
321/// // You can construct structs or enums with named fields
322/// fn ult() -> impl Parser<Ul> {
323///     let b = short('b').argument::<u32>("n");
324///     construct!(Ul::T { a(), b })
325/// }
326///
327/// // You can also construct simple tuples
328/// fn tuple() -> impl Parser<(u32, u32)> {
329///     let b = short('b').argument::<u32>("n");
330///     construct!(a(), b)
331/// }
332///
333/// // You can create boxed version of parsers so the type matches as long
334/// // as return type is the same - can be useful for all sort of dynamic parsers
335/// fn boxed() -> Box<dyn Parser<u32>> {
336///     let a = short('a').argument::<u32>("n");
337///     construct!(a)
338/// }
339///
340/// // In addition to having primitives defined before using them - you can also define
341/// // them directly inside construct macro. Probably only a good idea if you have only simple
342/// // components
343/// struct Options {
344///     arg: u32,
345///     switch: bool,
346/// }
347///
348/// fn coyoda() -> impl Parser<Options> {
349///     construct!(Options {
350///         arg(short('a').argument::<u32>("ARG")),
351///         switch(short('s').switch())
352///     })
353/// }
354/// ```
355///
356/// Parallel composition picks one of several available parsers (result types must match) and returns a
357/// parser object of the same type. Similar to sequential composition you can use parsers from variables
358/// or functions:
359///
360/// ```rust
361/// # use bpaf::*;
362/// fn b() -> impl Parser<u32> {
363///     short('b').argument::<u32>("NUM")
364/// }
365///
366/// fn a_or_b() -> impl Parser<u32> {
367///     let a = short('a').argument::<u32>("NUM");
368///     // equivalent way of writing this would be `a.or_else(b())`
369///     construct!([a, b()])
370/// }
371/// ```
372///
373/// # Derive usage
374///
375/// `bpaf` would combine fields of struct or enum constructors sequentially and enum
376/// variants in parallel.
377/// ```rust
378/// # use bpaf::*;
379/// // to satisfy this parser user needs to pass both -a and -b
380/// #[derive(Debug, Clone, Bpaf)]
381/// struct Res {
382///     a: u32,
383///     b: u32,
384/// }
385///
386/// // to satisfy this parser user needs to pass one (and only one) of -a, -b, -c or -d
387/// #[derive(Debug, Clone, Bpaf)]
388/// enum Enumeraton {
389///     A { a: u32 },
390///     B { b: u32 },
391///     C { c: u32 },
392///     D { d: u32 },
393/// }
394///
395/// // here user needs to pass either both -a AND -b or both -c AND -d
396/// #[derive(Debug, Clone, Bpaf)]
397/// enum Ult {
398///     AB { a: u32, b: u32 },
399///     CD { c: u32, d: u32 }
400/// }
401/// ```
402#[macro_export]
403macro_rules! construct {
404    // construct!(Enum::Cons { a, b, c })
405    ($(::)? $ns:ident $(:: $con:ident)* { $($tokens:tt)* }) => {{ $crate::construct!(@prepare [named [$ns $(:: $con)*]] [] $($tokens)*) }};
406
407    // construct!(Enum::Cons ( a, b, c ))
408    ($(::)? $ns:ident $(:: $con:ident)* ( $($tokens:tt)* )) => {{ $crate::construct!(@prepare [pos [$ns $(:: $con)*]] [] $($tokens)*) }};
409
410    // construct!( a, b, c )
411    ($first:ident $($tokens:tt)*) => {{ $crate::construct!(@prepare [pos] [] $first $($tokens)*) }};
412
413    // construct![a, b, c]
414    ([$first:ident $($tokens:tt)*]) => {{ $crate::construct!(@prepare [alt] [] $first $($tokens)*) }};
415
416    (@prepare $ty:tt [$($fields:tt)*] $field:ident () $(, $($rest:tt)*)? ) => {{
417        let $field = $field();
418        $crate::construct!(@prepare $ty [$($fields)* $field] $($($rest)*)?)
419    }};
420    (@prepare $ty:tt [$($fields:tt)*] $field:ident ($expr:expr) $(, $($rest:tt)*)?) => {{
421        let $field = $expr;
422        $crate::construct!(@prepare $ty [$($fields)* $field] $($($rest)*)?)
423    }};
424    (@prepare $ty:tt [$($fields:tt)*] $field:ident $(, $($rest:tt)*)? ) => {{
425        $crate::construct!(@prepare $ty [$($fields)* $field] $($($rest)* )?)
426    }};
427
428    (@prepare [alt] [$first:ident $($fields:ident)*]) => {
429        #[allow(deprecated)]
430        { use $crate::Parser; $first $(.or_else($fields))* }
431    };
432
433    (@prepare $ty:tt [$($fields:tt)*]) => {
434        $crate::construct!(@fin $ty [ $($fields)* ])
435    };
436
437    (@make [named [$($con:tt)+]] [$($fields:ident)*]) => { $($con)+ { $($fields),* } };
438    (@make [pos   [$($con:tt)+]] [$($fields:ident)*]) => { $($con)+ ( $($fields),* ) };
439    (@make [pos] [$($fields:ident)*]) => { ( $($fields),* ) };
440
441
442    (@fin [named [$($con:tt)+]] []) => { $crate::pure($($con)+ { })};
443    (@fin [pos   [$($con:tt)+]] []) => { $crate::pure($($con)+ ( ))};
444
445    (@fin [pos] [$field:ident]) => {{
446        use $crate::Parser;
447        $field.boxed()
448    }};
449
450    (@fin $ty:tt [$front:ident $($fields:ident)*]) => {{
451        use $crate::Parser;
452        let meta = $crate::Meta::And(vec![ $front.meta(), $($fields.meta()),* ]);
453        let inner = move |failfast: bool, args: &mut $crate::State| {
454            let mut $front = $front.eval(args);
455            if failfast {
456                $front = Ok($front?);
457            }
458            $(let $fields = $fields.eval(args);)*
459            let $front = $front?;
460            $(let $fields = $fields?;)*
461
462            args.current = None;
463            ::std::result::Result::Ok::<_, $crate::Error>
464                ($crate::construct!(@make $ty [$front $($fields)*]))
465        };
466        $crate::ParseCon { inner, meta, failfast: false }
467    }};
468}
469
470/// Simple or composed argument parser
471///
472/// # Overview
473///
474/// It's best to think of an object implementing [`Parser`] trait as a container with a value
475/// inside that is composable with other `Parser` containers using [`construct!`] and the only
476/// way to extract this value is by transforming it to [`OptionParser`] with
477/// [`to_options`](Parser::to_options) and running it with [`run`](OptionParser::run). At which
478/// point you either get your value out or `bpaf` would generate a message describing a problem
479/// (missing argument, validation failure, user requested help, etc) and the program would
480/// exit.
481///
482/// Values inside can be of any type for as long as they implement `Debug`, `Clone` and
483/// there are no lifetimes other than static.
484///
485/// When consuming the values you can jump straight to a value that implements
486/// [`FromStr`] trait and then transform it into something that your program would use. Alternatively,
487/// you can consume either `String` or `OsString` and parse that by hand. It's better to perform
488/// as much parsing and validation inside the `Parser` as possible so the program itself gets
489/// strictly typed and correct value while the user gets immediate feedback on what's wrong with the
490/// arguments they pass.
491///
492/// Order of operations matters, each subsequent parser gets the output of the earlier one. Both
493/// parsers `a` and `b` would consume multiple numeric values, each less than 10, but `a`
494/// validates a single value and then consumes multiple of them already validated, while `b` first
495/// consumes and then performs validation. The former approach is usually more readable.
496/// ```rust
497/// # use bpaf::*;
498/// # fn simple() {
499/// let a = short('a').argument::<usize>("N")
500///     .guard(|&a| a < 10, "`a` must be below 10")
501///     .many();
502/// let b = short('b').argument::<usize>("N")
503///     .many()
504///     .guard(|bs| bs.iter().all(|&b| b < 10), "`b` must be below 10");
505/// # }
506/// ```
507///
508/// The same logic applies to derive API - the current type depends on the order of annotations:
509/// ```rust
510/// # use bpaf::*;
511/// # fn less_than_10(a: &usize) -> bool { true }
512/// # fn all_less_than_10(a: &Vec<usize>) -> bool { true }
513/// #[derive(Bpaf, Debug, Clone)]
514/// struct Simple {
515///     #[bpaf(argument("N"), guard(less_than_10, "`a` must be below 10"), many)]
516///     a: Vec<usize>,
517///     #[bpaf(argument("N"), many, guard(all_less_than_10, "`b` must be below 10"))]
518///     b: Vec<usize>,
519/// }
520/// ```
521///
522/// For example suppose your program needs the user to specify dimensions of a rectangle, with sides
523/// being 1..20 units long and the total area must not exceed 200 units square. A parser that
524/// consumes it might look like this:
525///
526/// ```rust
527/// # use bpaf::*;
528/// #[derive(Debug, Copy, Clone)]
529/// struct Rectangle {
530///     width: u32,
531///     height: u32,
532/// }
533///
534/// fn rectangle() -> impl Parser<Rectangle> {
535///     let invalid_size = "Sides of a rectangle must be 1..20 units long";
536///     let invalid_area = "Area of a rectangle must not exceed 200 units square";
537///     let width = long("width")
538///         .help("Width of the rectangle")
539///         .argument::<u32>("PX")
540///         .guard(|&x| 1 <= x && x <= 10, invalid_size);
541///     let height = long("height")
542///         .help("Height of the rectangle")
543///         .argument::<u32>("PX")
544///         .guard(|&x| 1 <= x && x <= 10, invalid_size);
545///     construct!(Rectangle { width, height })
546///         .guard(|&r| r.width * r.height <= 400, invalid_area)
547/// }
548/// ```
549///
550///
551/// # Derive specific considerations
552///
553/// Every method defined on this trait belongs to the `postprocessing` section of the field
554/// annotation. `bpaf` would try to figure out what chain to use for as long as there are no
555/// options changing the type: you can use [`fallback`](Parser::fallback_with),
556/// [`fallback_with`](Parser::fallback_with), [`guard`](Parser::guard), [`hide`](Parser::hide`) and
557/// [`group_help`](Parser::group_help) but not the rest of them.
558///
559/// ```rust
560/// # use bpaf::*;
561/// #[derive(Debug, Clone, Bpaf)]
562/// struct Options {
563///     // no annotation at all - `bpaf` inserts implicit `argument` and gets the right type
564///     number_1: u32,
565///
566///     // fallback isn't changing the type so `bpaf` still handles it
567///     #[bpaf(fallback(42))]
568///     number_2: u32,
569///
570///     // `bpaf` inserts implicit `argument`, `optional` and the right type
571///     number_3: Option<u32>,
572///
573///     // fails to compile: you need to specify `argument`
574///     // #[bpaf(optional)]
575///     // number_4: Option<u32>,
576///
577///     #[bpaf(argument("N"), optional)]
578///     number_5: Option<u32>,
579///
580///     // explicit consumer and a full postprocessing chain
581///     #[bpaf(argument::<u32>("N"), optional)]
582///     number_6: Option<u32>,
583/// }
584/// ```
585pub trait Parser<T> {
586    /// Evaluate inner function
587    ///
588    /// Mostly internal implementation details, you can try using it to test your parsers
589    // it's possible to move this function from the trait to the structs but having it
590    // in the trait ensures the composition always works
591    #[doc(hidden)]
592    fn eval(&self, args: &mut State) -> Result<T, Error>;
593
594    /// Included information about the parser
595    ///
596    /// Mostly internal implementation details, you can try using it to test your parsers
597    // it's possible to move this function from the trait to the structs but having it
598    // in the trait ensures the composition always works
599    #[doc(hidden)]
600    fn meta(&self) -> Meta;
601
602    // change shape
603    // {{{ many
604    /// Consume zero or more items from a command line and collect them into a [`Vec`]
605    ///
606    /// `many` preserves any parsing failures and propagates them outwards, with an extra
607    /// [`catch`](ParseMany::catch) statement you can instead stop at the first value
608    /// that failed to parse and ignore it and all the subsequent ones.
609    ///
610    /// `many` will collect at most one result that does not consume anything from the argument
611    /// list allowing using it in combination with any parsers with a fallback. After the first
612    /// one, it will keep collecting the results as long as they consume something.
613    ///
614    /// For derive usage `bpaf` would insert implicit `many` when the resulting type is a
615    /// vector.
616    ///
617    #[cfg_attr(not(doctest), doc = include_str!("docs2/many.md"))]
618    ///
619    /// # See also
620    /// [`some`](Parser::some) also collects results to a vector but requires at least one
621    /// element to succeed, [`collect`](Parser::collect) collects results into a [`FromIterator`]
622    /// structure
623    fn many(self) -> ParseMany<Self>
624    where
625        Self: Sized,
626    {
627        ParseMany {
628            inner: self,
629            catch: false,
630        }
631    }
632    // }}}
633
634    // {{{ collect
635    /// Transform parser into a collection parser
636    ///
637    /// A generic variant of [`many`](Parser::many), instead of collecting into a vector
638    /// it collects into any collection that implements [`FromIterator`] trait
639    ///
640    /// `collect` preserves any parsing failures and propagates them outwards, with extra
641    /// [`catch`](ParseCollect::catch) statement you can instead stop at the first value
642    /// that failed to parse and ignore it and all the subsequent ones.
643    ///
644    #[cfg_attr(not(doctest), doc = include_str!("docs2/collect.md"))]
645    ///
646    /// `collect` will collect at most one result that does not consume anything from the argument
647    /// list allowing using it in combination of any parsers with a fallback. After the first one
648    /// it will keep collecting the results as long as they consume something.
649    fn collect<C>(self) -> ParseCollect<Self, C, T>
650    where
651        C: FromIterator<T>,
652        Self: Sized,
653    {
654        ParseCollect {
655            inner: self,
656            catch: false,
657            ctx: PhantomData,
658        }
659    }
660    // }}}
661
662    // {{{ some
663    /// Consume one or more items from a command line and collect them into a [`Vec`]
664    ///
665    /// Takes a string used as an error message if there are no specified parameters
666    ///
667    /// `some` preserves any parsing failures and propagates them outwards, with an extra
668    /// [`catch`](ParseSome::catch) statement you can instead stop at the first value
669    /// that failed to parse and ignore it and all the subsequent ones.
670    ///
671    /// `some` will collect at most one result that does not consume anything from the argument
672    /// list allowing using it in combination with any parsers with a fallback. After the first
673    /// one, it will keep collecting the results as long as they consume something.
674    ///
675    #[cfg_attr(not(doctest), doc = include_str!("docs2/some.md"))]
676    ///
677    /// # See also
678    /// [`many`](Parser::many) also collects results to a vector but succeeds with
679    /// no matching values. [`collect`](Parser::collect) collects results into a [`FromIterator`]
680    /// structure
681    #[must_use]
682    fn some(self, message: &'static str) -> ParseSome<Self>
683    where
684        Self: Sized + Parser<T>,
685    {
686        ParseSome {
687            inner: self,
688            message,
689            catch: false,
690        }
691    }
692    // }}}
693
694    // {{{ optional
695    /// Turn a required argument into an optional one
696    ///
697    /// `optional` converts any missing items into `None` and passes the remaining parsing
698    /// failures untouched. With an extra [`catch`](ParseOptional::catch) statement, you can handle
699    /// those failures too.
700    ///
701    /// # Derive usage
702    ///
703    /// By default, `bpaf` would automatically use optional for fields of type `Option<T>`,
704    /// for as long as it's not prevented from doing so by present postprocessing options.
705    /// But it's also possible to specify it explicitly.
706    ///
707    #[cfg_attr(not(doctest), doc = include_str!("docs2/optional.md"))]
708    ///
709    #[must_use]
710    fn optional(self) -> ParseOptional<Self>
711    where
712        Self: Sized + Parser<T>,
713    {
714        ParseOptional {
715            inner: self,
716            catch: false,
717        }
718    }
719    // }}}
720
721    #[must_use]
722    /// Count how many times the inner parser succeeds, and return that number.
723    ///
724    /// When you are dealing with a parser that can succeed without consuming
725    /// anything from a command line - `bpaf` will count first such success as well.
726    ///
727    #[cfg_attr(not(doctest), doc = include_str!("docs2/count.md"))]
728    fn count(self) -> ParseCount<Self, T>
729    where
730        Self: Sized + Parser<T>,
731    {
732        ParseCount {
733            inner: self,
734            ctx: PhantomData,
735        }
736    }
737
738    #[must_use]
739    /// Apply the inner parser as many times as it succeeds, return the last value
740    ///
741    /// You can use this to allow users to pick contradicting options
742    #[cfg_attr(not(doctest), doc = include_str!("docs2/last.md"))]
743    fn last(self) -> ParseLast<Self>
744    where
745        Self: Sized + Parser<T>,
746    {
747        ParseLast { inner: self }
748    }
749
750    // parse
751    // {{{ parse
752    /// Apply a failing transformation to a contained value
753    ///
754    /// Transformation preserves the present/absent state of the value: to parse an optional value you
755    /// can either first try to `parse` it and then mark it as [`optional`](Parser::optional) or first
756    /// deal with the optionality and then parse a value wrapped in [`Option`]. In most cases
757    /// the former approach is more concise.
758    ///
759    /// Similarly, it is possible to parse multiple items with [`many`](Parser::many) or
760    /// [`some`](Parser::some) by either parsing a single item first and then turning it into a [`Vec`]
761    /// or collecting them into a [`Vec`] first and then parsing the whole vector. The former approach
762    /// is more concise.
763    ///
764    /// This is a most general of transforming parsers and you can express
765    /// [`map`](Parser::map) and [`guard`](Parser::guard) in terms of it.
766    ///
767    /// Examples are a bit artificial, to parse a value from a string you can specify
768    /// the type directly in the `argument`'s turbofish and then apply `map`.
769    ///
770    /// # Derive usage:
771    /// `parse` takes a single parameter: function name to call. Function type should match
772    /// parameter `F` used by `parse` in combinatoric API.
773    ///
774    #[cfg_attr(not(doctest), doc = include_str!("docs2/parse.md"))]
775    ///
776    fn parse<F, R, E>(self, f: F) -> ParseWith<T, Self, F, E, R>
777    where
778        Self: Sized + Parser<T>,
779        F: Fn(T) -> Result<R, E>,
780        E: ToString,
781    {
782        ParseWith {
783            inner: self,
784            inner_res: PhantomData,
785            parse_fn: f,
786            res: PhantomData,
787            err: PhantomData,
788        }
789    }
790    // }}}
791
792    // {{{ map
793    /// Apply a pure transformation to a contained value
794    ///
795    /// A common case of the [`parse`](Parser::parse) method, exists mostly for convenience.
796    ///
797    /// # Derive usage:
798    /// The `map` takes a single parameter: function name to call. This function should transform
799    /// the value produced by the parser into a new value of the same or different type.
800    ///
801    #[cfg_attr(not(doctest), doc = include_str!("docs2/map.md"))]
802    ///
803    fn map<F, R>(self, map: F) -> ParseMap<T, Self, F, R>
804    where
805        Self: Sized + Parser<T>,
806        F: Fn(T) -> R + 'static,
807    {
808        ParseMap {
809            inner: self,
810            inner_res: PhantomData,
811            map_fn: map,
812            res: PhantomData,
813        }
814    }
815    // }}}
816
817    // {{{ guard
818    /// Validate or fail with a message
819    ///
820    /// If the value doesn't satisfy the constraint - the parser fails with the specified error message.
821    ///
822    /// # Derive usage
823    /// Derive variant of the `guard` takes a function name instead of a closure, mostly to keep things
824    /// clean. The second argument can be either a string literal or a constant name for a static [`str`].
825    ///
826    #[cfg_attr(not(doctest), doc = include_str!("docs2/guard.md"))]
827    ///
828    #[must_use]
829    fn guard<F>(self, check: F, message: &'static str) -> ParseGuard<Self, F>
830    where
831        Self: Sized + Parser<T>,
832        F: Fn(&T) -> bool,
833    {
834        ParseGuard {
835            inner: self,
836            check,
837            message,
838        }
839    }
840    // }}}
841
842    // combine
843    // {{{ fallback
844    /// Use this value as default if the value isn't present on a command line
845    ///
846    /// Parser would still fail if the value is present but failure comes from some transformation
847    ///
848    #[cfg_attr(not(doctest), doc = include_str!("docs2/dis_fallback.md"))]
849    ///
850    /// # See also
851    /// [`fallback_with`](Parser::fallback_with) would allow to try to fallback to a value that
852    /// comes from a failing computation such as reading a file. By default, the fallback value will
853    /// not be shown in the `--help` output; you can change that by using
854    /// [`display_fallback`](ParseFallback::display_fallback),
855    /// [`debug_fallback`](ParseFallback::debug_fallback), or
856    /// [`format_fallback`](ParseFallback::format_fallback).
857    #[must_use]
858    fn fallback(self, value: T) -> ParseFallback<Self, T>
859    where
860        Self: Sized + Parser<T>,
861    {
862        ParseFallback {
863            inner: self,
864            value,
865            value_str: String::new(),
866        }
867    }
868    // }}}
869
870    // {{{ fallback_with
871    /// Use value produced by this function as default if the value isn't present
872    ///
873    /// Would still fail if the value is present but failure comes from some earlier transformation
874    ///
875    #[cfg_attr(not(doctest), doc = include_str!("docs2/dis_fallback_with.md"))]
876    ///
877    /// # See also
878    /// [`fallback`](Parser::fallback) implements similar logic expect that failures aren't expected.
879    /// By default, the fallback value will
880    /// not be shown in the `--help` output; you can change that by using
881    /// [`display_fallback`](ParseFallbackWith::display_fallback),
882    /// [`debug_fallback`](ParseFallbackWith::debug_fallback), or
883    /// [`format_fallback`](ParseFallbackWith::format_fallback).
884    #[must_use]
885    fn fallback_with<F, E>(self, fallback: F) -> ParseFallbackWith<T, Self, F, E>
886    where
887        Self: Sized + Parser<T>,
888        F: Fn() -> Result<T, E>,
889        E: ToString,
890    {
891        ParseFallbackWith {
892            inner: self,
893            inner_res: PhantomData,
894            fallback,
895            value_str: String::new(),
896            err: PhantomData,
897        }
898    }
899    // }}}
900
901    // {{{ or_else
902    /// If first parser fails - try the second one
903    ///
904    /// For parser to succeed eiter of the components needs to succeed. If both succeed - `bpaf`
905    /// would use output from one that consumed the left most value. The second flag on the command
906    /// line remains unconsumed by `or_else`.
907    ///
908    /// # Combinatoric usage:
909    /// There's two ways to write this combinator with identical results:
910    /// ```rust
911    /// # use bpaf::*;
912    /// fn a() -> impl Parser<u32> {
913    ///     short('a').argument::<u32>("NUM")
914    /// }
915    ///
916    /// fn b() -> impl Parser<u32> {
917    ///     short('b').argument::<u32>("NUM")
918    /// }
919    ///
920    /// fn a_or_b_comb() -> impl Parser<u32> {
921    ///     construct!([a(), b()])
922    /// }
923    ///
924    /// fn a_or_b_comb2() -> impl Parser<u32> {
925    ///     a().or_else(b())
926    /// }
927    /// ```
928    ///
929    /// # Example
930    /// ```console
931    /// $ app -a 12 -b 3
932    /// // 12
933    /// $ app -b 3 -a 12
934    /// // 3
935    /// $ app -b 13
936    /// // 13
937    /// $ app
938    /// // fails asking for either -a NUM or -b NUM
939    /// ```
940    ///
941    /// # Derive usage:
942    ///
943    /// `bpaf` translates enum into alternative combinations, different shapes of variants
944    /// produce different results.
945    ///
946    ///
947    /// ```bpaf
948    /// # use bpaf::*;
949    /// #[derive(Debug, Clone, Bpaf)]
950    /// enum Flag {
951    ///     A { a: u32 }
952    ///     B { b: u32 }
953    /// }
954    /// ```
955    ///
956    /// ```console
957    /// $ app -a 12 -b 3
958    /// // Flag::A { a: 12 }
959    /// $ app -b 3 -a 12
960    /// // Flag::B { b: 3 }
961    /// $ app -b 3
962    /// // Flag::B { b: 3 }
963    /// $ app
964    /// // fails asking for either -a NUM or -b NUM
965    /// ```
966    ///
967    /// # Performance
968    ///
969    /// `bpaf` tries to evaluate both branches regardless of the successes to produce a
970    /// better error message for combinations of mutually exclusive parsers:
971    /// Suppose program accepts one of two mutually exclusive switches `-a` and `-b`
972    /// and both are present error message should point at the second flag
973    #[doc(hidden)]
974    #[deprecated(
975        since = "0.5.0",
976        note = "instead of a.or_else(b) you should use construct!([a, b])"
977    )]
978    fn or_else<P>(self, alt: P) -> ParseOrElse<T>
979    where
980        Self: Sized + Parser<T> + 'static,
981        P: Sized + Parser<T> + 'static,
982    {
983        ParseOrElse {
984            this: Box::new(self),
985            that: Box::new(alt),
986        }
987    }
988    // }}}
989
990    // misc
991    // {{{ hide
992    /// Ignore this parser during any sort of help generation
993    ///
994    /// Best used for optional parsers or parsers with a defined fallback, usually for implementing
995    /// backward compatibility or hidden aliases
996    ///
997    #[cfg_attr(not(doctest), doc = include_str!("docs2/hide.md"))]
998    ///
999    fn hide(self) -> ParseHide<Self>
1000    where
1001        Self: Sized + Parser<T>,
1002    {
1003        ParseHide { inner: self }
1004    }
1005    // }}}
1006
1007    /// Ignore this parser when generating a usage line
1008    ///
1009    /// Parsers hidden from usage will still show up in the available arguments list. Best used on
1010    /// optional things that augment the main application functionality but not define it.
1011    /// Alternatively, you can use [`custom_usage`](Parser::custom_usage) to replace a single
1012    /// option or a group of them with some other text.
1013    #[cfg_attr(not(doctest), doc = include_str!("docs2/hide_usage.md"))]
1014    #[must_use]
1015    fn hide_usage(self) -> ParseUsage<Self>
1016    where
1017        Self: Sized + Parser<T>,
1018    {
1019        ParseUsage {
1020            inner: self,
1021            usage: Doc::default(),
1022        }
1023    }
1024
1025    /// Customize how this parser looks like in the usage line
1026    ///
1027    #[cfg_attr(not(doctest), doc = include_str!("docs2/custom_usage.md"))]
1028    #[must_use]
1029    fn custom_usage<M>(self, usage: M) -> ParseUsage<Self>
1030    where
1031        M: Into<Doc>,
1032        Self: Sized + Parser<T>,
1033    {
1034        ParseUsage {
1035            inner: self,
1036            usage: usage.into(),
1037        }
1038    }
1039
1040    // {{{ group_help
1041    /// Attach a help message to a complex parser
1042    ///
1043    /// `bpaf` inserts the group help message before the block with all the fields
1044    /// from the inner parser and an empty line after the block.
1045    ///
1046    #[cfg_attr(not(doctest), doc = include_str!("docs2/group_help.md"))]
1047    fn group_help<M: Into<Doc>>(self, message: M) -> ParseGroupHelp<Self>
1048    where
1049        Self: Sized + Parser<T>,
1050    {
1051        ParseGroupHelp {
1052            inner: self,
1053            message: message.into(),
1054        }
1055    }
1056    // }}}
1057
1058    /// Make a help message for a complex parser from its [`MetaInfo`]
1059    ///
1060    #[cfg_attr(not(doctest), doc = include_str!("docs2/with_group_help.md"))]
1061    fn with_group_help<F>(self, f: F) -> ParseWithGroupHelp<Self, F>
1062    where
1063        Self: Sized + Parser<T>,
1064        F: Fn(MetaInfo) -> Doc,
1065    {
1066        ParseWithGroupHelp { inner: self, f }
1067    }
1068
1069    // {{{ comp
1070    /// Dynamic shell completion
1071    ///
1072    /// Allows to generate autocompletion information for the shell. Completer places generated input
1073    /// in place of metavar placeholders, so running `completer` on something that doesn't have a
1074    /// [`positional`] or an [`argument`](NamedArg::argument) doesn't make much sense.
1075    ///
1076    /// Takes a function as a parameter that tries to complete partial input to a full one with an
1077    /// optional description. `bpaf` would substitute a current positional item or an argument with an empty
1078    /// string if a value isn't available yet so it's best to run `complete` where parsing can't fail:
1079    /// right after [`argument`](NamedArg::argument) or [`positional`], but this isn't enforced.
1080    ///
1081    /// # Example
1082    /// ```console
1083    /// $ app --name L<TAB>
1084    /// $ app --name Lupusregina _
1085    /// ```
1086    ///
1087    #[cfg_attr(not(doctest), doc = include_str!("docs2/complete.md"))]
1088    ///
1089    /// ## A simple example
1090    ///
1091    #[cfg_attr(not(doctest), doc = include_str!("docs2/simple_dynamic.md"))]
1092    ///
1093    /// ## More detailed example
1094    ///
1095    #[cfg_attr(not(doctest), doc = include_str!("docs2/derive_show_asm.md"))]
1096    ///
1097    #[cfg(feature = "autocomplete")]
1098    fn complete<M, F>(self, op: F) -> ParseComp<Self, F>
1099    where
1100        M: Into<String>,
1101        F: Fn(&T) -> Vec<(M, Option<M>)>,
1102        Self: Sized + Parser<T>,
1103    {
1104        ParseComp {
1105            inner: self,
1106            op,
1107            group: None,
1108        }
1109    }
1110    // }}}
1111
1112    // {{{
1113    /// Static shell completion
1114    ///
1115    /// Allows to ask existing shell completion to provide some information such as a file or
1116    /// directory names or pass through existing shell completion scripts, see
1117    /// [`ShellComp`](complete_shell::ShellComp) for accessible functionality
1118    ///
1119    /// Places function calls in place of metavar placeholder, so running `complete_shell` on
1120    /// something that doesn't have a [`positional`] or [`argument`](NamedArg::argument) doesn't
1121    /// make much sense.
1122    ///
1123    /// # Example
1124    /// ```console
1125    /// $ app --output C<TAB>
1126    /// $ app --output Cargo.toml _
1127    /// ```
1128    ///
1129    /// # Combinatoric usage
1130    /// ```rust
1131    /// # use bpaf::*;
1132    /// fn output() -> impl Parser<String> {
1133    ///     long("output")
1134    ///         .help("Cargo.toml file to use as output")
1135    ///         .argument("OUTPUT")
1136    ///         .complete_shell(ShellComp::File { mask: Some("*.toml") })
1137    /// }
1138    /// ```
1139    ///
1140    /// # Derive usage
1141    /// ```rust
1142    /// # use bpaf::*;
1143    /// #[derive(Debug, Clone, Bpaf)]
1144    /// struct Options {
1145    ///     /// Cargo.toml file to use as output
1146    ///     #[bpaf(argument("OUTPUT"), complete_shell(ShellComp::File { mask: Some("*.toml") }))]
1147    ///     output: String,
1148    /// }
1149    /// ```
1150    ///
1151    /// For multiple file types correct mask syntax is `"*.(toml|md)"`.
1152    #[cfg(feature = "autocomplete")]
1153    fn complete_shell(
1154        self,
1155        op: complete_shell::ShellComp,
1156    ) -> crate::complete_shell::ParseCompShell<Self>
1157    where
1158        Self: Sized + Parser<T>,
1159    {
1160        crate::complete_shell::ParseCompShell { inner: self, op }
1161    }
1162    // }}}
1163
1164    // consume
1165    // {{{ to_options
1166    /// Transform `Parser` into [`OptionParser`] to get ready to [`run`](OptionParser::run) it
1167    ///
1168    ///
1169    /// # Derive usage
1170    /// Add a top-level `options` annotation to generate [`OptionParser`] instead of default
1171    /// [`Parser`].
1172    ///
1173    /// In addition to `options` annotation, you can also specify either `version` or
1174    /// `version(value)` annotation. The former uses version from `cargo`, later uses the
1175    /// specified value which should be an expression of type `&'static str`, see
1176    /// [`version`](OptionParser::version).
1177    ///
1178    #[cfg_attr(not(doctest), doc = include_str!("docs2/to_options.md"))]
1179    ///
1180    /// # See also
1181    /// There's some methods implemented on [`OptionParser`] directly to customize the appearance
1182    fn to_options(self) -> OptionParser<T>
1183    where
1184        Self: Sized + Parser<T> + 'static,
1185    {
1186        OptionParser {
1187            info: info::Info::default(),
1188            inner: Box::new(self),
1189        }
1190    }
1191    // }}}
1192
1193    /// Finalize and run the parser
1194    ///
1195    /// Generally, you'd want to use [`Parser::to_options`] to finalize the parser and [`OptionParser::run`],
1196    /// but this also works for simple cases:
1197    ///
1198    /// ```no_run
1199    /// # use bpaf::*;
1200    /// fn main() {
1201    ///     let name = short('n').long("name").argument::<String>("USER").run();
1202    ///     // do things with name
1203    /// }
1204    /// ```
1205    fn run(self) -> T
1206    where
1207        Self: Sized + Parser<T> + 'static,
1208    {
1209        self.to_options().run()
1210    }
1211
1212    /// Create a boxed representation for a parser
1213    ///
1214    /// The boxed parser doesn't expose internal representation in its type and allows to return
1215    /// of different parsers in different conditional branches
1216    ///
1217    /// You can create it with a single argument `construct` macro or by using `boxed` annotation
1218    #[cfg_attr(not(doctest), doc = include_str!("docs2/boxed.md"))]
1219    fn boxed(self) -> Box<dyn Parser<T>>
1220    where
1221        Self: Sized + Parser<T> + 'static,
1222    {
1223        Box::new(self)
1224    }
1225}
1226
1227/// Parser that produces a fixed value
1228///
1229/// This parser produces `T` without consuming anything from the command line, which can be useful
1230/// with [`construct!`]. As with any parsers, `T` should be `Clone` and `Debug`.
1231///
1232/// Both `pure` and [`pure_with`] are designed to put values into structures, to generate fallback
1233/// you should be using [`fallback`](Parser::fallback) and [`fallback_with`](Parser::fallback_with).
1234///
1235/// See also [`pure_with`] for a pure computation that can fail.
1236///
1237#[cfg_attr(not(doctest), doc = include_str!("docs2/pure.md"))]
1238#[must_use]
1239pub fn pure<T>(val: T) -> ParsePure<T> {
1240    ParsePure(val)
1241}
1242
1243/// Wrap a calculated value into a `Parser`
1244///
1245/// This parser represents a possibly failing equivalent to [`pure`].
1246/// It produces `T` by invoking the provided callback without consuming anything from the command
1247/// line, which can be useful with [`construct!`]. As with any parsers, `T` should be `Clone`
1248/// and `Debug`.
1249///
1250/// Both [`pure`] and `pure_with` are designed to put values into structures, to generate fallback
1251/// you should be using [`fallback`](Parser::fallback) and [`fallback_with`](Parser::fallback_with).
1252///
1253/// See also [`pure`] for a pure computation that can't fail.
1254///
1255#[cfg_attr(not(doctest), doc = include_str!("docs2/pure_with.md"))]
1256pub fn pure_with<T, F, E>(val: F) -> ParsePureWith<T, F, E>
1257where
1258    F: Fn() -> Result<T, E>,
1259    E: ToString,
1260{
1261    ParsePureWith(val)
1262}
1263
1264/// Fail with a fixed error message
1265///
1266/// This parser produces `T` of any type but instead of producing it when asked - it fails
1267/// with a custom error message. Can be useful for creating custom logic
1268///
1269/// # Combinatoric usage
1270/// ```rust
1271/// # use bpaf::*;
1272/// fn must_agree() -> impl Parser<()> {
1273///     let a = long("accept").req_flag(());
1274///     let no_a = fail("You must accept the license agreement with --agree before proceeding");
1275///     construct!([a, no_a])
1276/// }
1277/// ```
1278///
1279/// # Example
1280/// ```console
1281/// $ app
1282/// // exits with "You must accept the license agreement with --agree before proceeding"
1283/// $ app --agree
1284/// // succeeds
1285/// ```
1286#[must_use]
1287pub fn fail<T>(msg: &'static str) -> ParseFail<T> {
1288    ParseFail {
1289        field1: msg,
1290        field2: PhantomData,
1291    }
1292}
1293
1294/// Parse a [`flag`](NamedArg::flag)/[`switch`](NamedArg::switch)/[`argument`](NamedArg::argument) that has a short name
1295///
1296/// You can chain multiple [`short`](NamedArg::short), [`long`](NamedArg::long) and
1297/// [`env`](NamedArg::env()) for multiple names. You can specify multiple names of the same type,
1298///  `bpaf` would use items past the first one as hidden aliases.
1299#[cfg_attr(not(doctest), doc = include_str!("docs2/short_long_env.md"))]
1300#[must_use]
1301pub fn short(short: char) -> NamedArg {
1302    NamedArg {
1303        short: vec![short],
1304        env: Vec::new(),
1305        long: Vec::new(),
1306        help: None,
1307    }
1308}
1309
1310/// Parse a [`flag`](NamedArg::flag)/[`switch`](NamedArg::switch)/[`argument`](NamedArg::argument) that has a long name
1311///
1312/// You can chain multiple [`short`](NamedArg::short), [`long`](NamedArg::long) and
1313/// [`env`](NamedArg::env()) for multiple names. You can specify multiple names of the same type,
1314///  `bpaf` would use items past the first one as hidden aliases.
1315///
1316#[cfg_attr(not(doctest), doc = include_str!("docs2/short_long_env.md"))]
1317#[must_use]
1318pub fn long(long: &'static str) -> NamedArg {
1319    NamedArg {
1320        short: Vec::new(),
1321        long: vec![long],
1322        env: Vec::new(),
1323        help: None,
1324    }
1325}
1326
1327/// Parse an environment variable
1328///
1329/// You can chain multiple [`short`](NamedArg::short), [`long`](NamedArg::long) and
1330/// [`env`](NamedArg::env()) for multiple names. You can specify multiple names of the same type,
1331///  `bpaf` would use items past the first one as hidden aliases.
1332///
1333/// For [`flag`](NamedArg::flag) and [`switch`](NamedArg::switch) environment variable being present
1334/// gives the same result as the flag being present, allowing to implement things like `NO_COLOR`
1335/// variables:
1336///
1337/// ```console
1338/// $ NO_COLOR=1 app --do-something
1339/// ```
1340///
1341/// If you don't specify a short or a long name - whole argument is going to be absent from the
1342/// help message. Use it combined with a named or positional argument to have a hidden fallback
1343/// that wouldn't leak sensitive info.
1344///
1345#[cfg_attr(not(doctest), doc = include_str!("docs2/short_long_env.md"))]
1346#[must_use]
1347pub fn env(variable: &'static str) -> NamedArg {
1348    NamedArg {
1349        short: Vec::new(),
1350        long: Vec::new(),
1351        help: None,
1352        env: vec![variable],
1353    }
1354}
1355
1356/// Parse a positional argument
1357///
1358/// For named flags and arguments ordering generally doesn't matter: most programs would
1359/// understand `-O2 -v` the same way as `-v -O2`, but for positional items order matters: in *nix
1360/// `cat hello world` and `cat world hello` would display contents of the same two files but in
1361/// a different order.
1362///
1363/// When using combinatoric API you can specify the type with turbofish, for parsing types
1364/// that don't implement [`FromStr`] you can use consume a `String`/`OsString` first and parse
1365/// it by hand.
1366/// ```no_run
1367/// # use bpaf::*;
1368/// fn parse_pos() -> impl Parser<usize> {
1369///     positional::<usize>("POS")
1370/// }
1371/// ```
1372///
1373/// # Important restriction
1374/// To parse positional arguments from a command line you should place parsers for all your
1375/// named values before parsers for positional items and commands. In derive API fields parsed as
1376/// positional items or commands should be at the end of your `struct`/`enum`. The same rule applies
1377/// to parsers with positional fields or commands inside: such parsers should go to the end as well.
1378///
1379/// Use [`check_invariants`](OptionParser::check_invariants) in your test to ensure correctness.
1380///
1381/// For example for non-positional `non_pos` and positional `pos` parsers
1382/// ```rust
1383/// # use bpaf::*;
1384/// # let non_pos = || short('n').switch();
1385/// # let pos = ||positional::<String>("POS");
1386/// let valid = construct!(non_pos(), pos());
1387/// let invalid = construct!(pos(), non_pos());
1388/// ```
1389///
1390/// **`bpaf` panics during help generation unless this restriction holds**
1391///
1392/// Without using `--` `bpaf` would only accept items that don't start with `-` as positional, you
1393/// can use [`any`] to work around this restriction.
1394///
1395/// By default `bpaf` accepts positional items with or without `--` where values permit, you can
1396/// further restrict the parser to accept positional items only on the right side of `--` using
1397/// [`strict`](ParsePositional::strict).
1398#[cfg_attr(not(doctest), doc = include_str!("docs2/positional.md"))]
1399#[must_use]
1400pub fn positional<T>(metavar: &'static str) -> ParsePositional<T> {
1401    build_positional(metavar)
1402}
1403
1404#[doc(hidden)]
1405#[deprecated = "You should switch from command(name, sub) to sub.command(name)"]
1406pub fn command<T>(name: &'static str, subparser: OptionParser<T>) -> ParseCommand<T>
1407where
1408    T: 'static,
1409{
1410    ParseCommand {
1411        longs: vec![name],
1412        shorts: Vec::new(),
1413        help: subparser.short_descr(),
1414        subparser,
1415        adjacent: false,
1416    }
1417}
1418
1419/// Parse a single arbitrary item from a command line
1420///
1421/// **`any` is designed to consume items that don't fit into the usual [`flag`](NamedArg::flag)
1422/// /[`switch`](NamedArg::switch)/[`argument`](NamedArg::argument)/[`positional`]/
1423/// [`command`](OptionParser::command) classification, in most cases you don't need to use it**
1424///
1425/// By default, `any` behaves similarly to [`positional`] so you should be using it near the
1426/// rightmost end of the consumer struct and it will only try to parse the first unconsumed item
1427/// on the command line. It is possible to lift this restriction by calling
1428/// [`anywhere`](ParseAny::anywhere) on the parser.
1429///
1430/// `check` argument is a function from any type `I` that implements `FromStr` to `T`.
1431/// Usually this should be `String` or `OsString`, but feel free to experiment. When
1432/// running `any` tries to parse an item on a command line into that `I` and applies the `check`
1433/// function. If the `check` succeeds - parser `any` succeeds and produces `T`, otherwise it behaves
1434/// as if it hasn't seen it. If `any` works in `anywhere` mode - it will try to parse all other
1435/// unconsumed items, otherwise, `any` fails.
1436///
1437/// # Use `any` to capture the remaining arguments
1438/// Normally you would use [`positional`] with [`strict`](ParsePositional::strict) annotation for
1439/// that, but using any allows you to blur the boundary between arguments for child process and self
1440/// process a bit more.
1441#[cfg_attr(not(doctest), doc = include_str!("docs2/any_simple.md"))]
1442///
1443/// # Use `any` to parse a non standard flag
1444///
1445#[cfg_attr(not(doctest), doc = include_str!("docs2/any_switch.md"))]
1446///
1447/// # Use `any` to parse a non standard argument
1448/// Normally `any` would try to display itself as a usual metavariable in the usage line and
1449/// generated help, you can customize that with [`metavar`](ParseAny::metavar) method:
1450///
1451#[cfg_attr(not(doctest), doc = include_str!("docs2/any_literal.md"))]
1452///
1453/// # See also
1454/// [`literal`] - a specialized version of `any` that tries to parse a fixed literal
1455#[must_use]
1456pub fn any<I, T, F>(metavar: &str, check: F) -> ParseAny<T>
1457where
1458    I: FromStr + 'static,
1459    F: Fn(I) -> Option<T> + 'static,
1460    <I as std::str::FromStr>::Err: std::fmt::Display,
1461{
1462    ParseAny {
1463        metavar: [(metavar, Style::Metavar)][..].into(),
1464        help: None,
1465        check: Box::new(move |os: std::ffi::OsString| {
1466            match crate::from_os_str::parse_os_str::<I>(os) {
1467                Ok(v) => check(v),
1468                Err(_) => None,
1469            }
1470        }),
1471
1472        anywhere: false,
1473    }
1474}
1475
1476/// A specialized version of [`any`] that consumes an arbitrary string
1477///
1478/// By default `literal` behaves similarly to [`positional`] so you should be using it near the
1479/// rightmost end of the consumer struct and it will only try to parse the first unconsumed
1480/// item on the command line. It is possible to lift this restriction by calling
1481/// [`anywhere`](ParseAny::anywhere) on the parser.
1482///
1483#[cfg_attr(not(doctest), doc = include_str!("docs2/any_literal.md"))]
1484///
1485/// # See also
1486/// [`any`] - a generic version of `literal` that uses function to decide if value is to be parsed
1487/// or not.
1488#[must_use]
1489pub fn literal(val: &'static str) -> ParseAny<()> {
1490    any("", move |s: String| if s == val { Some(()) } else { None })
1491        .metavar(&[(val, crate::buffer::Style::Literal)][..])
1492}
1493
1494/// Strip a command name if present at the front when used as a `cargo` command
1495///
1496// this is exactly the same as batteries::cargo_helper, but used by derive macro...
1497#[must_use]
1498#[doc(hidden)]
1499pub fn cargo_helper<P, T>(cmd: &'static str, parser: P) -> impl Parser<T>
1500where
1501    T: 'static,
1502    P: Parser<T>,
1503{
1504    let skip = literal(cmd).optional().hide();
1505    construct!(skip, parser).map(|x| x.1)
1506}
1507
1508/// Choose between several parsers specified at runtime
1509///
1510/// You can use this function to create multiple parsers that produce the same type of value at a runtime
1511/// and let bpaf to pick one that best fits best. This function is designed to work in Combinatoric
1512/// API, but you can use it in Derive API with `extern`.
1513///
1514#[cfg_attr(not(doctest), doc = include_str!("docs2/choice.md"))]
1515pub fn choice<T: 'static>(parsers: impl IntoIterator<Item = Box<dyn Parser<T>>>) -> impl Parser<T> {
1516    let mut parsers = parsers.into_iter();
1517    let mut this = match parsers.next() {
1518        None => return fail("Invalid choice usage").boxed(),
1519        Some(p) => p,
1520    };
1521    for that in parsers {
1522        this = Box::new(ParseOrElse { this, that })
1523    }
1524    this
1525}
1526
1527/// Parse the application name
1528///
1529/// If you are using [`OptionParser::run`] then it should just work. If you are using
1530/// some variation of [`OptionParser::run_inner`] you'll need to set the application
1531/// name using [`Args::set_name`].
1532///
1533#[cfg_attr(not(doctest), doc = include_str!("docs2/appname.md"))]
1534pub fn appname() -> impl Parser<String> {
1535    ParseAppname
1536}
1537
1538#[derive(Debug, Copy, Clone)]
1539struct ParseAppname;
1540impl Parser<String> for ParseAppname {
1541    fn eval(&self, args: &mut State) -> Result<String, Error> {
1542        Ok(args
1543            .path
1544            .first()
1545            .cloned()
1546            .unwrap_or_else(|| String::from("app")))
1547    }
1548
1549    fn meta(&self) -> Meta {
1550        Meta::Skip
1551    }
1552}