1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

sort: clap 3

This commit is contained in:
Terts Diepraam 2022-01-11 14:51:52 +01:00
parent d0a52c95e6
commit b43839a8a8
3 changed files with 67 additions and 62 deletions

View file

@ -16,7 +16,7 @@ path = "src/sort.rs"
[dependencies]
binary-heap-plus = "0.4.1"
clap = { version = "2.33", features = ["wrap_help"] }
clap = { version = "3.0", features = ["wrap_help", "cargo"] }
compare = "0.1.0"
ctrlc = { version = "3.0", features = ["termination"] }
fnv = "1.0.7"

View file

@ -1046,8 +1046,8 @@ With no FILE, or when FILE is -, read standard input.",
}
/// Creates an `Arg` that conflicts with all other sort modes.
fn make_sort_mode_arg<'a, 'b>(mode: &'a str, short: &'b str, help: &'b str) -> Arg<'a, 'b> {
let mut arg = Arg::with_name(mode).short(short).long(mode).help(help);
fn make_sort_mode_arg<'a>(mode: &'a str, short: char, help: &'a str) -> Arg<'a> {
let mut arg = Arg::new(mode).short(short).long(mode).help(help);
for possible_mode in &options::modes::ALL_SORT_MODES {
if *possible_mode != mode {
arg = arg.conflicts_with(possible_mode);
@ -1064,7 +1064,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let usage = usage();
let mut settings: GlobalSettings = Default::default();
let matches = match uu_app().usage(&usage[..]).get_matches_from_safe(args) {
let matches = match uu_app()
.override_usage(&usage[..])
.try_get_matches_from(args)
{
Ok(t) => t,
Err(e) => {
// not all clap "Errors" are because of a failure to parse arguments.
@ -1072,11 +1075,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// nor return with a non-zero exit code in this case (we should print to stdout and return 0).
// This logic is similar to the code in clap, but we return 2 as the exit code in case of real failure
// (clap returns 1).
e.print().unwrap();
if e.use_stderr() {
eprintln!("{}", e.message);
set_exit_code(2);
} else {
println!("{}", e.message);
}
return Ok(());
}
@ -1209,11 +1210,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
));
}
if let Some(arg) = matches.args.get(options::SEPARATOR) {
let mut separator = arg.vals[0].to_str().ok_or_else(|| {
if let Some(arg) = matches.value_of_os(options::SEPARATOR) {
let mut separator = arg.to_str().ok_or_else(|| {
UUsageError::new(
2,
format!("separator is not valid unicode: {}", arg.vals[0].quote()),
format!("separator is not valid unicode: {}", arg.quote()),
)
})?;
if separator == "\\0" {
@ -1276,12 +1277,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
exec(&mut files, &settings, output, &mut tmp_dir)
}
pub fn uu_app() -> App<'static, 'static> {
pub fn uu_app<'a>() -> App<'a> {
App::new(uucore::util_name())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::modes::SORT)
Arg::new(options::modes::SORT)
.long(options::modes::SORT)
.takes_value(true)
.possible_values(&[
@ -1296,37 +1297,37 @@ pub fn uu_app() -> App<'static, 'static> {
)
.arg(make_sort_mode_arg(
options::modes::HUMAN_NUMERIC,
"h",
'h',
"compare according to human readable sizes, eg 1M > 100k",
))
.arg(make_sort_mode_arg(
options::modes::MONTH,
"M",
'M',
"compare according to month name abbreviation",
))
.arg(make_sort_mode_arg(
options::modes::NUMERIC,
"n",
'n',
"compare according to string numerical value",
))
.arg(make_sort_mode_arg(
options::modes::GENERAL_NUMERIC,
"g",
'g',
"compare according to string general numerical value",
))
.arg(make_sort_mode_arg(
options::modes::VERSION,
"V",
'V',
"Sort by SemVer version number, eg 1.12.2 > 1.1.2",
))
.arg(make_sort_mode_arg(
options::modes::RANDOM,
"R",
'R',
"shuffle in random order",
))
.arg(
Arg::with_name(options::DICTIONARY_ORDER)
.short("d")
Arg::new(options::DICTIONARY_ORDER)
.short('d')
.long(options::DICTIONARY_ORDER)
.help("consider only blanks and alphanumeric characters")
.conflicts_with_all(&[
@ -1337,14 +1338,14 @@ pub fn uu_app() -> App<'static, 'static> {
]),
)
.arg(
Arg::with_name(options::MERGE)
.short("m")
Arg::new(options::MERGE)
.short('m')
.long(options::MERGE)
.help("merge already sorted files; do not sort"),
)
.arg(
Arg::with_name(options::check::CHECK)
.short("c")
Arg::new(options::check::CHECK)
.short('c')
.long(options::check::CHECK)
.takes_value(true)
.require_equals(true)
@ -1358,8 +1359,8 @@ pub fn uu_app() -> App<'static, 'static> {
.help("check for sorted input; do not sort"),
)
.arg(
Arg::with_name(options::check::CHECK_SILENT)
.short("C")
Arg::new(options::check::CHECK_SILENT)
.short('C')
.long(options::check::CHECK_SILENT)
.conflicts_with(options::OUTPUT)
.help(
@ -1368,14 +1369,14 @@ pub fn uu_app() -> App<'static, 'static> {
),
)
.arg(
Arg::with_name(options::IGNORE_CASE)
.short("f")
Arg::new(options::IGNORE_CASE)
.short('f')
.long(options::IGNORE_CASE)
.help("fold lower case to upper case characters"),
)
.arg(
Arg::with_name(options::IGNORE_NONPRINTING)
.short("i")
Arg::new(options::IGNORE_NONPRINTING)
.short('i')
.long(options::IGNORE_NONPRINTING)
.help("ignore nonprinting characters")
.conflicts_with_all(&[
@ -1386,113 +1387,116 @@ pub fn uu_app() -> App<'static, 'static> {
]),
)
.arg(
Arg::with_name(options::IGNORE_LEADING_BLANKS)
.short("b")
Arg::new(options::IGNORE_LEADING_BLANKS)
.short('b')
.long(options::IGNORE_LEADING_BLANKS)
.help("ignore leading blanks when finding sort keys in each line"),
)
.arg(
Arg::with_name(options::OUTPUT)
.short("o")
Arg::new(options::OUTPUT)
.short('o')
.long(options::OUTPUT)
.help("write output to FILENAME instead of stdout")
.takes_value(true)
.value_name("FILENAME"),
)
.arg(
Arg::with_name(options::REVERSE)
.short("r")
Arg::new(options::REVERSE)
.short('r')
.long(options::REVERSE)
.help("reverse the output"),
)
.arg(
Arg::with_name(options::STABLE)
.short("s")
Arg::new(options::STABLE)
.short('s')
.long(options::STABLE)
.help("stabilize sort by disabling last-resort comparison"),
)
.arg(
Arg::with_name(options::UNIQUE)
.short("u")
Arg::new(options::UNIQUE)
.short('u')
.long(options::UNIQUE)
.help("output only the first of an equal run"),
)
.arg(
Arg::with_name(options::KEY)
.short("k")
Arg::new(options::KEY)
.short('k')
.long(options::KEY)
.help("sort by a key")
.long_help(LONG_HELP_KEYS)
.multiple(true)
.multiple_occurrences(true)
.number_of_values(1)
.takes_value(true),
)
.arg(
Arg::with_name(options::SEPARATOR)
.short("t")
Arg::new(options::SEPARATOR)
.short('t')
.long(options::SEPARATOR)
.help("custom separator for -k")
.takes_value(true),
.takes_value(true)
.allow_invalid_utf8(true),
)
.arg(
Arg::with_name(options::ZERO_TERMINATED)
.short("z")
Arg::new(options::ZERO_TERMINATED)
.short('z')
.long(options::ZERO_TERMINATED)
.help("line delimiter is NUL, not newline"),
)
.arg(
Arg::with_name(options::PARALLEL)
Arg::new(options::PARALLEL)
.long(options::PARALLEL)
.help("change the number of threads running concurrently to NUM_THREADS")
.takes_value(true)
.value_name("NUM_THREADS"),
)
.arg(
Arg::with_name(options::BUF_SIZE)
.short("S")
Arg::new(options::BUF_SIZE)
.short('S')
.long(options::BUF_SIZE)
.help("sets the maximum SIZE of each segment in number of sorted items")
.takes_value(true)
.value_name("SIZE"),
)
.arg(
Arg::with_name(options::TMP_DIR)
.short("T")
Arg::new(options::TMP_DIR)
.short('T')
.long(options::TMP_DIR)
.help("use DIR for temporaries, not $TMPDIR or /tmp")
.takes_value(true)
.value_name("DIR"),
)
.arg(
Arg::with_name(options::COMPRESS_PROG)
Arg::new(options::COMPRESS_PROG)
.long(options::COMPRESS_PROG)
.help("compress temporary files with PROG, decompress with PROG -d")
.long_help("PROG has to take input from stdin and output to stdout")
.value_name("PROG"),
)
.arg(
Arg::with_name(options::BATCH_SIZE)
Arg::new(options::BATCH_SIZE)
.long(options::BATCH_SIZE)
.help("Merge at most N_MERGE inputs at once.")
.value_name("N_MERGE"),
)
.arg(
Arg::with_name(options::FILES0_FROM)
Arg::new(options::FILES0_FROM)
.long(options::FILES0_FROM)
.help("read input from the files specified by NUL-terminated NUL_FILES")
.takes_value(true)
.value_name("NUL_FILES")
.multiple(true),
.multiple_occurrences(true)
.allow_invalid_utf8(true),
)
.arg(
Arg::with_name(options::DEBUG)
Arg::new(options::DEBUG)
.long(options::DEBUG)
.help("underline the parts of the line that are actually used for sorting"),
)
.arg(
Arg::with_name(options::FILES)
.multiple(true)
.takes_value(true),
Arg::new(options::FILES)
.multiple_occurrences(true)
.takes_value(true)
.allow_invalid_utf8(true),
)
}

View file

@ -996,7 +996,8 @@ fn test_conflict_check_out() {
.arg("-o=/dev/null")
.fails()
.stderr_contains(
"error: The argument '--output <FILENAME>' cannot be used with '--check",
// the rest of the message might be subject to change
"error: The argument",
);
}
}