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