1use bpaf::{any, construct, doc::Style, short, OptionParser, Parser};
4use std::str::FromStr;
5
6#[derive(Debug, Clone)]
7#[allow(dead_code)]
8pub struct Options {
9 magic: bool,
10 in_file: String,
11 out_file: String,
12 block_size: usize,
13}
14
15fn tag<T>(name: &'static str, meta: &str, help: &'static str) -> impl Parser<T>
17where
18 T: FromStr,
19 <T as std::str::FromStr>::Err: std::fmt::Display,
20{
21 any("", move |s: String| Some(s.strip_prefix(name)?.to_owned()))
24 .metavar(&[(name, Style::Literal), (meta, Style::Metavar)][..])
26 .help(help)
27 .anywhere()
28 .parse(|s| s.parse())
29}
30
31fn in_file() -> impl Parser<String> {
32 tag::<String>("if=", "FILE", "read from FILE")
33 .fallback(String::from("-"))
34 .display_fallback()
35}
36
37fn out_file() -> impl Parser<String> {
38 tag::<String>("of=", "FILE", "write to FILE")
39 .fallback(String::from("-"))
40 .display_fallback()
41}
42
43fn block_size() -> impl Parser<usize> {
44 tag::<usize>("bs=", "SIZE", "read/write SIZE blocks at once")
47 .fallback(512)
48 .display_fallback()
49}
50
51pub fn options() -> OptionParser<Options> {
52 let magic = short('m')
53 .long("magic")
54 .help("a usual switch still works")
55 .switch();
56 construct!(Options {
57 magic,
58 in_file(),
59 out_file(),
60 block_size(),
61 })
62 .to_options()
63}
64
65fn main() {
66 println!("{:#?}", options().run());
67}