wc: clean up of settings

The Settings object did not need a QuotingStyle member, it was basically
a static.
This commit is contained in:
Jed Denlea 2023-03-31 19:18:45 -07:00
parent 70765eea82
commit c3b06e10a6

View file

@ -42,23 +42,36 @@ struct Settings {
show_words: bool, show_words: bool,
show_max_line_length: bool, show_max_line_length: bool,
files0_from_stdin_mode: bool, files0_from_stdin_mode: bool,
title_quoting_style: QuotingStyle,
total_when: TotalWhen, total_when: TotalWhen,
} }
impl Default for Settings {
fn default() -> Self {
// Defaults if none of -c, -m, -l, -w, nor -L are specified.
Self {
show_bytes: true,
show_chars: false,
show_lines: true,
show_words: true,
show_max_line_length: false,
files0_from_stdin_mode: false,
total_when: TotalWhen::default(),
}
}
}
impl Settings { impl Settings {
fn new(matches: &ArgMatches) -> Self { fn new(matches: &ArgMatches) -> Self {
let title_quoting_style = QuotingStyle::Shell {
escape: true,
always_quote: false,
show_control: false,
};
let files0_from_stdin_mode = match matches.get_one::<String>(options::FILES0_FROM) { let files0_from_stdin_mode = match matches.get_one::<String>(options::FILES0_FROM) {
Some(files_0_from) => files_0_from == STDIN_REPR, Some(files_0_from) => files_0_from == STDIN_REPR,
None => false, None => false,
}; };
let total_when = matches
.get_one::<String>(options::TOTAL)
.map(Into::into)
.unwrap_or_default();
let settings = Self { let settings = Self {
show_bytes: matches.get_flag(options::BYTES), show_bytes: matches.get_flag(options::BYTES),
show_chars: matches.get_flag(options::CHAR), show_chars: matches.get_flag(options::CHAR),
@ -66,46 +79,38 @@ impl Settings {
show_words: matches.get_flag(options::WORDS), show_words: matches.get_flag(options::WORDS),
show_max_line_length: matches.get_flag(options::MAX_LINE_LENGTH), show_max_line_length: matches.get_flag(options::MAX_LINE_LENGTH),
files0_from_stdin_mode, files0_from_stdin_mode,
title_quoting_style, total_when,
total_when: matches.get_one::<String>(options::TOTAL).unwrap().into(),
}; };
if settings.show_bytes if settings.number_enabled() > 0 {
|| settings.show_chars settings
|| settings.show_lines } else {
|| settings.show_words Self {
|| settings.show_max_line_length files0_from_stdin_mode,
{ total_when,
return settings; ..Default::default()
} }
Self {
show_bytes: true,
show_chars: false,
show_lines: true,
show_words: true,
show_max_line_length: false,
files0_from_stdin_mode,
title_quoting_style: settings.title_quoting_style,
total_when: settings.total_when,
} }
} }
fn number_enabled(&self) -> u32 { fn number_enabled(&self) -> u32 {
let mut result = 0; [
result += self.show_bytes as u32; self.show_bytes,
result += self.show_chars as u32; self.show_chars,
result += self.show_lines as u32; self.show_lines,
result += self.show_max_line_length as u32; self.show_max_line_length,
result += self.show_words as u32; self.show_words,
result ]
.into_iter()
.map(Into::<u32>::into)
.sum()
} }
} }
const ABOUT: &str = help_about!("wc.md"); const ABOUT: &str = help_about!("wc.md");
const USAGE: &str = help_usage!("wc.md"); const USAGE: &str = help_usage!("wc.md");
pub mod options { mod options {
pub static BYTES: &str = "bytes"; pub static BYTES: &str = "bytes";
pub static CHAR: &str = "chars"; pub static CHAR: &str = "chars";
pub static FILES0_FROM: &str = "files0-from"; pub static FILES0_FROM: &str = "files0-from";
@ -118,6 +123,12 @@ pub mod options {
static ARG_FILES: &str = "files"; static ARG_FILES: &str = "files";
static STDIN_REPR: &str = "-"; static STDIN_REPR: &str = "-";
static QS_ESCAPE: &QuotingStyle = &QuotingStyle::Shell {
escape: true,
always_quote: false,
show_control: false,
};
enum StdinKind { enum StdinKind {
/// Stdin specified on command-line with "-". /// Stdin specified on command-line with "-".
Explicit, Explicit,
@ -147,35 +158,34 @@ impl From<&OsStr> for Input {
impl Input { impl Input {
/// Converts input to title that appears in stats. /// Converts input to title that appears in stats.
fn to_title(&self, quoting_style: &QuotingStyle) -> Option<String> { fn to_title(&self) -> Option<String> {
match self { match self {
Self::Path(path) => Some(escape_name(&path.clone().into_os_string(), quoting_style)), Self::Path(path) => Some(escape_name(path.as_os_str(), QS_ESCAPE)),
Self::Stdin(StdinKind::Explicit) => { Self::Stdin(StdinKind::Explicit) => Some(STDIN_REPR.into()),
Some(escape_name(OsStr::new(STDIN_REPR), quoting_style))
}
Self::Stdin(StdinKind::Implicit) => None, Self::Stdin(StdinKind::Implicit) => None,
} }
} }
fn path_display(&self, quoting_style: &QuotingStyle) -> String { fn path_display(&self) -> String {
match self { match self {
Self::Path(path) => escape_name(&path.clone().into_os_string(), quoting_style), Self::Path(path) => escape_name(OsStr::new(&path), QS_ESCAPE),
Self::Stdin(_) => escape_name(OsStr::new("standard input"), quoting_style), Self::Stdin(_) => escape_name(OsStr::new("standard input"), QS_ESCAPE),
} }
} }
} }
/// When to show the "total" line /// When to show the "total" line
#[derive(PartialEq)] #[derive(Clone, Copy, Default, PartialEq)]
enum TotalWhen { enum TotalWhen {
#[default]
Auto, Auto,
Always, Always,
Only, Only,
Never, Never,
} }
impl From<&String> for TotalWhen { impl<T: AsRef<str>> From<T> for TotalWhen {
fn from(s: &String) -> Self { fn from(s: T) -> Self {
match s.as_ref() { match s.as_ref() {
"auto" => Self::Auto, "auto" => Self::Auto,
"always" => Self::Always, "always" => Self::Always,
@ -261,11 +271,11 @@ pub fn uu_app() -> Command {
Arg::new(options::FILES0_FROM) Arg::new(options::FILES0_FROM)
.long(options::FILES0_FROM) .long(options::FILES0_FROM)
.value_name("F") .value_name("F")
.help( .help(concat!(
"read input from the files specified by "read input from the files specified by\n",
NUL-terminated names in file F; " NUL-terminated names in file F;\n",
If F is - then read names from standard input", " If F is - then read names from standard input"
) ))
.value_hint(clap::ValueHint::FilePath), .value_hint(clap::ValueHint::FilePath),
) )
.arg( .arg(
@ -286,10 +296,12 @@ pub fn uu_app() -> Command {
Arg::new(options::TOTAL) Arg::new(options::TOTAL)
.long(options::TOTAL) .long(options::TOTAL)
.value_parser(["auto", "always", "only", "never"]) .value_parser(["auto", "always", "only", "never"])
.default_value("auto")
.hide_default_value(true)
.value_name("WHEN") .value_name("WHEN")
.help("when to print a line with total counts"), .hide_possible_values(true)
.help(concat!(
"when to print a line with total counts;\n",
" WHEN can be: auto, always, only, never"
)),
) )
.arg( .arg(
Arg::new(options::WORDS) Arg::new(options::WORDS)
@ -627,28 +639,20 @@ fn wc(inputs: &[Input], settings: &Settings) -> UResult<()> {
CountResult::Interrupted(word_count, error) => { CountResult::Interrupted(word_count, error) => {
show!(USimpleError::new( show!(USimpleError::new(
1, 1,
format!( format!("{}: {}", input.path_display(), error)
"{}: {}",
input.path_display(&settings.title_quoting_style),
error
)
)); ));
word_count word_count
} }
CountResult::Failure(error) => { CountResult::Failure(error) => {
show!(USimpleError::new( show!(USimpleError::new(
1, 1,
format!( format!("{}: {}", input.path_display(), error)
"{}: {}",
input.path_display(&settings.title_quoting_style),
error
)
)); ));
continue; continue;
} }
}; };
total_word_count += word_count; total_word_count += word_count;
let result = word_count.with_title(input.to_title(&settings.title_quoting_style)); let result = word_count.with_title(input.to_title());
if are_stats_visible { if are_stats_visible {
if let Err(err) = print_stats(settings, &result, number_width) { if let Err(err) = print_stats(settings, &result, number_width) {