allow multiple inputs to -s and -u

rust
Avril 4 years ago
parent 39607dc97c
commit 204f511075
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -85,8 +85,15 @@ dependencies = [
"lazy_static",
"rand",
"rand_chacha",
"smallvec",
]
[[package]]
name = "smallvec"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"

@ -27,6 +27,7 @@ deferred-drop = []
cfg-if = "1.0.0"
lazy_static = "1.4.0"
rand = "0.8.3"
smallvec = "1.6.1"
[dev-dependencies]
rand_chacha = "0.3.0"

@ -1,4 +1,7 @@
use super::*;
use std::{fmt, error};
use std::path::PathBuf;
/// The executable program name
pub fn program_name() -> &'static str
@ -36,3 +39,84 @@ pub fn usage()
std::process::exit(2)
}
pub enum Mode
{
Help,
ShuffleInPlace(MaybeVec<PathBuf>),
UnshuffleInPlace(MaybeVec<PathBuf>),
}
/// Parse the `argv` of this process.
#[inline] pub fn parse_args() -> Result<Mode, Error>
{
parse(std::env::args().skip(1))
}
fn parse<I: IntoIterator<Item = String>>(args: I) -> Result<Mode, Error>
{
#[inline] fn validate_file(p: impl Into<PathBuf>) -> Result<PathBuf, Error>
{
let p = p.into();
if p.is_file()
{
Ok(p)
} else {
Err(Error::FileNotFound(p))
}
}
let mut args = args.into_iter();
let farg = args.next();
match farg
{
Some(yes) => {
match yes.trim()
{
"-h" => Ok(Mode::Help),
"-s" => {
Ok(Mode::ShuffleInPlace(
args
.map(|file| validate_file(file)).collect::<Result<MaybeVec<_>, Error>>()
.and_then(|v| if v.len() == 0 { Err(Error::InvalidUseArg("-s"))} else {Ok(v)})?))
},
"-u" => {
Ok(Mode::UnshuffleInPlace(
args
.map(|file| validate_file(file)).collect::<Result<MaybeVec<_>, Error>>()
.and_then(|v| if v.len() == 0 { Err(Error::InvalidUseArg("-u"))} else {Ok(v)})?))
},
_ => Err(Error::UnknownOpt(yes))
}
}
None => Err(Error::NoOpt),
}
}
/// Arg parsing error
#[derive(Debug)]
#[non_exhaustive]
pub enum Error
{
InvalidUseArg(&'static str),
NoOpt,
UnknownOpt(String),
FileNotFound(PathBuf),
}
impl error::Error for Error{}
impl fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::NoOpt => write!(f, "No options specified"),
Self::UnknownOpt(opt) => write!(f, "Unknown option {:?}", opt),
Self::FileNotFound(file) => write!(f, "File {:?} not found", file),
Self::InvalidUseArg(string) => write!(f, "Argument {:?} expects a parameter", string),
}
}
}

@ -4,6 +4,8 @@ use std::iter::{FusedIterator, DoubleEndedIterator};
use rand::Rng;
use crate::shuffle;
pub type MaybeVec<T> = smallvec::SmallVec<[T; 1]>;
pub trait SliceElementExt<T>
{
fn random_element<R: Rng + ?Sized>(&self, rng: &mut R) -> &T;

@ -10,9 +10,24 @@
mod shuffle;
mod arg;
use arg::Mode;
fn main() {
arg::help();
match arg::parse_args()
{
Ok(Mode::Help) => arg::usage(),
Ok(Mode::ShuffleInPlace(file)) => {
todo!()
},
Ok(Mode::UnshuffleInPlace(file)) => {
todo!()
},
Err(err) => {
eprintln!("Error: {}", err);
eprintln!("\nTry passing `-h`");
std::process::exit(1)
}
}
}
#[cfg(test)] mod test;

Loading…
Cancel
Save