summaryrefslogtreecommitdiff
path: root/mingling/src/parser/args.rs
blob: 2a07e971a40c473d7edd902db5f55cb39c6b9e1a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use std::mem::replace;

use mingling_core::{Flag, special_argument, special_arguments, special_flag};

/// User input arguments
#[derive(Debug, Default)]
pub struct Argument {
    vec: Vec<String>,
}

impl From<&'static str> for Argument {
    fn from(s: &'static str) -> Self {
        Argument {
            vec: vec![s.to_string()],
        }
    }
}

impl From<&'static [&'static str]> for Argument {
    fn from(slice: &'static [&'static str]) -> Self {
        Argument {
            vec: slice.iter().map(|&s| s.to_string()).collect(),
        }
    }
}

impl<const N: usize> From<[&'static str; N]> for Argument {
    fn from(slice: [&'static str; N]) -> Self {
        Argument {
            vec: slice.iter().map(|&s| s.to_string()).collect(),
        }
    }
}

impl<const N: usize> From<&'static [&'static str; N]> for Argument {
    fn from(slice: &'static [&'static str; N]) -> Self {
        Argument {
            vec: slice.iter().map(|&s| s.to_string()).collect(),
        }
    }
}

impl From<Vec<String>> for Argument {
    fn from(vec: Vec<String>) -> Self {
        Argument { vec }
    }
}

impl AsRef<[String]> for Argument {
    fn as_ref(&self) -> &[String] {
        &self.vec
    }
}

impl std::ops::Deref for Argument {
    type Target = Vec<String>;

    fn deref(&self) -> &Self::Target {
        &self.vec
    }
}

impl std::ops::DerefMut for Argument {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.vec
    }
}

impl Argument {
    /// Picks a single argument with the given flag
    pub fn pick_argument<F>(&mut self, flag: F) -> Option<String>
    where
        F: Into<Flag>,
    {
        if self.is_empty() {
            return None;
        }

        let flag: Flag = flag.into();
        if !flag.is_empty() {
            // Has any flag
            for argument in flag.iter() {
                let value = special_argument!(self.vec, argument);
                if value.is_some() {
                    return value;
                }
            }
        } else {
            // No flag
            return Some(self.vec.remove(0));
        }
        None
    }

    /// Picks arguments with the given flag
    pub fn pick_arguments<F>(&mut self, flag: F) -> Vec<String>
    where
        F: Into<Flag>,
    {
        let mut str_result = Vec::new();

        if self.is_empty() {
            return str_result;
        }

        let flag: Flag = flag.into();
        if flag.is_empty() {
            let value = special_arguments!(self.vec, "");
            str_result.extend(value);
        } else {
            for argument in flag.iter() {
                let value = special_arguments!(self.vec, argument);
                str_result.extend(value);
            }
        }

        str_result
    }

    /// Picks a flag with the given flag
    pub fn pick_flag<F>(&mut self, flag: F) -> bool
    where
        F: Into<Flag>,
    {
        if self.is_empty() {
            return false;
        }

        let flag: Flag = flag.into();
        if !flag.is_empty() {
            // Has any flag
            for argument in flag.iter() {
                let enabled = special_flag!(self.vec, argument);
                if enabled {
                    return enabled;
                }
            }
        } else {
            let first = self.vec.remove(0);
            let first_lower = first.to_lowercase();
            let trimmed = first_lower.trim();
            let result = match trimmed {
                "y" | "yes" | "true" | "1" => return true,
                "n" | "no" | "false" | "0" => return false,
                _ => false,
            };
            return result;
        }
        false
    }

    /// Dump all remaining arguments
    pub fn dump_remains(&mut self) -> Vec<String> {
        let new = Vec::new();
        replace(&mut self.vec, new)
    }
}