diff --git a/Cargo.lock b/Cargo.lock index 9f4bd4f..9da5444 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,15 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - [[package]] name = "ansi_term" version = "0.12.1" @@ -121,18 +112,36 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.4" +version = "3.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826bf7bc84f9435630275cb8e802a4a0ec792b615969934bd16d42ffed10f207" +checksum = "29e724a68d9319343bb3328c9cc2dfde263f4b3142ee1059a9980580171c954b" dependencies = [ - "ansi_term 0.11.0", "atty", "bitflags", + "clap_lex", + "indexmap", "strsim", - "term_size", + "termcolor", + "terminal_size", "textwrap", - "unicode-width", - "vec_map", +] + +[[package]] +name = "clap_complete" +version = "3.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4179da71abd56c26b54dd0c248cc081c1f43b0a1a7e8448e28e57a29baa993d" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", ] [[package]] @@ -400,7 +409,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e9323b3525d4efad2dead1837a105e313253bfdbad1d470994038eededa4d62" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", ] [[package]] @@ -412,6 +421,7 @@ dependencies = [ "chrono", "chrono-humanize", "clap", + "clap_complete", "crossterm", "dirs", "globset", @@ -491,6 +501,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + [[package]] name = "parking_lot" version = "0.11.2" @@ -768,9 +784,9 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -807,13 +823,12 @@ dependencies = [ ] [[package]] -name = "term_size" -version = "0.3.2" +name = "termcolor" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ - "libc", - "winapi", + "winapi-util", ] [[package]] @@ -834,12 +849,11 @@ checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" [[package]] name = "textwrap" -version = "0.11.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" dependencies = [ - "term_size", - "unicode-width", + "terminal_size", ] [[package]] @@ -944,12 +958,6 @@ dependencies = [ "log", ] -[[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.4" diff --git a/Cargo.toml b/Cargo.toml index 8fc29e8..29780ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,8 @@ name = "lsd" path = "src/main.rs" [build-dependencies] -clap = "2.33.*" +clap = "3.2.17" +clap_complete = "3.2.4" version_check = "0.9.*" [dependencies] @@ -47,7 +48,7 @@ winapi = {version = "0.3.*", features = ["aclapi", "accctrl", "winnt", "winerror [dependencies.clap] features = ["suggestions", "color", "wrap_help"] -version = "2.33.*" +version = "3.2.17" [dev-dependencies] assert_cmd = "1" diff --git a/build.rs b/build.rs index a6bd7d6..918f457 100644 --- a/build.rs +++ b/build.rs @@ -6,11 +6,11 @@ // notice may not be copied, modified, or distributed except // according to those terms. -#[macro_use] extern crate clap; extern crate version_check; -use clap::Shell; +use clap_complete::generate_to; +use clap_complete::shells::*; use std::fs; use std::process::exit; @@ -30,8 +30,10 @@ fn main() { fs::create_dir_all(&outdir).unwrap(); let mut app = build(); - app.gen_completions("lsd", Shell::Bash, &outdir); - app.gen_completions("lsd", Shell::Fish, &outdir); - app.gen_completions("lsd", Shell::Zsh, &outdir); - app.gen_completions("lsd", Shell::PowerShell, &outdir); + let bin_name = "lsd"; + generate_to(Bash, &mut app, bin_name, &outdir).expect("Failed to generate Bash completions"); + generate_to(Fish, &mut app, bin_name, &outdir).expect("Failed to generate Fish completions"); + generate_to(Zsh, &mut app, bin_name, &outdir).expect("Failed to generate Zsh completions"); + generate_to(PowerShell, &mut app, bin_name, &outdir) + .expect("Failed to generate PowerShell completions"); } diff --git a/src/app.rs b/src/app.rs index 4755083..b6978cd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,24 +1,24 @@ use clap::{App, Arg}; -pub fn build() -> App<'static, 'static> { +pub fn build() -> App<'static> { App::new("lsd") - .version(crate_version!()) - .about(crate_description!()) + .version(env!("CARGO_PKG_VERSION")) + .about(env!("CARGO_PKG_DESCRIPTION")) .arg(Arg::with_name("FILE").multiple(true).default_value(".")) .arg( Arg::with_name("all") - .short("a") + .short('a') .overrides_with("almost-all") .long("all") - .multiple(true) + .multiple_occurrences(true) .help("Do not ignore entries starting with ."), ) .arg( Arg::with_name("almost-all") - .short("A") + .short('A') .overrides_with("all") .long("almost-all") - .multiple(true) + .multiple_occurrences(true) .help("Do not list implied . and .."), ) .arg( @@ -28,7 +28,8 @@ pub fn build() -> App<'static, 'static> { .possible_value("auto") .possible_value("never") .default_value("auto") - .multiple(true) + .multiple_occurrences(true) + .takes_value(true) .number_of_values(1) .help("When to use terminal colours"), ) @@ -39,7 +40,8 @@ pub fn build() -> App<'static, 'static> { .possible_value("auto") .possible_value("never") .default_value("auto") - .multiple(true) + .multiple_occurrences(true) + .takes_value(true) .number_of_values(1) .help("When to print the icons"), ) @@ -49,22 +51,23 @@ pub fn build() -> App<'static, 'static> { .possible_value("fancy") .possible_value("unicode") .default_value("fancy") - .multiple(true) + .multiple_occurrences(true) + .takes_value(true) .number_of_values(1) .help("Whether to use fancy or unicode icons"), ) .arg( Arg::with_name("indicators") - .short("F") + .short('F') .long("classify") - .multiple(true) + .multiple_occurrences(true) .help("Append indicator (one of */=>@|) at the end of the file names"), ) .arg( Arg::with_name("long") - .short("l") + .short('l') .long("long") - .multiple(true) + .multiple_occurrences(true) .help("Display extended file metadata as a table"), ) .arg( @@ -81,44 +84,44 @@ pub fn build() -> App<'static, 'static> { ) .arg( Arg::with_name("oneline") - .short("1") + .short('1') .long("oneline") - .multiple(true) + .multiple_occurrences(true) .help("Display one entry per line"), ) .arg( Arg::with_name("recursive") - .short("R") + .short('R') .long("recursive") - .multiple(true) + .multiple_occurrences(true) .conflicts_with("tree") .help("Recurse into directories"), ) .arg( Arg::with_name("human_readable") - .short("h") + .short('h') .long("human-readable") - .multiple(true) + .multiple_occurrences(true) .help("For ls compatibility purposes ONLY, currently set by default"), ) .arg( Arg::with_name("tree") .long("tree") - .multiple(true) + .multiple_occurrences(true) .conflicts_with("recursive") .help("Recurse into directories and present the result as a tree"), ) .arg( Arg::with_name("depth") .long("depth") - .multiple(true) + .multiple_occurrences(true) .takes_value(true) .value_name("num") .help("Stop recursing into directories after reaching specified depth"), ) .arg( Arg::with_name("directory-only") - .short("d") + .short('d') .long("directory-only") .conflicts_with("depth") .conflicts_with("recursive") @@ -130,7 +133,8 @@ pub fn build() -> App<'static, 'static> { .default_value("rwx") .possible_value("rwx") .possible_value("octal") - .multiple(true) + .multiple_occurrences(true) + .takes_value(true) .number_of_values(1) .help("How to display permissions"), ) @@ -141,14 +145,15 @@ pub fn build() -> App<'static, 'static> { .possible_value("short") .possible_value("bytes") .default_value("default") - .multiple(true) + .multiple_occurrences(true) + .takes_value(true) .number_of_values(1) .help("How to display size"), ) .arg( Arg::with_name("total-size") .long("total-size") - .multiple(true) + .multiple_occurrences(true) .help("Display the total size of directories"), ) .arg( @@ -156,51 +161,52 @@ pub fn build() -> App<'static, 'static> { .long("date") .validator(validate_date_argument) .default_value("date") - .multiple(true) + .multiple_occurrences(true) + .takes_value(true) .number_of_values(1) .help("How to display date [possible values: date, relative, +date-time-format]"), ) .arg( Arg::with_name("timesort") - .short("t") + .short('t') .long("timesort") .overrides_with("sizesort") .overrides_with("extensionsort") .overrides_with("versionsort") .overrides_with("sort") .overrides_with("no-sort") - .multiple(true) + .multiple_occurrences(true) .help("Sort by time modified"), ) .arg( Arg::with_name("sizesort") - .short("S") + .short('S') .long("sizesort") .overrides_with("timesort") .overrides_with("extensionsort") .overrides_with("versionsort") .overrides_with("sort") .overrides_with("no-sort") - .multiple(true) + .multiple_occurrences(true) .help("Sort by size"), ) .arg( Arg::with_name("extensionsort") - .short("X") + .short('X') .long("extensionsort") .overrides_with("sizesort") .overrides_with("timesort") .overrides_with("versionsort") .overrides_with("sort") .overrides_with("no-sort") - .multiple(true) + .multiple_occurrences(true) .help("Sort by file extension"), ) .arg( Arg::with_name("versionsort") - .short("v") + .short('v') .long("versionsort") - .multiple(true) + .multiple_occurrences(true) .overrides_with("timesort") .overrides_with("sizesort") .overrides_with("extensionsort") @@ -211,7 +217,7 @@ pub fn build() -> App<'static, 'static> { .arg( Arg::with_name("sort") .long("sort") - .multiple(true) + .multiple_occurrences(true) .possible_values(&["size", "time", "version", "extension", "none"]) .takes_value(true) .value_name("WORD") @@ -224,9 +230,9 @@ pub fn build() -> App<'static, 'static> { ) .arg( Arg::with_name("no-sort") - .short("U") + .short('U') .long("no-sort") - .multiple(true) + .multiple_occurrences(true) .overrides_with("timesort") .overrides_with("sizesort") .overrides_with("extensionsort") @@ -236,9 +242,9 @@ pub fn build() -> App<'static, 'static> { ) .arg( Arg::with_name("reverse") - .short("r") + .short('r') .long("reverse") - .multiple(true) + .multiple_occurrences(true) .help("Reverse the order of the sort"), ) .arg( @@ -247,7 +253,7 @@ pub fn build() -> App<'static, 'static> { .possible_value("none") .possible_value("first") .possible_value("last") - .multiple(true) + .multiple_occurrences(true) .number_of_values(1) .help("Sort the directories then the files"), ) @@ -259,8 +265,10 @@ pub fn build() -> App<'static, 'static> { .arg( Arg::with_name("blocks") .long("blocks") - .multiple(true) - .number_of_values(1) + .multiple_occurrences(true) + .multiple_values(true) + .takes_value(true) + .use_value_delimiter(true) .require_delimiter(true) .possible_values(&[ "permission", @@ -283,14 +291,14 @@ pub fn build() -> App<'static, 'static> { .arg( Arg::with_name("no-symlink") .long("no-symlink") - .multiple(true) + .multiple_occurrences(true) .help("Do not display symlink target"), ) .arg( Arg::with_name("ignore-glob") - .short("I") + .short('I') .long("ignore-glob") - .multiple(true) + .multiple_occurrences(true) .number_of_values(1) .value_name("pattern") .default_value("") @@ -298,21 +306,21 @@ pub fn build() -> App<'static, 'static> { ) .arg( Arg::with_name("inode") - .short("i") + .short('i') .long("inode") - .multiple(true) + .multiple_occurrences(true) .help("Display the index number of each file"), ) .arg( Arg::with_name("dereference") - .short("L") + .short('L') .long("dereference") - .multiple(true) + .multiple_occurrences(true) .help("When showing file information for a symbolic link, show information for the file the link references rather than for the link itself"), ) .arg( Arg::with_name("context") - .short("Z") + .short('Z') .long("context") .required(false) .takes_value(false) @@ -325,7 +333,8 @@ pub fn build() -> App<'static, 'static> { .possible_value("auto") .possible_value("never") .default_value("never") - .multiple(true) + .multiple_occurrences(true) + .takes_value(true) .number_of_values(1) .help("Attach hyperlink to filenames"), ) @@ -336,7 +345,7 @@ pub fn build() -> App<'static, 'static> { ) } -fn validate_date_argument(arg: String) -> Result<(), String> { +fn validate_date_argument(arg: &str) -> Result<(), String> { if arg.starts_with('+') { validate_time_format(&arg) } else if arg == "date" || arg == "relative" { diff --git a/src/flags/ignore_globs.rs b/src/flags/ignore_globs.rs index 2e254c8..46c6c78 100644 --- a/src/flags/ignore_globs.rs +++ b/src/flags/ignore_globs.rs @@ -98,10 +98,7 @@ impl IgnoreGlobs { fn create_glob(pattern: &str) -> Result { match Glob::new(pattern) { Ok(glob) => Ok(glob), - Err(err) => Err(Error::with_description( - &err.to_string(), - ErrorKind::ValueValidation, - )), + Err(err) => Err(Error::raw(ErrorKind::ValueValidation, err)), } } @@ -111,10 +108,7 @@ impl IgnoreGlobs { fn create_glob_set(builder: &GlobSetBuilder) -> Result { match builder.build() { Ok(glob_set) => Ok(glob_set), - Err(err) => Err(Error::with_description( - &err.to_string(), - ErrorKind::ValueValidation, - )), + Err(err) => Err(Error::raw(ErrorKind::ValueValidation, err)), } } } diff --git a/src/flags/recursion.rs b/src/flags/recursion.rs index 3319c82..27b0311 100644 --- a/src/flags/recursion.rs +++ b/src/flags/recursion.rs @@ -106,9 +106,9 @@ impl Recursion { match str.parse::() { Ok(value) => return Some(Ok(value)), Err(_) => { - return Some(Err(Error::with_description( - "The argument '--depth' requires a valid positive number.", + return Some(Err(Error::raw( ErrorKind::ValueValidation, + "The argument '--depth' requires a valid positive number.", ))) } }