clap 0.4.0

A Command Line Argument Parser written in Rust
use std::collections::HashMap;

use args::{ FlagArg, OptArg, PosArg };
use subcommand::SubCommand;

/// Used to get information about the arguments that
/// where supplied to the program at runtime.
///
///
/// Fields of `ArgMatches` aren't designed to be used directly, only 
/// the methods in order to query information.
///
/// # Example
///
/// ```no_run
/// # use clap::{App, Arg};
///  let matches = App::new("MyApp")
/// // adding of arguments and configuration goes here...
/// #                    .arg(Arg::new("config")
/// #                               .long("config")
/// #                               .required(true)
/// #                               .takes_value(true))
/// #                    .arg(Arg::new("debug")
/// #                                   .short("d")
/// #                                   .multiple(true))
///                     .get_matches();
///    // if you had an argument named "output" that takes a value 
///    if let Some(o) = matches.value_of("output") {
///        println!("Value for output: {}", o);
///    }
///
///    // Although not advised, if you have a required argument
///    // you can call .unwrap() because the program will exit long before
///    // here at noticing the user didn't supply a required argument...
///    // use at your own risk ;)
///    println!("Config file: {}", matches.value_of("config").unwrap());
///
///    // You can check the present of an argument
///    if matches.is_present("debug") {
///        // Checking if "debug" was present was necessary,
///        // as occurrences returns 0 if a flag isn't found
///        // but we can check how many times "debug" was found
///        // if we allow multiple (if multiple isn't allowed it always be 1 or 0)
///        if matches.occurrences_of("debug") > 1 {
///            println!("Debug mode is REALLY on");
///        } else {
///            println!("Debug mode kind of on");
///        }
///    }
///
///    // You can get the sub-matches of a particular subcommand (in this case "test")
///    // If "test" had it's own "-l" flag you could check for it's presence accordingly
///    if let Some(ref matches) = matches.subcommand_matches("test") {
///      if matches.is_present("list") {
///             println!("Printing testing lists...");
///         } else {
///             println!("Not printing testing lists...");
///         }
///     }
/// }
pub struct ArgMatches {
    pub matches_of: &'static str,
    pub flags: HashMap<&'static str, FlagArg>,
    pub opts: HashMap<&'static str, OptArg>,
    pub positionals: HashMap<&'static str, PosArg>,
    pub subcommand: Option<(&'static str, Box<SubCommand>)>
}

impl ArgMatches {
    /// Creates a new instance of `ArgMatches`. This ins't called directly, but
    /// through the `.get_matches()` method of `App`
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// let matches = App::new("myprog").get_matches();
    /// ```
	pub fn new(name: &'static str) -> ArgMatches {
		ArgMatches {
    		matches_of: name,
            flags: HashMap::new(),
            opts: HashMap::new(),
            positionals: HashMap::new(),
            subcommand: None
    	}
	}

    /// Gets the value of a specific option or positional argument (i.e. an argument that takes
    /// an additional value at runtime). If the option wasn't present at runtime
    /// it returns `None`
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let matches = App::new("myapp").arg(Arg::new("output").takes_value(true)).get_matches();
    /// if let Some(o) = matches.value_of("output") {
    ///        println!("Value for output: {}", o);
    /// }
    /// ```
	pub fn value_of(&self, name: &'static str) -> Option<&String> {
        if let Some(ref opt) = self.opts.get(name) {
        	if let Some(ref v) = opt.value {
        		return Some(v);
        	} 
        }
        if let Some(ref pos) = self.positionals.get(name) {
        	if let Some(ref v) = pos.value {
        		return Some(v);
        	}  
        }
        None
	}

    /// Checks if a flag was argument was supplied at runtime. **DOES NOT** work for
    /// option or positional arguments (use `.value_of()` instead)
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let matches = App::new("myapp").arg(Arg::new("output").takes_value(true)).get_matches();
    /// if matches.is_present("output") {
    ///        println!("The output argument was used!");
    /// }
    /// ```
	pub fn is_present(&self, name: &'static str) -> bool {
        if let Some((sc_name, _ )) = self.subcommand {
            if sc_name == name { return true; } 
        }
        if self.flags.contains_key(name) ||
             self.opts.contains_key(name) ||
              self.positionals.contains_key(name) {
                return true;
              }
        false
	}

    /// Checks the number of occurrences of a flag at runtime.
    ///
    /// This **DOES NOT** work for option or positional arguments 
    /// (use `.value_of()` instead). If a flag isn't present it will
    /// return `0`, if a flag doesn't allow multiple occurrences, it will
    /// return `1` no matter how many times it occurred (unless it wasn't prsent)
    /// at all.
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let matches = App::new("myapp").arg(Arg::new("output").takes_value(true)).get_matches();
    /// if matches.occurrences_of("debug") > 1 {
    ///     println!("Debug mode is REALLY on");
    /// } else {
    ///     println!("Debug mode kind of on");
    /// }
    /// ```
    pub fn occurrences_of(&self, name: &'static str) -> u8 {
        if let Some(ref f) = self.flags.get(name) {
            return f.occurrences;
        }
        0
    }

    /// If a subcommand was found, returns the ArgMatches struct associated with it's matches
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg, SubCommand};
    /// # let matches = App::new("myapp").subcommand(SubCommand::new("test")).get_matches();
    /// if let Some(matches) = app_matches.subcommand_matches("test") {
    ///     // Use matches as normal
    /// }
    /// ```
    pub fn subcommand_matches(&self, name: &'static str) -> Option<&ArgMatches> {
        if let Some( ( sc_name, ref sc)) = self.subcommand {
            if sc_name != name { return None; }
            return Some(&sc.matches);
        }
        None
    }

    /// If a subcommand was found, returns the name associated with it
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg, SubCommand};
    /// # let matches = App::new("myapp").subcommand(SubCommand::new("test")).get_matches();
    /// match app_matches.subcommand_() {
    ///     Some("test")   => {}, // test was used
    ///     Some("config") => {}, // config was used
    ///     _              => {}, // Either no subcommand or one not tested for...
    /// }
    /// ```
    pub fn subcommand_name(&self) -> Option<&'static str> {
        if let Some((name, _)) = self.subcommand {
            return Some(name);
        }
        None
    }
}