diff options
-rw-r--r-- | src/uu/ls/src/ls.rs | 61 | ||||
-rw-r--r-- | tests/by-util/test_ls.rs | 99 |
2 files changed, 128 insertions, 32 deletions
diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 65e0969cb..0221ae096 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -6,7 +6,7 @@ // spell-checker:ignore (ToDO) somegroup nlink tabsize dired subdired dtype colorterm stringly use clap::{ - builder::{NonEmptyStringValueParser, ValueParser}, + builder::{NonEmptyStringValueParser, PossibleValue, ValueParser}, crate_version, Arg, ArgAction, Command, }; use glob::{MatchOptions, Pattern}; @@ -62,6 +62,7 @@ use uucore::{ format_usage, fs::display_permissions, parse_size::parse_size_u64, + shortcut_value_parser::ShortcutValueParser, version_cmp::version_cmp, }; use uucore::{help_about, help_section, help_usage, parse_glob, show, show_error, show_warning}; @@ -1203,7 +1204,7 @@ pub fn uu_app() -> Command { Arg::new(options::FORMAT) .long(options::FORMAT) .help("Set the display format.") - .value_parser([ + .value_parser(ShortcutValueParser::new([ "long", "verbose", "single-column", @@ -1212,7 +1213,7 @@ pub fn uu_app() -> Command { "across", "horizontal", "commas", - ]) + ])) .hide_possible_values(true) .require_equals(true) .overrides_with_all([ @@ -1303,9 +1304,11 @@ pub fn uu_app() -> Command { Arg::new(options::HYPERLINK) .long(options::HYPERLINK) .help("hyperlink file names WHEN") - .value_parser([ - "always", "yes", "force", "auto", "tty", "if-tty", "never", "no", "none", - ]) + .value_parser(ShortcutValueParser::new([ + PossibleValue::new("always").alias("yes").alias("force"), + PossibleValue::new("auto").alias("tty").alias("if-tty"), + PossibleValue::new("never").alias("no").alias("none"), + ])) .require_equals(true) .num_args(0..=1) .default_missing_value("always") @@ -1351,15 +1354,15 @@ pub fn uu_app() -> Command { Arg::new(options::QUOTING_STYLE) .long(options::QUOTING_STYLE) .help("Set quoting style.") - .value_parser([ - "literal", - "shell", - "shell-always", - "shell-escape", - "shell-escape-always", - "c", - "escape", - ]) + .value_parser(ShortcutValueParser::new([ + PossibleValue::new("literal"), + PossibleValue::new("shell"), + PossibleValue::new("shell-escape"), + PossibleValue::new("shell-always"), + PossibleValue::new("shell-escape-always"), + PossibleValue::new("c").alias("c-maybe"), + PossibleValue::new("escape"), + ])) .overrides_with_all([ options::QUOTING_STYLE, options::quoting::LITERAL, @@ -1434,9 +1437,11 @@ pub fn uu_app() -> Command { \tbirth time: birth, creation;", ) .value_name("field") - .value_parser([ - "atime", "access", "use", "ctime", "status", "birth", "creation", - ]) + .value_parser(ShortcutValueParser::new([ + PossibleValue::new("atime").alias("access").alias("use"), + PossibleValue::new("ctime").alias("status"), + PossibleValue::new("birth").alias("creation"), + ])) .hide_possible_values(true) .require_equals(true) .overrides_with_all([options::TIME, options::time::ACCESS, options::time::CHANGE]), @@ -1496,7 +1501,7 @@ pub fn uu_app() -> Command { .long(options::SORT) .help("Sort by <field>: name, none (-U), time (-t), size (-S), extension (-X) or width") .value_name("field") - .value_parser(["name", "none", "time", "size", "version", "extension", "width"]) + .value_parser(ShortcutValueParser::new(["name", "none", "time", "size", "version", "extension", "width"])) .require_equals(true) .overrides_with_all([ options::SORT, @@ -1744,9 +1749,11 @@ pub fn uu_app() -> Command { Arg::new(options::COLOR) .long(options::COLOR) .help("Color output based on file type.") - .value_parser([ - "always", "yes", "force", "auto", "tty", "if-tty", "never", "no", "none", - ]) + .value_parser(ShortcutValueParser::new([ + PossibleValue::new("always").alias("yes").alias("force"), + PossibleValue::new("auto").alias("tty").alias("if-tty"), + PossibleValue::new("never").alias("no").alias("none"), + ])) .require_equals(true) .num_args(0..=1), ) @@ -1757,7 +1764,7 @@ pub fn uu_app() -> Command { "Append indicator with style WORD to entry names: \ none (default), slash (-p), file-type (--file-type), classify (-F)", ) - .value_parser(["none", "slash", "file-type", "classify"]) + .value_parser(ShortcutValueParser::new(["none", "slash", "file-type", "classify"])) .overrides_with_all([ options::indicator_style::FILE_TYPE, options::indicator_style::SLASH, @@ -1788,9 +1795,11 @@ pub fn uu_app() -> Command { --dereference-command-line-symlink-to-dir options are specified.", ) .value_name("when") - .value_parser([ - "always", "yes", "force", "auto", "tty", "if-tty", "never", "no", "none", - ]) + .value_parser(ShortcutValueParser::new([ + PossibleValue::new("always").alias("yes").alias("force"), + PossibleValue::new("auto").alias("tty").alias("if-tty"), + PossibleValue::new("never").alias("no").alias("none"), + ])) .default_missing_value("always") .require_equals(true) .num_args(0..=1) diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 2f48e4460..099f18fb8 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -27,6 +27,7 @@ const LONG_ARGS: &[&str] = &[ "-l", "--long", "--format=long", + "--format=lon", "--for=long", "--format=verbose", "--for=verbose", @@ -35,6 +36,7 @@ const LONG_ARGS: &[&str] = &[ const ACROSS_ARGS: &[&str] = &[ "-x", "--format=across", + "--format=acr", "--format=horizontal", "--for=across", "--for=horizontal", @@ -999,6 +1001,8 @@ fn test_ls_zero() { let ignored_opts = [ "--quoting-style=c", "--color=always", + "--color=alway", + "--color=al", "-m", "--hide-control-chars", ]; @@ -1603,6 +1607,24 @@ fn test_ls_deref() { let result = scene .ucmd() + .arg("-l") + .arg("--color=neve") // spell-checker:disable-line + .arg("test-long") + .arg("test-long.link") + .succeeds(); + assert!(re.is_match(result.stdout_str().trim())); + + let result = scene + .ucmd() + .arg("-l") + .arg("--color=n") + .arg("test-long") + .arg("test-long.link") + .succeeds(); + assert!(re.is_match(result.stdout_str().trim())); + + let result = scene + .ucmd() .arg("-L") .arg("--color=never") .arg("test-long") @@ -1676,6 +1698,10 @@ fn test_ls_sort_none() { // Order is not specified so we just check that it doesn't // give any errors. scene.ucmd().arg("--sort=none").succeeds(); + scene.ucmd().arg("--sort=non").succeeds(); + scene.ucmd().arg("--sort=no").succeeds(); + // scene.ucmd().arg("--sort=n").succeeds(); + // We refuse to accept "--sort=n", since this is too confusable with "--sort=name", which is our own extension. scene.ucmd().arg("-U").succeeds(); } @@ -1693,6 +1719,16 @@ fn test_ls_sort_name() { .arg("--sort=name") .succeeds() .stdout_is("test-1\ntest-2\ntest-3\n"); + scene + .ucmd() + .arg("--sort=nam") + .succeeds() + .stdout_is("test-1\ntest-2\ntest-3\n"); + scene + .ucmd() + .arg("--sort=na") + .succeeds() + .stdout_is("test-1\ntest-2\ntest-3\n"); let scene_dot = TestScenario::new(util_name!()); let at = &scene_dot.fixtures; @@ -1729,6 +1765,16 @@ fn test_ls_sort_width() { .arg("--sort=width") .succeeds() .stdout_is("d\nzz\nabc\nbbb\neee\ncccc\naaaaa\nbcdef\nfffff\n"); + scene + .ucmd() + .arg("--sort=widt") // spell-checker:disable-line + .succeeds() + .stdout_is("d\nzz\nabc\nbbb\neee\ncccc\naaaaa\nbcdef\nfffff\n"); + scene + .ucmd() + .arg("--sort=w") + .succeeds() + .stdout_is("d\nzz\nabc\nbbb\neee\ncccc\naaaaa\nbcdef\nfffff\n"); } #[test] @@ -1757,6 +1803,12 @@ fn test_ls_order_size() { let result = scene.ucmd().arg("--sort=size").succeeds(); result.stdout_only("test-4\ntest-3\ntest-2\ntest-1\n"); + let result = scene.ucmd().arg("--sort=siz").succeeds(); + result.stdout_only("test-4\ntest-3\ntest-2\ntest-1\n"); + + let result = scene.ucmd().arg("--sort=s").succeeds(); + result.stdout_only("test-4\ntest-3\ntest-2\ntest-1\n"); + let result = scene.ucmd().arg("--sort=size").arg("-r").succeeds(); result.stdout_only("test-1\ntest-2\ntest-3\ntest-4\n"); } @@ -1961,7 +2013,14 @@ fn test_ls_order_time() { // 3 was accessed last in the read // So the order should be 2 3 4 1 - for arg in ["-u", "--time=atime", "--time=access", "--time=use"] { + for arg in [ + "-u", + "--time=atime", + "--time=atim", // spell-checker:disable-line + "--time=a", + "--time=access", + "--time=use", + ] { let result = scene.ucmd().arg("-t").arg(arg).succeeds(); at.open("test-3").metadata().unwrap().accessed().unwrap(); at.open("test-4").metadata().unwrap().accessed().unwrap(); @@ -2216,12 +2275,16 @@ fn test_ls_indicator_style() { for opt in [ "--indicator-style=classify", "--ind=classify", + "--indicator-style=clas", // spell-checker:disable-line + "--indicator-style=c", "--indicator-style=file-type", "--ind=file-type", "--indicator-style=slash", "--ind=slash", "--classify", "--classify=always", + "--classify=alway", // spell-checker:disable-line + "--classify=al", "--classify=yes", "--classify=force", "--class", @@ -2236,10 +2299,13 @@ fn test_ls_indicator_style() { // Classify, Indicator options should not contain any indicators when value is none. for opt in [ "--indicator-style=none", + "--indicator-style=n", "--ind=none", "--classify=none", "--classify=never", + "--classify=non", "--classify=no", + "--classify=n", ] { // Verify that there are no indicators for any of the file types. scene @@ -2553,6 +2619,12 @@ fn test_ls_version_sort() { expected ); + let result = scene.ucmd().arg("-1").arg("--sort=v").succeeds(); + assert_eq!( + result.stdout_str().split('\n').collect::<Vec<_>>(), + expected + ); + let result = scene.ucmd().arg("-a1v").succeeds(); expected.insert(expected.len() - 1, ".."); expected.insert(0, "."); @@ -2589,19 +2661,27 @@ fn test_ls_quoting_style() { for (arg, correct) in [ ("--quoting-style=literal", "one?two"), + ("--quoting-style=litera", "one?two"), // spell-checker:disable-line + ("--quoting-style=li", "one?two"), ("-N", "one?two"), ("--literal", "one?two"), ("--l", "one?two"), ("--quoting-style=c", "\"one\\ntwo\""), + ("--quoting-style=c-", "\"one\\ntwo\""), + ("--quoting-style=c-maybe", "\"one\\ntwo\""), ("-Q", "\"one\\ntwo\""), ("--quote-name", "\"one\\ntwo\""), ("--quoting-style=escape", "one\\ntwo"), + ("--quoting-style=escap", "one\\ntwo"), // spell-checker:disable-line ("-b", "one\\ntwo"), ("--escape", "one\\ntwo"), ("--quoting-style=shell-escape", "'one'$'\\n''two'"), ("--quoting-style=shell-escape-always", "'one'$'\\n''two'"), + ("--quoting-style=shell-escape-alway", "'one'$'\\n''two'"), + ("--quoting-style=shell-escape-a", "'one'$'\\n''two'"), ("--quoting-style=shell", "one?two"), ("--quoting-style=shell-always", "'one?two'"), + ("--quoting-style=shell-a", "'one?two'"), ] { scene .ucmd() @@ -4244,11 +4324,18 @@ fn test_ls_hyperlink() { .stdout_str() .contains(&format!("{path}{separator}{file}\x07{file}\x1b]8;;\x07"))); - scene - .ucmd() - .arg("--hyperlink=never") - .succeeds() - .stdout_is(format!("{file}\n")); + for argument in [ + "--hyperlink=never", + "--hyperlink=neve", // spell-checker:disable-line + "--hyperlink=ne", // spell-checker:disable-line + "--hyperlink=n", + ] { + scene + .ucmd() + .arg(argument) + .succeeds() + .stdout_is(format!("{file}\n")); + } } // spell-checker: disable |