Skip to main content

cargo_dev_install/
cli.rs

1use clap::Parser;
2
3#[derive(Debug, Parser)]
4#[command(author, version, about, long_about = None)]
5struct Args {
6    #[arg(long)]
7    bin: Option<String>,
8    #[arg(long)]
9    force: bool,
10}
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct CliArgs {
14    pub bin: Option<String>,
15    pub force: bool,
16}
17
18pub fn parse_args<I, T>(args: I) -> Result<CliArgs, clap::Error>
19where
20    I: IntoIterator<Item = T>,
21    T: Into<std::ffi::OsString> + Clone,
22{
23    let mut args_iter = args.into_iter();
24    let program = args_iter.next();
25    let mut remaining: Vec<T> = args_iter.collect();
26
27    if remaining
28        .first()
29        .map(|arg| arg.clone().into())
30        .as_ref()
31        .map(|arg| arg == "dev-install")
32        .unwrap_or(false)
33    {
34        remaining.remove(0);
35    }
36
37    let mut argv = Vec::with_capacity(1 + remaining.len());
38    if let Some(program) = program {
39        argv.push(program);
40    }
41    argv.extend(remaining);
42
43    let parsed = Args::try_parse_from(argv)?;
44    Ok(CliArgs {
45        bin: parsed.bin,
46        force: parsed.force,
47    })
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn parses_default_args() {
56        let args = parse_args(["cargo-dev-install"]).expect("parse args");
57        assert_eq!(
58            args,
59            CliArgs {
60                bin: None,
61                force: false,
62            }
63        );
64    }
65
66    #[test]
67    fn parses_bin_and_force() {
68        let args =
69            parse_args(["cargo-dev-install", "--bin", "demo", "--force"]).expect("parse args");
70        assert_eq!(
71            args,
72            CliArgs {
73                bin: Some("demo".to_string()),
74                force: true,
75            }
76        );
77    }
78
79    #[test]
80    fn parses_subcommand_invocation() {
81        let args = parse_args(["cargo", "dev-install", "--force"]).expect("parse args");
82        assert_eq!(
83            args,
84            CliArgs {
85                bin: None,
86                force: true,
87            }
88        );
89    }
90
91    #[test]
92    fn errors_on_unknown_flag() {
93        let err = parse_args(["cargo-dev-install", "--unknown"])
94            .expect_err("expected error for unknown flag");
95        assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument);
96    }
97}