add simple error messages (with a lot of room for improvement)

This commit is contained in:
Terts Diepraam
2022-12-31 13:55:58 +01:00
parent b5e955222a
commit 77e0bcda48
13 changed files with 295 additions and 288 deletions
+3 -2
View File
@@ -26,9 +26,10 @@ struct Settings {
count: u8,
}
fn main() {
let settings = Settings::parse(std::env::args_os()).unwrap();
fn main() -> Result<(), uutils_args::Error> {
let settings = Settings::parse(std::env::args_os());
for _ in 0..settings.count {
println!("Hello, {}!", settings.name);
}
Ok(())
}
+132
View File
@@ -0,0 +1,132 @@
use std::{
error::Error as StdError,
ffi::OsString,
fmt::{Debug, Display},
};
pub enum Error {
MissingValue {
option: Option<String>,
},
MissingPositionalArguments(Vec<String>),
UnexpectedOption(String),
UnexpectedArgument(OsString),
UnexpectedValue {
option: String,
value: OsString,
},
ParsingFailed {
option: String,
value: String,
error: Box<dyn StdError + Send + Sync + 'static>,
},
AmbiguousOption {
option: String,
candidates: Vec<String>,
},
AmbiguousValue {
option: String,
value: String,
candidates: Vec<String>,
},
NonUnicodeValue(OsString),
Custom(Box<dyn StdError + Send + Sync + 'static>),
}
impl StdError for Error {}
impl Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self, f)
}
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "error: ")?;
match self {
Error::MissingValue { option } => match option {
Some(option) => write!(f, "Missing value for '{option}'."),
None => write!(f, "Missing value"),
},
Error::MissingPositionalArguments(args) => {
write!(f, "Missing values for the following positional arguments:")?;
for arg in args {
write!(f, " - {arg}")?;
}
Ok(())
}
Error::UnexpectedOption(opt) => {
write!(f, "Found an invalid option '{opt}'.")
}
Error::UnexpectedArgument(arg) => {
write!(f, "Found an invalid argument '{}'.", arg.to_string_lossy())
}
Error::UnexpectedValue { option, value } => {
write!(
f,
"Got an unexpected value '{}' for option '{option}'.",
value.to_string_lossy(),
)
}
Error::ParsingFailed {
option,
value,
error,
} => {
if option.is_empty() {
write!(f, "Could not parse value '{value}': {error}")
} else {
write!(
f,
"Could not parse value '{value}' for option '{option}': {error}"
)
}
}
Error::AmbiguousOption { option, candidates } => {
write!(
f,
"Option '{option}' is ambiguous. The following candidates match:"
)?;
for candidate in candidates {
write!(f, " - {candidate}")?;
}
Ok(())
}
Error::AmbiguousValue {
option,
value,
candidates,
} => {
write!(
f,
"Value '{value}' for option '{option}' is ambiguous. The following candidates match:",
)?;
for candidate in candidates {
write!(f, " - {candidate}")?;
}
Ok(())
}
Error::NonUnicodeValue(x) => {
write!(f, "Invalid unicode value found: {}", x.to_string_lossy())
}
Error::Custom(err) => std::fmt::Display::fmt(err, f),
}
}
}
impl From<lexopt::Error> for Error {
fn from(other: lexopt::Error) -> Error {
match other {
lexopt::Error::MissingValue { option } => Self::MissingValue { option },
lexopt::Error::UnexpectedOption(s) => Self::UnexpectedOption(s),
lexopt::Error::UnexpectedArgument(s) => Self::UnexpectedArgument(s),
lexopt::Error::UnexpectedValue { option, value } => {
Self::UnexpectedValue { option, value }
}
lexopt::Error::ParsingFailed { .. } => panic!("Conversion not supported"),
lexopt::Error::NonUnicodeValue(s) => Self::NonUnicodeValue(s),
lexopt::Error::Custom(e) => Self::Custom(e),
}
}
}
+17 -48
View File
@@ -1,58 +1,13 @@
mod error;
pub use derive::*;
pub use lexopt;
pub use term_md;
use std::error::Error as StdError;
pub use error::Error;
use std::num::ParseIntError;
use std::path::PathBuf;
use std::{ffi::OsString, marker::PhantomData};
#[derive(Debug)]
pub enum Error {
MissingValue {
option: Option<String>,
},
MissingPositionalArguments(Vec<String>),
UnexpectedOption(String),
UnexpectedArgument(OsString),
UnexpectedValue {
option: String,
value: OsString,
},
ParsingFailed {
option: String,
value: String,
error: Box<dyn StdError + Send + Sync + 'static>,
},
AmbiguousOption {
option: String,
candidates: Vec<String>,
},
AmbiguousValue {
option: String,
value: String,
candidates: Vec<String>,
},
NonUnicodeValue(OsString),
Custom(Box<dyn StdError + Send + Sync + 'static>),
}
impl From<lexopt::Error> for Error {
fn from(other: lexopt::Error) -> Error {
match other {
lexopt::Error::MissingValue { option } => Self::MissingValue { option },
lexopt::Error::UnexpectedOption(s) => Self::UnexpectedOption(s),
lexopt::Error::UnexpectedArgument(s) => Self::UnexpectedArgument(s),
lexopt::Error::UnexpectedValue { option, value } => {
Self::UnexpectedValue { option, value }
}
lexopt::Error::ParsingFailed { .. } => panic!("Conversion not supported"),
lexopt::Error::NonUnicodeValue(s) => Self::NonUnicodeValue(s),
lexopt::Error::Custom(e) => Self::Custom(e),
}
}
}
#[derive(Clone)]
pub enum Argument<T: Arguments> {
Help,
@@ -114,7 +69,21 @@ impl<T: Arguments> ArgumentIter<T> {
}
pub trait Options: Sized + Default {
fn parse<I>(args: I) -> Result<Self, Error>
fn parse<I>(args: I) -> Self
where
I: IntoIterator + 'static,
I::Item: Into<OsString>,
{
match Self::try_parse(args) {
Ok(v) => v,
Err(err) => {
eprintln!("{err}");
std::process::exit(0);
}
}
}
fn try_parse<I>(args: I) -> Result<Self, Error>
where
I: IntoIterator + 'static,
I::Item: Into<OsString>,
+4 -4
View File
@@ -11,12 +11,12 @@ struct Settings {}
#[test]
fn no_args() {
assert!(Settings::parse(["arch"]).is_ok());
assert!(Settings::try_parse(["arch"]).is_ok());
}
#[test]
fn one_arg_fails() {
assert!(Settings::parse(["arch", "-f"]).is_err());
assert!(Settings::parse(["arch", "--foo"]).is_err());
assert!(Settings::parse(["arch", "foo"]).is_err());
assert!(Settings::try_parse(["arch", "-f"]).is_err());
assert!(Settings::try_parse(["arch", "--foo"]).is_err());
assert!(Settings::try_parse(["arch", "foo"]).is_err());
}
+17 -33
View File
@@ -73,64 +73,48 @@ struct Settings {
#[test]
fn binary() {
assert!(!Settings::parse(["b2sum"]).unwrap().binary);
assert!(!Settings::parse(["b2sum", "--text"]).unwrap().binary);
assert!(!Settings::parse(["b2sum", "-t"]).unwrap().binary);
assert!(
!Settings::parse(["b2sum", "--binary", "--text"])
.unwrap()
.binary
);
assert!(!Settings::parse(["b2sum", "-b", "-t"]).unwrap().binary);
assert!(!Settings::parse(["b2sum"]).binary);
assert!(!Settings::parse(["b2sum", "--text"]).binary);
assert!(!Settings::parse(["b2sum", "-t"]).binary);
assert!(!Settings::parse(["b2sum", "--binary", "--text"]).binary);
assert!(!Settings::parse(["b2sum", "-b", "-t"]).binary);
assert!(Settings::parse(["b2sum", "--binary"]).unwrap().binary);
assert!(Settings::parse(["b2sum", "-b"]).unwrap().binary);
assert!(
Settings::parse(["b2sum", "--text", "--binary"])
.unwrap()
.binary
);
assert!(Settings::parse(["b2sum", "-t", "-b"]).unwrap().binary);
assert!(Settings::parse(["b2sum", "--binary"]).binary);
assert!(Settings::parse(["b2sum", "-b"]).binary);
assert!(Settings::parse(["b2sum", "--text", "--binary"]).binary);
assert!(Settings::parse(["b2sum", "-t", "-b"]).binary);
}
#[test]
fn check_output() {
assert_eq!(
Settings::parse(["b2sum", "--warn"]).unwrap().check_output,
Settings::parse(["b2sum", "--warn"]).check_output,
CheckOutput::Warn
);
assert_eq!(
Settings::parse(["b2sum", "--quiet"]).unwrap().check_output,
Settings::parse(["b2sum", "--quiet"]).check_output,
CheckOutput::Quiet
);
assert_eq!(
Settings::parse(["b2sum", "--status"]).unwrap().check_output,
Settings::parse(["b2sum", "--status"]).check_output,
CheckOutput::Status
);
assert_eq!(
Settings::parse(["b2sum", "--status", "--warn"])
.unwrap()
.check_output,
Settings::parse(["b2sum", "--status", "--warn"]).check_output,
CheckOutput::Warn
);
assert_eq!(
Settings::parse(["b2sum", "--status", "--warn"])
.unwrap()
.check_output,
Settings::parse(["b2sum", "--status", "--warn"]).check_output,
CheckOutput::Warn
);
assert_eq!(
Settings::parse(["b2sum", "--warn", "--quiet"])
.unwrap()
.check_output,
Settings::parse(["b2sum", "--warn", "--quiet"]).check_output,
CheckOutput::Quiet
);
assert_eq!(
Settings::parse(["b2sum", "--quiet", "--status"])
.unwrap()
.check_output,
Settings::parse(["b2sum", "--quiet", "--status"]).check_output,
CheckOutput::Status
);
}
@@ -138,7 +122,7 @@ fn check_output() {
#[test]
fn files() {
assert_eq!(
Settings::parse(["b2sum", "foo", "bar"]).unwrap().files,
Settings::parse(["b2sum", "foo", "bar"]).files,
vec![Path::new("foo"), Path::new("bar")]
);
}
+4 -10
View File
@@ -41,14 +41,8 @@ struct Settings {
#[test]
fn wrap() {
assert_eq!(Settings::parse(["base32"]).unwrap().wrap, Some(76));
assert_eq!(Settings::parse(["base32", "-w0"]).unwrap().wrap, None);
assert_eq!(
Settings::parse(["base32", "-w100"]).unwrap().wrap,
Some(100)
);
assert_eq!(
Settings::parse(["base32", "--wrap=100"]).unwrap().wrap,
Some(100)
);
assert_eq!(Settings::parse(["base32"]).wrap, Some(76));
assert_eq!(Settings::parse(["base32", "-w0"]).wrap, None);
assert_eq!(Settings::parse(["base32", "-w100"]).wrap, Some(100));
assert_eq!(Settings::parse(["base32", "--wrap=100"]).wrap, Some(100));
}
+7 -7
View File
@@ -33,18 +33,18 @@ struct Settings {
names: Vec<String>,
}
fn parse(args: &'static [&'static str]) -> Result<Settings, uutils_args::Error> {
let mut settings = Settings::parse(args)?;
fn parse(args: &'static [&'static str]) -> Settings {
let mut settings = Settings::parse(args);
if !settings.multiple {
assert_eq!(settings.names.len(), 2);
settings.suffix = settings.names.pop().unwrap();
}
Ok(settings)
settings
}
#[test]
fn name_and_suffix() {
let settings = parse(&["basename", "foobar", "bar"]).unwrap();
let settings = parse(&["basename", "foobar", "bar"]);
assert!(!settings.zero);
assert_eq!(settings.names, vec!["foobar"]);
assert_eq!(settings.suffix, "bar");
@@ -52,7 +52,7 @@ fn name_and_suffix() {
#[test]
fn zero_name_and_suffix() {
let settings = parse(&["basename", "-z", "foobar", "bar"]).unwrap();
let settings = parse(&["basename", "-z", "foobar", "bar"]);
assert!(settings.zero);
assert_eq!(settings.names, vec!["foobar"]);
assert_eq!(settings.suffix, "bar");
@@ -60,7 +60,7 @@ fn zero_name_and_suffix() {
#[test]
fn all_and_names() {
let settings = parse(&["basename", "-a", "foobar", "bar"]).unwrap();
let settings = parse(&["basename", "-a", "foobar", "bar"]);
assert!(settings.multiple);
assert!(!settings.zero);
assert_eq!(settings.names, vec!["foobar", "bar"]);
@@ -69,7 +69,7 @@ fn all_and_names() {
#[test]
fn option_like_names() {
let settings = parse(&["basename", "-a", "--", "-a", "-z", "--suffix=SUFFIX"]).unwrap();
let settings = parse(&["basename", "-a", "--", "-a", "-z", "--suffix=SUFFIX"]);
assert!(settings.multiple);
assert!(!settings.zero);
assert_eq!(settings.names, vec!["-a", "-z", "--suffix=SUFFIX"]);
+8 -8
View File
@@ -78,27 +78,27 @@ struct Settings {
#[test]
fn show() {
let s = Settings::parse(["cat", "-v"]).unwrap();
let s = Settings::parse(["cat", "-v"]);
assert!(!s.show_ends && !s.show_tabs && s.show_nonprinting);
let s = Settings::parse(["cat", "-E"]).unwrap();
let s = Settings::parse(["cat", "-E"]);
assert!(s.show_ends && !s.show_tabs && !s.show_nonprinting);
let s = Settings::parse(["cat", "-T"]).unwrap();
let s = Settings::parse(["cat", "-T"]);
assert!(!s.show_ends && s.show_tabs && !s.show_nonprinting);
let s = Settings::parse(["cat", "-e"]).unwrap();
let s = Settings::parse(["cat", "-e"]);
assert!(s.show_ends && !s.show_tabs && s.show_nonprinting);
let s = Settings::parse(["cat", "-t"]).unwrap();
let s = Settings::parse(["cat", "-t"]);
assert!(!s.show_ends && s.show_tabs && s.show_nonprinting);
let s = Settings::parse(["cat", "-A"]).unwrap();
let s = Settings::parse(["cat", "-A"]);
assert!(s.show_ends && s.show_tabs && s.show_nonprinting);
let s = Settings::parse(["cat", "-te"]).unwrap();
let s = Settings::parse(["cat", "-te"]);
assert!(s.show_ends && s.show_tabs && s.show_nonprinting);
let s = Settings::parse(["cat", "-vET"]).unwrap();
let s = Settings::parse(["cat", "-vET"]);
assert!(s.show_ends && s.show_tabs && s.show_nonprinting);
}
+10 -10
View File
@@ -55,35 +55,35 @@ struct Settings {
#[test]
fn suffix() {
let s = Settings::parse(["mktemp", "--suffix=hello"]).unwrap();
let s = Settings::parse(["mktemp", "--suffix=hello"]);
assert_eq!(s.suffix.unwrap(), "hello");
let s = Settings::parse(["mktemp", "--suffix="]).unwrap();
let s = Settings::parse(["mktemp", "--suffix="]);
assert_eq!(s.suffix.unwrap(), "");
let s = Settings::parse(["mktemp", "--suffix="]).unwrap();
let s = Settings::parse(["mktemp", "--suffix="]);
assert_eq!(s.suffix.unwrap(), "");
let s = Settings::parse(["mktemp"]).unwrap();
let s = Settings::parse(["mktemp"]);
assert_eq!(s.suffix, None);
}
#[test]
fn tmpdir() {
let s = Settings::parse(["mktemp", "--tmpdir"]).unwrap();
let s = Settings::parse(["mktemp", "--tmpdir"]);
assert_eq!(s.tmp_dir.unwrap(), Path::new("."));
let s = Settings::parse(["mktemp", "--tmpdir="]).unwrap();
let s = Settings::parse(["mktemp", "--tmpdir="]);
assert_eq!(s.tmp_dir.unwrap(), Path::new(""));
let s = Settings::parse(["mktemp", "-p", "foo"]).unwrap();
let s = Settings::parse(["mktemp", "-p", "foo"]);
assert_eq!(s.tmp_dir.unwrap(), Path::new("foo"));
let s = Settings::parse(["mktemp", "-pfoo"]).unwrap();
let s = Settings::parse(["mktemp", "-pfoo"]);
assert_eq!(s.tmp_dir.unwrap(), Path::new("foo"));
let s = Settings::parse(["mktemp", "-p", ""]).unwrap();
let s = Settings::parse(["mktemp", "-p", ""]);
assert_eq!(s.tmp_dir.unwrap(), Path::new(""));
assert!(Settings::parse(["mktemp", "-p"]).is_err());
assert!(Settings::try_parse(["mktemp", "-p"]).is_err());
}
+5 -5
View File
@@ -16,8 +16,8 @@ fn true_default() {
foo: bool,
}
assert!(Settings::parse(["test"]).unwrap().foo);
assert!(!Settings::parse(["test", "--foo"]).unwrap().foo);
assert!(Settings::parse(["test"]).foo);
assert!(!Settings::parse(["test", "--foo"]).foo);
}
#[test]
@@ -37,11 +37,11 @@ fn env_var_string() {
}
std::env::set_var("FOO", "one");
assert_eq!(Settings::parse(["test"]).unwrap().foo, "one");
assert_eq!(Settings::parse(["test"]).foo, "one");
std::env::set_var("FOO", "two");
assert_eq!(Settings::parse(["test"]).unwrap().foo, "two");
assert_eq!(Settings::parse(["test"]).foo, "two");
std::env::remove_var("FOO");
assert_eq!(Settings::parse(["test"]).unwrap().foo, "");
assert_eq!(Settings::parse(["test"]).foo, "");
}
+42 -93
View File
@@ -15,7 +15,7 @@ fn one_flag() {
foo: bool,
}
let settings = Settings::parse(["test", "-f"]).unwrap();
let settings = Settings::parse(["test", "-f"]);
assert!(settings.foo);
}
@@ -39,19 +39,16 @@ fn two_flags() {
}
assert_eq!(
Settings::parse(["test", "-a"]).unwrap(),
Settings::parse(["test", "-a"]),
Settings { a: true, b: false }
);
assert_eq!(Settings::parse(["test"]), Settings { a: false, b: false });
assert_eq!(
Settings::parse::<&[&std::ffi::OsStr]>(&[]).unwrap(),
Settings { a: false, b: false }
);
assert_eq!(
Settings::parse(["test", "-b"]).unwrap(),
Settings::parse(["test", "-b"]),
Settings { a: false, b: true }
);
assert_eq!(
Settings::parse(["test", "-a", "-b"]).unwrap(),
Settings::parse(["test", "-a", "-b"]),
Settings { a: true, b: true }
);
}
@@ -71,18 +68,9 @@ fn long_and_short_flag() {
foo: bool,
}
assert_eq!(
Settings::parse::<&[&std::ffi::OsStr]>(&[]).unwrap(),
Settings { foo: false },
);
assert_eq!(
Settings::parse(["test", "--foo"]).unwrap(),
Settings { foo: true },
);
assert_eq!(
Settings::parse(["test", "-f"]).unwrap(),
Settings { foo: true },
);
assert_eq!(Settings::parse(["test"]), Settings { foo: false },);
assert_eq!(Settings::parse(["test", "--foo"]), Settings { foo: true },);
assert_eq!(Settings::parse(["test", "-f"]), Settings { foo: true },);
}
#[test]
@@ -100,10 +88,7 @@ fn short_alias() {
foo: bool,
}
assert_eq!(
Settings::parse(["test", "-b"]).unwrap(),
Settings { foo: true },
);
assert_eq!(Settings::parse(["test", "-b"]), Settings { foo: true },);
}
#[test]
@@ -121,10 +106,7 @@ fn long_alias() {
foo: bool,
}
assert_eq!(
Settings::parse(["test", "--bar"]).unwrap(),
Settings { foo: true },
);
assert_eq!(Settings::parse(["test", "--bar"]), Settings { foo: true },);
}
#[test]
@@ -156,10 +138,10 @@ fn short_and_long_alias() {
bar: true,
};
assert_eq!(Settings::parse(["test", "--bar"]).unwrap(), foo_true);
assert_eq!(Settings::parse(["test", "-b"]).unwrap(), foo_true);
assert_eq!(Settings::parse(["test", "--foo"]).unwrap(), bar_true);
assert_eq!(Settings::parse(["test", "-f"]).unwrap(), bar_true);
assert_eq!(Settings::parse(["test", "--bar"]), foo_true);
assert_eq!(Settings::parse(["test", "-b"]), foo_true);
assert_eq!(Settings::parse(["test", "--foo"]), bar_true);
assert_eq!(Settings::parse(["test", "-f"]), bar_true);
}
#[test]
@@ -186,7 +168,7 @@ fn xyz_map_to_abc() {
}
assert_eq!(
Settings::parse(["test", "-x"]).unwrap(),
Settings::parse(["test", "-x"]),
Settings {
a: true,
b: true,
@@ -195,7 +177,7 @@ fn xyz_map_to_abc() {
);
assert_eq!(
Settings::parse(["test", "-y"]).unwrap(),
Settings::parse(["test", "-y"]),
Settings {
a: false,
b: true,
@@ -204,7 +186,7 @@ fn xyz_map_to_abc() {
);
assert_eq!(
Settings::parse(["test", "-xy"]).unwrap(),
Settings::parse(["test", "-xy"]),
Settings {
a: true,
b: true,
@@ -213,7 +195,7 @@ fn xyz_map_to_abc() {
);
assert_eq!(
Settings::parse(["test", "-z"]).unwrap(),
Settings::parse(["test", "-z"]),
Settings {
a: true,
b: true,
@@ -242,7 +224,7 @@ fn non_rust_ident() {
}
assert_eq!(
Settings::parse(["test", "--foo-bar", "--super"]).unwrap(),
Settings::parse(["test", "--foo-bar", "--super"]),
Settings { a: true, b: true }
)
}
@@ -261,10 +243,7 @@ fn number_flag() {
one: bool,
}
assert_eq!(
Settings::parse(["test", "-1"]).unwrap(),
Settings { one: true }
)
assert_eq!(Settings::parse(["test", "-1"]), Settings { one: true })
}
#[test]
@@ -287,28 +266,16 @@ fn false_bool() {
foo: bool,
}
assert_eq!(Settings::parse(["test", "-a"]), Settings { foo: true });
assert_eq!(Settings::parse(["test", "-b"]), Settings { foo: false });
assert_eq!(Settings::parse(["test", "-ab"]), Settings { foo: false });
assert_eq!(Settings::parse(["test", "-ba"]), Settings { foo: true });
assert_eq!(
Settings::parse(["test", "-a"]).unwrap(),
Settings { foo: true }
);
assert_eq!(
Settings::parse(["test", "-b"]).unwrap(),
Settings::parse(["test", "-a", "-b"]),
Settings { foo: false }
);
assert_eq!(
Settings::parse(["test", "-ab"]).unwrap(),
Settings { foo: false }
);
assert_eq!(
Settings::parse(["test", "-ba"]).unwrap(),
Settings { foo: true }
);
assert_eq!(
Settings::parse(["test", "-a", "-b"]).unwrap(),
Settings { foo: false }
);
assert_eq!(
Settings::parse(["test", "-b", "-a"]).unwrap(),
Settings::parse(["test", "-b", "-a"]),
Settings { foo: true }
);
@@ -322,28 +289,16 @@ fn false_bool() {
foo: bool,
}
assert_eq!(Settings2::parse(["test", "-a"]), Settings2 { foo: true });
assert_eq!(Settings2::parse(["test", "-b"]), Settings2 { foo: false });
assert_eq!(Settings2::parse(["test", "-ab"]), Settings2 { foo: false });
assert_eq!(Settings2::parse(["test", "-ba"]), Settings2 { foo: true });
assert_eq!(
Settings2::parse(["test", "-a"]).unwrap(),
Settings2 { foo: true }
);
assert_eq!(
Settings2::parse(["test", "-b"]).unwrap(),
Settings2::parse(["test", "-a", "-b"]),
Settings2 { foo: false }
);
assert_eq!(
Settings2::parse(["test", "-ab"]).unwrap(),
Settings2 { foo: false }
);
assert_eq!(
Settings2::parse(["test", "-ba"]).unwrap(),
Settings2 { foo: true }
);
assert_eq!(
Settings2::parse(["test", "-a", "-b"]).unwrap(),
Settings2 { foo: false }
);
assert_eq!(
Settings2::parse(["test", "-b", "-a"]).unwrap(),
Settings2::parse(["test", "-b", "-a"]),
Settings2 { foo: true }
);
}
@@ -379,17 +334,11 @@ fn enum_flag() {
foo: SomeEnum,
}
assert_eq!(Settings::parse(&[] as &[&str]).unwrap().foo, SomeEnum::Foo);
assert_eq!(Settings::parse(&[] as &[&str]).foo, SomeEnum::Foo);
assert_eq!(
Settings::parse(["test", "--bar"]).unwrap().foo,
SomeEnum::Bar
);
assert_eq!(Settings::parse(["test", "--bar"]).foo, SomeEnum::Bar);
assert_eq!(
Settings::parse(["test", "--baz"]).unwrap().foo,
SomeEnum::Baz,
);
assert_eq!(Settings::parse(["test", "--baz"]).foo, SomeEnum::Baz,);
}
#[test]
@@ -407,9 +356,9 @@ fn count() {
verbosity: u8,
}
assert_eq!(Settings::parse(["test", "-v"]).unwrap().verbosity, 1);
assert_eq!(Settings::parse(["test", "-vv"]).unwrap().verbosity, 2);
assert_eq!(Settings::parse(["test", "-vvv"]).unwrap().verbosity, 3);
assert_eq!(Settings::parse(["test", "-v"]).verbosity, 1);
assert_eq!(Settings::parse(["test", "-vv"]).verbosity, 2);
assert_eq!(Settings::parse(["test", "-vvv"]).verbosity, 3);
}
#[test]
@@ -437,8 +386,8 @@ fn infer_long_args() {
author: bool,
}
assert!(Settings::parse(["test", "--all"]).unwrap().all);
assert!(Settings::parse(["test", "--alm"]).unwrap().almost_all);
assert!(Settings::parse(["test", "--au"]).unwrap().author);
assert!(Settings::parse(["test", "--a"]).is_err());
assert!(Settings::parse(["test", "--all"]).all);
assert!(Settings::parse(["test", "--alm"]).almost_all);
assert!(Settings::parse(["test", "--au"]).author);
assert!(Settings::try_parse(["test", "--a"]).is_err());
}
+35 -57
View File
@@ -18,9 +18,7 @@ fn string_option() {
}
assert_eq!(
Settings::parse(["test", "--message=hello"])
.unwrap()
.message,
Settings::parse(["test", "--message=hello"]).message,
"hello"
);
}
@@ -52,12 +50,12 @@ fn enum_option() {
}
assert_eq!(
Settings::parse(["test", "--format=bar"]).unwrap().format,
Settings::parse(["test", "--format=bar"]).format,
Format::Bar
);
assert_eq!(
Settings::parse(["test", "--format", "baz"]).unwrap().format,
Settings::parse(["test", "--format", "baz"]).format,
Format::Baz
);
}
@@ -87,11 +85,11 @@ fn enum_option_with_fields() {
}
assert_eq!(
Settings::parse(["test", "-i=thin"]).unwrap().indent,
Settings::parse(["test", "-i=thin"]).indent,
Indent::Spaces(4)
);
assert_eq!(
Settings::parse(["test", "-i=wide"]).unwrap().indent,
Settings::parse(["test", "-i=wide"]).indent,
Indent::Spaces(8)
);
}
@@ -135,14 +133,8 @@ fn enum_with_complex_from_value() {
indent: Indent,
}
assert_eq!(
Settings::parse(["test", "-i=tabs"]).unwrap().indent,
Indent::Tabs
);
assert_eq!(
Settings::parse(["test", "-i=4"]).unwrap().indent,
Indent::Spaces(4)
);
assert_eq!(Settings::parse(["test", "-i=tabs"]).indent, Indent::Tabs);
assert_eq!(Settings::parse(["test", "-i=4"]).indent, Indent::Spaces(4));
}
#[test]
@@ -175,29 +167,20 @@ fn color() {
}
assert_eq!(
Settings::parse(["test", "--color=yes"]).unwrap().color,
Settings::parse(["test", "--color=yes"]).color,
Color::Always
);
assert_eq!(
Settings::parse(["test", "--color=always"]).unwrap().color,
Settings::parse(["test", "--color=always"]).color,
Color::Always
);
assert_eq!(Settings::parse(["test", "--color=no"]).color, Color::Never);
assert_eq!(
Settings::parse(["test", "--color=no"]).unwrap().color,
Settings::parse(["test", "--color=never"]).color,
Color::Never
);
assert_eq!(
Settings::parse(["test", "--color=never"]).unwrap().color,
Color::Never
);
assert_eq!(
Settings::parse(["test", "--color=auto"]).unwrap().color,
Color::Auto
);
assert_eq!(
Settings::parse(["test", "--color"]).unwrap().color,
Color::Always
)
assert_eq!(Settings::parse(["test", "--color=auto"]).color, Color::Auto);
assert_eq!(Settings::parse(["test", "--color"]).color, Color::Always)
}
#[test]
@@ -232,7 +215,7 @@ fn actions() {
messages: Vec<String>,
}
let settings = Settings::parse(["test", "-m=Hello", "-m=World", "--send"]).unwrap();
let settings = Settings::parse(["test", "-m=Hello", "-m=World", "--send"]);
assert_eq!(settings.messages, vec!["Hello", "World"]);
assert_eq!(settings.message1, "World");
assert_eq!(settings.message2, "World");
@@ -257,8 +240,8 @@ fn width() {
width: Option<u64>,
}
assert_eq!(Settings::parse(["test", "-w=0"]).unwrap().width, None);
assert_eq!(Settings::parse(["test", "-w=1"]).unwrap().width, Some(1));
assert_eq!(Settings::parse(["test", "-w=0"]).width, None);
assert_eq!(Settings::parse(["test", "-w=1"]).width, Some(1));
}
#[test]
@@ -305,17 +288,17 @@ fn integers() {
n: i128,
}
assert_eq!(Settings::parse(["test", "--u8=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--u16=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--u32=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--u64=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--u128=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--u8=5"]).n, 5);
assert_eq!(Settings::parse(["test", "--u16=5"]).n, 5);
assert_eq!(Settings::parse(["test", "--u32=5"]).n, 5);
assert_eq!(Settings::parse(["test", "--u64=5"]).n, 5);
assert_eq!(Settings::parse(["test", "--u128=5"]).n, 5);
assert_eq!(Settings::parse(["test", "--i8=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--i16=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--i32=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--i64=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--i128=5"]).unwrap().n, 5);
assert_eq!(Settings::parse(["test", "--i8=5"]).n, 5);
assert_eq!(Settings::parse(["test", "--i16=5"]).n, 5);
assert_eq!(Settings::parse(["test", "--i32=5"]).n, 5);
assert_eq!(Settings::parse(["test", "--i64=5"]).n, 5);
assert_eq!(Settings::parse(["test", "--i128=5"]).n, 5);
}
#[test]
@@ -347,22 +330,17 @@ fn ls_classify() {
classify: When,
}
assert_eq!(Settings::parse(["test"]).unwrap().classify, When::Auto);
assert_eq!(Settings::parse(["test"]).classify, When::Auto);
assert_eq!(
Settings::parse(["test", "--classify=never"])
.unwrap()
.classify,
Settings::parse(["test", "--classify=never"]).classify,
When::Never,
);
assert_eq!(
Settings::parse(["test", "--classify"]).unwrap().classify,
Settings::parse(["test", "--classify"]).classify,
When::Always,
);
assert_eq!(
Settings::parse(["test", "-F"]).unwrap().classify,
When::Always,
);
assert!(Settings::parse(["test", "-Falways"]).is_err());
assert_eq!(Settings::parse(["test", "-F"]).classify, When::Always,);
assert!(Settings::try_parse(["test", "-Falways"]).is_err());
}
#[test]
@@ -383,16 +361,16 @@ fn mktemp_tmpdir() {
tmpdir: Option<String>,
}
let settings = Settings::parse(["test", "-p", "X"]).unwrap();
let settings = Settings::parse(["test", "-p", "X"]);
assert_eq!(settings.tmpdir.unwrap(), "X");
let settings = Settings::parse(["test", "--tmpdir=X"]).unwrap();
let settings = Settings::parse(["test", "--tmpdir=X"]);
assert_eq!(settings.tmpdir.unwrap(), "X");
let settings = Settings::parse(["test", "--tmpdir"]).unwrap();
let settings = Settings::parse(["test", "--tmpdir"]);
assert_eq!(settings.tmpdir.unwrap(), "/tmp");
assert!(Settings::parse(["test", "-p"]).is_err());
assert!(Settings::try_parse(["test", "-p"]).is_err());
}
#[test]
+11 -11
View File
@@ -15,10 +15,10 @@ fn one_positional() {
file1: String,
}
let settings = Settings::parse(["test", "foo"]).unwrap();
let settings = Settings::parse(["test", "foo"]);
assert_eq!(settings.file1, "foo");
assert!(Settings::parse(["test"]).is_err());
assert!(Settings::try_parse(["test"]).is_err());
}
#[test]
@@ -40,11 +40,11 @@ fn two_positionals() {
bar: String,
}
let settings = Settings::parse(["test", "a", "b"]).unwrap();
let settings = Settings::parse(["test", "a", "b"]);
assert_eq!(settings.foo, "a");
assert_eq!(settings.bar, "b");
assert!(Settings::parse(["test"]).is_err());
assert!(Settings::try_parse(["test"]).is_err());
}
#[test]
@@ -62,9 +62,9 @@ fn optional_positional() {
foo: Option<String>,
}
let settings = Settings::parse(["test"]).unwrap();
let settings = Settings::parse(["test"]);
assert_eq!(settings.foo, None);
let settings = Settings::parse(["test", "bar"]).unwrap();
let settings = Settings::parse(["test", "bar"]);
assert_eq!(settings.foo.unwrap(), "bar");
}
@@ -83,9 +83,9 @@ fn collect_positional() {
foo: Vec<String>,
}
let settings = Settings::parse(["test", "a", "b", "c"]).unwrap();
let settings = Settings::parse(["test", "a", "b", "c"]);
assert_eq!(settings.foo, vec!["a", "b", "c"]);
let settings = Settings::parse(["test"]).unwrap();
let settings = Settings::parse(["test"]);
assert_eq!(settings.foo, Vec::<String>::new());
}
@@ -104,7 +104,7 @@ fn last1() {
foo: Vec<String>,
}
let settings = Settings::parse(["test", "a", "-b", "c"]).unwrap();
let settings = Settings::parse(["test", "a", "-b", "c"]);
assert_eq!(settings.foo, vec!["a", "-b", "c"]);
}
@@ -126,9 +126,9 @@ fn last2() {
foo: Vec<String>,
}
let settings = Settings::parse(["test", "-a"]).unwrap();
let settings = Settings::parse(["test", "-a"]);
assert_eq!(settings.foo, Vec::<String>::new());
let settings = Settings::parse(["test", "--", "-a"]).unwrap();
let settings = Settings::parse(["test", "--", "-a"]);
assert_eq!(settings.foo, vec!["-a"]);
}