1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 19:47:45 +00:00

ls: extract most of the content into functions

This commit is contained in:
Sylvestre Ledru 2023-04-11 23:02:15 +02:00
parent 1a8f2a78c0
commit 33d4ab82ba

View file

@ -426,36 +426,194 @@ struct PaddingCollection {
block_size: usize, block_size: usize,
} }
fn extract_format(options: &clap::ArgMatches) -> (Format, Option<&'static str>) {
if let Some(format_) = options.get_one::<String>(options::FORMAT) {
(
match format_.as_str() {
"long" | "verbose" => Format::Long,
"single-column" => Format::OneLine,
"columns" | "vertical" => Format::Columns,
"across" | "horizontal" => Format::Across,
"commas" => Format::Commas,
// below should never happen as clap already restricts the values.
_ => unreachable!("Invalid field for --format"),
},
Some(options::FORMAT),
)
} else if options.get_flag(options::format::LONG) {
(Format::Long, Some(options::format::LONG))
} else if options.get_flag(options::format::ACROSS) {
(Format::Across, Some(options::format::ACROSS))
} else if options.get_flag(options::format::COMMAS) {
(Format::Commas, Some(options::format::COMMAS))
} else if options.get_flag(options::format::COLUMNS) {
(Format::Columns, Some(options::format::COLUMNS))
} else if std::io::stdout().is_terminal() {
(Format::Columns, None)
} else {
(Format::OneLine, None)
}
}
fn extract_files(options: &clap::ArgMatches) -> Files {
if options.get_flag(options::files::ALL) {
Files::All
} else if options.get_flag(options::files::ALMOST_ALL) {
Files::AlmostAll
} else {
Files::Normal
}
}
fn extract_sort(options: &clap::ArgMatches) -> Sort {
if let Some(field) = options.get_one::<String>(options::SORT) {
match field.as_str() {
"none" => Sort::None,
"name" => Sort::Name,
"time" => Sort::Time,
"size" => Sort::Size,
"version" => Sort::Version,
"extension" => Sort::Extension,
// below should never happen as clap already restricts the values.
_ => unreachable!("Invalid field for --sort"),
}
} else if options.get_flag(options::sort::TIME) {
Sort::Time
} else if options.get_flag(options::sort::SIZE) {
Sort::Size
} else if options.get_flag(options::sort::NONE) {
Sort::None
} else if options.get_flag(options::sort::VERSION) {
Sort::Version
} else if options.get_flag(options::sort::EXTENSION) {
Sort::Extension
} else {
Sort::Name
}
}
fn extract_time(options: &clap::ArgMatches) -> Time {
if let Some(field) = options.get_one::<String>(options::TIME) {
match field.as_str() {
"ctime" | "status" => Time::Change,
"access" | "atime" | "use" => Time::Access,
"birth" | "creation" => Time::Birth,
// below should never happen as clap already restricts the values.
_ => unreachable!("Invalid field for --time"),
}
} else if options.get_flag(options::time::ACCESS) {
Time::Access
} else if options.get_flag(options::time::CHANGE) {
Time::Change
} else {
Time::Modification
}
}
fn extract_color(options: &clap::ArgMatches) -> bool {
match options.get_one::<String>(options::COLOR) {
None => options.contains_id(options::COLOR),
Some(val) => match val.as_str() {
"" | "always" | "yes" | "force" => true,
"auto" | "tty" | "if-tty" => std::io::stdout().is_terminal(),
/* "never" | "no" | "none" | */ _ => false,
},
}
}
fn extract_quoting_style(options: &clap::ArgMatches, show_control: bool) -> QuotingStyle {
let opt_quoting_style = options
.get_one::<String>(options::QUOTING_STYLE)
.map(|cmd_line_qs| cmd_line_qs.to_owned());
if let Some(style) = opt_quoting_style {
match style.as_str() {
"literal" => QuotingStyle::Literal { show_control },
"shell" => QuotingStyle::Shell {
escape: false,
always_quote: false,
show_control,
},
"shell-always" => QuotingStyle::Shell {
escape: false,
always_quote: true,
show_control,
},
"shell-escape" => QuotingStyle::Shell {
escape: true,
always_quote: false,
show_control,
},
"shell-escape-always" => QuotingStyle::Shell {
escape: true,
always_quote: true,
show_control,
},
"c" => QuotingStyle::C {
quotes: quoting_style::Quotes::Double,
},
"escape" => QuotingStyle::C {
quotes: quoting_style::Quotes::None,
},
_ => unreachable!("Should have been caught by Clap"),
}
} else if options.get_flag(options::quoting::LITERAL) {
QuotingStyle::Literal { show_control }
} else if options.get_flag(options::quoting::ESCAPE) {
QuotingStyle::C {
quotes: quoting_style::Quotes::None,
}
} else if options.get_flag(options::quoting::C) {
QuotingStyle::C {
quotes: quoting_style::Quotes::Double,
}
} else {
// TODO: use environment variable if available
QuotingStyle::Shell {
escape: true,
always_quote: false,
show_control,
}
}
}
fn extract_indicator_style(options: &clap::ArgMatches) -> IndicatorStyle {
if let Some(field) = options.get_one::<String>(options::INDICATOR_STYLE) {
match field.as_str() {
"none" => IndicatorStyle::None,
"file-type" => IndicatorStyle::FileType,
"classify" => IndicatorStyle::Classify,
"slash" => IndicatorStyle::Slash,
&_ => IndicatorStyle::None,
}
} else if let Some(field) = options.get_one::<String>(options::indicator_style::CLASSIFY) {
match field.as_str() {
"never" | "no" | "none" => IndicatorStyle::None,
"always" | "yes" | "force" => IndicatorStyle::Classify,
"auto" | "tty" | "if-tty" => {
if std::io::stdout().is_terminal() {
IndicatorStyle::Classify
} else {
IndicatorStyle::None
}
}
&_ => IndicatorStyle::None,
}
} else if options.get_flag(options::indicator_style::SLASH) {
IndicatorStyle::Slash
} else if options.get_flag(options::indicator_style::FILE_TYPE) {
IndicatorStyle::FileType
} else {
IndicatorStyle::None
}
}
impl Config { impl Config {
#[allow(clippy::cognitive_complexity)] #[allow(clippy::cognitive_complexity)]
pub fn from(options: &clap::ArgMatches) -> UResult<Self> { pub fn from(options: &clap::ArgMatches) -> UResult<Self> {
let context = options.get_flag(options::CONTEXT); let context = options.get_flag(options::CONTEXT);
let (mut format, opt) = if let Some(format_) = options.get_one::<String>(options::FORMAT) { let (mut format, opt) = extract_format(options);
( let files = extract_files(options);
match format_.as_str() {
"long" | "verbose" => Format::Long,
"single-column" => Format::OneLine,
"columns" | "vertical" => Format::Columns,
"across" | "horizontal" => Format::Across,
"commas" => Format::Commas,
// below should never happen as clap already restricts the values.
_ => unreachable!("Invalid field for --format"),
},
Some(options::FORMAT),
)
} else if options.get_flag(options::format::LONG) {
(Format::Long, Some(options::format::LONG))
} else if options.get_flag(options::format::ACROSS) {
(Format::Across, Some(options::format::ACROSS))
} else if options.get_flag(options::format::COMMAS) {
(Format::Commas, Some(options::format::COMMAS))
} else if options.get_flag(options::format::COLUMNS) {
(Format::Columns, Some(options::format::COLUMNS))
} else if std::io::stdout().is_terminal() {
(Format::Columns, None)
} else {
(Format::OneLine, None)
};
// The -o, -n and -g options are tricky. They cannot override with each // The -o, -n and -g options are tricky. They cannot override with each
// other because it's possible to combine them. For example, the option // other because it's possible to combine them. For example, the option
@ -504,63 +662,11 @@ impl Config {
} }
} }
let files = if options.get_flag(options::files::ALL) { let sort = extract_sort(options);
Files::All
} else if options.get_flag(options::files::ALMOST_ALL) {
Files::AlmostAll
} else {
Files::Normal
};
let sort = if let Some(field) = options.get_one::<String>(options::SORT) { let time = extract_time(options);
match field.as_str() {
"none" => Sort::None,
"name" => Sort::Name,
"time" => Sort::Time,
"size" => Sort::Size,
"version" => Sort::Version,
"extension" => Sort::Extension,
// below should never happen as clap already restricts the values.
_ => unreachable!("Invalid field for --sort"),
}
} else if options.get_flag(options::sort::TIME) {
Sort::Time
} else if options.get_flag(options::sort::SIZE) {
Sort::Size
} else if options.get_flag(options::sort::NONE) {
Sort::None
} else if options.get_flag(options::sort::VERSION) {
Sort::Version
} else if options.get_flag(options::sort::EXTENSION) {
Sort::Extension
} else {
Sort::Name
};
let time = if let Some(field) = options.get_one::<String>(options::TIME) { let mut needs_color = extract_color(options);
match field.as_str() {
"ctime" | "status" => Time::Change,
"access" | "atime" | "use" => Time::Access,
"birth" | "creation" => Time::Birth,
// below should never happen as clap already restricts the values.
_ => unreachable!("Invalid field for --time"),
}
} else if options.get_flag(options::time::ACCESS) {
Time::Access
} else if options.get_flag(options::time::CHANGE) {
Time::Change
} else {
Time::Modification
};
let mut needs_color = match options.get_one::<String>(options::COLOR) {
None => options.contains_id(options::COLOR),
Some(val) => match val.as_str() {
"" | "always" | "yes" | "force" => true,
"auto" | "tty" | "if-tty" => std::io::stdout().is_terminal(),
/* "never" | "no" | "none" | */ _ => false,
},
};
let cmd_line_bs = options.get_one::<String>(options::size::BLOCK_SIZE); let cmd_line_bs = options.get_one::<String>(options::size::BLOCK_SIZE);
let opt_si = cmd_line_bs.is_some() let opt_si = cmd_line_bs.is_some()
@ -681,90 +787,8 @@ impl Config {
!std::io::stdout().is_terminal() !std::io::stdout().is_terminal()
}; };
let opt_quoting_style = options let mut quoting_style = extract_quoting_style(options, show_control);
.get_one::<String>(options::QUOTING_STYLE) let indicator_style = extract_indicator_style(options);
.map(|cmd_line_qs| cmd_line_qs.to_owned());
let mut quoting_style = if let Some(style) = opt_quoting_style {
match style.as_str() {
"literal" => QuotingStyle::Literal { show_control },
"shell" => QuotingStyle::Shell {
escape: false,
always_quote: false,
show_control,
},
"shell-always" => QuotingStyle::Shell {
escape: false,
always_quote: true,
show_control,
},
"shell-escape" => QuotingStyle::Shell {
escape: true,
always_quote: false,
show_control,
},
"shell-escape-always" => QuotingStyle::Shell {
escape: true,
always_quote: true,
show_control,
},
"c" => QuotingStyle::C {
quotes: quoting_style::Quotes::Double,
},
"escape" => QuotingStyle::C {
quotes: quoting_style::Quotes::None,
},
_ => unreachable!("Should have been caught by Clap"),
}
} else if options.get_flag(options::quoting::LITERAL) {
QuotingStyle::Literal { show_control }
} else if options.get_flag(options::quoting::ESCAPE) {
QuotingStyle::C {
quotes: quoting_style::Quotes::None,
}
} else if options.get_flag(options::quoting::C) {
QuotingStyle::C {
quotes: quoting_style::Quotes::Double,
}
} else {
// TODO: use environment variable if available
QuotingStyle::Shell {
escape: true,
always_quote: false,
show_control,
}
};
let indicator_style = if let Some(field) =
options.get_one::<String>(options::INDICATOR_STYLE)
{
match field.as_str() {
"none" => IndicatorStyle::None,
"file-type" => IndicatorStyle::FileType,
"classify" => IndicatorStyle::Classify,
"slash" => IndicatorStyle::Slash,
&_ => IndicatorStyle::None,
}
} else if let Some(field) = options.get_one::<String>(options::indicator_style::CLASSIFY) {
match field.as_str() {
"never" | "no" | "none" => IndicatorStyle::None,
"always" | "yes" | "force" => IndicatorStyle::Classify,
"auto" | "tty" | "if-tty" => {
if std::io::stdout().is_terminal() {
IndicatorStyle::Classify
} else {
IndicatorStyle::None
}
}
&_ => IndicatorStyle::None,
}
} else if options.get_flag(options::indicator_style::SLASH) {
IndicatorStyle::Slash
} else if options.get_flag(options::indicator_style::FILE_TYPE) {
IndicatorStyle::FileType
} else {
IndicatorStyle::None
};
let time_style = parse_time_style(options)?; let time_style = parse_time_style(options)?;
let mut ignore_patterns: Vec<Pattern> = Vec::new(); let mut ignore_patterns: Vec<Pattern> = Vec::new();