You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
3.2 KiB
149 lines
3.2 KiB
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 <number>] [-] <files...>
|
|
Usage: {prog} --help
|
|
|
|
OPTIONS:
|
|
--max-children <number> Max subprocesses allowed to live at once. Infinite by default.
|
|
|
|
ENVIRONMENT VARS:
|
|
LEANIFY=<process name> 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<ParseIntError> 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<NonZeroUsize>,
|
|
pub files: Vec<String>,
|
|
}
|
|
|
|
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<Config, Error>
|
|
{
|
|
let args = std::env::args();
|
|
if args.len() <= 1 {
|
|
println!("Warning: No arguments specified, try passing `--help`.");
|
|
}
|
|
parse(args.skip(1))
|
|
}
|
|
|
|
fn parse<I,T>(args: I) -> Result<Config, Error>
|
|
where I: IntoIterator<Item=T>,
|
|
T: Into<String>
|
|
{
|
|
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)
|
|
}
|