cli_rs/
arg.rs

1use std::str::FromStr;
2
3use crate::{
4    cli_error::{CliError, CliResult},
5    input::{Completor, Input, InputType},
6};
7
8#[derive(Default)]
9pub struct Arg<'a, T: FromStr + Clone> {
10    pub name: String,
11    pub description: Option<String>,
12    pub value: Option<T>,
13    pub completor: Option<Completor<'a>>,
14    pub default_value: Option<T>,
15}
16
17impl<'a, T> Arg<'a, T>
18where
19    T: FromStr + Clone,
20{
21    pub fn name(name: &str) -> Self {
22        Self {
23            name: name.to_string(),
24            description: None,
25            value: None,
26            completor: None,
27            default_value: None,
28        }
29    }
30
31    pub fn default(mut self, default: T) -> Self {
32        self.default_value = Some(default);
33        self
34    }
35
36    pub fn description(mut self, description: &str) -> Self {
37        self.description = Some(description.to_string());
38        self
39    }
40
41    pub fn get(&self) -> T {
42        self.value
43            .clone()
44            .unwrap_or_else(|| self.default_value.clone().unwrap())
45    }
46
47    pub fn completor<F>(mut self, completor: F) -> Self
48    where
49        F: FnMut(&str) -> CliResult<Vec<String>> + 'a,
50    {
51        self.completor = Some(Box::new(completor));
52        self
53    }
54}
55
56impl<'a> Arg<'a, String> {
57    pub fn str(name: &str) -> Self {
58        Self::name(name)
59    }
60}
61
62impl<'a> Arg<'a, i32> {
63    pub fn i32(name: &str) -> Self {
64        Self::name(name)
65    }
66}
67
68impl<'a, T: FromStr + Clone> Input for Arg<'a, T> {
69    fn parse(&mut self, token: &str) -> CliResult<bool> {
70        if token.len() > 2 && &token[0..1] == "-" && &token[0..2] == "--" {
71            return Err(CliError::from(format!(
72                "unexpected flag \"{}\" found while looking for argument \"{}\"",
73                token, self.name
74            )));
75        }
76        self.value = Some(token.parse().map_err(|_| {
77            CliError::from(format!("{} cannot be parsed for {}.", token, self.name))
78        })?);
79
80        Ok(true)
81    }
82
83    fn display_name(&self) -> String {
84        self.name.clone()
85    }
86
87    fn type_name(&self) -> InputType {
88        InputType::Arg
89    }
90
91    fn parsed(&self) -> bool {
92        self.value.is_some()
93    }
94
95    fn complete(&mut self, value: &str) -> CliResult<Vec<String>> {
96        if let Some(completor) = &mut self.completor {
97            completor(value)
98        } else {
99            Ok(vec![])
100        }
101    }
102
103    fn is_bool_flag(&self) -> bool {
104        false
105    }
106
107    fn description(&self) -> Option<String> {
108        self.description.clone()
109    }
110
111    fn has_default(&self) -> bool {
112        self.default_value.is_some()
113    }
114}