structopt_flags/lib.rs
1//! `structopt-flags` is a collection of reusable CLI flags and options
2//! based on structopt
3//!
4//! Every flag or option is already pre-configured and can be used marking the field as `flatten`
5//!
6//! # Verbosity
7//! Currently, a set of verbosity flags, connected to log levels option, are provided.
8//! Some flags and options are provided in multiple configuration, to leave the choice to the
9//! developer which one to use.
10//! For instance, there are 4 type for vebosity flag:
11//! * Verbose: -v flag, it provides a log level with Error as default level
12//! * QuietVerbose: -v flag to increase vebosity, -q to decrease it; default level: Warning
13//! * SimpleVebose: -v flag as boolean, no default log level provided
14//! * VeboseNoDef: -v flag, to increase verbosity, but without a default value
15//! ### Verbose
16//! This struct provides the `--verbose` cli option
17//!
18//! By default, the log level is set to error.
19//! Multiple occurrences, will increase the verbosity level up to 4.
20//!
21//! ```rust
22//! use structopt::StructOpt;
23//! use structopt_flags::LogLevel; // to access get_log_level
24//!
25//! #[derive(Debug, StructOpt)]
26//! #[structopt(name = "verbose", about = "An example using verbose flag")]
27//! struct Opt {
28//! #[structopt(flatten)]
29//! verbose: structopt_flags::Verbose,
30//! }
31//!
32//! let opt = Opt::from_args();
33//! let filter_level = opt.verbose.get_level_filter();
34//! // set log level
35//! ```
36//! ### VerboseNoDef
37//! This struct provides the `--verbose` cli option, without a predefined default
38//!
39//! Multiple occurrences, will increase the verbosity level
40//!
41//! ```rust
42//! use log::LevelFilter;
43//! use structopt::StructOpt;
44//! use structopt_flags::GetWithDefault; // to access get_log_level
45//!
46//! #[derive(Debug, StructOpt)]
47//! #[structopt( name = "verbose_no_def", about = "An example using verbose flag with no predefined default")]
48//! struct Opt {
49//! #[structopt(flatten)]
50//! verbose: structopt_flags::VerboseNoDef,
51//! }
52//!
53//! let opt = Opt::from_args();
54//! let filter_level = opt.verbose.get_with_default(LevelFilter::Off);
55//! // set log level
56//! ```
57//! ### QuietVerbose
58//! This struct implements the `--verbose` and the `--quiet` cli options
59//!
60//! By default, the log level is set to warning.
61//! Multiple occurrences of `-v`, will increase the verbosity level up to 3.
62//! The flag `-q` is used to decrease verbosity.
63//! Using it twice, will silent the log.
64//!
65//! ```rust
66//! use structopt::StructOpt;
67//! use structopt_flags::LogLevel; // to access get_log_level
68//!
69//! #[derive(Debug, StructOpt)]
70//! #[structopt(name = "quietverbose", about = "An example using quietverbose flag")]
71//! struct Opt {
72//! #[structopt(flatten)]
73//! verbose: structopt_flags::QuietVerbose,
74//! }
75//!
76//! let opt = Opt::from_args();
77//! let filter_level = opt.verbose.get_level_filter();
78//! // set log level
79//! ```
80//! ### SimpleVerbose
81//! This struct implements the `--verbose` cli option as a boolean flag
82//!
83//! By default, the log level is set to warning.
84//! Multiple occurrences of `-v` are not supported
85//!
86//! ```rust
87//! use structopt::StructOpt;
88//!
89//! #[derive(Debug, StructOpt)]
90//! #[structopt(name = "verbose", about = "An example using verbose flag")]
91//! struct Opt {
92//! #[structopt(flatten)]
93//! verbose: structopt_flags::SimpleVerbose,
94//! }
95//!
96//! let opt = Opt::from_args();
97//! if opt.verbose.verbose {
98//! println!("Verbose output enabled");
99//! } else {
100//! println!("No verbose output");
101//! }
102//! ```
103//! # Log levels
104//! There are several options available to specify a log level:
105//!
106//! ### LogLevelOpt
107//! This struct provides the `--log` and `-L` cli option
108//!
109//! By default, the log level is set to info.
110//!
111//! ```rust
112//! use structopt::StructOpt;
113//! use structopt_flags::LogLevel; // to access get_log_level
114//!
115//! #[derive(Debug, StructOpt)]
116//! #[structopt(name = "log_level_opt", about = "An example using the LogLevelOpt option")]
117//! struct Opt {
118//! #[structopt(flatten)]
119//! log_level: structopt_flags::LogLevelOpt,
120//! }
121//!
122//! let opt = Opt::from_args();
123//! let filter_level = opt.log_level.get_level_filter();
124//! // set log level
125//! ```
126//! ### LogLevelOptLower
127//! This struct provides the `--log` and `-l` cli option, with a lower case letter
128//!
129//! By default, the log level is set to info.
130//!
131//! ```rust
132//! use structopt::StructOpt;
133//! use structopt_flags::LogLevel; // to access get_log_level
134//!
135//! #[derive(Debug, StructOpt)]
136//! #[structopt(name = "log_level_opt_lower", about = "An example using the LogLevelOptLower option")]
137//! struct Opt {
138//! #[structopt(flatten)]
139//! log_level: structopt_flags::LogLevelOptLower,
140//! }
141//!
142//! let opt = Opt::from_args();
143//! let filter_level = opt.log_level.get_level_filter();
144//! // set log level
145//! ```
146//! ### LogLevelNoDev
147//! This struct provides the `--log` and `-L` cli option, with no default value
148//!
149//! No default value is provided
150//!
151//! ```rust
152//! use log::LevelFilter;
153//! use structopt::StructOpt;
154//! use structopt_flags::GetWithDefault; // to access get_log_level
155//!
156//! #[derive(Debug, StructOpt)]
157//! #[structopt(name = "log_level_no_def", about = "An example using the LogLevelNoDef option")]
158//! struct Opt {
159//! #[structopt(flatten)]
160//! log_level: structopt_flags::LogLevelNoDef,
161//! }
162//!
163//! let opt = Opt::from_args();
164//! let filter_level = opt.log_level.get_with_default(LevelFilter::Warn);
165//! // set log level
166//! ```
167//! ### LogLevelNoDefLower
168//! This struct provides the `--log` and `-l` cli option, with no default value and with a lower case
169//! letter
170//!
171//! No default value is provided
172//!
173//! ```rust
174//! use log::LevelFilter;
175//! use structopt::StructOpt;
176//! use structopt_flags::GetWithDefault; // to access get_log_level
177//!
178//! #[derive(Debug, StructOpt)]
179//! #[structopt(name = "log_level_no_def_lower", about = "An example using the LogLevelNoDefLower option")]
180//! struct Opt {
181//! #[structopt(flatten)]
182//! log_level: structopt_flags::LogLevelNoDefLower,
183//! }
184//!
185//! let opt = Opt::from_args();
186//! let filter_level = opt.log_level.get_with_default(LevelFilter::Warn);
187//! // set log level
188//! ```
189//!# Configuration file
190//!This reusable flag can be used to specify a configuration file
191//!
192//!### ConfigFile
193//!This struct provides the `--config_file` cli option
194//! The option is mandatory and require a filename
195//!
196//! ```should_panic
197//! use structopt::StructOpt;
198//! use structopt_flags::ConfigFile; // to access get_log_level
199//!
200//! #[derive(Debug, StructOpt)]
201//! #[structopt(name = "config-file", about = "An example using config_file option")]
202//! struct Opt {
203//! #[structopt(flatten)]
204//! config: structopt_flags::ConfigFile,
205//! }
206//!
207//! let opt = Opt::from_args();
208//! let config_file = opt.config.get_filename();
209//! // use the config file
210//! ```
211//!
212//! ### ConfigFileNoDef
213//! This struct provides the `--config_file` cli option
214//!
215//! The option is no mandatory, but a default value can be provided wit the get_with_default()
216//!
217//! ```rust
218//! use structopt::StructOpt;
219//! use structopt_flags::GetWithDefault; // to access get_log_level
220//! use std::path::PathBuf;
221//!
222//! #[derive(Debug, StructOpt)]
223//! #[structopt(name = "config-file", about = "An example using config_file option")]
224//! struct Opt {
225//! #[structopt(flatten)]
226//! config: structopt_flags::ConfigFileNoDef,
227//! }
228//!
229//! let opt = Opt::from_args();
230//! let config_file = opt.config.get_with_default("config-file.toml");
231//! // use the config file
232//! ```
233//! # Host IP address
234//! There several ways to provide an IP address
235//!
236//! ### HostV4Opt
237//! This struct provides the `--host` and `-H` cli option to get an IPv4 address
238//!
239//! No default is provided
240//!
241//! ```rust
242//! use std::net::Ipv4Addr;
243//! use structopt::StructOpt;
244//! use structopt_flags::GetWithDefault; // to access get_with_default
245//!
246//! #[derive(Debug, StructOpt)]
247//! #[structopt(name = "ipv4_opt", about = "An example using the HostV4Opt option")]
248//! struct Opt {
249//! #[structopt(flatten)]
250//! host_ip: structopt_flags::HostV4Opt,
251//! }
252//!
253//! let opt = Opt::from_args();
254//! let ipv4 = opt.host_ip.get_with_default(Ipv4Addr::new(127,0,0,1));
255//! ```
256//! ### HostV4Param
257//! This struct provides the `--host` and `-H` cli option to get an IPv4 address
258//!
259//! No default is provided and the parameter is mandatory
260//! This option is not global
261//!
262//! ```should_panic
263//! use std::net::Ipv4Addr;
264//! use structopt::StructOpt;
265//!
266//! #[derive(Debug, StructOpt)]
267//! #[structopt(name = "ipv4_param", about = "An example using the HostV4Param option")]
268//! struct Opt {
269//! #[structopt(flatten)]
270//! host_ip: structopt_flags::HostV4Param,
271//! }
272//!
273//! let opt = Opt::from_args();
274//! let ipv4 = opt.host_ip.host_addr;
275//! ```
276//! ### HostV6Opt
277//! This struct provides the `--host` and `-H` cli option to get an IPv6 address
278//!
279//! No default is provided
280//!
281//! ```rust
282//! use std::net::Ipv6Addr;
283//! use structopt::StructOpt;
284//! use structopt_flags::GetWithDefault; // to access get_with_default
285//!
286//! #[derive(Debug, StructOpt)]
287//! #[structopt(name = "ipv6_opt", about = "An example using the HostV6Opt option")]
288//! struct Opt {
289//! #[structopt(flatten)]
290//! host_ip: structopt_flags::HostV6Opt,
291//! }
292//!
293//! let opt = Opt::from_args();
294//! let ipv6 = opt.host_ip.get_with_default(Ipv6Addr::new(0,0,0,0,0,0,0,1));
295//! ```
296//! ### HostV6Param
297//! This struct provides the `--host` and `-H` cli option to get an IPv6 address
298//!
299//! No default is provided and the parameter is mandatory
300//! This option is not global
301//!
302//! ```should_panic
303//! use std::net::Ipv6Addr;
304//! use structopt::StructOpt;
305//!
306//! #[derive(Debug, StructOpt)]
307//! #[structopt(name = "ipv6_param", about = "An example using the HostV6Param option")]
308//! struct Opt {
309//! #[structopt(flatten)]
310//! host_ip: structopt_flags::HostV6Param,
311//! }
312//!
313//! let opt = Opt::from_args();
314//! let ipv6 = opt.host_ip.host_addr;
315//! ```
316//! ### HostOpt
317//! This struct provides the `--host` and `-H` cli option to get ageneric IP address
318//!
319//! No default is provided
320//!
321//! ```rust
322//! use std::net::{IpAddr,Ipv6Addr};
323//! use structopt::StructOpt;
324//! use structopt_flags::GetWithDefault; // to access get_with_default
325//!
326//! #[derive(Debug, StructOpt)]
327//! #[structopt(name = "ip_opt", about = "An example using the HostOpt option")]
328//! struct Opt {
329//! #[structopt(flatten)]
330//! host_ip: structopt_flags::HostOpt,
331//! }
332//!
333//! let opt = Opt::from_args();
334//! let ip = opt.host_ip.get_with_default(IpAddr::V6(Ipv6Addr::new(0,0,0,0,0,0,0,1)));
335//! ```
336//! ### HostParam
337//! This struct provides the `--host` and `-H` cli option to get ageneric IP address
338//!
339//! No default is provided and the parameter is mandatory
340//! This option is not global
341//!
342//! ```should_panic
343//! use std::net::{IpAddr,Ipv6Addr};
344//! use structopt::StructOpt;
345//!
346//! #[derive(Debug, StructOpt)]
347//! #[structopt(name = "ip_param", about = "An example using the HostParam option")]
348//! struct Opt {
349//! #[structopt(flatten)]
350//! host_ip: structopt_flags::HostParam,
351//! }
352//!
353//! let opt = Opt::from_args();
354//! let ip = opt.host_ip.host_addr;
355//! ```
356//! # Force flag
357//! This struct implements the `--force` cli option as a boolean flag
358//!
359//! The short form is `-f`
360//!
361//! ```rust
362//! use structopt::StructOpt;
363//!
364//! #[derive(Debug, StructOpt)]
365//! #[structopt(name = "force", about = "An example using force flag")]
366//! struct Opt {
367//! #[structopt(flatten)]
368//! force_flag: structopt_flags::ForceFlag,
369//! }
370//!
371//! let opt = Opt::from_args();
372//! if opt.force_flag.force {
373//! println!("Force operation");
374//! } else {
375//! println!("No forced behavior ");
376//! }
377//! ```
378mod config;
379mod force;
380mod ip;
381mod logopt;
382mod verbose;
383
384#[cfg(feature = "simplelog")]
385use simplelog::{Config, TermLogger, TerminalMode};
386
387pub use log::{Level, LevelFilter};
388/// This trait is designed to provide a log level filter, compatible with the Log crates, derived
389/// from an option or a flag. Options that can induce a log level, can implement this trait
390///
391/// If the simplelog features is configured, the `set_log_level()` function will provide an easy way
392/// to set the log level to the TermLogger
393pub trait LogLevel {
394 /// Return the level filter.
395 ///
396 /// The log level could be None if the log has been switched off
397 fn get_level_filter(&self) -> LevelFilter;
398
399 /// Return the log level.
400 ///
401 /// The log level could be None if the log has been switched off
402 fn get_log_level(&self) -> Option<Level> {
403 self.get_level_filter().to_level()
404 }
405
406 #[cfg(feature = "simplelog")]
407 /// This function will set the log level provided by the option/flag
408 /// if the feature `simplelog` is enabled
409 fn set_log_level(&self) {
410 TermLogger::init(
411 self.get_level_filter(),
412 Config::default(),
413 TerminalMode::Mixed,
414 )
415 .unwrap_or(());
416 }
417}
418
419/// This trait is designed to provide a rude form of default value for options
420/// If an option doesn't have a default value, it will implement this trait
421pub trait GetWithDefault {
422 type Item;
423 /// This function can be used to retrieve the value of the command line option
424 /// taking in account the default value used as argument
425 fn get_with_default<T: Into<Self::Item>>(&self, default: T) -> Self::Item;
426}
427#[cfg(feature = "simplelog")]
428/// This trait is designed to provide a way to set the log level, when the option
429/// or the flag doesn't have a default level and the `simplelog` feature is eanbled
430pub trait SetLogWithDefault: GetWithDefault {
431 /// This function can be used to set the loglevel
432 /// if the feature `simplelog` is enabled
433 fn set_with_default(&self, default: LevelFilter);
434}
435
436pub use crate::config::ConfigFile;
437pub use crate::config::ConfigFileNoDef;
438pub use crate::force::ForceFlag;
439pub use crate::ip::HostOpt;
440pub use crate::ip::HostParam;
441pub use crate::ip::HostV4Opt;
442pub use crate::ip::HostV4Param;
443pub use crate::ip::HostV6Opt;
444pub use crate::ip::HostV6Param;
445pub use crate::logopt::LogLevelNoDef;
446pub use crate::logopt::LogLevelNoDefLower;
447pub use crate::logopt::LogLevelOpt;
448pub use crate::logopt::LogLevelOptLower;
449pub use crate::verbose::QuietVerbose;
450pub use crate::verbose::SimpleVerbose;
451pub use crate::verbose::Verbose;
452pub use crate::verbose::VerboseNoDef;