1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-09-15 19:36:16 +00:00

basename: move from getopts to clap (#2117)

Use clap for argument parsing instead of getopts
Also, make the following changes

* Use `executable!()` macro to output the name of utility

* Add another usage to help message
This commit is contained in:
bashi8128 2021-05-02 17:08:14 +09:00
parent 4275661020
commit 47a5dd0f97
2 changed files with 58 additions and 34 deletions

View file

@ -15,6 +15,7 @@ edition = "2018"
path = "src/basename.rs"
[dependencies]
clap = "2.33.2"
uucore = { version=">=0.0.8", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -10,80 +10,103 @@
#[macro_use]
extern crate uucore;
use clap::{App, Arg};
use std::path::{is_separator, PathBuf};
use uucore::InvalidEncodingHandling;
static NAME: &str = "basename";
static SYNTAX: &str = "NAME [SUFFIX]";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static SUMMARY: &str = "Print NAME with any leading directory components removed
If specified, also remove a trailing SUFFIX";
static LONG_HELP: &str = "";
fn get_usage() -> String {
format!(
"{0} NAME [SUFFIX]
{0} OPTION... NAME...",
executable!()
)
}
pub mod options {
pub static MULTIPLE: &str = "multiple";
pub static NAME: &str = "name";
pub static SUFFIX: &str = "suffix";
pub static ZERO: &str = "zero";
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let usage = get_usage();
//
// Argument parsing
//
let matches = app!(SYNTAX, SUMMARY, LONG_HELP)
.optflag(
"a",
"multiple",
"Support more than one argument. Treat every argument as a name.",
let matches = App::new(executable!())
.version(VERSION)
.about(SUMMARY)
.usage(&usage[..])
.arg(
Arg::with_name(options::MULTIPLE)
.short("a")
.long(options::MULTIPLE)
.help("support multiple arguments and treat each as a NAME"),
)
.optopt(
"s",
"suffix",
"Remove a trailing suffix. This option implies the -a option.",
"SUFFIX",
.arg(Arg::with_name(options::NAME).multiple(true).hidden(true))
.arg(
Arg::with_name(options::SUFFIX)
.short("s")
.long(options::SUFFIX)
.value_name("SUFFIX")
.help("remove a trailing SUFFIX; implies -a"),
)
.optflag(
"z",
"zero",
"Output a zero byte (ASCII NUL) at the end of each line, rather than a newline.",
.arg(
Arg::with_name(options::ZERO)
.short("z")
.long(options::ZERO)
.help("end each output line with NUL, not newline"),
)
.parse(args);
.get_matches_from(args);
// too few arguments
if matches.free.is_empty() {
if !matches.is_present(options::NAME) {
crash!(
1,
"{0}: {1}\nTry '{0} --help' for more information.",
NAME,
executable!(),
"missing operand"
);
}
let opt_s = matches.opt_present("s");
let opt_a = matches.opt_present("a");
let opt_z = matches.opt_present("z");
let opt_s = matches.is_present(options::SUFFIX);
let opt_a = matches.is_present(options::MULTIPLE);
let opt_z = matches.is_present(options::ZERO);
let multiple_paths = opt_s || opt_a;
// too many arguments
if !multiple_paths && matches.free.len() > 2 {
if !multiple_paths && matches.occurrences_of(options::NAME) > 2 {
crash!(
1,
"{0}: extra operand '{1}'\nTry '{0} --help' for more information.",
NAME,
matches.free[2]
executable!(),
matches.values_of(options::NAME).unwrap().nth(2).unwrap()
);
}
let suffix = if opt_s {
matches.opt_str("s").unwrap()
} else if !opt_a && matches.free.len() > 1 {
matches.free[1].clone()
matches.value_of(options::SUFFIX).unwrap()
} else if !opt_a && matches.occurrences_of(options::NAME) > 1 {
matches.values_of(options::NAME).unwrap().nth(1).unwrap()
} else {
"".to_owned()
""
};
//
// Main Program Processing
//
let paths = if multiple_paths {
&matches.free[..]
let paths: Vec<_> = if multiple_paths {
matches.values_of(options::NAME).unwrap().collect()
} else {
&matches.free[0..1]
matches.values_of(options::NAME).unwrap().take(1).collect()
};
let line_ending = if opt_z { "\0" } else { "\n" };