Skip to main content

ytil_sys/
cli.rs

1const HELP_ARG: &str = "--help";
2
3/// Abstraction over command-line argument collections.
4pub trait Args<T> {
5    /// Checks if the help flag (`--help`) is present.
6    fn has_help(&self) -> bool;
7
8    /// Returns a copy of all arguments.
9    fn all(&self) -> Vec<T>;
10}
11
12impl<T: AsRef<str> + Clone> Args<T> for Vec<T> {
13    fn has_help(&self) -> bool {
14        self.iter().any(|arg| arg.as_ref() == HELP_ARG)
15    }
16
17    fn all(&self) -> Self {
18        self.clone()
19    }
20}
21
22impl Args<String> for pico_args::Arguments {
23    fn has_help(&self) -> bool {
24        self.clone().contains(HELP_ARG)
25    }
26
27    fn all(&self) -> Vec<String> {
28        self.clone()
29            .finish()
30            .into_iter()
31            .map(|arg| arg.to_string_lossy().into_owned())
32            .collect()
33    }
34}
35
36/// Retrieves command-line arguments excluding the program name, returning them as a [`Vec`] of [`String`].
37pub fn get() -> Vec<String> {
38    let mut args = std::env::args();
39    args.next();
40    args.collect::<Vec<String>>()
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[rstest::rstest]
48    #[case::empty_vec(vec![], false)]
49    #[case::no_help(vec!["arg1", "arg2"], false)]
50    #[case::has_help(vec!["--help"], true)]
51    #[case::help_among_others(vec!["foo", "--help", "bar"], true)]
52    fn has_help_for_vec_returns_expected(#[case] args: Vec<&str>, #[case] expected: bool) {
53        pretty_assertions::assert_eq!(args.has_help(), expected);
54    }
55
56    #[rstest::rstest]
57    #[case::empty_vec(Vec::<String>::new(), Vec::<String>::new())]
58    #[case::clones_all(vec!["a".to_owned(), "b".to_owned()], vec!["a".to_owned(), "b".to_owned()])]
59    fn all_for_vec_returns_clone(#[case] args: Vec<String>, #[case] expected: Vec<String>) {
60        pretty_assertions::assert_eq!(args.all(), expected);
61    }
62}