Now returns an error when not all program args are passed via command-line

There was a lot of stuff added here. The most important addition is
how Pirate now returns a MissingArgument kinded error if a required
program argument isn't passed to the program.
This commit is contained in:
Zach Dziura 2015-04-30 15:14:34 +00:00
parent da684ab0f7
commit 25327fa441
5 changed files with 25 additions and 14 deletions

View file

@ -13,9 +13,10 @@ Ever.
In all seriousness, `getopts` is a fantastic library that gives the developers all of the tools In all seriousness, `getopts` is a fantastic library that gives the developers all of the tools
necessary to create and interface with command-line arguments. However, with all that power comes necessary to create and interface with command-line arguments. However, with all that power comes
complexity. `getopts`, while straight forward to use, is verbose. The developer has to make repeated complexity. `getopts` -- while straight forward to use -- is verbose. The developer has to call
method calls to add different command-line options. And while the only victim here is the different functions repeatedly in order to add different command-line options to their programs. And
developer's wrists due to carpal tunnel, I felt that there was a better way to do things. while the only victim here is the developer's wrists due to carpal tunnel, I felt that there was a
better way to do things.
Enter Pirate (which should totally usurp `getopts` for the award of Most Originally Named Project Ever). Enter Pirate (which should totally usurp `getopts` for the award of Most Originally Named Project Ever).
@ -32,7 +33,7 @@ pirate = "0.1.0"
and this to your crate root: and this to your crate root:
```rust ```rust
extern crate getopts; extern crate pirate;
``` ```
Usage Usage
@ -145,7 +146,7 @@ To Do
- [ ] Create a helper function for generating `--help` output, rather than having the user create it - [ ] Create a helper function for generating `--help` output, rather than having the user create it
manually. manually.
- [ ] Also create helper functions for defining the description section of the `--help` output. - [ ] Also create helper functions for defining the description section of the `--help` output.
- [ ] Refactor the `ErrorKind` enum into a struct that is able to represent more complex data (such - [x] Refactor the `ErrorKind` enum into a struct that is able to represent more complex data (such
giving the value of the invalid argument passed to the program). giving the value of the invalid argument passed to the program).
License License

View file

@ -28,34 +28,36 @@ pub struct Error {
impl Error { impl Error {
pub fn new(kind: ErrorKind, offender: String) -> Error { pub fn new(kind: ErrorKind, offender: String) -> Error {
Error { Error {
kind: kind, kind: kind.clone(),
offender: offender, offender: offender.clone(),
desc: format!("{} {}", kind.description(), offender.clone()),
} }
} }
} }
impl error::Error for Error { impl error::Error for Error {
fn description(&self) -> &str { fn description(&self) -> &str {
&format!("{} {}", self.kind.description(), self.offender); &self.desc
} }
} }
impl Display for Error { impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result { fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}", self.description()) write!(f, "{}", self.desc)
} }
} }
#[derive(Clone, Debug)]
pub enum ErrorKind { pub enum ErrorKind {
InvalidOption, InvalidOption,
MissingArgument, MissingArgument,
} }
impl ErrorKind { impl ErrorKind {
fn description(&self) -> &str { fn description(&self) -> String {
match *self { match *self {
ErrorKind::InvalidOption => "An invalid option was passed to the program:", ErrorKind::InvalidOption => String::from("An invalid option was passed to the program:"),
ErrorKind::MissingArgument => "A required argument is missing:", ErrorKind::MissingArgument => String::from("A required argument is missing:"),
} }
} }
} }

View file

@ -25,7 +25,7 @@ pub use errors::{Error, ErrorKind};
pub use matches::Matches; pub use matches::Matches;
use opts::Opts; use opts::Opts;
pub fn parse(mut args: Args, options: &[&'static str]) -> Result<Matches, ErrorKind> { pub fn parse(mut args: Args, options: &[&'static str]) -> Result<Matches, Error> {
let mut matches: Matches = Matches::new(); let mut matches: Matches = Matches::new();
let mut opts: Opts = opts(options); // Jesus, this is redundant... let mut opts: Opts = opts(options); // Jesus, this is redundant...
@ -73,7 +73,10 @@ pub fn parse(mut args: Args, options: &[&'static str]) -> Result<Matches, ErrorK
next_arg = args.next(); next_arg = args.next();
} }
Ok(matches) match opts.arg_len() {
0 => Ok(matches),
_ => Err(Error::new(ErrorKind::MissingArgument, opts.get_arg().unwrap())),
}
} }
fn opts(opts: &[&'static str]) -> Opts { fn opts(opts: &[&'static str]) -> Opts {

View file

@ -50,4 +50,8 @@ impl Opts {
pub fn get_arg(&mut self) -> Option<String> { pub fn get_arg(&mut self) -> Option<String> {
self.args.pop_front() self.args.pop_front()
} }
pub fn arg_len(&self) -> usize {
self.args.len()
}
} }

View file

@ -23,6 +23,7 @@ fn main() {
} }
let input = matches.get("input").unwrap().parse::<i32>().unwrap(); let input = matches.get("input").unwrap().parse::<i32>().unwrap();
let num = match matches.get("n") { let num = match matches.get("n") {
Some(n) => n.parse::<i32>().unwrap(), Some(n) => n.parse::<i32>().unwrap(),
None => 1 None => 1