1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
//! # Using the library in derive style
//! # About examples
//!
//! Most of the examples omit adding doc comments to the fields, to keep things clearer, you should do
//! that when possible for better end user experience. Don't forget to add `#[bpaf(options)]` for a top level
//! structure that defines the option parser itself.
//!
//! ```rust
//! # use bpaf::*;
//! #[derive(Debug, Clone, Bpaf)]
//! #[bpaf(options)] // <- important bit
//! struct Config {
//! /// number used by the program
//! number: u32,
//! }
//! ```
//!
//! In addition to examples in the documentation there's a bunch more in the github repository:
//! <https://github.com/pacak/bpaf/tree/master/examples>
//! # Recommended reading order
//!
//! Combinatoric and derive APIs share the documentation and most of the names, recommended reading order:
//! 1. [`construct!`] - what combinations are
//! 2. [`NamedArg`], [`positional`] and [`command`] - on consuming data
//! 3. [`Parser`] - on transforming the data
//! 4. [`OptionParser`] - on running the result
//! # Getting started
//!
//! 1. To use derive style API you need to enable `"derive"` feature for `bpaf`, **by default it's not
//! enabled**.
//!
//! 2. Define primitive parsers if you want to use any. While it's possible to define most of them
//! in derive style - doing complex parsing or validation is often easier in combinatoric style
//!
//! 3. Define types used to derive parsers, structs correspond to *AND* combination and require for
//! all the fields to have a value, enums to *OR* combinations and require (and consume) all the
//! values for one branch only.
//!
//! 4. Add annotations to the top level of a struct if needed, there's several to choose from and
//! you can specify several of them. For this annotation ordering doesn't matter.
//!
//! - ### Generated function name: `generate`
//!
//! Unlike usual derive macro `bpaf_derive` generates a function with a name
//! derived from a struct name by transforming it from `CamelCase` to `snake_case`. `generate`
//! annotation allows to override a name for the function
//!
//! ```rust
//! # use bpaf::*;
//! #[derive(Debug, Clone, Bpaf)]
//! #[bpaf(generate(make_config))] // function name is now make_config()
//! pub struct Config {
//! pub flag: bool
//! }
//! ```
//!
//! - ### Generated function visibility: `private`
//!
//! By default `bpaf` uses the same visibility as the datatype,
//! `private` makes it module private:
//!
//! ```rust
//! # use bpaf::*;
//! #[derive(Debug, Clone, Bpaf)]
//! #[bpaf(private)] // config() is now module private
//! pub struct Config {
//! pub flag: bool
//! }
//! ```
//!
//! - ### Generated function types: `command`, `options`
//!
//! By default `bpaf_derive` would generate a function that generates a regular [`Parser`]
//! it's possible instead to turn it into a
//! [`command`] with `command` annotation or into a top level [`OptionParser`] with `options`
//! annotation.
//! Those annotations are mutually exclusive. `options` annotation takes an optional argument
//! to use for [`cargo_helper`], `command` annotation takes an optional argument to
//! override a command name.
//!
//! ```rust
//! # use bpaf::*;
//! #[derive(Debug, Clone, Bpaf)]
//! pub struct Flag { // impl Parser by default
//! pub flag: bool
//! }
//!
//! #[derive(Debug, Clone, Bpaf)]
//! #[bpaf(command)]
//! pub struct Make { // generates a command "make"
//! pub level: u32,
//! }
//!
//!
//! #[derive(Debug, Clone, Bpaf)]
//! #[bpaf(options)] // config() is now OptionParser
//! pub struct Config {
//! pub flag: bool
//! }
//! ```
//!
//! - ### Specify version for generated command: `version`
//!
//! By default `bpaf_derive` embedds no version information. With `version` with no argument
//! results in using version from `CARGO_PKG_VERSION` env variable (specified by cargo on
//! compile time, usually originates from `Cargo.toml`), `version` with argument results in
//! using tht specific version - can be string literal or static string expression.
//! Only makes sense for `command` and `options` annotations. For more information see
//! [`version`](OptionParser::version).
//!
//! ```rust
//! # use bpaf::*;
//! #[derive(Debug, Clone, Bpaf)]
//! #[bpaf(options, version("3.1415"))] // --version is now 3.1415
//! pub struct Config {
//! pub flag: bool
//! }
//! ```
//!
//! - ### Fallback value if all parsers fails: `fallback`
//!
//! You can add a fallback value to use if all the values required are missing.
//! See [`req_flag`](NamedArg::req_flag) examples.
//!
//! 5. Add annotations to individual fields. Structure for annotation for individual fields
//! is similar to how you would write the same code with combinatoric API with exception
//! of `external` and usually looks something like this:
//!
//! `((<naming> <consumer>) | <external>) <postprocessing>`
//!
//! - `naming` section corresponds to [`short`], [`long`] and [`env`](env()). `short` takes an optional
//! character literal as a parameter, `long` takes an optional string, `env` takes an
//! expression of type `&'static str` as a parameter - could be a string literal or a
//! constant.
//!
//! + If parameter for `short`/`long` is parameter isn't present it's derived from the field
//! name: first character and a whole name respectively.
//!
//! + If either of `short` or `long` is present - `bpaf_derive` would not add the other one.
//!
//! + If neither is present - `bpaf_derive` would add a `long` one.
//!
//! ```rust
//! # use bpaf::*;
//! const DB: &str = "top_secret_database";
//!
//! #[derive(Debug, Clone, Bpaf)]
//! pub struct Config {
//! pub flag_1: bool, // no annotation: --flag_1
//!
//! #[bpaf(short)]
//! pub flag_2: bool, // explicit short suppresses long: -f
//!
//! #[bpaf(short('z'))]
//! pub flag_3: bool, // explicit short with custom letter: -z
//!
//! #[bpaf(short, long)]
//! pub deposit: bool, // explicit short and long: -d --deposit
//!
//! #[bpaf(env(DB))]
//! pub database: String, // --database + env variable from DB constant
//!
//! #[bpaf(env("USER"))] // --user + env variable "USER"
//! pub user: String,
//! }
//! ```
//!
//! - `consumer` section corresponds to [`argument`](NamedArg::argument), [`positional`],
//! [`flag`](NamedArg::flag), [`switch`](NamedArg::switch) and [`any`].
//!
//! + With no consumer annotations `bpaf_derive` parses tuple structs (`struct Config(String)`)
//! as positional items, but it's possible to override it by giving it a name:
//!
//! ```rust
//! # use bpaf::*;
//! # use std::path::PathBuf;
//! #[derive(Debug, Clone, Bpaf)]
//! struct Opt(PathBuf); // stays positional
//!
//! #[derive(Debug, Clone, Bpaf)]
//! struct Config(#[bpaf(long("input"))] PathBuf); // turns into a named argument
//! ```
//!
//! + `bpaf_derive` handles fields of type `Option<Foo>` with [`optional`](Parser::optional)
//! and `Vec<Foo>` with [`many`](Parser::many), see `postprocessing` for more details.
//!
//! + `bpaf_derive` handles `bool` fields with [`switch`](NamedArg::switch),
//! `()` with [`req_flag`](NamedArg::req_flag), [`OsString`] and [`PathBuf`] are parsed from
//! `OsString` and anything else with [`FromStr`] trait. See documentation for
//! [`argument`](NamedArg::argument) and [`positional`] for more details.
//!
//! - If `external` is present - it usually serves function of `naming` and `consumer`, allowing
//! more for `postprocessing` annotations after it. Takes an optional parameter - a function
//! name to call, if not present - `bpaf_derive` uses field name for this purpose.
//! Functions should return impl [`Parser`] and you can either declare them manually
//! or derive with `Bpaf` macro.
//!
//! ```rust
//! # use bpaf::*;
//! fn verbosity() -> impl Parser<usize> {
//! short('v')
//! .help("vebosity, can specify multiple times")
//! .req_flag(())
//! .many()
//! .map(|x| x.len())
//! }
//!
//! #[derive(Debug, Clone, Bpaf)]
//! pub struct Username {
//! pub user: String
//! }
//!
//! #[derive(Debug, Clone, Bpaf)]
//! pub struct Config {
//! #[bpaf(external)]
//! pub verbosity: usize, // implicit name - "verbosity"
//!
//! #[bpaf(external(username))]
//! pub custom_user: Username, // explicit name - "username"
//! }
//! ```
//!
//! - `postprocessing` - various methods from [`Parser`] trait, order matters, most of them are
//! taken literal, see documentation for the trait for more details. `bpaf_derive` automatically
//! uses [`many`](Parser::many) and [`optional`](Parser::optional) to handle `Vec<T>` and
//! `Option<T>` fields respectively.
//!
//! Any operation that can change the type (such as [`parse`](Parser::parse) or [`map`](Parser::map))
//! for disables this logic for the field and also requires to specify the consumer:
//! ```rust
//! # use bpaf::*;
//! #[derive(Debug, Clone, Bpaf)]
//! struct Options {
//! #[bpaf(argument::<u32>("NUM"), many)]
//! numbers: Vec<u32>
//! }
//! ```
//!
//! - field-less enum variants obey slightly different set of rules, see
//! [`req_flag`](NamedArg::req_flag) for more details.
//!
//! - any constructor in `enum` can have `skip` annotation - `bpaf_derive`
//! would ignore them when generating code:
//! ```rust
//! # use bpaf::*;
//! #[derive(Debug, Clone, Bpaf)]
//! enum Decision {
//! Yes,
//! No,
//! #[bpaf(skip)]
//! Maybe
//! }
//!
//! ```
//!
//! 6. Add documentation for help messages.
//! `bpaf_derive` generates help messages from doc comments, it skips single empty lines and stops
//! processing after double empty line:
//!
//! ```rust
//! # use bpaf::*;
//! #[derive(Debug, Clone, Bpaf)]
//! pub struct Username {
//! /// this is a part of a help message
//! ///
//! /// so is this
//! ///
//! ///
//! /// but this isn't
//! pub user: String
//! }
//! ```
//!
//! 7. Add [`check_invariants`](OptionParser::check_invariants) to your test code.
#[cfg(doc)]
use crate::{params::*, parsers::*, *};
#[cfg(doc)]
use std::{ffi::OsString, path::PathBuf};
#[cfg(all(doc, feature = "batteries"))]
use crate::batteries::cargo_helper;