diff options
author | Sebastian Thiel <sebastian.thiel@icloud.com> | 2020-07-02 11:02:59 +0800 |
---|---|---|
committer | Sebastian Thiel <sebastian.thiel@icloud.com> | 2020-07-02 11:02:59 +0800 |
commit | e32778b00dd38bc2053d325453ec19f498b68a29 (patch) | |
tree | b8ef1fd8a643c3599022a6a4487d3fac1e417d3e /src | |
parent | 10aecc0ce7d33afc1fdbe8ce88b1aa871f055cf8 (diff) |
Bring structopt back, argh doesn't support OsStrings
https://www.reddit.com/r/rust/comments/hjn64e/dua_28_disk_usage_analyzer_is_now_430kb_smaller/fwnjjp9?utm_source=share&utm_medium=web2x
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 26 | ||||
-rw-r--r-- | src/options.rs | 179 |
2 files changed, 74 insertions, 131 deletions
diff --git a/src/main.rs b/src/main.rs index 8104490..ebc6f6b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ use crate::interactive::{Interaction, TerminalApp}; use anyhow::{Context, Result}; use dua::{ByteFormat, Color, TraversalSorting}; use std::{fs, io, io::Write, path::PathBuf, process}; +use structopt::StructOpt; use termion::{raw::IntoRawMode, screen::AlternateScreen}; use tui::backend::TermionBackend; use tui_react::Terminal; @@ -12,9 +13,9 @@ mod interactive; mod options; fn main() -> Result<()> { - use options::*; + use options::Command::*; - let opt: options::Args = argh::from_env(); + let opt: options::Args = options::Args::from_args(); let walk_options = dua::WalkOptions { threads: opt.threads.unwrap_or(0), byte_format: opt.format.map(Into::into).unwrap_or(ByteFormat::Metric), @@ -29,8 +30,7 @@ fn main() -> Result<()> { cross_filesystems: !opt.stay_on_filesystem, }; let res = match opt.command { - Some(Command::Interactive(Interactive { input })) - | Some(Command::InteractiveAlias(InteractiveAlias { input })) => { + Some(Interactive { input }) => { let mut terminal = { let stdout = io::stdout() .into_raw_mode() @@ -59,29 +59,23 @@ fn main() -> Result<()> { // Exit 'quickly' to avoid having to not have to deal with slightly different types in the other match branches std::process::exit(res.transpose()?.map(|e| e.to_exit_code()).unwrap_or(0)); } - Some(Command::Aggregate(Aggregate { + Some(Aggregate { input, no_total, no_sort, - stats, - })) - | Some(Command::AggregateAlias(AggregateAlias { - input, - no_total, - no_sort, - stats, - })) => { + statistics, + }) => { let stdout = io::stdout(); let stdout_locked = stdout.lock(); - let (res, statistics) = dua::aggregate( + let (res, stats) = dua::aggregate( stdout_locked, walk_options, !no_total, !no_sort, paths_from(input)?, )?; - if stats { - writeln!(io::stderr(), "{:?}", statistics).ok(); + if statistics { + writeln!(io::stderr(), "{:?}", stats).ok(); } res } diff --git a/src/options.rs b/src/options.rs index 219afe0..5b9d604 100644 --- a/src/options.rs +++ b/src/options.rs @@ -1,63 +1,47 @@ +use dua::ByteFormat as LibraryByteFormat; use std::path::PathBuf; - -use argh::{FromArgValue, FromArgs}; -use dua::ByteFormat; - -pub enum CliByteFormat { - Metric, - Binary, - Bytes, - GB, - GiB, - MB, - MiB, -} - -impl FromArgValue for CliByteFormat { - fn from_arg_value(value: &str) -> Result<Self, String> { - use CliByteFormat::*; - let value_lc = value.to_ascii_lowercase(); - Ok(match value_lc.as_str() { - "metric" => Metric, - "binary" => Binary, - "bytes" => Bytes, - "gb" => GB, - "gib" => GiB, - "mb" => MB, - "mib" => MiB, - _ => return Err(format!("Invalid byte format: {}", value)), - }) +use structopt::{clap::arg_enum, StructOpt}; + +arg_enum! { + #[derive(PartialEq, Debug)] + pub enum ByteFormat { + Metric, + Binary, + Bytes, + GB, + GiB, + MB, + MiB } } -impl From<CliByteFormat> for ByteFormat { - fn from(input: CliByteFormat) -> Self { - use CliByteFormat::*; +impl From<ByteFormat> for LibraryByteFormat { + fn from(input: ByteFormat) -> Self { match input { - Metric => ByteFormat::Metric, - Binary => ByteFormat::Binary, - Bytes => ByteFormat::Bytes, - GB => ByteFormat::GB, - GiB => ByteFormat::GiB, - MB => ByteFormat::MB, - MiB => ByteFormat::MiB, + ByteFormat::Metric => LibraryByteFormat::Metric, + ByteFormat::Binary => LibraryByteFormat::Binary, + ByteFormat::Bytes => LibraryByteFormat::Bytes, + ByteFormat::GB => LibraryByteFormat::GB, + ByteFormat::GiB => LibraryByteFormat::GiB, + ByteFormat::MB => LibraryByteFormat::MB, + ByteFormat::MiB => LibraryByteFormat::MiB, } } } -/// a tool to learn about disk usage, fast! -#[derive(FromArgs)] -#[argh(name = "dua")] +#[derive(Debug, StructOpt)] +#[structopt(name = "dua", about = "A tool to learn about disk usage, fast!")] +#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)] pub struct Args { - #[argh(subcommand)] + #[structopt(subcommand)] pub command: Option<Command>, - /// the amount of threads to use. Defaults to the amount of logical processors. + /// The amount of threads to use. Defaults to the amount of logical processors. /// Set to 1 to use only a single thread. - #[argh(option, short = 't')] + #[structopt(short = "t", long = "threads")] pub threads: Option<usize>, - /// the format with which to print byte counts. + /// The format with which to print byte counts. /// Metric - uses 1000 as base (default) /// Binary - uses 1024 as base /// Bytes - plain bytes without any formatting @@ -65,85 +49,50 @@ pub struct Args { /// GiB - only gibibytes /// MB - only megabytes /// MiB - only mebibytes - #[argh(option, short = 'f')] - pub format: Option<CliByteFormat>, + #[structopt(short = "f", long)] + pub format: Option<ByteFormat>, - /// display apparent size instead of disk usage. - #[argh(switch, short = 'A')] + /// Display apparent size instead of disk usage. + #[structopt(short = "A", long)] pub apparent_size: bool, - /// count hard-linked files each time they are seen - #[argh(switch, short = 'l')] + /// Count hard-linked files each time they are seen + #[structopt(short = "l", long)] pub count_hard_links: bool, - /// if set, we will not cross filesystems or traverse mount points - #[argh(switch, short = 'x')] + /// If set, we will not cross filesystems or traverse mount points + #[structopt(short = "x", long)] pub stay_on_filesystem: bool, - /// one or more input files or directories. If unset, we will use all entries in the current working directory. - #[argh(positional)] + /// One or more input files or directories. If unset, we will use all entries in the current working directory. + #[structopt(parse(from_os_str))] pub input: Vec<PathBuf>, } -#[derive(FromArgs)] -#[argh(subcommand)] +#[derive(Debug, StructOpt)] pub enum Command { - Interactive(Interactive), - InteractiveAlias(InteractiveAlias), - Aggregate(Aggregate), - AggregateAlias(AggregateAlias), -} - -/// Launch the terminal user interface -#[derive(FromArgs)] -#[argh(subcommand, name = "interactive")] -pub struct Interactive { - /// one or more input files or directories. If unset, we will use all entries in the current working directory. - #[argh(positional)] - pub input: Vec<PathBuf>, -} - -/// Alias for 'interactive' -#[derive(FromArgs)] -#[argh(subcommand, name = "i")] -pub struct InteractiveAlias { - #[argh(positional)] - pub input: Vec<PathBuf>, -} - -/// Aggregate the consumed space of one or more directories or files -#[derive(FromArgs)] -#[argh(subcommand, name = "aggregate")] -pub struct Aggregate { - /// if set, print additional statistics about the file traversal to stderr - #[argh(switch)] - pub stats: bool, - /// if set, paths will be printed in their order of occurrence on the command-line. - /// Otherwise they are sorted by their size in bytes, ascending. - #[argh(switch)] - pub no_sort: bool, - /// if set, no total column will be computed for multiple inputs - #[argh(switch)] - pub no_total: bool, - /// one or more input files or directories. If unset, we will use all entries in the current working directory. - #[argh(positional)] - pub input: Vec<PathBuf>, -} - -/// An alias for "aggregate" -#[derive(FromArgs)] -#[argh(subcommand, name = "a")] -pub struct AggregateAlias { - /// see `dua aggregate --help` - #[argh(switch)] - pub stats: bool, - /// see `dua aggregate --help` - #[argh(switch)] - pub no_sort: bool, - /// see `dua aggregate --help` - #[argh(switch)] - pub no_total: bool, - /// see `dua aggregate --help` - #[argh(positional)] - pub input: Vec<PathBuf>, + /// Launch the terminal user interface + #[structopt(name = "interactive", alias = "i")] + Interactive { + /// One or more input files or directories. If unset, we will use all entries in the current working directory. + #[structopt(parse(from_os_str))] + input: Vec<PathBuf>, + }, + /// Aggregrate the consumed space of one or more directories or files + #[structopt(name = "aggregate", alias = "a")] + Aggregate { + /// If set, print additional statistics about the file traversal to stderr + #[structopt(long = "stats")] + statistics: bool, + /// If set, paths will be printed in their order of occurrence on the command-line. + /// Otherwise they are sorted by their size in bytes, ascending. + #[structopt(long)] + no_sort: bool, + /// If set, no total column will be computed for multiple inputs + #[structopt(long)] + no_total: bool, + /// One or more input files or directories. If unset, we will use all entries in the current working directory. + #[structopt(parse(from_os_str))] + input: Vec<PathBuf>, + }, } |