summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Thiel <sebastian.thiel@icloud.com>2020-07-02 11:02:59 +0800
committerSebastian Thiel <sebastian.thiel@icloud.com>2020-07-02 11:02:59 +0800
commite32778b00dd38bc2053d325453ec19f498b68a29 (patch)
treeb8ef1fd8a643c3599022a6a4487d3fac1e417d3e
parent10aecc0ce7d33afc1fdbe8ce88b1aa871f055cf8 (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
-rw-r--r--Cargo.lock134
-rw-r--r--Cargo.toml2
-rw-r--r--src/main.rs26
-rw-r--r--src/options.rs179
4 files changed, 179 insertions, 162 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4caa48a..6356946 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -16,35 +16,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
[[package]]
-name = "argh"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca1877e24cecacd700d469066e0160c4f8497cc5635367163f50c8beec820154"
-dependencies = [
- "argh_derive",
- "argh_shared",
-]
-
-[[package]]
-name = "argh_derive"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e742194e0f43fc932bcb801708c2b279d3ec8f527e3acda05a6a9f342c5ef764"
-dependencies = [
- "argh_shared",
- "heck",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "argh_shared"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1ba68f4276a778591e36a0c348a269888f3a177c8d2054969389e3b59611ff5"
-
-[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -86,6 +57,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
+name = "clap"
+version = "2.33.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
name = "crossbeam"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -178,7 +164,6 @@ name = "dua-cli"
version = "2.8.1"
dependencies = [
"anyhow",
- "argh",
"atty",
"byte-unit",
"filesize",
@@ -190,6 +175,7 @@ dependencies = [
"open",
"petgraph",
"pretty_assertions",
+ "structopt",
"termion",
"tui",
"tui-react",
@@ -365,6 +351,32 @@ dependencies = [
]
[[package]]
+name = "proc-macro-error"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "syn-mid",
+ "version_check",
+]
+
+[[package]]
name = "proc-macro2"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -435,6 +447,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "structopt"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c"
+dependencies = [
+ "clap",
+ "lazy_static",
+ "structopt-derive",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "510413f9de616762a4fbeab62509bf15c729603b72d7cd71280fbca431b1c118"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "syn"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -446,6 +488,17 @@ dependencies = [
]
[[package]]
+name = "syn-mid"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "termion"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -458,6 +511,15 @@ dependencies = [
]
[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
name = "tui"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -501,6 +563,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "version_check"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
+
+[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 8117262..6f3d32f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,7 +10,7 @@ license = "MIT"
include = ["src/**/*", "Cargo.*", "LICENSE", "README.md", "CHANGELOG.md", "!**/*_test/*"]
[dependencies]
-argh = "0.1.3"
+structopt = "0.3.15"
jwalk = "0.5.0"
byte-unit = "4"
termion = "1.5.2"
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>,
+ },
}