auto_args/
guide.rs

1//! # A user's guide for auto_args.
2//! 
3//! AutoArgs allows you to parse command line arguments by defining a
4//! struct.  It combines [clap](https://crates.io/crates/clap) with
5//! custom derive.
6//! 
7//! The basic idea is that you define a type that represents the
8//! information you want on the command-line from the person running
9//! your program, and `derive(AutoArgs)` on that type, and then call
10//! `YourType::from_args()` to find out what your user gave you.
11//! To begin with, let's look at an example of how you might actually
12//! use `AutoArgs` in a real program.
13//! 
14//! ```should_panic
15//! #[macro_use]
16//! extern crate auto_args;
17//! 
18//! use std::path::PathBuf;
19//! use auto_args::AutoArgs;
20//! 
21//! #[derive(Debug, AutoArgs)]
22//! struct Opt {
23//! /// Filling fraction
24//! filling_fraction: f64,
25//! /// Number of atoms
26//! N: u32,
27//! /// Output directory, working directory if not present
28//! dir: Option<PathBuf>,
29//! /// Activate verbose printing
30//! verbose: bool,
31//! }
32//! 
33//! fn main() {
34//! let opt = Opt::from_args();
35//! println!("{:?}", opt);
36//! }
37//! ```
38//! The remainder of this guide will give examples of how the
39//! command-line flags are constructed from your type, starting with
40//! simple cases and moving gradually to more complex ones.  In no
41//! case does your code involve more than defining a type, deriving
42//! `AutoArgs` and calling the `from_args` method of your type.
43//! I want to note that `AutoArgs` *almost always* produces long flags.
44//! This is because I feel that long flags are generally the easiest
45//! to use.  If you want to fine-tune your command-line interface,
46//! `AutoArgs` may not be for you.
47//! ## Just a flag
48//! Most often, you will define a struct as your type.  We'll
49//! start out with the simplest case, which is a single boolean
50//! field within that struct.
51//! ```
52//! struct Foo {
53//!     foo: bool,
54//! }
55//! ```
56//! This gives the following usage.
57//! ```ignore
58//! USAGE:
59//!   create_guide-5214c7bad433b4e9  [--foo]
60//! 
61//! For more information try --help
62//! ```
63//! and the following help message.
64//! ```ignore
65//! USAGE:
66//!   create_guide-5214c7bad433b4e9  [--foo]
67//! 
68//!   [--foo] 
69//! 
70//! 
71//! For more information try --help
72//! ```
73//! A single boolean flag is treated as an optional flag.
74//! ## Adding help information
75//! We add help information simply by adding ordinary doc comments
76//! to our struct.
77//! ```
78//! struct Help {
79//!     /// Print excess messages.
80//!     verbose: bool,
81//!     /// The temperature.
82//!     T: bool,
83//! }
84//! ```
85//! This gives the following usage.
86//! ```ignore
87//! USAGE:
88//!   create_guide-5214c7bad433b4e9  [--verbose] [--T]
89//! 
90//! For more information try --help
91//! ```
92//! and the following help message.
93//! ```ignore
94//! USAGE:
95//!   create_guide-5214c7bad433b4e9  [--verbose] [--T]
96//! 
97//!   [--verbose] Print excess messages.
98//!   [--T]       The temperature.
99//! 
100//! 
101//! For more information try --help
102//! ```
103//! I would always documentation for actual projects, so I'll try
104//! to model that here, even though these examples are all
105//! fictitious.
106//! ## How the flag is determined
107//! We saw above that the flag just had `--` prepended to the
108//! field name.  The rule in general is only slightly more
109//! complicated: every underscore is replaced with a `-`.
110//! ```
111//! struct Flags {
112//!     /// a simple word has "--" prepended to it.
113//!     verbose: bool,
114//!     /// Underscores are replaced with "-" ...
115//!     blue_is_nice_: bool,
116//!     /// and capital letters are preserved.
117//!     min_T: bool,
118//! }
119//! ```
120//! This gives the following usage.
121//! ```ignore
122//! USAGE:
123//!   create_guide-5214c7bad433b4e9  [--verbose] [--blue-is-nice-] [--min-T]
124//! 
125//!   [--verbose]       a simple word has "--" prepended to it.
126//!   [--blue-is-nice-] Underscores are replaced with "-" ...
127//!   [--min-T]         and capital letters are preserved.
128//! 
129//! 
130//! For more information try --help
131//! ```
132//! Thus you can create most any flag name you care for, and it is
133//! easy to tell which flag corresponds to which field in your
134//! struct.
135//! ## Other types
136//! You can add most standard library types to your struct,
137//! basically anything that can be read or parsed from a `&str`.
138//! I'd recommend sticking to owned types.
139//! ```
140//! struct Types {
141//!     /// The name of the type
142//!     name: String,
143//!     /// The temperature of the type
144//!     T: f64,
145//!     /// The place where it is
146//!     directory: std::path::PathBuf,
147//! }
148//! ```
149//! This gives the following usage.
150//! ```ignore
151//! USAGE:
152//!   create_guide-5214c7bad433b4e9  --name STRING --T FLOAT --directory STRING
153//! 
154//!   --name STRING      The name of the type
155//!   --T FLOAT          The temperature of the type
156//!   --directory STRING The place where it is
157//! 
158//! 
159//! For more information try --help
160//! ```
161//! I should note that integer types do allow their value to be
162//! specified using scientific notation, as in `1e6` rather than
163//! `1000000`.  This is in different from rust's `FromStr`
164//! implementation.  AutoArgs does reject floating point values that
165//! cannot be reversibly converted to the integer type that is
166//! requested.
167//! 
168//! Furthermore, when providing numerical user input, users may
169//! specify an expression such as `1/3` or `sqrt(2)`.  This is
170//! most useful for floating point input where makes it easier to
171//! give high-precision input when needed, but may also be helpful
172//! for integers.
173//! ## Optional flags
174//! In the previous examples, every flag (except a `bool` flag)
175//! was required to be specified by the user.  If you want a flag
176//! to be optional, you just use the standard `Option` type.
177//! ```
178//! struct Optional {
179//!     /// The name is an optional argument.
180//!     name: Option<String>,
181//! }
182//! ```
183//! This gives the following usage.
184//! ```ignore
185//! USAGE:
186//!   create_guide-5214c7bad433b4e9  [--name STRING]
187//! 
188//!   [--name STRING] The name is an optional argument.
189//! 
190//! 
191//! For more information try --help
192//! ```
193//! The value is then `None` if the user did not specify that flag.
194//! ## Exclusive flags
195//! If you want to make certain flags/values mutually exclusive,
196//! you use an `enum` (just as always, in rust).
197//! ```
198//! enum Exclusive {
199//!     /// In this context, the doc comment for the variant is not
200//!     /// used by auto_args.
201//!     First {
202//!         /// This is the "a" value
203//!         a: String,
204//!         /// Only the first line of comment shows up in help.
205//!         /// This is the "b" value, which you cannot specify unless
206//!         /// you also specify the "a" value.
207//!         b: String,
208//!     },
209//!     /// A string that cannot be used with any other flag
210//!     SecondFlag(String),
211//!     /// A flag with no value, and with a capital letter.
212//!     Third_,
213//! }
214//! ```
215//! This gives the following usage.
216//! ```ignore
217//! USAGE:
218//!   create_guide-5214c7bad433b4e9 (  --first-a STRING --first-b STRING | --second-flag STRING | --Third )
219//! 
220//! For more information try --help
221//! ```
222//! and the following help message.
223//! ```ignore
224//! USAGE:
225//!   create_guide-5214c7bad433b4e9 (  --first-a STRING --first-b STRING | --second-flag STRING | --Third )
226//! 
227//!   EITHER               
228//!   --first-a STRING     This is the "a" value
229//!   --first-b STRING     Only the first line of comment shows up in help.
230//!   OR                   
231//!   --second-flag STRING A string that cannot be used with any other flag
232//!   OR                   
233//!   --Third              A flag with no value, and with a capital letter.
234//!                        
235//! 
236//! 
237//! For more information try --help
238//! ```
239//! This example illustrates the three kinds of `enum` variants.
240//! Sadly, the help message does not indicate that these flags are
241//! exlusive.  However, if a user tries to specify both `--third`
242//! and `--second FOO`, however, they will get a nice error
243//! message.  Note that you cannot use a tuple variant with more
244//! than one field.
245//! Note that the rules for constructing flags from enum variants
246//! are more complicated than for struct fields.  This is because
247//! by convention variants are given `CamelCase` names, which
248//! aren't suitable as flags.  If a variant name contains an
249//! underscore, then it is treated like a field name (as described
250//! above), with any trailing underscores removed.  Otherwise the
251//! name is converted from `CamelCase` to `kebab-case`.
252//! ## Nesting types
253//! You can use any `AutoArgs` type as a field within a struct or
254//! enum.  Doing so will give flag names that combine the nested
255//! field names.
256//! ```ignore
257//! #[derive(AutoArgs)]
258//! /// I'm not putting doc-comments on `x` and `y`, because auto_args
259//! /// would give the same help message for `--position-x` as for
260//! /// `--velocity-x`, which would be pretty useless.
261//! struct Vec2d {
262//!     x: f64,
263//!     y: f64,
264//! }
265//! #[derive(AutoArgs)]
266//! struct Nested {
267//!     /// We would like for this to be the help for both components
268//!     /// of the position, but auto_args is not that clever.  Ideally
269//!     /// the help should read something like: the x component of
270//!     /// the position/velocity, but that would require combining
271//!     /// information at multiple levels and sounds hard.
272//!     position: Vec2d,
273//!     velocity: Vec2d,
274//! }
275//! ```
276//! This gives the following usage.
277//! ```ignore
278//! USAGE:
279//!   create_guide-5214c7bad433b4e9   --position-x FLOAT --position-y FLOAT  --velocity-x FLOAT --velocity-y FLOAT
280//! 
281//!   --position-x FLOAT 
282//!   --position-y FLOAT 
283//!   --velocity-x FLOAT 
284//!   --velocity-y FLOAT 
285//! 
286//! 
287//! For more information try --help
288//! ```
289//! ## Flattened nesting types
290//! As you say in the last example, nesting types allows you to
291//! make your own complex types that can be reused.  Sometimes,
292//! however, you would like to nest structs for a different
293//! reason: to separate concerns in the code.  In this case, you
294//! may not want the nesting to be visible in the user interface.
295//! This can be acheived with a leading underscore on a field
296//! name.  The catch is that when you do this, you could run into
297//! a runtime error if you have duplicate field names.
298//! ```ignore
299//! #[derive(AutoArgs)]
300//! struct MyConfig {
301//!     /// The user's name
302//!     name: String,
303//! }
304//! #[derive(AutoArgs)]
305//! struct YourConfig {
306//!     /// The user's address
307//!     address: String,
308//! }
309//! #[derive(AutoArgs)]
310//! struct Flattened {
311//!     _mine: MyConfig,
312//!     _yours: YourConfig,
313//! }
314//! ```
315//! This gives the following usage.
316//! ```ignore
317//! USAGE:
318//!   create_guide-5214c7bad433b4e9   --name STRING  --address STRING
319//! 
320//! For more information try --help
321//! ```
322//! and the following help message.
323//! ```ignore
324//! USAGE:
325//!   create_guide-5214c7bad433b4e9   --name STRING  --address STRING
326//! 
327//!   --name STRING    The user's name
328//!   --address STRING The user's address
329//! 
330//! 
331//! For more information try --help
332//! ```
333//! This may be a good idea if `MyConfig` and `YourConfig` are
334//! implementation details that your user need not be aware of.
335//! ## Other possibilities
336//! There may be a few other features that auto_args has, for which I
337//! have not bothered to create an entire example.  I will list
338//! them here when they come to mind.
339//! 1. You can use a `Vec<T>` for many values of `T` to create an
340//! option that can be specified more than once.
341//! ## Conclusion
342//! There is more that could be said and more possible examples,
343//! but I think this is enough to get you started using `AutoArgs`.
344//! The intent is that any reasonable type that *can* be obtained
345//! from one or more strings should work with auto_args.  Please fill
346//! an issue on github if there is a type that you would like to
347//! have supported by auto_args.  Pull requests are most welcome.