mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
ls: update to clap 4
This commit is contained in:
parent
eadbea74d6
commit
c6cff20f18
3 changed files with 161 additions and 119 deletions
|
@ -16,7 +16,7 @@ path = "src/ls.rs"
|
|||
|
||||
[dependencies]
|
||||
chrono = { version="^0.4.19", default-features=false, features=["std", "alloc", "clock"]}
|
||||
clap = { version = "3.2", features = ["wrap_help", "cargo", "env"] }
|
||||
clap = { version = "4.0", features = ["wrap_help", "cargo", "env"] }
|
||||
unicode-width = "0.1.8"
|
||||
number_prefix = "0.4"
|
||||
term_grid = "0.1.5"
|
||||
|
|
|
@ -12,7 +12,7 @@ extern crate uucore;
|
|||
|
||||
use clap::{
|
||||
builder::{NonEmptyStringValueParser, ValueParser},
|
||||
crate_version, Arg, Command,
|
||||
crate_version, Arg, ArgAction, Command,
|
||||
};
|
||||
use glob::{MatchOptions, Pattern};
|
||||
use lscolors::LsColors;
|
||||
|
@ -268,7 +268,7 @@ impl Display for LsError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub enum Format {
|
||||
Columns,
|
||||
Long,
|
||||
|
@ -328,7 +328,7 @@ fn parse_time_style(options: &clap::ArgMatches) -> Result<TimeStyle, LsError> {
|
|||
if let Some(field) = options.get_one::<String>(options::TIME_STYLE) {
|
||||
//If both FULL_TIME and TIME_STYLE are present
|
||||
//The one added last is dominant
|
||||
if options.contains_id(options::FULL_TIME)
|
||||
if options.get_flag(options::FULL_TIME)
|
||||
&& options.indices_of(options::FULL_TIME).unwrap().last()
|
||||
> options.indices_of(options::TIME_STYLE).unwrap().last()
|
||||
{
|
||||
|
@ -348,7 +348,7 @@ fn parse_time_style(options: &clap::ArgMatches) -> Result<TimeStyle, LsError> {
|
|||
},
|
||||
}
|
||||
}
|
||||
} else if options.contains_id(options::FULL_TIME) {
|
||||
} else if options.get_flag(options::FULL_TIME) {
|
||||
Ok(TimeStyle::FullIso)
|
||||
} else {
|
||||
Ok(TimeStyle::Locale)
|
||||
|
@ -425,7 +425,7 @@ struct PaddingCollection {
|
|||
impl Config {
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub fn from(options: &clap::ArgMatches) -> UResult<Self> {
|
||||
let context = options.contains_id(options::CONTEXT);
|
||||
let context = options.get_flag(options::CONTEXT);
|
||||
let (mut format, opt) = if let Some(format_) = options.get_one::<String>(options::FORMAT) {
|
||||
(
|
||||
match format_.as_str() {
|
||||
|
@ -439,13 +439,13 @@ impl Config {
|
|||
},
|
||||
Some(options::FORMAT),
|
||||
)
|
||||
} else if options.contains_id(options::format::LONG) {
|
||||
} else if options.get_flag(options::format::LONG) {
|
||||
(Format::Long, Some(options::format::LONG))
|
||||
} else if options.contains_id(options::format::ACROSS) {
|
||||
} else if options.get_flag(options::format::ACROSS) {
|
||||
(Format::Across, Some(options::format::ACROSS))
|
||||
} else if options.contains_id(options::format::COMMAS) {
|
||||
} else if options.get_flag(options::format::COMMAS) {
|
||||
(Format::Commas, Some(options::format::COMMAS))
|
||||
} else if options.contains_id(options::format::COLUMNS) {
|
||||
} else if options.get_flag(options::format::COLUMNS) {
|
||||
(Format::Columns, Some(options::format::COLUMNS))
|
||||
} else if atty::is(atty::Stream::Stdout) {
|
||||
(Format::Columns, None)
|
||||
|
@ -479,21 +479,30 @@ impl Config {
|
|||
options::FULL_TIME,
|
||||
]
|
||||
.iter()
|
||||
.flat_map(|opt| options.indices_of(opt))
|
||||
.flat_map(|opt| {
|
||||
if options.value_source(opt) == Some(clap::parser::ValueSource::CommandLine) {
|
||||
options.indices_of(opt)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.any(|i| i >= idx)
|
||||
{
|
||||
format = Format::Long;
|
||||
} else if let Some(mut indices) = options.indices_of(options::format::ONE_LINE) {
|
||||
if indices.any(|i| i > idx) {
|
||||
if options.value_source(options::format::ONE_LINE)
|
||||
== Some(clap::parser::ValueSource::CommandLine)
|
||||
&& indices.any(|i| i > idx)
|
||||
{
|
||||
format = Format::OneLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let files = if options.contains_id(options::files::ALL) {
|
||||
let files = if options.get_flag(options::files::ALL) {
|
||||
Files::All
|
||||
} else if options.contains_id(options::files::ALMOST_ALL) {
|
||||
} else if options.get_flag(options::files::ALMOST_ALL) {
|
||||
Files::AlmostAll
|
||||
} else {
|
||||
Files::Normal
|
||||
|
@ -510,15 +519,15 @@ impl Config {
|
|||
// below should never happen as clap already restricts the values.
|
||||
_ => unreachable!("Invalid field for --sort"),
|
||||
}
|
||||
} else if options.contains_id(options::sort::TIME) {
|
||||
} else if options.get_flag(options::sort::TIME) {
|
||||
Sort::Time
|
||||
} else if options.contains_id(options::sort::SIZE) {
|
||||
} else if options.get_flag(options::sort::SIZE) {
|
||||
Sort::Size
|
||||
} else if options.contains_id(options::sort::NONE) {
|
||||
} else if options.get_flag(options::sort::NONE) {
|
||||
Sort::None
|
||||
} else if options.contains_id(options::sort::VERSION) {
|
||||
} else if options.get_flag(options::sort::VERSION) {
|
||||
Sort::Version
|
||||
} else if options.contains_id(options::sort::EXTENSION) {
|
||||
} else if options.get_flag(options::sort::EXTENSION) {
|
||||
Sort::Extension
|
||||
} else {
|
||||
Sort::Name
|
||||
|
@ -532,9 +541,9 @@ impl Config {
|
|||
// below should never happen as clap already restricts the values.
|
||||
_ => unreachable!("Invalid field for --time"),
|
||||
}
|
||||
} else if options.contains_id(options::time::ACCESS) {
|
||||
} else if options.get_flag(options::time::ACCESS) {
|
||||
Time::Access
|
||||
} else if options.contains_id(options::time::CHANGE) {
|
||||
} else if options.get_flag(options::time::CHANGE) {
|
||||
Time::Change
|
||||
} else {
|
||||
Time::Modification
|
||||
|
@ -555,14 +564,14 @@ impl Config {
|
|||
.get_one::<String>(options::size::BLOCK_SIZE)
|
||||
.unwrap()
|
||||
.eq("si")
|
||||
|| options.contains_id(options::size::SI);
|
||||
|| options.get_flag(options::size::SI);
|
||||
let opt_hr = (cmd_line_bs.is_some()
|
||||
&& options
|
||||
.get_one::<String>(options::size::BLOCK_SIZE)
|
||||
.unwrap()
|
||||
.eq("human-readable"))
|
||||
|| options.contains_id(options::size::HUMAN_READABLE);
|
||||
let opt_kb = options.contains_id(options::size::KIBIBYTES);
|
||||
|| options.get_flag(options::size::HUMAN_READABLE);
|
||||
let opt_kb = options.get_flag(options::size::KIBIBYTES);
|
||||
|
||||
let bs_env_var = std::env::var_os("BLOCK_SIZE");
|
||||
let ls_bs_env_var = std::env::var_os("LS_BLOCK_SIZE");
|
||||
|
@ -611,12 +620,12 @@ impl Config {
|
|||
};
|
||||
|
||||
let long = {
|
||||
let author = options.contains_id(options::AUTHOR);
|
||||
let group = !options.contains_id(options::NO_GROUP)
|
||||
&& !options.contains_id(options::format::LONG_NO_GROUP);
|
||||
let owner = !options.contains_id(options::format::LONG_NO_OWNER);
|
||||
let author = options.get_flag(options::AUTHOR);
|
||||
let group = !options.get_flag(options::NO_GROUP)
|
||||
&& !options.get_flag(options::format::LONG_NO_GROUP);
|
||||
let owner = !options.get_flag(options::format::LONG_NO_OWNER);
|
||||
#[cfg(unix)]
|
||||
let numeric_uid_gid = options.contains_id(options::format::LONG_NUMERIC_UID_GID);
|
||||
let numeric_uid_gid = options.get_flag(options::format::LONG_NUMERIC_UID_GID);
|
||||
LongFormat {
|
||||
author,
|
||||
group,
|
||||
|
@ -660,9 +669,9 @@ impl Config {
|
|||
};
|
||||
|
||||
#[allow(clippy::needless_bool)]
|
||||
let mut show_control = if options.contains_id(options::HIDE_CONTROL_CHARS) {
|
||||
let mut show_control = if options.get_flag(options::HIDE_CONTROL_CHARS) {
|
||||
false
|
||||
} else if options.contains_id(options::SHOW_CONTROL_CHARS) {
|
||||
} else if options.get_flag(options::SHOW_CONTROL_CHARS) {
|
||||
true
|
||||
} else {
|
||||
!atty::is(atty::Stream::Stdout)
|
||||
|
@ -703,13 +712,13 @@ impl Config {
|
|||
},
|
||||
_ => unreachable!("Should have been caught by Clap"),
|
||||
}
|
||||
} else if options.contains_id(options::quoting::LITERAL) {
|
||||
} else if options.get_flag(options::quoting::LITERAL) {
|
||||
QuotingStyle::Literal { show_control }
|
||||
} else if options.contains_id(options::quoting::ESCAPE) {
|
||||
} else if options.get_flag(options::quoting::ESCAPE) {
|
||||
QuotingStyle::C {
|
||||
quotes: quoting_style::Quotes::None,
|
||||
}
|
||||
} else if options.contains_id(options::quoting::C) {
|
||||
} else if options.get_flag(options::quoting::C) {
|
||||
QuotingStyle::C {
|
||||
quotes: quoting_style::Quotes::Double,
|
||||
}
|
||||
|
@ -745,9 +754,9 @@ impl Config {
|
|||
}
|
||||
&_ => IndicatorStyle::None,
|
||||
}
|
||||
} else if options.contains_id(options::indicator_style::SLASH) {
|
||||
} else if options.get_flag(options::indicator_style::SLASH) {
|
||||
IndicatorStyle::Slash
|
||||
} else if options.contains_id(options::indicator_style::FILE_TYPE) {
|
||||
} else if options.get_flag(options::indicator_style::FILE_TYPE) {
|
||||
IndicatorStyle::FileType
|
||||
} else {
|
||||
IndicatorStyle::None
|
||||
|
@ -756,7 +765,7 @@ impl Config {
|
|||
|
||||
let mut ignore_patterns: Vec<Pattern> = Vec::new();
|
||||
|
||||
if options.contains_id(options::IGNORE_BACKUPS) {
|
||||
if options.get_flag(options::IGNORE_BACKUPS) {
|
||||
ignore_patterns.push(Pattern::new("*~").unwrap());
|
||||
ignore_patterns.push(Pattern::new(".*~").unwrap());
|
||||
}
|
||||
|
@ -815,7 +824,13 @@ impl Config {
|
|||
options::quoting::ESCAPE,
|
||||
options::quoting::LITERAL,
|
||||
];
|
||||
let get_last = |flag: &str| -> usize { options.index_of(flag).unwrap_or(0) };
|
||||
let get_last = |flag: &str| -> usize {
|
||||
if options.value_source(flag) == Some(clap::parser::ValueSource::CommandLine) {
|
||||
options.index_of(flag).unwrap_or(0)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
};
|
||||
if get_last(options::ZERO)
|
||||
> zero_formats_opts
|
||||
.into_iter()
|
||||
|
@ -863,13 +878,13 @@ impl Config {
|
|||
None
|
||||
};
|
||||
|
||||
let dereference = if options.contains_id(options::dereference::ALL) {
|
||||
let dereference = if options.get_flag(options::dereference::ALL) {
|
||||
Dereference::All
|
||||
} else if options.contains_id(options::dereference::ARGS) {
|
||||
} else if options.get_flag(options::dereference::ARGS) {
|
||||
Dereference::Args
|
||||
} else if options.contains_id(options::dereference::DIR_ARGS) {
|
||||
} else if options.get_flag(options::dereference::DIR_ARGS) {
|
||||
Dereference::DirArgs
|
||||
} else if options.contains_id(options::DIRECTORY)
|
||||
} else if options.get_flag(options::DIRECTORY)
|
||||
|| indicator_style == IndicatorStyle::Classify
|
||||
|| format == Format::Long
|
||||
{
|
||||
|
@ -882,18 +897,18 @@ impl Config {
|
|||
format,
|
||||
files,
|
||||
sort,
|
||||
recursive: options.contains_id(options::RECURSIVE),
|
||||
reverse: options.contains_id(options::REVERSE),
|
||||
recursive: options.get_flag(options::RECURSIVE),
|
||||
reverse: options.get_flag(options::REVERSE),
|
||||
dereference,
|
||||
ignore_patterns,
|
||||
size_format,
|
||||
directory: options.contains_id(options::DIRECTORY),
|
||||
directory: options.get_flag(options::DIRECTORY),
|
||||
time,
|
||||
color,
|
||||
#[cfg(unix)]
|
||||
inode: options.contains_id(options::INODE),
|
||||
inode: options.get_flag(options::INODE),
|
||||
long,
|
||||
alloc_size: options.contains_id(options::size::ALLOCATION_SIZE),
|
||||
alloc_size: options.get_flag(options::size::ALLOCATION_SIZE),
|
||||
block_size,
|
||||
width,
|
||||
quoting_style,
|
||||
|
@ -910,8 +925,8 @@ impl Config {
|
|||
false
|
||||
}
|
||||
},
|
||||
group_directories_first: options.contains_id(options::GROUP_DIRECTORIES_FIRST),
|
||||
eol: if options.contains_id(options::ZERO) {
|
||||
group_directories_first: options.get_flag(options::GROUP_DIRECTORIES_FIRST),
|
||||
eol: if options.get_flag(options::ZERO) {
|
||||
'\0'
|
||||
} else {
|
||||
'\n'
|
||||
|
@ -936,23 +951,24 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
list(locs, &config)
|
||||
}
|
||||
|
||||
pub fn uu_app<'a>() -> Command<'a> {
|
||||
pub fn uu_app() -> Command {
|
||||
Command::new(uucore::util_name())
|
||||
.version(crate_version!())
|
||||
.override_usage(format_usage(USAGE))
|
||||
.about(ABOUT)
|
||||
.infer_long_args(true)
|
||||
.disable_help_flag(true)
|
||||
.arg(
|
||||
Arg::new(options::HELP)
|
||||
.long(options::HELP)
|
||||
.help("Print help information."),
|
||||
.help("Print help information.")
|
||||
.action(ArgAction::Help),
|
||||
)
|
||||
// Format arguments
|
||||
.arg(
|
||||
Arg::new(options::FORMAT)
|
||||
.long(options::FORMAT)
|
||||
.help("Set the display format.")
|
||||
.takes_value(true)
|
||||
.value_parser([
|
||||
"long",
|
||||
"verbose",
|
||||
|
@ -983,7 +999,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::format::LONG,
|
||||
options::format::ACROSS,
|
||||
options::format::COLUMNS,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::format::LONG)
|
||||
|
@ -996,7 +1013,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::format::LONG,
|
||||
options::format::ACROSS,
|
||||
options::format::COLUMNS,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::format::ACROSS)
|
||||
|
@ -1008,7 +1026,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::format::LONG,
|
||||
options::format::ACROSS,
|
||||
options::format::COLUMNS,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
// silently ignored (see #3624)
|
||||
|
@ -1016,7 +1035,6 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
.short('T')
|
||||
.long(options::format::TAB_SIZE)
|
||||
.env("TABSIZE")
|
||||
.takes_value(true)
|
||||
.value_name("COLS")
|
||||
.help("Assume tab stops at each COLS instead of 8 (unimplemented)"),
|
||||
)
|
||||
|
@ -1030,20 +1048,23 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::format::LONG,
|
||||
options::format::ACROSS,
|
||||
options::format::COLUMNS,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::ZERO)
|
||||
.long(options::ZERO)
|
||||
.conflicts_with(options::DIRED)
|
||||
.overrides_with(options::ZERO)
|
||||
.help("List entries separated by ASCII NUL characters."),
|
||||
.help("List entries separated by ASCII NUL characters.")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::DIRED)
|
||||
.long(options::DIRED)
|
||||
.short('D')
|
||||
.hide(true),
|
||||
.hide(true)
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
// The next four arguments do not override with the other format
|
||||
// options, see the comment in Config::from for the reason.
|
||||
|
@ -1055,7 +1076,7 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
Arg::new(options::format::ONE_LINE)
|
||||
.short('1')
|
||||
.help("List one file per line.")
|
||||
.multiple_occurrences(true),
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::format::LONG_NO_GROUP)
|
||||
|
@ -1064,26 +1085,25 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
"Long format without group information. \
|
||||
Identical to --format=long with --no-group.",
|
||||
)
|
||||
.multiple_occurrences(true),
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::format::LONG_NO_OWNER)
|
||||
.short('g')
|
||||
.help("Long format without owner information.")
|
||||
.multiple_occurrences(true),
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::format::LONG_NUMERIC_UID_GID)
|
||||
.short('n')
|
||||
.long(options::format::LONG_NUMERIC_UID_GID)
|
||||
.help("-l with numeric UIDs and GIDs.")
|
||||
.multiple_occurrences(true),
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
// Quoting style
|
||||
.arg(
|
||||
Arg::new(options::QUOTING_STYLE)
|
||||
.long(options::QUOTING_STYLE)
|
||||
.takes_value(true)
|
||||
.help("Set quoting style.")
|
||||
.value_parser([
|
||||
"literal",
|
||||
|
@ -1111,7 +1131,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::quoting::LITERAL,
|
||||
options::quoting::ESCAPE,
|
||||
options::quoting::C,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::quoting::ESCAPE)
|
||||
|
@ -1123,7 +1144,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::quoting::LITERAL,
|
||||
options::quoting::ESCAPE,
|
||||
options::quoting::C,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::quoting::C)
|
||||
|
@ -1135,7 +1157,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::quoting::LITERAL,
|
||||
options::quoting::ESCAPE,
|
||||
options::quoting::C,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
// Control characters
|
||||
.arg(
|
||||
|
@ -1143,13 +1166,15 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
.short('q')
|
||||
.long(options::HIDE_CONTROL_CHARS)
|
||||
.help("Replace control characters with '?' if they are not escaped.")
|
||||
.overrides_with_all(&[options::HIDE_CONTROL_CHARS, options::SHOW_CONTROL_CHARS]),
|
||||
.overrides_with_all(&[options::HIDE_CONTROL_CHARS, options::SHOW_CONTROL_CHARS])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::SHOW_CONTROL_CHARS)
|
||||
.long(options::SHOW_CONTROL_CHARS)
|
||||
.help("Show control characters 'as is' if they are not escaped.")
|
||||
.overrides_with_all(&[options::HIDE_CONTROL_CHARS, options::SHOW_CONTROL_CHARS]),
|
||||
.overrides_with_all(&[options::HIDE_CONTROL_CHARS, options::SHOW_CONTROL_CHARS])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
// Time arguments
|
||||
.arg(
|
||||
|
@ -1162,7 +1187,6 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
\tbirth time: birth, creation;",
|
||||
)
|
||||
.value_name("field")
|
||||
.takes_value(true)
|
||||
.value_parser([
|
||||
"atime", "access", "use", "ctime", "status", "birth", "creation",
|
||||
])
|
||||
|
@ -1179,7 +1203,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
time. When explicitly sorting by time (--sort=time or -t) or when not \
|
||||
using a long listing format, sort according to the status change time.",
|
||||
)
|
||||
.overrides_with_all(&[options::TIME, options::time::ACCESS, options::time::CHANGE]),
|
||||
.overrides_with_all(&[options::TIME, options::time::ACCESS, options::time::CHANGE])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::time::ACCESS)
|
||||
|
@ -1190,14 +1215,14 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
sorting by time (--sort=time or -t) or when not using a long listing \
|
||||
format, sort according to the access time.",
|
||||
)
|
||||
.overrides_with_all(&[options::TIME, options::time::ACCESS, options::time::CHANGE]),
|
||||
.overrides_with_all(&[options::TIME, options::time::ACCESS, options::time::CHANGE])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
// Hide and ignore
|
||||
.arg(
|
||||
Arg::new(options::HIDE)
|
||||
.long(options::HIDE)
|
||||
.takes_value(true)
|
||||
.multiple_occurrences(true)
|
||||
.action(ArgAction::Append)
|
||||
.value_name("PATTERN")
|
||||
.help(
|
||||
"do not list implied entries matching shell PATTERN (overridden by -a or -A)",
|
||||
|
@ -1207,8 +1232,7 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
Arg::new(options::IGNORE)
|
||||
.short('I')
|
||||
.long(options::IGNORE)
|
||||
.takes_value(true)
|
||||
.multiple_occurrences(true)
|
||||
.action(ArgAction::Append)
|
||||
.value_name("PATTERN")
|
||||
.help("do not list implied entries matching shell PATTERN"),
|
||||
)
|
||||
|
@ -1216,7 +1240,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
Arg::new(options::IGNORE_BACKUPS)
|
||||
.short('B')
|
||||
.long(options::IGNORE_BACKUPS)
|
||||
.help("Ignore entries which end with ~."),
|
||||
.help("Ignore entries which end with ~.")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
// Sort arguments
|
||||
.arg(
|
||||
|
@ -1224,7 +1249,6 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
.long(options::SORT)
|
||||
.help("Sort by <field>: name, none (-U), time (-t), size (-S) or extension (-X)")
|
||||
.value_name("field")
|
||||
.takes_value(true)
|
||||
.value_parser(["name", "none", "time", "size", "version", "extension"])
|
||||
.require_equals(true)
|
||||
.overrides_with_all(&[
|
||||
|
@ -1247,7 +1271,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::sort::NONE,
|
||||
options::sort::VERSION,
|
||||
options::sort::EXTENSION,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::sort::TIME)
|
||||
|
@ -1260,7 +1285,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::sort::NONE,
|
||||
options::sort::VERSION,
|
||||
options::sort::EXTENSION,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::sort::VERSION)
|
||||
|
@ -1273,7 +1299,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::sort::NONE,
|
||||
options::sort::VERSION,
|
||||
options::sort::EXTENSION,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::sort::EXTENSION)
|
||||
|
@ -1286,7 +1313,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::sort::NONE,
|
||||
options::sort::VERSION,
|
||||
options::sort::EXTENSION,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::sort::NONE)
|
||||
|
@ -1303,7 +1331,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::sort::NONE,
|
||||
options::sort::VERSION,
|
||||
options::sort::EXTENSION,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
// Dereferencing
|
||||
.arg(
|
||||
|
@ -1318,7 +1347,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::dereference::ALL,
|
||||
options::dereference::DIR_ARGS,
|
||||
options::dereference::ARGS,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::dereference::DIR_ARGS)
|
||||
|
@ -1331,7 +1361,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::dereference::ALL,
|
||||
options::dereference::DIR_ARGS,
|
||||
options::dereference::ARGS,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::dereference::ARGS)
|
||||
|
@ -1342,40 +1373,42 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::dereference::ALL,
|
||||
options::dereference::DIR_ARGS,
|
||||
options::dereference::ARGS,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
// Long format options
|
||||
.arg(
|
||||
Arg::new(options::NO_GROUP)
|
||||
.long(options::NO_GROUP)
|
||||
.short('G')
|
||||
.help("Do not show group in long format."),
|
||||
.help("Do not show group in long format.")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(Arg::new(options::AUTHOR).long(options::AUTHOR).help(
|
||||
"Show author in long format. \
|
||||
On the supported platforms, the author always matches the file owner.",
|
||||
))
|
||||
"Show author in long format. On the supported platforms, \
|
||||
the author always matches the file owner.",
|
||||
).action(ArgAction::SetTrue))
|
||||
// Other Flags
|
||||
.arg(
|
||||
Arg::new(options::files::ALL)
|
||||
.short('a')
|
||||
.long(options::files::ALL)
|
||||
// Overrides -A (as the order matters)
|
||||
.overrides_with(options::files::ALMOST_ALL)
|
||||
.multiple_occurrences(true)
|
||||
.help("Do not ignore hidden files (files with names that start with '.')."),
|
||||
.overrides_with_all([options::files::ALL, options::files::ALMOST_ALL])
|
||||
.help("Do not ignore hidden files (files with names that start with '.').")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::files::ALMOST_ALL)
|
||||
.short('A')
|
||||
.long(options::files::ALMOST_ALL)
|
||||
// Overrides -a (as the order matters)
|
||||
.overrides_with(options::files::ALL)
|
||||
.multiple_occurrences(true)
|
||||
.overrides_with_all([options::files::ALL, options::files::ALMOST_ALL])
|
||||
.help(
|
||||
"In a directory, do not ignore all file names that start with '.', \
|
||||
only ignore '.' and '..'.",
|
||||
),
|
||||
)
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::DIRECTORY)
|
||||
|
@ -1386,14 +1419,16 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
This will not follow symbolic links unless one of `--dereference-command-line \
|
||||
(-H)`, `--dereference (-L)`, or `--dereference-command-line-symlink-to-dir` is \
|
||||
specified.",
|
||||
),
|
||||
)
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::size::HUMAN_READABLE)
|
||||
.short('h')
|
||||
.long(options::size::HUMAN_READABLE)
|
||||
.help("Print human readable file sizes (e.g. 1K 234M 56G).")
|
||||
.overrides_with(options::size::SI),
|
||||
.overrides_with(options::size::SI)
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::size::KIBIBYTES)
|
||||
|
@ -1402,17 +1437,18 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
.help(
|
||||
"default to 1024-byte blocks for file system usage; used only with -s and per \
|
||||
directory totals",
|
||||
),
|
||||
)
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::size::SI)
|
||||
.long(options::size::SI)
|
||||
.help("Print human readable file sizes using powers of 1000 instead of 1024."),
|
||||
.help("Print human readable file sizes using powers of 1000 instead of 1024.")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::size::BLOCK_SIZE)
|
||||
.long(options::size::BLOCK_SIZE)
|
||||
.takes_value(true)
|
||||
.require_equals(true)
|
||||
.value_name("BLOCK_SIZE")
|
||||
.help("scale sizes by BLOCK_SIZE when printing them"),
|
||||
|
@ -1421,7 +1457,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
Arg::new(options::INODE)
|
||||
.short('i')
|
||||
.long(options::INODE)
|
||||
.help("print the index number of each file"),
|
||||
.help("print the index number of each file")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::REVERSE)
|
||||
|
@ -1430,38 +1467,39 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
.help(
|
||||
"Reverse whatever the sorting method is e.g., list files in reverse \
|
||||
alphabetical order, youngest first, smallest first, or whatever.",
|
||||
),
|
||||
)
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::RECURSIVE)
|
||||
.short('R')
|
||||
.long(options::RECURSIVE)
|
||||
.help("List the contents of all directories recursively."),
|
||||
.help("List the contents of all directories recursively.")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::WIDTH)
|
||||
.long(options::WIDTH)
|
||||
.short('w')
|
||||
.help("Assume that the terminal is COLS columns wide.")
|
||||
.value_name("COLS")
|
||||
.takes_value(true),
|
||||
.value_name("COLS"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::size::ALLOCATION_SIZE)
|
||||
.short('s')
|
||||
.long(options::size::ALLOCATION_SIZE)
|
||||
.help("print the allocated size of each file, in blocks"),
|
||||
.help("print the allocated size of each file, in blocks")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::COLOR)
|
||||
.long(options::COLOR)
|
||||
.help("Color output based on file type.")
|
||||
.takes_value(true)
|
||||
.value_parser([
|
||||
"always", "yes", "force", "auto", "tty", "if-tty", "never", "no", "none",
|
||||
])
|
||||
.require_equals(true)
|
||||
.min_values(0),
|
||||
.num_args(0..=1),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::INDICATOR_STYLE)
|
||||
|
@ -1470,7 +1508,6 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
"Append indicator with style WORD to entry names: \
|
||||
none (default), slash (-p), file-type (--file-type), classify (-F)",
|
||||
)
|
||||
.takes_value(true)
|
||||
.value_parser(["none", "slash", "file-type", "classify"])
|
||||
.overrides_with_all(&[
|
||||
options::indicator_style::FILE_TYPE,
|
||||
|
@ -1501,14 +1538,13 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
--dereference-command-line (-H), --dereference (-L), or \
|
||||
--dereference-command-line-symlink-to-dir options are specified.",
|
||||
)
|
||||
.takes_value(true)
|
||||
.value_name("when")
|
||||
.value_parser([
|
||||
"always", "yes", "force", "auto", "tty", "if-tty", "never", "no", "none",
|
||||
])
|
||||
.default_missing_value("always")
|
||||
.require_equals(true)
|
||||
.min_values(0)
|
||||
.num_args(0..=1)
|
||||
.overrides_with_all(&[
|
||||
options::indicator_style::FILE_TYPE,
|
||||
options::indicator_style::SLASH,
|
||||
|
@ -1525,7 +1561,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::indicator_style::SLASH,
|
||||
options::indicator_style::CLASSIFY,
|
||||
options::INDICATOR_STYLE,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::indicator_style::SLASH)
|
||||
|
@ -1536,7 +1573,8 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
options::indicator_style::SLASH,
|
||||
options::indicator_style::CLASSIFY,
|
||||
options::INDICATOR_STYLE,
|
||||
]),
|
||||
])
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
//This still needs support for posix-*
|
||||
|
@ -1552,13 +1590,15 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
Arg::new(options::FULL_TIME)
|
||||
.long(options::FULL_TIME)
|
||||
.overrides_with(options::FULL_TIME)
|
||||
.help("like -l --time-style=full-iso"),
|
||||
.help("like -l --time-style=full-iso")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::CONTEXT)
|
||||
.short('Z')
|
||||
.long(options::CONTEXT)
|
||||
.help(CONTEXT_HELP_TEXT),
|
||||
.help(CONTEXT_HELP_TEXT)
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::GROUP_DIRECTORIES_FIRST)
|
||||
|
@ -1566,13 +1606,13 @@ pub fn uu_app<'a>() -> Command<'a> {
|
|||
.help(
|
||||
"group directories before files; can be augmented with \
|
||||
a --sort option, but any use of --sort=none (-U) disables grouping",
|
||||
),
|
||||
)
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
// Positional arguments
|
||||
.arg(
|
||||
Arg::new(options::PATHS)
|
||||
.multiple_occurrences(true)
|
||||
.takes_value(true)
|
||||
.action(ArgAction::Append)
|
||||
.value_hint(clap::ValueHint::AnyPath)
|
||||
.value_parser(ValueParser::os_string()),
|
||||
)
|
||||
|
|
|
@ -3248,6 +3248,7 @@ fn test_ls_multiple_a_A() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "ln")]
|
||||
fn test_ls_quoting() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
|
@ -3267,6 +3268,7 @@ fn test_ls_quoting() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "ln")]
|
||||
fn test_ls_quoting_color() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue