2017-07-26 16:48:18 +00:00
|
|
|
|
use std::ffi::{OsStr, OsString};
|
2016-04-17 19:38:37 +00:00
|
|
|
|
use std::fmt;
|
|
|
|
|
use std::num::ParseIntError;
|
|
|
|
|
|
2016-10-30 14:43:33 +00:00
|
|
|
|
use glob;
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
2017-08-05 18:46:47 +00:00
|
|
|
|
use options::{HelpString, VersionString};
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
use options::parser::{Arg, Flag, ParseError};
|
2017-06-23 21:50:29 +00:00
|
|
|
|
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
2016-08-29 01:56:32 +00:00
|
|
|
|
/// A list of legal choices for an argument-taking option
|
|
|
|
|
#[derive(PartialEq, Debug)]
|
2017-06-23 21:58:07 +00:00
|
|
|
|
pub struct Choices(&'static [&'static str]);
|
2016-08-29 01:56:32 +00:00
|
|
|
|
|
|
|
|
|
impl fmt::Display for Choices {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2017-07-26 16:48:18 +00:00
|
|
|
|
write!(f, "(choices: {})", self.0.join(", "))
|
2016-08-29 01:56:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-17 19:38:37 +00:00
|
|
|
|
/// A **misfire** is a thing that can happen instead of listing files -- a
|
|
|
|
|
/// catch-all for anything outside the program’s normal execution.
|
|
|
|
|
#[derive(PartialEq, Debug)]
|
|
|
|
|
pub enum Misfire {
|
|
|
|
|
|
2017-07-26 16:48:18 +00:00
|
|
|
|
/// The getopts crate didn’t like these Arguments.
|
|
|
|
|
InvalidOptions(ParseError),
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
2017-07-26 16:48:18 +00:00
|
|
|
|
/// The user supplied an illegal choice to an Argument.
|
|
|
|
|
BadArgument(&'static Arg, OsString, Choices),
|
2016-08-29 01:56:32 +00:00
|
|
|
|
|
2016-04-17 19:38:37 +00:00
|
|
|
|
/// The user asked for help. This isn’t strictly an error, which is why
|
|
|
|
|
/// this enum isn’t named Error!
|
2017-06-23 21:50:29 +00:00
|
|
|
|
Help(HelpString),
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
|
|
|
|
/// The user wanted the version number.
|
2017-08-05 18:46:47 +00:00
|
|
|
|
Version(VersionString),
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
/// An option was given twice or more in strict mode.
|
|
|
|
|
Duplicate(Flag, Flag),
|
|
|
|
|
|
2016-04-17 19:38:37 +00:00
|
|
|
|
/// Two options were given that conflict with one another.
|
2017-07-26 16:48:18 +00:00
|
|
|
|
Conflict(&'static Arg, &'static Arg),
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
|
|
|
|
/// An option was given that does nothing when another one either is or
|
|
|
|
|
/// isn't present.
|
2017-07-26 16:48:18 +00:00
|
|
|
|
Useless(&'static Arg, bool, &'static Arg),
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
|
|
|
|
/// An option was given that does nothing when either of two other options
|
|
|
|
|
/// are not present.
|
2017-07-26 16:48:18 +00:00
|
|
|
|
Useless2(&'static Arg, &'static Arg, &'static Arg),
|
|
|
|
|
|
|
|
|
|
/// A very specific edge case where --tree can’t be used with --all twice.
|
|
|
|
|
TreeAllAll,
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
|
|
|
|
/// A numeric option was given that failed to be parsed as a number.
|
|
|
|
|
FailedParse(ParseIntError),
|
2016-10-30 14:43:33 +00:00
|
|
|
|
|
|
|
|
|
/// A glob ignore was given that failed to be parsed as a pattern.
|
|
|
|
|
FailedGlobPattern(String),
|
2016-04-17 19:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Misfire {
|
|
|
|
|
|
|
|
|
|
/// The OS return code this misfire should signify.
|
2017-06-23 21:12:21 +00:00
|
|
|
|
pub fn is_error(&self) -> bool {
|
2017-05-17 20:01:12 +00:00
|
|
|
|
match *self {
|
2017-08-05 18:46:47 +00:00
|
|
|
|
Misfire::Help(_) => false,
|
|
|
|
|
Misfire::Version(_) => false,
|
|
|
|
|
_ => true,
|
2017-05-17 20:01:12 +00:00
|
|
|
|
}
|
2016-04-17 19:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The Misfire that happens when an option gets given the wrong
|
|
|
|
|
/// argument. This has to use one of the `getopts` failure
|
|
|
|
|
/// variants--it’s meant to take just an option name, rather than an
|
|
|
|
|
/// option *and* an argument, but it works just as well.
|
2017-07-26 16:48:18 +00:00
|
|
|
|
pub fn bad_argument(option: &'static Arg, otherwise: &OsStr, legal: &'static [&'static str]) -> Misfire {
|
|
|
|
|
Misfire::BadArgument(option, otherwise.to_os_string(), Choices(legal))
|
2016-04-17 19:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-30 14:43:33 +00:00
|
|
|
|
impl From<glob::PatternError> for Misfire {
|
|
|
|
|
fn from(error: glob::PatternError) -> Misfire {
|
|
|
|
|
Misfire::FailedGlobPattern(error.to_string())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-17 19:38:37 +00:00
|
|
|
|
impl fmt::Display for Misfire {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
use self::Misfire::*;
|
|
|
|
|
|
|
|
|
|
match *self {
|
2017-07-26 16:48:18 +00:00
|
|
|
|
BadArgument(ref a, ref b, ref c) => write!(f, "Option {} has no value {:?} (Choices: {})", a, b, c),
|
|
|
|
|
InvalidOptions(ref e) => write!(f, "{:?}", e),
|
|
|
|
|
Help(ref text) => write!(f, "{}", text),
|
2017-08-05 18:46:47 +00:00
|
|
|
|
Version(ref version) => write!(f, "{}", version),
|
2017-07-26 16:48:18 +00:00
|
|
|
|
Conflict(ref a, ref b) => write!(f, "Option {} conflicts with option {}.", a, b),
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
Duplicate(ref a, ref b) => write!(f, "Flag {:?} conflicts with flag {:?}.", a, b),
|
2017-07-26 16:48:18 +00:00
|
|
|
|
Useless(ref a, false, ref b) => write!(f, "Option {} is useless without option {}.", a, b),
|
|
|
|
|
Useless(ref a, true, ref b) => write!(f, "Option {} is useless given option {}.", a, b),
|
|
|
|
|
Useless2(ref a, ref b1, ref b2) => write!(f, "Option {} is useless without options {} or {}.", a, b1, b2),
|
|
|
|
|
TreeAllAll => write!(f, "Option --tree is useless given --all --all."),
|
|
|
|
|
FailedParse(ref e) => write!(f, "Failed to parse number: {}", e),
|
|
|
|
|
FailedGlobPattern(ref e) => write!(f, "Failed to parse glob pattern: {}", e),
|
2016-04-17 19:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|