use super::*; use std::{ num::{ NonZeroUsize, ParseIntError, }, }; use lazy_static::lazy_static; #[inline] pub fn program_name() -> &'static str { lazy_static!{ static ref PROG: &'static str = Box::leak(std::env::args().next().unwrap().into_boxed_str()); } &PROG[..] } pub fn usage() -> ! { #[cfg(feature="splash")] splash::print(); println!(r"Usage: {prog} [--max-children ] [-] Usage: {prog} --help OPTIONS: --max-children Max subprocesses allowed to live at once. Infinite by default. ENVIRONMENT VARS: LEANIFY= Path to leanify executable, defaults to looking in `PATH' if set.", prog = program_name()); std::process::exit(1) } #[derive(Debug)] pub enum Error { #[cfg(nightly)] BadNumber(std::num::IntErrorKind), #[cfg(not(nightly))] BadNumber(()), NoFiles, } impl std::error::Error for Error{} impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { //write!(f, "arg parsing failed: ")?; match self { Self::BadNumber(_v) => { write!(f, "expected non-zero integer")?; #[cfg(nightly)] use std::num::IntErrorKind; #[cfg(nightly)] return match _v { IntErrorKind::Empty => write!(f, ": argument empty"), IntErrorKind::InvalidDigit => write!(f, ": invalid digit"), IntErrorKind::Overflow => write!(f, ": conversion would result in overflow"), IntErrorKind::Underflow => write!(f, ": conversion would result in underflow"), IntErrorKind::Zero => write!(f, ": found zero"), _=> Ok(()), }; #[cfg(not(nightly))] Ok(()) }, Self::NoFiles => write!(f, "need at least one argument") } } } impl From for Error { fn from(_er: ParseIntError) -> Self { #[cfg(nightly)] return Self::BadNumber(_er.kind().clone()); #[cfg(not(nightly))] Self::BadNumber } } #[derive(Debug, Clone, PartialEq, Eq)] pub struct Config { pub max_children: Option, pub files: Vec, } impl Default for Config { #[inline] fn default() -> Self { Self { max_children: None, files: Vec::new(), } } } /// Parse the `env::args()` #[inline] pub fn parse_args() -> Result { let args = std::env::args(); if args.len() <= 1 { println!("Warning: No arguments specified, try passing `--help`."); } parse(args.skip(1)) } fn parse(args: I) -> Result where I: IntoIterator, T: Into { let mut args = args.into_iter().map(|x| x.into()); let mut cfg = Config::default(); let mut reading=true; let mut first=true; while let Some(arg) = args.next() { if reading { let lw_arg = arg.trim().to_lowercase(); if first { match lw_arg.as_str() { "--help" => { usage() }, _ => (), } } first=false; match lw_arg.as_str() { "--max-children" => { if let Some(nzi) = args.next() { cfg.max_children = Some(nzi.parse()?); continue; } } "-" => { reading= false; continue; }, _ => (), } } reading = false; cfg.files.push(arg); } if cfg.files.len() == 0 { return Err(Error::NoFiles); } Ok(cfg) }