mirror of
https://github.com/uutils/coreutils
synced 2024-12-04 18:39:52 +00:00
wip ~ (wc) revise clap defaults and usage
This commit is contained in:
parent
d458f3e594
commit
8436d14520
5 changed files with 79 additions and 31 deletions
|
@ -44,6 +44,7 @@ struct Settings {
|
|||
files0_from_stdin_mode: bool,
|
||||
title_quoting_style: QuotingStyle,
|
||||
total_when: TotalWhen,
|
||||
total_only: bool,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
|
@ -55,7 +56,7 @@ impl Settings {
|
|||
};
|
||||
|
||||
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_FILENAME,
|
||||
None => false,
|
||||
};
|
||||
|
||||
|
@ -68,6 +69,7 @@ impl Settings {
|
|||
files0_from_stdin_mode,
|
||||
title_quoting_style,
|
||||
total_when: matches.get_one::<String>(options::TOTAL).unwrap().into(),
|
||||
total_only: matches.get_flag(options::TOTAL_ONLY),
|
||||
};
|
||||
|
||||
if settings.show_bytes
|
||||
|
@ -88,6 +90,7 @@ impl Settings {
|
|||
files0_from_stdin_mode,
|
||||
title_quoting_style: settings.title_quoting_style,
|
||||
total_when: settings.total_when,
|
||||
total_only: settings.total_only,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,11 +115,11 @@ pub mod options {
|
|||
pub static LINES: &str = "lines";
|
||||
pub static MAX_LINE_LENGTH: &str = "max-line-length";
|
||||
pub static TOTAL: &str = "total";
|
||||
pub static TOTAL_ONLY: &str = "total-only";
|
||||
pub static WORDS: &str = "words";
|
||||
}
|
||||
|
||||
static ARG_FILES: &str = "files";
|
||||
static STDIN_REPR: &str = "-";
|
||||
static ARG_FILES: &str = "FILE";
|
||||
static STDIN_FILENAME: &str = "-";
|
||||
|
||||
enum StdinKind {
|
||||
/// Stdin specified on command-line with "-".
|
||||
|
@ -137,7 +140,7 @@ enum Input {
|
|||
|
||||
impl From<&OsStr> for Input {
|
||||
fn from(input: &OsStr) -> Self {
|
||||
if input == STDIN_REPR {
|
||||
if input == STDIN_FILENAME {
|
||||
Self::Stdin(StdinKind::Explicit)
|
||||
} else {
|
||||
Self::Path(input.into())
|
||||
|
@ -151,7 +154,7 @@ impl Input {
|
|||
match self {
|
||||
Self::Path(path) => Some(escape_name(&path.clone().into_os_string(), quoting_style)),
|
||||
Self::Stdin(StdinKind::Explicit) => {
|
||||
Some(escape_name(OsStr::new(STDIN_REPR), quoting_style))
|
||||
Some(escape_name(OsStr::new(STDIN_FILENAME), quoting_style))
|
||||
}
|
||||
Self::Stdin(StdinKind::Implicit) => None,
|
||||
}
|
||||
|
@ -170,7 +173,6 @@ impl Input {
|
|||
enum TotalWhen {
|
||||
Auto,
|
||||
Always,
|
||||
Only,
|
||||
Never,
|
||||
}
|
||||
|
||||
|
@ -179,7 +181,6 @@ impl From<&String> for TotalWhen {
|
|||
match s.as_ref() {
|
||||
"auto" => Self::Auto,
|
||||
"always" => Self::Always,
|
||||
"only" => Self::Only,
|
||||
"never" => Self::Never,
|
||||
_ => unreachable!("Should have been caught by clap"),
|
||||
}
|
||||
|
@ -190,7 +191,7 @@ impl TotalWhen {
|
|||
fn is_total_row_visible(&self, num_inputs: usize) -> bool {
|
||||
match self {
|
||||
Self::Auto => num_inputs > 1,
|
||||
Self::Always | Self::Only => true,
|
||||
Self::Always => true,
|
||||
Self::Never => false,
|
||||
}
|
||||
}
|
||||
|
@ -238,23 +239,25 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
}
|
||||
|
||||
pub fn uu_app() -> Command {
|
||||
Command::new(uucore::util_name())
|
||||
.version(crate_version!())
|
||||
.about(ABOUT)
|
||||
.override_usage(format_usage(USAGE))
|
||||
let app = uucore::clap_defaults(ABOUT, USAGE);
|
||||
app
|
||||
// .version(crate_version!())
|
||||
// .about(ABOUT)
|
||||
// .override_usage(format_usage(USAGE))
|
||||
// .after_help(uucore::after_help_text())
|
||||
.infer_long_args(true)
|
||||
.arg(
|
||||
Arg::new(options::BYTES)
|
||||
.short('c')
|
||||
.long(options::BYTES)
|
||||
.help("print the byte counts")
|
||||
.help("Display the byte counts")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::CHAR)
|
||||
.short('m')
|
||||
.long(options::CHAR)
|
||||
.help("print the character counts")
|
||||
.help("Display the character counts")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
|
@ -262,7 +265,7 @@ pub fn uu_app() -> Command {
|
|||
.long(options::FILES0_FROM)
|
||||
.value_name("F")
|
||||
.help(
|
||||
"read input from the files specified by
|
||||
"Read input from the files specified by
|
||||
NUL-terminated names in file F;
|
||||
If F is - then read names from standard input",
|
||||
)
|
||||
|
@ -272,34 +275,43 @@ pub fn uu_app() -> Command {
|
|||
Arg::new(options::LINES)
|
||||
.short('l')
|
||||
.long(options::LINES)
|
||||
.help("print the newline counts")
|
||||
.help("Display the newline counts")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::MAX_LINE_LENGTH)
|
||||
.short('L')
|
||||
.long(options::MAX_LINE_LENGTH)
|
||||
.help("print the length of the longest line")
|
||||
.help("Display the length of the longest line")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::TOTAL)
|
||||
.long(options::TOTAL)
|
||||
.value_parser(["auto", "always", "only", "never"])
|
||||
.value_parser(["auto", "always", "never"])
|
||||
.default_value("auto")
|
||||
.default_missing_value("always")
|
||||
.num_args(0..=1)
|
||||
.hide_default_value(true)
|
||||
.value_name("WHEN")
|
||||
.help("when to print a line with total counts"),
|
||||
.help("WHEN to display a line with total counts"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::TOTAL_ONLY)
|
||||
.long(options::TOTAL_ONLY)
|
||||
.help("Display *only* the total counts")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::WORDS)
|
||||
.short('w')
|
||||
.long(options::WORDS)
|
||||
.help("print the word counts")
|
||||
.help("Display the word counts")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(ARG_FILES)
|
||||
.help("FILE(s) to process")
|
||||
.action(ArgAction::Append)
|
||||
.value_parser(ValueParser::os_string())
|
||||
.value_hint(clap::ValueHint::FilePath),
|
||||
|
@ -327,7 +339,7 @@ fn inputs(matches: &ArgMatches) -> UResult<Vec<Input>> {
|
|||
|
||||
fn create_paths_from_files0(files_0_from: &str) -> UResult<Vec<Input>> {
|
||||
let mut paths = String::new();
|
||||
let read_from_stdin = files_0_from == STDIN_REPR;
|
||||
let read_from_stdin = files_0_from == STDIN_FILENAME;
|
||||
|
||||
if read_from_stdin {
|
||||
io::stdin().lock().read_to_string(&mut paths)?;
|
||||
|
@ -337,9 +349,13 @@ fn create_paths_from_files0(files_0_from: &str) -> UResult<Vec<Input>> {
|
|||
|
||||
let paths: Vec<&str> = paths.split_terminator('\0').collect();
|
||||
|
||||
if read_from_stdin && paths.contains(&STDIN_REPR) {
|
||||
if read_from_stdin && paths.contains(&STDIN_FILENAME) {
|
||||
return Err(WcError::StdinReprNotAllowed(
|
||||
"when reading file names from stdin, no file name of '-' allowed".into(),
|
||||
format!(
|
||||
"when reading file names from stdin, '{}' is not allowed as a file name",
|
||||
STDIN_FILENAME
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
@ -610,7 +626,7 @@ fn wc(inputs: &[Input], settings: &Settings) -> UResult<()> {
|
|||
let mut total_word_count = WordCount::default();
|
||||
|
||||
let (number_width, are_stats_visible, total_row_title) =
|
||||
if settings.total_when == TotalWhen::Only {
|
||||
if settings.total_only {
|
||||
(1, false, None)
|
||||
} else {
|
||||
let number_width = compute_number_width(inputs, settings);
|
||||
|
@ -619,7 +635,7 @@ fn wc(inputs: &[Input], settings: &Settings) -> UResult<()> {
|
|||
(number_width, true, title)
|
||||
};
|
||||
|
||||
let is_total_row_visible = settings.total_when.is_total_row_visible(inputs.len());
|
||||
let is_total_row_visible = settings.total_when.is_total_row_visible(inputs.len()) || settings.total_only;
|
||||
|
||||
for input in inputs {
|
||||
let word_count = match word_count_from_input(input, settings) {
|
||||
|
|
|
@ -5,4 +5,7 @@ wc [OPTION]... [FILE]...
|
|||
```
|
||||
|
||||
Display newline, word, and byte counts for each FILE, and a total line if
|
||||
more than one FILE is specified. With no FILE, or when FILE is -, read standard input.
|
||||
more than one FILE is specified. A word is a non-zero-length sequence of
|
||||
characters delimited by white space.
|
||||
|
||||
With no FILE, or when FILE is -, read standard input.
|
||||
|
|
|
@ -78,6 +78,9 @@ pub use crate::features::utmpx;
|
|||
#[cfg(all(windows, feature = "wide"))]
|
||||
pub use crate::features::wide;
|
||||
|
||||
//## clap
|
||||
use clap::{crate_version};
|
||||
|
||||
//## core functions
|
||||
|
||||
use std::ffi::OsString;
|
||||
|
@ -110,6 +113,26 @@ pub fn format_usage(s: &str) -> String {
|
|||
s.replace("{}", crate::execution_phrase())
|
||||
}
|
||||
|
||||
pub fn after_help_text() -> String {
|
||||
format!("* From [uutils/coreutils v{}](https://github.com/uutils/coreutils)\n* Copyright (C) * uutils developers (MIT license)\n", crate_version!())
|
||||
}
|
||||
|
||||
// pub fn clap_defaults() -> clap::App<'static, 'static> {
|
||||
// clap::App::new(crate_name!())
|
||||
// .version(crate_version!())
|
||||
// .about(crate_description!())
|
||||
// .after_help(after_help_text().as_str())
|
||||
// }
|
||||
pub fn clap_defaults(about: &str, usage: &str) -> clap::Command {
|
||||
clap::Command::new(util_name())
|
||||
.version(crate_version!())
|
||||
.about(about.to_string())
|
||||
.override_usage(format_usage(&usage))
|
||||
.after_help(after_help_text())
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn get_utility_is_second_arg() -> bool {
|
||||
crate::macros::UTILITY_IS_SECOND_ARG.load(Ordering::SeqCst)
|
||||
}
|
||||
|
|
|
@ -740,7 +740,13 @@ impl UError for ClapErrorWrapper {
|
|||
|
||||
impl Error for ClapErrorWrapper {}
|
||||
|
||||
// This is abuse of the Display trait
|
||||
// impl Display for ClapErrorWrapper {
|
||||
// fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
// self.error.fmt(f).unwrap();
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
// FixME: [2022-04; terts] (HACK!) this is abuse of the Display trait to enable `clap` to display color
|
||||
impl Display for ClapErrorWrapper {
|
||||
fn fmt(&self, _f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
self.error.print().unwrap();
|
||||
|
|
|
@ -18,16 +18,16 @@ pub fn main(_args: TokenStream, stream: TokenStream) -> TokenStream {
|
|||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
#stream
|
||||
let result = uumain(args);
|
||||
// eprintln!("result={:?}", result);
|
||||
match result {
|
||||
Ok(()) => uucore::error::get_exit_code(),
|
||||
Err(e) => {
|
||||
// FixME: [2022-04; terts] (HACK!) for color output, `clap` error text is directly displayed on stdout/stderr when "formatted"
|
||||
// ! ... (see `impl Display for ClapErrorWrapper` in `uucore/src/error.rs`)
|
||||
let s = format!("{}", e);
|
||||
if s != "" {
|
||||
uucore::show_error!("{}", s);
|
||||
}
|
||||
if e.usage() {
|
||||
eprintln!("Try '{} --help' for more information.", uucore::execution_phrase());
|
||||
}
|
||||
e.code()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue