parent
e9a72f7513
commit
0e407dc375
@ -0,0 +1,124 @@
|
||||
//! Argument parsing and handling
|
||||
use super::*;
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use config::Config;
|
||||
|
||||
/// Executable name
|
||||
pub fn program_name() -> &'static str
|
||||
{
|
||||
lazy_static! {
|
||||
static ref NAME: String = std::env::args().next().unwrap();
|
||||
}
|
||||
&NAME[..]
|
||||
}
|
||||
|
||||
#[cfg(feature="splash")]
|
||||
/// Print splash screen
|
||||
#[inline] pub fn splash()
|
||||
{
|
||||
eprintln!("dirstat version {}", env!("CARGO_PKG_VERSION"));
|
||||
eprintln!("Made by {} with <3.\n Licensed with GPL v3.0 +", env!("CARGO_PKG_AUTHORS"));
|
||||
}
|
||||
|
||||
/// Print usage message
|
||||
pub fn usage()
|
||||
{
|
||||
#[cfg(feature="splash")]
|
||||
{
|
||||
splash(); println!();
|
||||
}
|
||||
|
||||
println!("{} [OPTIONS] [-] <paths...>", program_name());
|
||||
println!("{} --help", program_name());
|
||||
println!(r#"
|
||||
OPTIONS:
|
||||
--recursive <number> Set max directory recursion depth limit (1 = No recursion (default), 0 = Unlimited recursion).
|
||||
-r Set unlimited directory recursion depth. (same as `--recursive 0`).
|
||||
--threads <number> Limit the maximum number of tasks allowed to process concurrently (Set to 0 for unlimited.)
|
||||
-M Set number of parallel running tasks to unlimited. (Same as `--threads 0`).
|
||||
-m Limit number of parallel tasks to the number of active CPU processors. (default).
|
||||
- Stop parsing arguments, treat all the rest as paths.
|
||||
|
||||
--help Print this message and exit.
|
||||
|
||||
NOTES:
|
||||
The first time a non-option argument is encountered, the program stops parsing arguments and assumes the rest of the arguments are paths.
|
||||
If parallelism is set to unlimited, there can be a huge syscall overhead. It is recommended to use `-m` (which is default anyway).
|
||||
"#);
|
||||
}
|
||||
|
||||
/// Print usage message then exit with code 1.
|
||||
pub fn help() -> !
|
||||
{
|
||||
usage();
|
||||
|
||||
std::process::exit(1)
|
||||
}
|
||||
|
||||
/// Which mode to run in
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Mode
|
||||
{
|
||||
Normal(Config),
|
||||
Help,
|
||||
}
|
||||
|
||||
/// Parse command-line arguments
|
||||
#[inline] pub fn parse_args() -> eyre::Result<Mode>
|
||||
{
|
||||
parse(std::env::args().skip(1))
|
||||
}
|
||||
|
||||
fn parse<I: IntoIterator<Item=String>>(args: I) -> eyre::Result<Mode>
|
||||
{
|
||||
let suggestion_intended_arg = || "If this was intended as a path instead of an option, use option `-` before it.";
|
||||
|
||||
let mut args = args.into_iter();
|
||||
let mut cfg = Config::default();
|
||||
|
||||
let mut reading = true;
|
||||
while let Some(opt) = args.next()
|
||||
{
|
||||
if reading {
|
||||
match opt.trim()
|
||||
{
|
||||
"--help" => return Ok(Mode::Help),
|
||||
"-" => reading = false,
|
||||
|
||||
"--threads" => {
|
||||
let max = args.next().ok_or(eyre!("`--threads` expects a parameter"))
|
||||
.with_suggestion(suggestion_intended_arg.clone())?;
|
||||
cfg.max_tasks = NonZeroUsize::new(max.parse::<usize>()
|
||||
.wrap_err(eyre!("`--threads` expects a non-negative number"))
|
||||
.with_suggestion(suggestion_intended_arg.clone())
|
||||
.with_section(move || max.header("Parameter given was"))?);
|
||||
},
|
||||
"-M" => cfg.max_tasks = None,
|
||||
"-m" => {
|
||||
cfg.max_tasks = config::max_tasks_cpus(); // this is the default, but it is possible an earlier command mutated it, so doing nothing here would be a bug for that corner case
|
||||
},
|
||||
|
||||
"--recursive" => {
|
||||
let max = args.next().ok_or(eyre!("`--recursive` expects a parameter"))
|
||||
.with_suggestion(suggestion_intended_arg.clone())?;
|
||||
|
||||
cfg.recursive = max.parse::<usize>()
|
||||
.wrap_err(eyre!("`--recursive` expects a non-negative number"))
|
||||
.with_suggestion(suggestion_intended_arg.clone())
|
||||
.with_section(move || max.header("Parameter given was"))?.into();
|
||||
},
|
||||
"-r" => cfg.recursive = config::Recursion::Unlimited,
|
||||
|
||||
_ => {
|
||||
cfg.paths.push(opt.into());
|
||||
reading = false;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
cfg.paths.push(opt.into());
|
||||
}
|
||||
}
|
||||
Ok(Mode::Normal(cfg))
|
||||
}
|
Loading…
Reference in new issue