commandlines/
lib.rs

1// Copyright 2018 Christopher Simpkins
2// Licensed under the MIT license
3
4//! `commandlines` is a command line argument parsing library for the development of Rust command line interface (CLI) applications that follow the [POSIX / GNU conventions for command line arguments](https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html).
5//!
6//! It is in development and the API is not stable.  Please see the [source repository README.md page](https://github.com/chrissimpkins/commandlines-rust) for updates on the level of library support for the POSIX/GNU command line argument syntax.
7
8#![cfg_attr(feature = "cargo-clippy", allow(new_without_default_derive))]
9
10pub mod parsers;
11
12use std::borrow::Cow;
13use std::collections::HashMap;
14use std::fmt;
15
16/// A command line argument object
17///
18/// The `Command` struct defines fields that hold parsed command line argument data and provides methods that can be used to define the logic of a command line interface application.
19///
20/// # Examples
21///
22/// ## Instantiation
23///
24/// ```norun
25/// extern crate commandlines;
26///
27/// use commandlines::Command;
28///
29/// def main() {
30///     let c = Command::new();
31/// }
32/// ```
33///
34/// ## Debugging
35///
36/// The `Command` struct supports pretty-printed display of all parsed data fields to the standard output stream with the `{:#?}` formatting idiom:
37///
38/// ```
39/// use commandlines::Command;
40///
41/// println!("{:#?}", Command::new());
42/// ```
43///
44/// # Remarks
45///
46/// The Vector of command line arguments presented to the executable in `std::env::args().collect()` is used to define the `Command` struct fields.
47///
48/// See the documentation for the `Command` struct methods and fields to learn how to use the parsed data in your command line interface application logic.
49#[derive(Clone, Debug, PartialEq)]
50pub struct Command {
51    /// Vector of ordered command line arguments
52    pub argv: Vec<String>,
53    /// number of strings in `Command.argv`
54    pub argc: usize,
55    /// The executable path at index position `0` of `Command.argv`
56    pub executable: String,
57    /// Vector of command line options in `Command.argv`
58    pub options: Vec<String>,
59    /// HashMap of command line option definitions mapped as key=option:value=definition
60    pub definitions: HashMap<String, String>,
61    /// `Option<String>` of first positional argument to the executable. `None` if there are no arguments to the executable.
62    pub first_arg: Option<String>,
63    /// `Option<String>` of last positional argument to the executable. `None` if there are no arguments to the executable.
64    pub last_arg: Option<String>,
65    /// `Option<Vec<String>>` of ordered arguments that follow a double hyphen command line idiom. `None` if a double hyphen argument is not present or there are no arguments after the double hyphen argument.
66    pub double_hyphen_argv: Option<Vec<String>>,
67}
68
69// Traits
70
71// Display trait
72impl fmt::Display for Command {
73    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74        write!(f, "Command: '{}'", self.argv.join(" "))
75    }
76}
77
78// Methods
79impl Command {
80    /// Instantiates and returns a new `Command` struct with the command line argument data in `std::env::args().collect()`
81    ///
82    /// # Remarks
83    ///
84    /// Instantiate a `Command` struct in the `main()` method of the `main.rs` file of your Rust executable project.
85    ///
86    /// # Examples
87    ///
88    /// ```norun
89    /// extern crate commandlines;
90    ///
91    /// use commandlines::Command;
92    ///
93    /// def main() {
94    ///     let c = Command::new();
95    /// }
96    /// ```
97    pub fn new() -> Self {
98        Command::new_with_vec(std::env::args().collect())
99    }
100
101    // Instantiates and returns a new `Command` struct with mocked command line argument data that is passed in the `arguments` argument.
102    //
103    // # Arguments
104    //
105    // - arguments: (`Vec<String>`) - a Vector of ordered String items
106    #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
107    fn new_with_vec(arguments: Vec<String>) -> Self {
108        let arguments_definition = arguments.to_owned();
109        let executable_definition = &arguments[0];
110        let size_definition = arguments.len();
111        let vec_options = parsers::parse_options(&arguments);
112        let definitions_hm = parsers::parse_definitions(&arguments);
113        let first_arg_definition = parsers::parse_first_arg(&arguments);
114        let last_arg_definition = parsers::parse_last_arg(&arguments);
115        let double_hyphen_definition = parsers::parse_double_hyphen_args(&arguments);
116
117        Command {
118            argv: arguments_definition,
119            argc: size_definition,
120            executable: executable_definition.to_string(),
121            options: vec_options,
122            definitions: definitions_hm,
123            first_arg: first_arg_definition,
124            last_arg: last_arg_definition,
125            double_hyphen_argv: double_hyphen_definition,
126        }
127    }
128
129    /// Returns a boolean for the question "Does the command include any arguments to the executable?"
130    ///
131    /// # Remarks
132    /// This method defines an argument as a command line string that occurs *after the executable path string located at index position `0`* of `Command.argv`. Please note that the executable path at index position `0` in the `Vec<String>` returned by `std::env::args().collect()` will always be present and is intentionally not part of this definition.
133    ///
134    /// # Examples
135    ///
136    /// ```
137    /// let c = commandlines::Command::new();
138    ///
139    /// if !c.has_args() {
140    ///    eprintln!("Missing arguments");
141    /// }
142    /// ```
143    pub fn has_args(&self) -> bool {
144        !self.argv[1..].is_empty()
145    }
146
147    /// Returns a boolean for the question "Does the command include any definition options?"
148    ///
149    /// # Remarks
150    /// A definition option is defined as a command line string that takes a short or long option format with an equal symbol character that is used to indicate that an option definition string follows.  This library supports the following formats:
151    ///
152    /// - `--option=def`
153    /// - `-o=def`
154    ///
155    /// The long format with two hyphens is specified in the GNU command line argument conventions.  The short format with a single hyphen is not specified in the POSIX or GNU guidelines.
156    ///
157    /// # Examples
158    ///
159    /// ```
160    /// let c = commandlines::Command::new();
161    ///
162    /// if c.has_definitions() {
163    ///    // definitions were parsed in the command
164    /// }
165    /// ```
166    pub fn has_definitions(&self) -> bool {
167        !self.definitions.is_empty()
168    }
169
170    /// Returns a boolean for the question "Does the command include any arguments following the double hyphen (--) idiom?"
171    ///
172    /// # Examples
173    ///
174    /// ```
175    /// let c = commandlines::Command::new();
176    ///
177    /// if c.has_double_hyphen_args() {
178    ///     // arguments were identified following a double hyphen idiom
179    /// }
180    /// ```
181    pub fn has_double_hyphen_args(&self) -> bool {
182        match &self.double_hyphen_argv {
183            Some(_) => true,
184            None => false,
185        }
186    }
187
188    /// Returns a boolean for the question "Does the command include any multi-option short syntax style option arguments?"
189    ///
190    /// # Remarks
191    /// POSIX defines a short option style that uses a single hyphen delimiter with more than one option indicated by the individual characters defined in the argument string (e.g., `-hij` means that the command has the options `-h -i -j`).  This method provides support for determining whether a mops style option is present in the command string.
192    ///
193    /// # Examples
194    ///
195    /// ```
196    /// let c = commandlines::Command::new();
197    ///
198    /// if c.has_mops() {
199    ///     // at least one multi-option short syntax style argument was parsed in the command
200    /// }
201    /// ```
202    pub fn has_mops(&self) -> bool {
203        for arg in &self.options {
204            if parsers::is_mops_option(&arg[..]) {
205                return true;
206            }
207        }
208        false
209    }
210
211    /// Returns a boolean for the question "Does the command include any options?"
212    ///
213    /// # Remarks
214    /// An option is defined as a command line argument that starts with one or two hyphen characters. This definition includes standard long (e.g., `--longoption`) and short (e.g., `-s`) command line options.
215    ///
216    /// If you use POSIX multi-option short syntax style arguments (e.g., "-lmn" is used to indicate "-l -m -n") in your application, see the `Command::contains_mops()` method.  This method does not test against mops style command line arguments.
217    ///
218    /// # Examples
219    ///
220    /// ```
221    /// let c = commandlines::Command::new();
222    ///
223    /// if c.has_options() {
224    ///    // start application-specific option parsing logic
225    /// }
226    /// ```
227    pub fn has_options(&self) -> bool {
228        !self.options.is_empty()
229    }
230
231    /// Returns a boolean for the question "Does the command include the argument string `needle`?" at any index
232    ///
233    /// # Examples
234    ///
235    /// ```
236    /// let c = commandlines::Command::new();
237    ///
238    /// if c.contains_arg("spam") {
239    ///     // a `spam` argument was in the command
240    /// }
241    /// ```
242    pub fn contains_arg(&self, needle: &str) -> bool {
243        self.argv[1..].contains(&String::from(needle))
244    }
245
246    /// Returns a boolean for the question "Does the command include the definition option `needle`?"
247    ///
248    /// # Examples
249    ///
250    /// ```
251    /// let c = commandlines::Command::new();
252    ///
253    /// if c.contains_definition("--spam") {
254    ///     // command included a `--spam=[definition]` option
255    /// }
256    /// ```
257    pub fn contains_definition(&self, needle: &str) -> bool {
258        match self.definitions.get(&String::from(needle)) {
259            Some(_) => true,
260            None => false,
261        }
262    }
263
264    /// Returns a boolean for the question "Does the command include the option `needle` when the POSIX multi-option short syntax option style is used?"
265    ///
266    /// # Remarks
267    /// The mops style defined by POSIX includes a single hyphen character followed by one or more alphanumeric characters in the Unicode Basic Latin set.  Each character represents a unique option switch.  For example, "-lmn" is used to indicate "-l -m -n".  This method tests against any short option formatted argument included in the command irrespective of the number of alphanumeric characters that are included.  The method does not test against long options (i.e., those that begin with two hyphens).
268    ///
269    /// If you do not use the mops option syntax in your application, use the `Command::contains_option()` method instead.
270    ///
271    /// # Examples
272    ///
273    /// ```
274    /// let c = commandlines::Command::new();
275    ///
276    /// if c.contains_mops("-j") {
277    ///     // the `j` switch was identified in a short format option on the command line
278    /// }
279    /// ```
280    pub fn contains_mops(&self, needle: &str) -> bool {
281        match parsers::parse_mops(&self.options) {
282            Some(haystack) => haystack.contains(&String::from(needle)),
283            None => false,
284        }
285    }
286
287    /// Returns a boolean for the question "Does the command include the option string `needle` at any index?"
288    ///
289    /// # Examples
290    ///
291    /// ```
292    /// let c = commandlines::Command::new();
293    ///
294    /// if c.contains_option("--help") {
295    ///     // you have a standard request for help documentation
296    /// }
297    /// ````
298    pub fn contains_option(&self, needle: &str) -> bool {
299        self.options.contains(&String::from(needle))
300    }
301
302    /// Returns a boolean for the question "Does the command include the option `needle` when the POSIX multi-option short syntax option style is used?"
303    ///
304    /// # Remarks
305    /// The mops style defined by POSIX includes a single hyphen character followed by one or more alphanumeric characters in the Unicode Basic Latin set.  Each character represents a unique option switch.  For example, "-lmn" is used to indicate "-l -m -n".  This method tests against any short option formatted argument included in the command irrespective of the number of alphanumeric characters that are included.  The method does not test against long options (i.e., those that begin with two hyphens).
306    ///
307    /// If you do not use the mops option syntax in your application, use the `Command::contains_all_options()` method instead.
308    ///
309    /// # Examples
310    ///
311    /// ```
312    /// let c = commandlines::Command::new();
313    ///
314    /// if c.contains_all_mops(vec!["-j", "-k", "-l"]) {
315    ///     // the `j`, `k` and `l` switches were identified in short format options on the command line
316    /// }
317    /// ```
318    pub fn contains_all_mops(&self, needle_vec: Vec<&str>) -> bool {
319        let some_haystack = parsers::parse_mops(&self.options);
320        if some_haystack.is_some() {
321            let haystack = some_haystack.unwrap();
322            for needle in needle_vec {
323                if !haystack.contains(&String::from(needle)) {
324                    return false;
325                }
326            }
327        } else {
328            return false; // there were no mops parsed in the command so there is no match
329        }
330
331        true
332    }
333
334    /// Returns a boolean for the question "Does the command include all of the option strings in `needle_vec` Vector?"
335    ///
336    /// # Examples
337    ///
338    /// ```
339    /// let c = commandlines::Command::new();
340    ///
341    /// if c.contains_all_options(vec!["--some", "--things"]) {
342    ///     // implement whatever requires `some` && `things` condition
343    /// }
344    /// ```
345    pub fn contains_all_options(&self, needle_vec: Vec<&str>) -> bool {
346        for needle in needle_vec {
347            if !self.options.contains(&String::from(needle)) {
348                return false;
349            }
350        }
351        true
352    }
353
354    /// Returns a boolean for the question "Does the command include the option `needle` when the POSIX multi-option short syntax option style is used?"
355    ///
356    /// # Remarks
357    /// The mops style defined by POSIX includes a single hyphen character followed by one or more alphanumeric characters in the Unicode Basic Latin set.  Each character represents a unique option switch.  For example, "-lmn" is used to indicate "-l -m -n".  This method tests against any short option formatted argument included in the command irrespective of the number of alphanumeric characters that are included.  The method does not test against long options (i.e., those that begin with two hyphens).
358    ///
359    /// If you do not use the mops option syntax in your application, use the `Command::contains_any_options()` method instead.
360    ///
361    /// # Examples
362    /// ```
363    /// let c = commandlines::Command::new();
364    ///
365    /// if c.contains_any_mops(vec!["-j", "-k", "-l"]) {
366    ///     // the `j` or `k` or `l` switch was identified in short format options on the command line
367    /// }
368    /// ```
369    pub fn contains_any_mops(&self, needle_vec: Vec<&str>) -> bool {
370        let some_haystack = parsers::parse_mops(&self.options);
371        if some_haystack.is_some() {
372            let haystack = some_haystack.unwrap();
373            for needle in needle_vec {
374                if haystack.contains(&String::from(needle)) {
375                    return true;
376                }
377            }
378        } else {
379            return false; // there were no mops parsed in the command so there is no match
380        }
381
382        false
383    }
384
385    /// Returns a boolean for the question "Does the command include any of the option strings in the `needle_vec` Vector?"
386    ///
387    /// # Examples
388    ///
389    /// ```
390    /// let c = commandlines::Command::new();
391    ///
392    /// if c.contains_any_option(vec!["-h", "--help"]) {
393    ///     // received a help request with `-h` || `--help` condition
394    /// }
395    /// ```
396    pub fn contains_any_option(&self, needle_vec: Vec<&str>) -> bool {
397        for needle in needle_vec {
398            if self.options.contains(&String::from(needle)) {
399                return true;
400            }
401        }
402        false
403    }
404
405    /// Returns boolean for the question "Do the command arguments to the executable match the argument strings and sequence in `needle_vec` Vector?"
406    ///
407    /// # Examples
408    ///
409    /// ```
410    /// let c = commandlines::Command::new();
411    ///
412    /// if c.contains_sequence(vec!["filter", "help"]) {
413    ///     // the command sequence was identified as "[executable] filter help"
414    /// }
415    /// ```
416    #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
417    pub fn contains_sequence(&self, needle_vec: Vec<&str>) -> bool {
418        // confirm that the request does not exceed the length of arguments in the command
419        // subtract value of 1 for the executable which is excluded in this test
420        if needle_vec.len() > (self.argv.len() - 1) {
421            return false;
422        }
423        for (index, arg) in needle_vec.iter().enumerate() {
424            if *arg != self.argv[index + 1] {
425                return false;
426            }
427        }
428
429        true
430    }
431
432    /// Returns `Option<Cow<str>>` definition for a key defined by `needle`
433    ///
434    /// Returns `None` if the option was not used in the command
435    ///
436    /// # Examples
437    ///
438    /// The following example demonstrates how to get the definition string for a command line option with the format `--name=[definition]`:
439    ///
440    /// ```
441    /// let c = commandlines::Command::new();
442    ///
443    /// match c.get_definition_for("--name") {
444    ///     Some(x) => println!("The definition for --name is {}", x),
445    ///     None => eprintln!("Missing")
446    /// };
447    /// ```
448    pub fn get_definition_for(&self, needle: &str) -> Option<Cow<str>> {
449        if let Some(x) = self.definitions.get(&String::from(needle)) {
450            return Some(Cow::Borrowed(x));
451        }
452
453        None
454    }
455
456    /// Returns `Option<Cow<str>>` for argument at index position `i+1` for `needle` at index position `i`
457    ///
458    /// Returns `None` if `needle` is the last positional argument in the command
459    ///
460    /// # Remarks
461    ///
462    /// This method can be used to obtain space-delimited definition arguments that follow an option (e.g., `-o [filepath]`).
463    ///
464    /// # Examples
465    ///
466    /// For a command with the syntax `test -o [filepath]` the following can be used to get the filepath definition after the `-o` option:
467    ///
468    /// ```
469    /// let c = commandlines::Command::new();
470    ///
471    /// match c.get_argument_after("-o") {
472    ///     Some(x) => println!("The filepath definition after -o is {}", x),
473    ///     None => eprintln!("-o is the last positional argument in the command")
474    /// }
475    /// ```
476    pub fn get_argument_after(&self, needle: &str) -> Option<Cow<str>> {
477        for (index, value) in self.argv.iter().enumerate() {
478            if value == needle {
479                if let Some(x) = self.argv.get(index + 1) {
480                    return Some(Cow::Borrowed(x));
481                }
482            }
483        }
484
485        None
486    }
487
488    /// Returns `Option<Vec<Cow<str>>>` for the one or more ordered arguments that follow the `needle` argument
489    ///
490    /// Returns `None` if `needle` is not in the command or there are no arguments after the `needle` argument
491    ///
492    /// # Examples
493    ///
494    /// ```
495    /// let c = commandlines::Command::new();
496    ///
497    /// match c.get_arguments_after("-o") {
498    ///     Some(x) => println!("The arguments after the -o option are {:?}", x),
499    ///     None => eprintln!("-o not found or there were no arguments after -o")
500    /// }
501    /// ```
502    pub fn get_arguments_after(&self, needle: &str) -> Option<Vec<Cow<str>>> {
503        for (index, value) in self.argv.iter().enumerate() {
504            // test for presence of needle in argv vector
505            if value == needle {
506                // if found, confirm that there is at least one arg after
507                if self.argv.get(index + 1).is_some() {
508                    // make a new Vec<Cow<str>> to fill with arg strings for return to calling code
509                    // and fill with the arguments, maintaining valid sequence of arguments
510                    let mut v: Vec<Cow<str>> = Vec::new();
511                    for arg in &self.argv[(index + 1)..] {
512                        v.push(Cow::Borrowed(arg));
513                    }
514                    return Some(v);
515                } else {
516                    return None;
517                }
518            }
519        }
520
521        None
522    }
523
524    /// Returns `Option<Cow<str>>` for the argument at index position `needle`
525    ///
526    /// Returns `None` if `needle` is outside of the bounds of valid index values
527    ///
528    /// # Examples
529    ///
530    /// ```
531    /// // example command = "test subcmd --option"
532    /// let c = commandlines::Command::new();
533    ///
534    /// match c.get_argument_at(0) {
535    ///     Some(x) => println!("The executable is {}", x),
536    ///     None => eprintln!("Error")
537    /// }
538    ///
539    /// match c.get_argument_at(1) {
540    ///     Some(x) => println!("The first positional argument is {}", x),
541    ///     None => eprintln!("There is no first positional argument")
542    /// }
543    /// ```
544    pub fn get_argument_at(&self, needle: usize) -> Option<Cow<str>> {
545        if let Some(x) = self.argv.get(needle) {
546            return Some(Cow::Borrowed(x));
547        }
548
549        None
550    }
551
552    /// Returns `Option<Vec<Cow<str>>>` for the arguments in sequence that follow a double hyphen `--` command line idiom
553    ///
554    /// Returns `None` if there is no double hyphen idiom or there are no arguments that follow the idiom
555    ///
556    /// # Examples
557    ///
558    /// ```
559    /// let c = commandlines::Command::new();
560    ///
561    /// match c.get_arguments_after_double_hyphen() {
562    ///     Some(x) => println!("Args following double hyphen: {:?}", x),
563    ///     None => eprintln!("There are no arguments that follow a double hyphen idiom")
564    /// }
565    /// ```
566    pub fn get_arguments_after_double_hyphen(&self) -> Option<Vec<Cow<str>>> {
567        if let Some(x) = &self.double_hyphen_argv {
568            let mut v: Vec<Cow<str>> = Vec::new();
569            for arg in x {
570                v.push(Cow::Borrowed(arg))
571            }
572            return Some(v);
573        }
574
575        None
576    }
577
578    /// Returns `Option<Cow<str>>` for the first positional argument to the executable
579    ///
580    /// Returns `None` if there are no arguments to the executable
581    ///
582    /// # Examples
583    ///
584    /// ```
585    /// let c = commandlines::Command::new();
586    ///
587    /// match c.get_argument_first() {
588    ///     Some(x) => println!("The first positional argument is {}", x),
589    ///     None => eprintln!("There are no arguments to the executable")
590    /// }
591    /// ```
592    pub fn get_argument_first(&self) -> Option<Cow<str>> {
593        match &self.first_arg {
594            Some(x) => Some(Cow::Borrowed(x)),
595            None => None,
596        }
597    }
598
599    /// Returns `Option<Cow<str>>` for the last positional argument to the executable
600    ///
601    /// Returns `None` if there are no arguments to the executable
602    ///
603    /// # Examples
604    ///
605    /// ```
606    /// let c = commandlines::Command::new();
607    ///
608    /// match c.get_argument_last() {
609    ///     Some(x) => println!("The last positional argument is {}", x),
610    ///     None => eprintln!("There are no arguments to the executable")
611    /// }
612    /// ```
613    pub fn get_argument_last(&self) -> Option<Cow<str>> {
614        match &self.last_arg {
615            Some(x) => Some(Cow::Borrowed(x)),
616            None => None,
617        }
618    }
619
620    /// Returns `Cow<str>` for the executable
621    ///
622    /// # Examples
623    ///
624    /// ```
625    /// let c = commandlines::Command::new();
626    ///
627    /// println!("{} v1.0.0", c.get_executable())
628    ///
629    /// ```
630    pub fn get_executable(&self) -> Cow<str> {
631        Cow::Borrowed(&self.executable)
632    }
633
634    /// Returns `Option<usize>` for index position of the argument `needle` in the `Command.argv` Vector
635    ///
636    /// Returns `None` if `needle` does not match a string in the Vector
637    ///
638    /// # Examples
639    ///
640    /// In the following example, the command is `test -o [filepath]`:
641    ///
642    /// ```
643    /// let c = commandlines::Command::new();
644    ///
645    /// match c.get_index_of("-o") {
646    ///     Some(x) => println!("The index position of -o is {}", x), // prints 1
647    ///     None => eprintln!("The requested argument was not found")
648    /// }
649    /// ```
650    pub fn get_index_of(&self, needle: &str) -> Option<usize> {
651        self.argv.iter().position(|x| x == needle)
652    }
653
654    /// Returns boolean for the question "Is the command a help request with a `-h` or `--help` flag?"
655    ///
656    /// # Examples
657    ///
658    /// ```
659    /// let c = commandlines::Command::new();
660    ///
661    /// if c.is_help_request() {
662    ///     // handle help request
663    /// }
664    /// ```
665    pub fn is_help_request(&self) -> bool {
666        self.options.contains(&"--help".to_string()) || self.options.contains(&"-h".to_string())
667    }
668
669    /// Returns boolean for the question "Is the command a version request with a `-v` or `--version` flag?"
670    ///
671    /// # Examples
672    ///
673    /// ```
674    /// let c = commandlines::Command::new();
675    ///
676    /// if c.is_version_request() {
677    ///     // handle version request
678    /// }
679    /// ```
680    pub fn is_version_request(&self) -> bool {
681        self.options.contains(&"--version".to_string()) || self.options.contains(&"-v".to_string())
682    }
683
684    /// Returns boolean for the question "Is the command a usage request with a `--usage` flag?"
685    ///
686    /// # Examples
687    ///
688    /// ```
689    /// let c = commandlines::Command::new();
690    ///
691    /// if c.is_usage_request() {
692    ///     // handle usage request
693    /// }
694    /// ```
695    pub fn is_usage_request(&self) -> bool {
696        self.options.contains(&"--usage".to_string())
697    }
698}
699
700// Tests
701#[cfg(test)]
702mod tests {
703    use super::*;
704
705    #[test]
706    fn command_instantiation_partial_eq() {
707        let c1 = Command::new_with_vec(vec!["test".to_string(), "arg".to_string()]);
708        let c2 = Command::new_with_vec(vec!["test".to_string(), "arg".to_string()]);
709        let c3 = Command::new_with_vec(vec!["test".to_string(), "else".to_string()]);
710        assert!(c1 == c2);
711        assert!(c1 != c3);
712    }
713
714    #[test]
715    fn command_instantiation_environment_args_test() {
716        let c = Command::new();
717        assert!(!c.argv.is_empty()); // should always be a Vector with length 1 or more
718    }
719
720    #[test]
721    fn command_instantiation_argv_field() {
722        let c = Command::new_with_vec(vec!["test".to_string(), "--help".to_string()]);
723        assert!(c.argv == vec!["test".to_string(), "--help".to_string()]);
724    }
725
726    #[test]
727    fn command_instantiation_argc_field_one_arg() {
728        let c = Command::new_with_vec(vec!["test".to_string()]);
729        assert!(c.argc == 1);
730    }
731
732    #[test]
733    fn command_instantiation_argc_field_two_args() {
734        let c = Command::new_with_vec(vec!["test".to_string(), "--help".to_string()]);
735        assert!(c.argc == 2);
736    }
737
738    #[test]
739    fn command_instantiation_executable_field() {
740        let c = Command::new_with_vec(vec!["test".to_string(), "--help".to_string()]);
741        assert!(c.executable == "test");
742    }
743
744    #[test]
745    fn command_instantiation_definitions_field_single_def() {
746        let c = Command::new_with_vec(vec![
747            "test".to_string(),
748            "--something".to_string(),
749            "--option=define".to_string(),
750        ]);
751        let mut expected_hm: HashMap<String, String> = HashMap::new();
752        expected_hm.insert("--option".to_string(), "define".to_string());
753        assert_eq!(c.definitions, expected_hm);
754    }
755
756    #[test]
757    fn command_instantiation_definitions_field_multi_def() {
758        let c = Command::new_with_vec(vec![
759            "test".to_string(),
760            "--something".to_string(),
761            "--option=define".to_string(),
762            "--another=otherdef".to_string(),
763            "--".to_string(),
764            "--absent=true".to_string(),
765        ]);
766        let mut expected_hm: HashMap<String, String> = HashMap::new();
767        expected_hm.insert("--option".to_string(), "define".to_string());
768        expected_hm.insert("--another".to_string(), "otherdef".to_string());
769        assert_eq!(c.definitions, expected_hm);
770    }
771
772    #[test]
773    fn command_instantiation_first_arg_field() {
774        let c = Command::new_with_vec(vec![
775            "test".to_string(),
776            "--help".to_string(),
777            "arg".to_string(),
778        ]);
779        assert_eq!(c.first_arg, Some(String::from("--help")));
780    }
781
782    #[test]
783    fn command_instantiation_first_arg_field_executable_only() {
784        let c = Command::new_with_vec(vec!["test".to_string()]);
785        assert_eq!(c.first_arg, None);
786    }
787
788    #[test]
789    fn command_instantiation_last_arg_field() {
790        let c = Command::new_with_vec(vec![
791            "test".to_string(),
792            "--help".to_string(),
793            "arg".to_string(),
794        ]);
795        assert_eq!(c.last_arg, Some(String::from("arg")));
796    }
797
798    #[test]
799    fn command_instantiation_last_arg_field_executable_only() {
800        let c = Command::new_with_vec(vec!["test".to_string()]);
801        assert_eq!(c.last_arg, None);
802    }
803
804    #[test]
805    fn command_instantiation_double_hyphen_argv() {
806        let c = Command::new_with_vec(vec![
807            "test".to_string(),
808            "--something".to_string(),
809            "--option=define".to_string(),
810            "--another=otherdef".to_string(),
811            "--".to_string(),
812            "--double".to_string(),
813            "lastpos".to_string(),
814        ]);
815        let expected_vec = vec![String::from("--double"), String::from("lastpos")];
816        assert_eq!(c.double_hyphen_argv, Some(expected_vec));
817    }
818
819    #[test]
820    fn command_instantiation_double_hyphen_argv_no_args() {
821        let c = Command::new_with_vec(vec![
822            "test".to_string(),
823            "--something".to_string(),
824            "--option=define".to_string(),
825            "--another=otherdef".to_string(),
826            "--".to_string(),
827        ]);
828        assert_eq!(c.double_hyphen_argv, None);
829    }
830
831    #[test]
832    fn command_instantiation_double_hyphen_argv_no_double_hyphen() {
833        let c = Command::new_with_vec(vec![
834            "test".to_string(),
835            "--something".to_string(),
836            "--option=define".to_string(),
837            "--another=otherdef".to_string(),
838        ]);
839        assert_eq!(c.double_hyphen_argv, None);
840    }
841
842    #[test]
843    fn command_method_has_args_true() {
844        let c = Command::new_with_vec(vec!["test".to_string(), "--help".to_string()]);
845        assert_eq!(c.has_args(), true);
846
847        let c = Command::new_with_vec(vec!["test".to_string(), "subcmd".to_string()]);
848        assert_eq!(c.has_args(), true);
849    }
850
851    #[test]
852    fn command_method_has_args_false() {
853        let c = Command::new_with_vec(vec!["test".to_string()]); // ignores the executable as not an argument
854        assert_eq!(c.has_args(), false);
855    }
856
857    #[test]
858    fn command_method_has_definitions_true() {
859        let c = Command::new_with_vec(vec!["test".to_string(), "--opt=def".to_string()]);
860        assert_eq!(c.has_definitions(), true);
861
862        let c = Command::new_with_vec(vec!["test".to_string(), "-o=d".to_string()]);
863        assert_eq!(c.has_definitions(), true);
864    }
865
866    #[test]
867    fn command_method_has_definitions_false() {
868        let c = Command::new_with_vec(vec!["test".to_string()]); // ignores the executable as not an argument
869        assert_eq!(c.has_definitions(), false);
870    }
871
872    #[test]
873    fn command_method_has_double_hyphen_args() {
874        let c1 = Command::new_with_vec(vec![
875            "test".to_string(),
876            "-o".to_string(),
877            "--".to_string(),
878            "arg1".to_string(),
879            "--arg2".to_string(),
880        ]);
881        let c2 =
882            Command::new_with_vec(vec!["test".to_string(), "-o".to_string(), "--".to_string()]);
883        let c3 = Command::new_with_vec(vec![
884            "test".to_string(),
885            "-o".to_string(),
886            "--test".to_string(),
887            "arg1".to_string(),
888            "--arg2".to_string(),
889        ]);
890
891        assert_eq!(c1.has_double_hyphen_args(), true);
892        assert_eq!(c2.has_double_hyphen_args(), false);
893        assert_eq!(c3.has_double_hyphen_args(), false);
894    }
895
896    #[test]
897    fn command_has_mops_true() {
898        let c = Command::new_with_vec(vec![
899            String::from("command"),
900            String::from("-lmn"),
901            String::from("lastpos"),
902        ]);
903        assert_eq!(c.has_mops(), true);
904    }
905
906    #[test]
907    fn command_has_mops_false() {
908        let c = Command::new_with_vec(vec![
909            String::from("command"),
910            String::from("--long"),
911            String::from("-o"),
912            String::from("path"),
913            String::from("lastpos"),
914            String::from("--"),
915            String::from("-"),
916        ]);
917        assert_eq!(c.has_mops(), false);
918    }
919
920    #[test]
921    fn command_method_has_options_true() {
922        let c = Command::new_with_vec(vec!["test".to_string(), "--help".to_string()]);
923        assert_eq!(c.has_options(), true);
924    }
925
926    #[test]
927    fn command_method_has_options_false() {
928        let c = Command::new_with_vec(vec!["test".to_string(), "subcmd".to_string()]);
929        assert_eq!(c.has_options(), false);
930    }
931
932    #[test]
933    fn command_method_contains_arg() {
934        let c = Command::new_with_vec(vec![
935            "test".to_string(),
936            "subcmd".to_string(),
937            "--help".to_string(),
938        ]);
939        assert_eq!(c.contains_arg("subcmd"), true);
940        assert_eq!(c.contains_arg("--help"), true);
941        assert_eq!(c.contains_arg("bogus"), false);
942        assert_eq!(c.contains_arg("test"), false); // executable not considered argument
943    }
944
945    #[test]
946    fn command_method_contains_definition() {
947        let c = Command::new_with_vec(vec![
948            "test".to_string(),
949            "subcmd".to_string(),
950            "--help".to_string(),
951            "--option=definition".to_string(),
952            "--another=deftwo".to_string(),
953        ]);
954        assert_eq!(c.contains_definition("--option"), true);
955        assert_eq!(c.contains_definition("--another"), true);
956        assert_eq!(c.contains_definition("--bogus"), false);
957        assert_eq!(c.contains_definition("--help"), false);
958    }
959
960    #[test]
961    fn command_method_contains_mops_true() {
962        let c = Command::new_with_vec(vec![
963            "test".to_string(),
964            "subcmd".to_string(),
965            "-hij".to_string(),
966            "-l".to_string(),
967            "--option=definition".to_string(),
968            "--another=deftwo".to_string(),
969            "lastpos".to_string(),
970        ]);
971        assert_eq!(c.contains_mops("-h"), true);
972        assert_eq!(c.contains_mops("-i"), true);
973        assert_eq!(c.contains_mops("-j"), true);
974        assert_eq!(c.contains_mops("-l"), true); // should pick up every short option, including those that are not mops formatted
975        assert_eq!(c.contains_mops("-z"), false);
976        assert_eq!(c.contains_mops("-o"), false);
977        assert_eq!(c.contains_mops("-a"), false);
978    }
979
980    #[test]
981    fn command_method_contains_mops_false() {
982        let c = Command::new_with_vec(vec![
983            "test".to_string(),
984            "subcmd".to_string(),
985            "--option=definition".to_string(),
986            "--another=deftwo".to_string(),
987            "lastpos".to_string(),
988            "--".to_string(),
989            "-hij".to_string(),
990        ]);
991        assert_eq!(c.contains_mops("-o"), false);
992        assert_eq!(c.contains_mops("-a"), false);
993        assert_eq!(c.contains_mops("-h"), false); // should ignore all options after a double hyphen idiom
994        assert_eq!(c.contains_mops("-i"), false); // should ignore all options after a double hyphen idiom
995        assert_eq!(c.contains_mops("-j"), false); // should ignore all options after a double hyphen idiom
996    }
997
998    #[test]
999    fn command_method_contains_option() {
1000        let c = Command::new_with_vec(vec![
1001            "test".to_string(),
1002            "subcmd".to_string(),
1003            "--help".to_string(),
1004        ]);
1005        assert_eq!(c.contains_option("--help"), true);
1006        assert_eq!(c.contains_option("--bogus"), false);
1007        assert_eq!(c.contains_option("help"), false); // must include the option indicator in string
1008    }
1009
1010    #[test]
1011    fn command_method_contains_all_mops_true() {
1012        let c = Command::new_with_vec(vec![
1013            "test".to_string(),
1014            "subcmd".to_string(),
1015            "-hij".to_string(),
1016            "-l".to_string(),
1017            "--option=definition".to_string(),
1018            "--another=deftwo".to_string(),
1019            "lastpos".to_string(),
1020        ]);
1021        assert_eq!(c.contains_all_mops(vec!["-h", "-i", "-j", "-l"]), true);
1022    }
1023
1024    #[test]
1025    fn command_method_contains_all_mops_false() {
1026        let c = Command::new_with_vec(vec![
1027            "test".to_string(),
1028            "subcmd".to_string(),
1029            "-hij".to_string(),
1030            "-l".to_string(),
1031            "--option=definition".to_string(),
1032            "--another=deftwo".to_string(),
1033            "lastpos".to_string(),
1034        ]);
1035        assert_eq!(c.contains_all_mops(vec!["-z", "-h"]), false);
1036    }
1037
1038    #[test]
1039    fn command_method_contains_all_mops_missing_mops() {
1040        let c = Command::new_with_vec(vec![
1041            "test".to_string(),
1042            "subcmd".to_string(),
1043            "--option=definition".to_string(),
1044            "--another=deftwo".to_string(),
1045            "lastpos".to_string(),
1046        ]);
1047        assert_eq!(c.contains_all_mops(vec!["-i", "-j"]), false);
1048    }
1049
1050    #[test]
1051    fn command_method_contains_all_options() {
1052        let c = Command::new_with_vec(vec![
1053            "test".to_string(),
1054            "subcmd".to_string(),
1055            "--help".to_string(),
1056            "--more".to_string(),
1057        ]);
1058        assert_eq!(c.contains_all_options(vec!["--more", "--help"]), true);
1059        assert_eq!(c.contains_all_options(vec!["--help", "--bogus"]), false);
1060        assert_eq!(c.contains_all_options(vec!["--bogus"]), false);
1061        assert_eq!(c.contains_all_options(vec!["subcmd"]), false); // not an option, should not be included in test
1062    }
1063
1064    #[test]
1065    fn command_method_contains_any_mops() {
1066        let c = Command::new_with_vec(vec![
1067            "test".to_string(),
1068            "subcmd".to_string(),
1069            "-hij".to_string(),
1070            "-l".to_string(),
1071            "--option=definition".to_string(),
1072            "--another=deftwo".to_string(),
1073            "lastpos".to_string(),
1074        ]);
1075        assert_eq!(c.contains_any_mops(vec!["-z", "-t", "-h"]), true);
1076        assert_eq!(c.contains_any_mops(vec!["-z", "-t", "-l"]), true);
1077        assert_eq!(c.contains_any_mops(vec!["-z", "-t", "-a"]), false);
1078    }
1079
1080    #[test]
1081    fn command_method_contains_any_mops_missing_mops() {
1082        let c = Command::new_with_vec(vec![
1083            "test".to_string(),
1084            "subcmd".to_string(),
1085            "--option=definition".to_string(),
1086            "--another=deftwo".to_string(),
1087            "lastpos".to_string(),
1088        ]);
1089        assert_eq!(c.contains_any_mops(vec!["-z", "-t", "-h"]), false);
1090    }
1091
1092    #[test]
1093    fn command_method_contains_any_option() {
1094        let c1 = Command::new_with_vec(vec![
1095            "test".to_string(),
1096            "subcmd".to_string(),
1097            "--help".to_string(),
1098        ]);
1099        let c2 = Command::new_with_vec(vec![
1100            "test".to_string(),
1101            "subcmd".to_string(),
1102            "-h".to_string(),
1103        ]);
1104        assert_eq!(c1.contains_any_option(vec!["--help", "-h"]), true);
1105        assert_eq!(c2.contains_any_option(vec!["--help", "-h"]), true);
1106        assert_eq!(c1.contains_any_option(vec!["--bogus", "-t"]), false);
1107        assert_eq!(c1.contains_any_option(vec!["subcmd", "bogus"]), false);
1108    }
1109
1110    #[test]
1111    fn command_method_contains_sequence() {
1112        let c = Command::new_with_vec(vec![
1113            "test".to_string(),
1114            "subcmd".to_string(),
1115            "subsubcmd".to_string(),
1116        ]);
1117        assert_eq!(c.contains_sequence(vec!["subcmd", "subsubcmd"]), true);
1118        assert_eq!(c.contains_sequence(vec!["subcmd"]), true);
1119        assert_eq!(c.contains_sequence(vec!["subsubcmd", "subcmd"]), false); // wrong order fails
1120        assert_eq!(c.contains_sequence(vec!["bogus", "subsubcmd"]), false); // any invalid string fails
1121        assert_eq!(c.contains_sequence(vec!["subcmd", "bogus"]), false); // any invalid string fails
1122        assert_eq!(
1123            c.contains_sequence(vec!["subcmd", "subsubcmd", "toomuchinfo"]),
1124            false
1125        ); // fail with too many argument requests c/w command that was entered
1126        assert_eq!(c.contains_sequence(vec!["bogus", "bogus", "bogus"]), false); // fail all invalid strings
1127        assert_eq!(
1128            c.contains_sequence(vec!["subcmd", "subsubcmd", "more", "evenmore", "lotsmore"]),
1129            false
1130        );
1131    }
1132
1133    #[test]
1134    fn command_method_get_definition_for_def_present() {
1135        let c = Command::new_with_vec(vec![
1136            "test".to_string(),
1137            "subcmd".to_string(),
1138            "--help".to_string(),
1139            "--option=definition".to_string(),
1140        ]);
1141
1142        assert_eq!(
1143            c.get_definition_for("--option"),
1144            Some(Cow::Borrowed("definition"))
1145        );
1146    }
1147
1148    #[test]
1149    fn command_method_get_definition_for_def_absent() {
1150        let c = Command::new_with_vec(vec![
1151            "test".to_string(),
1152            "subcmd".to_string(),
1153            "--help".to_string(),
1154        ]);
1155
1156        assert_eq!(c.get_definition_for("--option"), None);
1157    }
1158
1159    #[test]
1160    fn command_method_get_argument_after_arg_present() {
1161        let c = Command::new_with_vec(vec![
1162            "test".to_string(),
1163            "-o".to_string(),
1164            "path".to_string(),
1165        ]);
1166
1167        assert_eq!(c.get_argument_after("-o"), Some(Cow::Borrowed("path")));
1168    }
1169
1170    #[test]
1171    fn command_method_get_argument_after_arg_absent() {
1172        let c = Command::new_with_vec(vec!["test".to_string(), "-o".to_string()]);
1173
1174        assert_eq!(c.get_argument_after("-o"), None);
1175    }
1176
1177    #[test]
1178    fn command_method_get_argument_after_missing_needle_arg() {
1179        let c = Command::new_with_vec(vec!["test".to_string(), "-o".to_string()]);
1180
1181        assert_eq!(c.get_argument_after("bogus"), None);
1182    }
1183
1184    #[test]
1185    fn command_method_get_arguments_after() {
1186        let c1 = Command::new_with_vec(vec![
1187            "test".to_string(),
1188            "-o".to_string(),
1189            "path1".to_string(),
1190        ]);
1191
1192        let c2 = Command::new_with_vec(vec![
1193            "test".to_string(),
1194            "-o".to_string(),
1195            "path1".to_string(),
1196            "path2".to_string(),
1197        ]);
1198
1199        let c3 = Command::new_with_vec(vec![
1200            "test".to_string(),
1201            "-o".to_string(),
1202            "--out".to_string(),
1203            "--other".to_string(),
1204        ]);
1205
1206        let c4 = Command::new_with_vec(vec!["test".to_string(), "-o".to_string()]);
1207
1208        let c1_exp = Some(vec![Cow::Borrowed("path1")]);
1209        let c2_exp = Some(vec![Cow::Borrowed("path1"), Cow::Borrowed("path2")]);
1210        let c3_exp = Some(vec![Cow::Borrowed("--out"), Cow::Borrowed("--other")]);
1211
1212        assert_eq!(c1.get_arguments_after("-o"), c1_exp); // collects single non-option arg
1213        assert_eq!(c2.get_arguments_after("-o"), c2_exp); // collects multiple non-option args
1214        assert_eq!(c3.get_arguments_after("-o"), c3_exp); // collects option args
1215        assert_eq!(c4.get_arguments_after("-o"), None); // missing args after request
1216        assert_eq!(c1.get_arguments_after("--bogus"), None); // invalid request (not present in command)
1217    }
1218
1219    #[test]
1220    fn command_method_get_argument_at() {
1221        let c = Command::new_with_vec(vec!["test".to_string(), "-o".to_string()]);
1222
1223        assert_eq!(c.get_argument_at(0), Some(Cow::Borrowed("test"))); // zero indexed request
1224        assert_eq!(c.get_argument_at(1), Some(Cow::Borrowed("-o"))); // valid index
1225        assert_eq!(c.get_argument_at(10), None); // invalid index
1226    }
1227
1228    #[test]
1229    fn command_method_get_arguments_after_double_hyphen() {
1230        let c1 = Command::new_with_vec(vec![
1231            "test".to_string(),
1232            "-o".to_string(),
1233            "--".to_string(),
1234            "--after1".to_string(),
1235            "--after2".to_string(),
1236            "path".to_string(),
1237        ]);
1238        let c2 =
1239            Command::new_with_vec(vec!["test".to_string(), "-o".to_string(), "--".to_string()]);
1240        let c3 = Command::new_with_vec(vec![
1241            "test".to_string(),
1242            "-o".to_string(),
1243            "--after1".to_string(),
1244            "--after2".to_string(),
1245        ]);
1246
1247        let c1_exp = Some(vec![
1248            Cow::Borrowed("--after1"),
1249            Cow::Borrowed("--after2"),
1250            Cow::Borrowed("path"),
1251        ]);
1252
1253        assert_eq!(c1.get_arguments_after_double_hyphen(), c1_exp);
1254        assert_eq!(c2.get_arguments_after_double_hyphen(), None);
1255        assert_eq!(c3.get_arguments_after_double_hyphen(), None);
1256    }
1257
1258    #[test]
1259    fn command_method_get_argument_first() {
1260        let c1 = Command::new_with_vec(vec!["test".to_string(), "-o".to_string()]);
1261        let c2 = Command::new_with_vec(vec![
1262            "test".to_string(),
1263            "-o".to_string(),
1264            "more".to_string(),
1265        ]);
1266        let c3 = Command::new_with_vec(vec!["test".to_string(), "first".to_string()]);
1267        let c4 = Command::new_with_vec(vec!["test".to_string(), "--help".to_string()]);
1268        let c5 = Command::new_with_vec(vec![
1269            "test".to_string(),
1270            "--help".to_string(),
1271            "more".to_string(),
1272        ]);
1273        let c6 = Command::new_with_vec(vec!["test".to_string()]);
1274
1275        assert_eq!(c1.get_argument_first(), Some(Cow::Borrowed("-o"))); // short option
1276        assert_eq!(c2.get_argument_first(), Some(Cow::Borrowed("-o"))); // short option with additional args
1277        assert_eq!(c3.get_argument_first(), Some(Cow::Borrowed("first"))); // subcommand style argument
1278        assert_eq!(c4.get_argument_first(), Some(Cow::Borrowed("--help"))); // long option
1279        assert_eq!(c5.get_argument_first(), Some(Cow::Borrowed("--help"))); // long option with additional args
1280        assert_eq!(c6.get_argument_first(), None);
1281    }
1282
1283    #[test]
1284    fn command_method_get_argument_last() {
1285        let c1 = Command::new_with_vec(vec!["test".to_string(), "-o".to_string()]);
1286        let c2 = Command::new_with_vec(vec![
1287            "test".to_string(),
1288            "-o".to_string(),
1289            "more".to_string(),
1290        ]);
1291        let c3 = Command::new_with_vec(vec!["test".to_string(), "first".to_string()]);
1292        let c4 = Command::new_with_vec(vec!["test".to_string(), "--help".to_string()]);
1293        let c5 = Command::new_with_vec(vec![
1294            "test".to_string(),
1295            "--help".to_string(),
1296            "more".to_string(),
1297        ]);
1298        let c6 = Command::new_with_vec(vec!["test".to_string()]);
1299
1300        assert_eq!(c1.get_argument_last(), Some(Cow::Borrowed("-o"))); // short option
1301        assert_eq!(c2.get_argument_last(), Some(Cow::Borrowed("more"))); // short option followed by LP arg
1302        assert_eq!(c3.get_argument_last(), Some(Cow::Borrowed("first"))); // subcommand style argument
1303        assert_eq!(c4.get_argument_last(), Some(Cow::Borrowed("--help"))); // long option
1304        assert_eq!(c5.get_argument_last(), Some(Cow::Borrowed("more"))); // long option followed by LP arg
1305        assert_eq!(c1.get_argument_last(), Some(Cow::Borrowed("-o")));
1306        assert_eq!(c6.get_argument_last(), None);
1307    }
1308
1309    #[test]
1310    fn command_method_get_executable() {
1311        let c1 = Command::new_with_vec(vec!["test".to_string(), "-o".to_string()]);
1312        let c2 = Command::new_with_vec(vec!["~/user/path/to/test".to_string(), "-o".to_string()]);
1313        assert_eq!(c1.get_executable(), Cow::Borrowed("test"));
1314        assert_eq!(c2.get_executable(), Cow::Borrowed("~/user/path/to/test"));
1315    }
1316
1317    #[test]
1318    fn command_method_get_index_of() {
1319        let c = Command::new_with_vec(vec!["test".to_string(), "-o".to_string()]);
1320
1321        assert_eq!(c.get_index_of("test"), Some(0));
1322        assert_eq!(c.get_index_of("-o"), Some(1));
1323        assert_eq!(c.get_index_of("missing"), None);
1324    }
1325
1326    #[test]
1327    fn command_method_is_help_request() {
1328        let c1 = Command::new_with_vec(vec!["test".to_string(), "-h".to_string()]);
1329        let c2 = Command::new_with_vec(vec!["test".to_string(), "--help".to_string()]);
1330        let c3 = Command::new_with_vec(vec!["test".to_string(), "-help".to_string()]);
1331        let c4 = Command::new_with_vec(vec!["test".to_string(), "--h".to_string()]);
1332        let c5 = Command::new_with_vec(vec!["test".to_string(), "--else".to_string()]);
1333        let c6 = Command::new_with_vec(vec!["test".to_string(), "h".to_string()]);
1334        let c7 = Command::new_with_vec(vec!["test".to_string(), "help".to_string()]);
1335
1336        assert_eq!(c1.is_help_request(), true);
1337        assert_eq!(c2.is_help_request(), true);
1338        assert_eq!(c3.is_help_request(), false);
1339        assert_eq!(c4.is_help_request(), false);
1340        assert_eq!(c5.is_help_request(), false);
1341        assert_eq!(c6.is_help_request(), false);
1342        assert_eq!(c7.is_help_request(), false);
1343    }
1344
1345    #[test]
1346    fn command_method_is_version_request() {
1347        let c1 = Command::new_with_vec(vec!["test".to_string(), "-v".to_string()]);
1348        let c2 = Command::new_with_vec(vec!["test".to_string(), "--version".to_string()]);
1349        let c3 = Command::new_with_vec(vec!["test".to_string(), "-version".to_string()]);
1350        let c4 = Command::new_with_vec(vec!["test".to_string(), "--v".to_string()]);
1351        let c5 = Command::new_with_vec(vec!["test".to_string(), "--else".to_string()]);
1352        let c6 = Command::new_with_vec(vec!["test".to_string(), "v".to_string()]);
1353        let c7 = Command::new_with_vec(vec!["test".to_string(), "version".to_string()]);
1354
1355        assert_eq!(c1.is_version_request(), true);
1356        assert_eq!(c2.is_version_request(), true);
1357        assert_eq!(c3.is_version_request(), false);
1358        assert_eq!(c4.is_version_request(), false);
1359        assert_eq!(c5.is_version_request(), false);
1360        assert_eq!(c6.is_version_request(), false);
1361        assert_eq!(c7.is_version_request(), false);
1362    }
1363
1364    #[test]
1365    fn command_method_is_usage_request() {
1366        let c1 = Command::new_with_vec(vec!["test".to_string(), "--usage".to_string()]);
1367        let c2 = Command::new_with_vec(vec!["test".to_string(), "-u".to_string()]);
1368        let c3 = Command::new_with_vec(vec!["test".to_string(), "-usage".to_string()]);
1369        let c4 = Command::new_with_vec(vec!["test".to_string(), "--else".to_string()]);
1370        let c5 = Command::new_with_vec(vec!["test".to_string(), "usage".to_string()]);
1371
1372        assert_eq!(c1.is_usage_request(), true);
1373        assert_eq!(c2.is_usage_request(), false);
1374        assert_eq!(c3.is_usage_request(), false);
1375        assert_eq!(c4.is_usage_request(), false);
1376        assert_eq!(c5.is_usage_request(), false);
1377    }
1378}