1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-01 05:27:45 +00:00

refactor(sort): move to clap

This commit is contained in:
Sylvestre Ledru 2020-10-18 21:27:49 +02:00 committed by Roy Ivy III
parent 58d7d89e07
commit 58b0aeabee
3 changed files with 138 additions and 87 deletions

2
Cargo.lock generated
View file

@ -2096,7 +2096,7 @@ dependencies = [
name = "uu_sort" name = "uu_sort"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uucore 0.0.4 (git+https://github.com/uutils/uucore.git?branch=canary)", "uucore 0.0.4 (git+https://github.com/uutils/uucore.git?branch=canary)",

View file

@ -15,7 +15,7 @@ edition = "2018"
path = "src/sort.rs" path = "src/sort.rs"
[dependencies] [dependencies]
getopts = "0.2.18" clap = "2.33"
itertools = "0.8.0" itertools = "0.8.0"
semver = "0.9.0" semver = "0.9.0"
uucore = { version="0.0.4", package="uucore", git="https://github.com/uutils/uucore.git", branch="canary", features=["fs"] } uucore = { version="0.0.4", package="uucore", git="https://github.com/uutils/uucore.git", branch="canary", features=["fs"] }

View file

@ -8,13 +8,14 @@
// spell-checker:ignore (ToDO) outfile nondictionary // spell-checker:ignore (ToDO) outfile nondictionary
extern crate getopts; extern crate clap;
extern crate semver; extern crate semver;
extern crate itertools; extern crate itertools;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use clap::{App, Arg};
use itertools::Itertools; use itertools::Itertools;
use semver::Version; use semver::Version;
use std::cmp::Ordering; use std::cmp::Ordering;
@ -26,8 +27,23 @@ use std::path::Path;
use uucore::fs::is_stdin_interactive; // for Iterator::dedup() use uucore::fs::is_stdin_interactive; // for Iterator::dedup()
static NAME: &str = "sort"; static NAME: &str = "sort";
static ABOUT: &str = "sort lines of text files";
static VERSION: &str = env!("CARGO_PKG_VERSION"); static VERSION: &str = env!("CARGO_PKG_VERSION");
const OPT_NUMERIC_SORT: &str = "numeric-sort";
const OPT_HUMAN_NUMERIC_SORT: &str = "human-numeric-sort";
const OPT_MONTH_SORT: &str = "month-sort";
const OPT_VERSION_SORT: &str = "version-sort";
const OPT_OUTPUT: &str = "output";
const OPT_FILES: &str = "files";
const OPT_MERGE: &str = "merge";
const OPT_REVERSE: &str = "reverse";
const OPT_STABLE: &str = "stable";
const OPT_UNIQUE: &str = "unique";
const OPT_CHECK: &str = "check";
const OPT_DICTIONARY_ORDER: &str = "dictionary-order";
const OPT_IGNORE_CASE: &str = "ignore-case";
const DECIMAL_PT: char = '.'; const DECIMAL_PT: char = '.';
const THOUSANDS_SEP: char = ','; const THOUSANDS_SEP: char = ',';
@ -142,68 +158,9 @@ impl<'a> Iterator for FileMerger<'a> {
} }
} }
} }
fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 { format!(
let args = args.collect_str(); "{0} {1}
let mut settings: Settings = Default::default();
let mut opts = getopts::Options::new();
opts.optflag(
"d",
"dictionary-order",
"consider only blanks and alphanumeric characters",
);
opts.optflag(
"f",
"ignore-case",
"fold lower case to upper case characters",
);
opts.optflag(
"n",
"numeric-sort",
"compare according to string numerical value",
);
opts.optflag(
"h",
"human-numeric-sort",
"compare according to human readable sizes, eg 1M > 100k",
);
opts.optflag(
"M",
"month-sort",
"compare according to month name abbreviation",
);
opts.optflag("r", "reverse", "reverse the output");
opts.optflag("h", "help", "display this help and exit");
opts.optflag("", "version", "output version information and exit");
opts.optflag("m", "merge", "merge already sorted files; do not sort");
opts.optopt(
"o",
"output",
"write output to FILENAME instead of stdout",
"FILENAME",
);
opts.optflag(
"s",
"stable",
"stabilize sort by disabling last-resort comparison",
);
opts.optflag("u", "unique", "output only the first of an equal run");
opts.optflag(
"V",
"version-sort",
"Sort by SemVer version number, eg 1.12.2 > 1.1.2",
);
opts.optflag("c", "check", "check for sorted input; do not sort");
let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(f) => crash!(1, "Invalid options\n{}", f),
};
if matches.opt_present("help") {
let msg = format!(
"{0} {1}
Usage: Usage:
{0} [OPTION]... [FILE]... {0} [OPTION]... [FILE]...
@ -213,44 +170,138 @@ Write the sorted concatenation of all FILE(s) to standard output.
Mandatory arguments for long options are mandatory for short options too. Mandatory arguments for long options are mandatory for short options too.
With no FILE, or when FILE is -, read standard input.", With no FILE, or when FILE is -, read standard input.",
NAME, VERSION NAME, VERSION
); )
print!("{}", opts.usage(&msg)); }
return 0;
}
if matches.opt_present("version") { pub fn uumain(args: impl uucore::Args) -> i32 {
println!("{} {}", NAME, VERSION); let args = args.collect_str();
return 0; let usage = get_usage();
} let mut settings: Settings = Default::default();
settings.mode = if matches.opt_present("numeric-sort") { let matches = App::new(executable!())
.version(VERSION)
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_DICTIONARY_ORDER)
.short("d")
.long(OPT_DICTIONARY_ORDER)
.help("consider only blanks and alphanumeric characters"),
)
.arg(
Arg::with_name(OPT_IGNORE_CASE)
.short("f")
.long(OPT_IGNORE_CASE)
.help("fold lower case to upper case characters"),
)
.arg(
Arg::with_name(OPT_NUMERIC_SORT)
.short("n")
.long(OPT_NUMERIC_SORT)
.help("compare according to string numerical value"),
)
.arg(
Arg::with_name(OPT_HUMAN_NUMERIC_SORT)
.short("h")
.long(OPT_HUMAN_NUMERIC_SORT)
.help("compare according to human readable sizes, eg 1M > 100k"),
)
.arg(
Arg::with_name(OPT_MONTH_SORT)
.short("M")
.long(OPT_MONTH_SORT)
.help("compare according to month name abbreviation"),
)
.arg(
Arg::with_name(OPT_REVERSE)
.short("r")
.long(OPT_REVERSE)
.help("reverse the output"),
)
.arg(
Arg::with_name("h")
.long("help")
.help("display this help and exit"),
)
.arg(
Arg::with_name("version")
.long("version")
.help("output version information and exit"),
)
.arg(
Arg::with_name(OPT_MERGE)
.short("m")
.long(OPT_MERGE)
.help("merge already sorted files; do not sort"),
)
.arg(
Arg::with_name(OPT_OUTPUT)
.short("o")
.long(OPT_OUTPUT)
.help("write output to FILENAME instead of stdout")
.takes_value(true)
.value_name("FILENAME"),
)
.arg(
Arg::with_name(OPT_STABLE)
.short("s")
.long(OPT_STABLE)
.help("stabilize sort by disabling last-resort comparison"),
)
.arg(
Arg::with_name(OPT_UNIQUE)
.short("u")
.long(OPT_UNIQUE)
.help("output only the first of an equal run"),
)
.arg(
Arg::with_name(OPT_VERSION_SORT)
.short("V")
.long(OPT_VERSION_SORT)
.help("Sort by SemVer version number, eg 1.12.2 > 1.1.2"),
)
.arg(
Arg::with_name(OPT_CHECK)
.short("c")
.long(OPT_CHECK)
.help("check for sorted input; do not sort"),
)
.arg(Arg::with_name(OPT_FILES).multiple(true).takes_value(true))
.get_matches_from(args);
let mut files: Vec<String> = matches
.values_of(OPT_FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
settings.mode = if matches.is_present(OPT_NUMERIC_SORT) {
SortMode::Numeric SortMode::Numeric
} else if matches.opt_present("human-numeric-sort") { } else if matches.is_present(OPT_HUMAN_NUMERIC_SORT) {
SortMode::HumanNumeric SortMode::HumanNumeric
} else if matches.opt_present("month-sort") { } else if matches.is_present(OPT_MONTH_SORT) {
SortMode::Month SortMode::Month
} else if matches.opt_present("version-sort") { } else if matches.is_present(OPT_VERSION_SORT) {
SortMode::Version SortMode::Version
} else { } else {
SortMode::Default SortMode::Default
}; };
settings.merge = matches.opt_present("merge"); settings.merge = matches.is_present(OPT_MERGE);
settings.reverse = matches.opt_present("reverse"); settings.reverse = matches.is_present(OPT_REVERSE);
settings.outfile = matches.opt_str("output"); settings.outfile = matches.value_of(OPT_OUTPUT).map(String::from);
settings.stable = matches.opt_present("stable"); settings.stable = matches.is_present(OPT_STABLE);
settings.unique = matches.opt_present("unique"); settings.unique = matches.is_present(OPT_UNIQUE);
settings.check = matches.opt_present("check"); settings.check = matches.is_present(OPT_CHECK);
if matches.opt_present("dictionary-order") { if matches.is_present(OPT_DICTIONARY_ORDER) {
settings.transform_fns.push(remove_nondictionary_chars); settings.transform_fns.push(remove_nondictionary_chars);
} }
if matches.opt_present("ignore-case") { if matches.is_present(OPT_IGNORE_CASE) {
settings.transform_fns.push(|s| s.to_uppercase()); settings.transform_fns.push(|s| s.to_uppercase());
} }
let mut files = matches.free; //let mut files = matches.free;
if files.is_empty() { if files.is_empty() {
/* if no file, default to stdin */ /* if no file, default to stdin */
files.push("-".to_owned()); files.push("-".to_owned());