1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-31 04:57:45 +00:00

sort: move options to the options module

Be more consistent with other utilities
This commit is contained in:
Michael Debertol 2021-06-10 22:21:45 +02:00
parent 7e47836e94
commit cc0df6ea43

View file

@ -45,8 +45,8 @@ use std::path::PathBuf;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use uucore::InvalidEncodingHandling; use uucore::InvalidEncodingHandling;
static NAME: &str = "sort"; const NAME: &str = "sort";
static ABOUT: &str = "Display sorted concatenation of all FILE(s)."; const ABOUT: &str = "Display sorted concatenation of all FILE(s).";
const LONG_HELP_KEYS: &str = "The key format is FIELD[.CHAR][OPTIONS][,FIELD[.CHAR]][OPTIONS]. const LONG_HELP_KEYS: &str = "The key format is FIELD[.CHAR][OPTIONS][,FIELD[.CHAR]][OPTIONS].
@ -58,49 +58,53 @@ If CHAR is set 0, it means the end of the field. CHAR defaults to 1 for the star
Valid options are: MbdfhnRrV. They override the global options for this key."; Valid options are: MbdfhnRrV. They override the global options for this key.";
static OPT_HUMAN_NUMERIC_SORT: &str = "human-numeric-sort"; mod options {
static OPT_MONTH_SORT: &str = "month-sort"; pub mod modes {
static OPT_NUMERIC_SORT: &str = "numeric-sort"; pub const SORT: &str = "sort";
static OPT_GENERAL_NUMERIC_SORT: &str = "general-numeric-sort";
static OPT_VERSION_SORT: &str = "version-sort";
static OPT_SORT: &str = "sort"; pub const HUMAN_NUMERIC: &str = "human-numeric-sort";
pub const MONTH: &str = "month-sort";
pub const NUMERIC: &str = "numeric-sort";
pub const GENERAL_NUMERIC: &str = "general-numeric-sort";
pub const VERSION: &str = "version-sort";
pub const RANDOM: &str = "random-sort";
static ALL_SORT_MODES: &[&str] = &[ pub const ALL_SORT_MODES: [&str; 6] = [
OPT_GENERAL_NUMERIC_SORT, GENERAL_NUMERIC,
OPT_HUMAN_NUMERIC_SORT, HUMAN_NUMERIC,
OPT_MONTH_SORT, MONTH,
OPT_NUMERIC_SORT, NUMERIC,
OPT_VERSION_SORT, VERSION,
OPT_RANDOM, RANDOM,
]; ];
}
static OPT_DICTIONARY_ORDER: &str = "dictionary-order"; pub const DICTIONARY_ORDER: &str = "dictionary-order";
static OPT_MERGE: &str = "merge"; pub const MERGE: &str = "merge";
static OPT_CHECK: &str = "check"; pub const CHECK: &str = "check";
static OPT_CHECK_SILENT: &str = "check-silent"; pub const CHECK_SILENT: &str = "check-silent";
static OPT_DEBUG: &str = "debug"; pub const DEBUG: &str = "debug";
static OPT_IGNORE_CASE: &str = "ignore-case"; pub const IGNORE_CASE: &str = "ignore-case";
static OPT_IGNORE_BLANKS: &str = "ignore-blanks"; pub const IGNORE_BLANKS: &str = "ignore-blanks";
static OPT_IGNORE_NONPRINTING: &str = "ignore-nonprinting"; pub const IGNORE_NONPRINTING: &str = "ignore-nonprinting";
static OPT_OUTPUT: &str = "output"; pub const OUTPUT: &str = "output";
static OPT_REVERSE: &str = "reverse"; pub const REVERSE: &str = "reverse";
static OPT_STABLE: &str = "stable"; pub const STABLE: &str = "stable";
static OPT_UNIQUE: &str = "unique"; pub const UNIQUE: &str = "unique";
static OPT_KEY: &str = "key"; pub const KEY: &str = "key";
static OPT_SEPARATOR: &str = "field-separator"; pub const SEPARATOR: &str = "field-separator";
static OPT_RANDOM: &str = "random-sort"; pub const ZERO_TERMINATED: &str = "zero-terminated";
static OPT_ZERO_TERMINATED: &str = "zero-terminated"; pub const PARALLEL: &str = "parallel";
static OPT_PARALLEL: &str = "parallel"; pub const FILES0_FROM: &str = "files0-from";
static OPT_FILES0_FROM: &str = "files0-from"; pub const BUF_SIZE: &str = "buffer-size";
static OPT_BUF_SIZE: &str = "buffer-size"; pub const TMP_DIR: &str = "temporary-directory";
static OPT_TMP_DIR: &str = "temporary-directory"; pub const COMPRESS_PROG: &str = "compress-program";
static OPT_COMPRESS_PROG: &str = "compress-program"; pub const BATCH_SIZE: &str = "batch-size";
static OPT_BATCH_SIZE: &str = "batch-size";
static ARG_FILES: &str = "files"; pub const FILES: &str = "files";
}
static DECIMAL_PT: char = '.'; const DECIMAL_PT: char = '.';
const NEGATIVE: char = '-'; const NEGATIVE: char = '-';
const POSITIVE: char = '+'; const POSITIVE: char = '+';
@ -108,7 +112,7 @@ const POSITIVE: char = '+';
// Choosing a higher buffer size does not result in performance improvements // Choosing a higher buffer size does not result in performance improvements
// (at least not on my machine). TODO: In the future, we should also take the amount of // (at least not on my machine). TODO: In the future, we should also take the amount of
// available memory into consideration, instead of relying on this constant only. // available memory into consideration, instead of relying on this constant only.
static DEFAULT_BUF_SIZE: usize = 1_000_000_000; // 1 GB const DEFAULT_BUF_SIZE: usize = 1_000_000_000; // 1 GB
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Copy, Debug)] #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Copy, Debug)]
enum SortMode { enum SortMode {
@ -889,9 +893,10 @@ 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> { 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); let mut arg = Arg::with_name(mode).short(short).long(mode).help(help);
for possible_mode in ALL_SORT_MODES { for possible_mode in &options::modes::ALL_SORT_MODES {
if *possible_mode != mode { if *possible_mode != mode {
arg = arg.conflicts_with(possible_mode); arg = arg.conflicts_with(possible_mode);
} }
@ -911,8 +916,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.about(ABOUT) .about(ABOUT)
.usage(&usage[..]) .usage(&usage[..])
.arg( .arg(
Arg::with_name(OPT_SORT) Arg::with_name(options::modes::SORT)
.long(OPT_SORT) .long(options::modes::SORT)
.takes_value(true) .takes_value(true)
.possible_values( .possible_values(
&[ &[
@ -924,199 +929,213 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
"random", "random",
] ]
) )
.conflicts_with_all(ALL_SORT_MODES) .conflicts_with_all(&options::modes::ALL_SORT_MODES)
) )
.arg( .arg(
make_sort_mode_arg( make_sort_mode_arg(
OPT_HUMAN_NUMERIC_SORT, options::modes::HUMAN_NUMERIC,
"h", "h",
"compare according to human readable sizes, eg 1M > 100k" "compare according to human readable sizes, eg 1M > 100k"
), ),
) )
.arg( .arg(
make_sort_mode_arg( make_sort_mode_arg(
OPT_MONTH_SORT, options::modes::MONTH,
"M", "M",
"compare according to month name abbreviation" "compare according to month name abbreviation"
), ),
) )
.arg( .arg(
make_sort_mode_arg( make_sort_mode_arg(
OPT_NUMERIC_SORT, options::modes::NUMERIC,
"n", "n",
"compare according to string numerical value" "compare according to string numerical value"
), ),
) )
.arg( .arg(
make_sort_mode_arg( make_sort_mode_arg(
OPT_GENERAL_NUMERIC_SORT, options::modes::GENERAL_NUMERIC,
"g", "g",
"compare according to string general numerical value" "compare according to string general numerical value"
), ),
) )
.arg( .arg(
make_sort_mode_arg( make_sort_mode_arg(
OPT_VERSION_SORT, options::modes::VERSION,
"V", "V",
"Sort by SemVer version number, eg 1.12.2 > 1.1.2", "Sort by SemVer version number, eg 1.12.2 > 1.1.2",
), ),
) )
.arg( .arg(
make_sort_mode_arg( make_sort_mode_arg(
OPT_RANDOM, options::modes::RANDOM,
"R", "R",
"shuffle in random order", "shuffle in random order",
), ),
) )
.arg( .arg(
Arg::with_name(OPT_DICTIONARY_ORDER) Arg::with_name(options::DICTIONARY_ORDER)
.short("d") .short("d")
.long(OPT_DICTIONARY_ORDER) .long(options::DICTIONARY_ORDER)
.help("consider only blanks and alphanumeric characters") .help("consider only blanks and alphanumeric characters")
.conflicts_with_all(&[OPT_NUMERIC_SORT, OPT_GENERAL_NUMERIC_SORT, OPT_HUMAN_NUMERIC_SORT, OPT_MONTH_SORT]), .conflicts_with_all(
&[
options::modes::NUMERIC,
options::modes::GENERAL_NUMERIC,
options::modes::HUMAN_NUMERIC,
options::modes::MONTH,
]
),
) )
.arg( .arg(
Arg::with_name(OPT_MERGE) Arg::with_name(options::MERGE)
.short("m") .short("m")
.long(OPT_MERGE) .long(options::MERGE)
.help("merge already sorted files; do not sort"), .help("merge already sorted files; do not sort"),
) )
.arg( .arg(
Arg::with_name(OPT_CHECK) Arg::with_name(options::CHECK)
.short("c") .short("c")
.long(OPT_CHECK) .long(options::CHECK)
.help("check for sorted input; do not sort"), .help("check for sorted input; do not sort"),
) )
.arg( .arg(
Arg::with_name(OPT_CHECK_SILENT) Arg::with_name(options::CHECK_SILENT)
.short("C") .short("C")
.long(OPT_CHECK_SILENT) .long(options::CHECK_SILENT)
.help("exit successfully if the given file is already sorted, and exit with status 1 otherwise."), .help("exit successfully if the given file is already sorted, and exit with status 1 otherwise."),
) )
.arg( .arg(
Arg::with_name(OPT_IGNORE_CASE) Arg::with_name(options::IGNORE_CASE)
.short("f") .short("f")
.long(OPT_IGNORE_CASE) .long(options::IGNORE_CASE)
.help("fold lower case to upper case characters"), .help("fold lower case to upper case characters"),
) )
.arg( .arg(
Arg::with_name(OPT_IGNORE_NONPRINTING) Arg::with_name(options::IGNORE_NONPRINTING)
.short("i") .short("i")
.long(OPT_IGNORE_NONPRINTING) .long(options::IGNORE_NONPRINTING)
.help("ignore nonprinting characters") .help("ignore nonprinting characters")
.conflicts_with_all(&[OPT_NUMERIC_SORT, OPT_GENERAL_NUMERIC_SORT, OPT_HUMAN_NUMERIC_SORT, OPT_MONTH_SORT]), .conflicts_with_all(
&[
options::modes::NUMERIC,
options::modes::GENERAL_NUMERIC,
options::modes::HUMAN_NUMERIC,
options::modes::MONTH
]
),
) )
.arg( .arg(
Arg::with_name(OPT_IGNORE_BLANKS) Arg::with_name(options::IGNORE_BLANKS)
.short("b") .short("b")
.long(OPT_IGNORE_BLANKS) .long(options::IGNORE_BLANKS)
.help("ignore leading blanks when finding sort keys in each line"), .help("ignore leading blanks when finding sort keys in each line"),
) )
.arg( .arg(
Arg::with_name(OPT_OUTPUT) Arg::with_name(options::OUTPUT)
.short("o") .short("o")
.long(OPT_OUTPUT) .long(options::OUTPUT)
.help("write output to FILENAME instead of stdout") .help("write output to FILENAME instead of stdout")
.takes_value(true) .takes_value(true)
.value_name("FILENAME"), .value_name("FILENAME"),
) )
.arg( .arg(
Arg::with_name(OPT_REVERSE) Arg::with_name(options::REVERSE)
.short("r") .short("r")
.long(OPT_REVERSE) .long(options::REVERSE)
.help("reverse the output"), .help("reverse the output"),
) )
.arg( .arg(
Arg::with_name(OPT_STABLE) Arg::with_name(options::STABLE)
.short("s") .short("s")
.long(OPT_STABLE) .long(options::STABLE)
.help("stabilize sort by disabling last-resort comparison"), .help("stabilize sort by disabling last-resort comparison"),
) )
.arg( .arg(
Arg::with_name(OPT_UNIQUE) Arg::with_name(options::UNIQUE)
.short("u") .short("u")
.long(OPT_UNIQUE) .long(options::UNIQUE)
.help("output only the first of an equal run"), .help("output only the first of an equal run"),
) )
.arg( .arg(
Arg::with_name(OPT_KEY) Arg::with_name(options::KEY)
.short("k") .short("k")
.long(OPT_KEY) .long(options::KEY)
.help("sort by a key") .help("sort by a key")
.long_help(LONG_HELP_KEYS) .long_help(LONG_HELP_KEYS)
.multiple(true) .multiple(true)
.takes_value(true), .takes_value(true),
) )
.arg( .arg(
Arg::with_name(OPT_SEPARATOR) Arg::with_name(options::SEPARATOR)
.short("t") .short("t")
.long(OPT_SEPARATOR) .long(options::SEPARATOR)
.help("custom separator for -k") .help("custom separator for -k")
.takes_value(true)) .takes_value(true))
.arg( .arg(
Arg::with_name(OPT_ZERO_TERMINATED) Arg::with_name(options::ZERO_TERMINATED)
.short("z") .short("z")
.long(OPT_ZERO_TERMINATED) .long(options::ZERO_TERMINATED)
.help("line delimiter is NUL, not newline"), .help("line delimiter is NUL, not newline"),
) )
.arg( .arg(
Arg::with_name(OPT_PARALLEL) Arg::with_name(options::PARALLEL)
.long(OPT_PARALLEL) .long(options::PARALLEL)
.help("change the number of threads running concurrently to NUM_THREADS") .help("change the number of threads running concurrently to NUM_THREADS")
.takes_value(true) .takes_value(true)
.value_name("NUM_THREADS"), .value_name("NUM_THREADS"),
) )
.arg( .arg(
Arg::with_name(OPT_BUF_SIZE) Arg::with_name(options::BUF_SIZE)
.short("S") .short("S")
.long(OPT_BUF_SIZE) .long(options::BUF_SIZE)
.help("sets the maximum SIZE of each segment in number of sorted items") .help("sets the maximum SIZE of each segment in number of sorted items")
.takes_value(true) .takes_value(true)
.value_name("SIZE"), .value_name("SIZE"),
) )
.arg( .arg(
Arg::with_name(OPT_TMP_DIR) Arg::with_name(options::TMP_DIR)
.short("T") .short("T")
.long(OPT_TMP_DIR) .long(options::TMP_DIR)
.help("use DIR for temporaries, not $TMPDIR or /tmp") .help("use DIR for temporaries, not $TMPDIR or /tmp")
.takes_value(true) .takes_value(true)
.value_name("DIR"), .value_name("DIR"),
) )
.arg( .arg(
Arg::with_name(OPT_COMPRESS_PROG) Arg::with_name(options::COMPRESS_PROG)
.long(OPT_COMPRESS_PROG) .long(options::COMPRESS_PROG)
.help("compress temporary files with PROG, decompress with PROG -d") .help("compress temporary files with PROG, decompress with PROG -d")
.long_help("PROG has to take input from stdin and output to stdout") .long_help("PROG has to take input from stdin and output to stdout")
.value_name("PROG") .value_name("PROG")
) )
.arg( .arg(
Arg::with_name(OPT_BATCH_SIZE) Arg::with_name(options::BATCH_SIZE)
.long(OPT_BATCH_SIZE) .long(options::BATCH_SIZE)
.help("Merge at most N_MERGE inputs at once.") .help("Merge at most N_MERGE inputs at once.")
.value_name("N_MERGE") .value_name("N_MERGE")
) )
.arg( .arg(
Arg::with_name(OPT_FILES0_FROM) Arg::with_name(options::FILES0_FROM)
.long(OPT_FILES0_FROM) .long(options::FILES0_FROM)
.help("read input from the files specified by NUL-terminated NUL_FILES") .help("read input from the files specified by NUL-terminated NUL_FILES")
.takes_value(true) .takes_value(true)
.value_name("NUL_FILES") .value_name("NUL_FILES")
.multiple(true), .multiple(true),
) )
.arg( .arg(
Arg::with_name(OPT_DEBUG) Arg::with_name(options::DEBUG)
.long(OPT_DEBUG) .long(options::DEBUG)
.help("underline the parts of the line that are actually used for sorting"), .help("underline the parts of the line that are actually used for sorting"),
) )
.arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true)) .arg(Arg::with_name(options::FILES).multiple(true).takes_value(true))
.get_matches_from(args); .get_matches_from(args);
settings.debug = matches.is_present(OPT_DEBUG); settings.debug = matches.is_present(options::DEBUG);
// check whether user specified a zero terminated list of files for input, otherwise read files from args // check whether user specified a zero terminated list of files for input, otherwise read files from args
let mut files: Vec<String> = if matches.is_present(OPT_FILES0_FROM) { let mut files: Vec<String> = if matches.is_present(options::FILES0_FROM) {
let files0_from: Vec<String> = matches let files0_from: Vec<String> = matches
.values_of(OPT_FILES0_FROM) .values_of(options::FILES0_FROM)
.map(|v| v.map(ToString::to_string).collect()) .map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default(); .unwrap_or_default();
@ -1135,80 +1154,86 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
files files
} else { } else {
matches matches
.values_of(ARG_FILES) .values_of(options::FILES)
.map(|v| v.map(ToString::to_string).collect()) .map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default() .unwrap_or_default()
}; };
settings.mode = if matches.is_present(OPT_HUMAN_NUMERIC_SORT) settings.mode = if matches.is_present(options::modes::HUMAN_NUMERIC)
|| matches.value_of(OPT_SORT) == Some("human-numeric") || matches.value_of(options::modes::SORT) == Some("human-numeric")
{ {
SortMode::HumanNumeric SortMode::HumanNumeric
} else if matches.is_present(OPT_MONTH_SORT) || matches.value_of(OPT_SORT) == Some("month") { } else if matches.is_present(options::modes::MONTH)
|| matches.value_of(options::modes::SORT) == Some("month")
{
SortMode::Month SortMode::Month
} else if matches.is_present(OPT_GENERAL_NUMERIC_SORT) } else if matches.is_present(options::modes::GENERAL_NUMERIC)
|| matches.value_of(OPT_SORT) == Some("general-numeric") || matches.value_of(options::modes::SORT) == Some("general-numeric")
{ {
SortMode::GeneralNumeric SortMode::GeneralNumeric
} else if matches.is_present(OPT_NUMERIC_SORT) || matches.value_of(OPT_SORT) == Some("numeric") } else if matches.is_present(options::modes::NUMERIC)
|| matches.value_of(options::modes::SORT) == Some("numeric")
{ {
SortMode::Numeric SortMode::Numeric
} else if matches.is_present(OPT_VERSION_SORT) || matches.value_of(OPT_SORT) == Some("version") } else if matches.is_present(options::modes::VERSION)
|| matches.value_of(options::modes::SORT) == Some("version")
{ {
SortMode::Version SortMode::Version
} else if matches.is_present(OPT_RANDOM) || matches.value_of(OPT_SORT) == Some("random") { } else if matches.is_present(options::modes::RANDOM)
|| matches.value_of(options::modes::SORT) == Some("random")
{
settings.salt = get_rand_string(); settings.salt = get_rand_string();
SortMode::Random SortMode::Random
} else { } else {
SortMode::Default SortMode::Default
}; };
settings.dictionary_order = matches.is_present(OPT_DICTIONARY_ORDER); settings.dictionary_order = matches.is_present(options::DICTIONARY_ORDER);
settings.ignore_non_printing = matches.is_present(OPT_IGNORE_NONPRINTING); settings.ignore_non_printing = matches.is_present(options::IGNORE_NONPRINTING);
if matches.is_present(OPT_PARALLEL) { if matches.is_present(options::PARALLEL) {
// "0" is default - threads = num of cores // "0" is default - threads = num of cores
settings.threads = matches settings.threads = matches
.value_of(OPT_PARALLEL) .value_of(options::PARALLEL)
.map(String::from) .map(String::from)
.unwrap_or_else(|| "0".to_string()); .unwrap_or_else(|| "0".to_string());
env::set_var("RAYON_NUM_THREADS", &settings.threads); env::set_var("RAYON_NUM_THREADS", &settings.threads);
} }
settings.buffer_size = matches settings.buffer_size = matches
.value_of(OPT_BUF_SIZE) .value_of(options::BUF_SIZE)
.map(GlobalSettings::parse_byte_count) .map(GlobalSettings::parse_byte_count)
.unwrap_or(DEFAULT_BUF_SIZE); .unwrap_or(DEFAULT_BUF_SIZE);
settings.tmp_dir = matches settings.tmp_dir = matches
.value_of(OPT_TMP_DIR) .value_of(options::TMP_DIR)
.map(PathBuf::from) .map(PathBuf::from)
.unwrap_or_else(env::temp_dir); .unwrap_or_else(env::temp_dir);
settings.compress_prog = matches.value_of(OPT_COMPRESS_PROG).map(String::from); settings.compress_prog = matches.value_of(options::COMPRESS_PROG).map(String::from);
if let Some(n_merge) = matches.value_of(OPT_BATCH_SIZE) { if let Some(n_merge) = matches.value_of(options::BATCH_SIZE) {
settings.merge_batch_size = n_merge settings.merge_batch_size = n_merge
.parse() .parse()
.unwrap_or_else(|_| crash!(2, "invalid --batch-size argument '{}'", n_merge)); .unwrap_or_else(|_| crash!(2, "invalid --batch-size argument '{}'", n_merge));
} }
settings.zero_terminated = matches.is_present(OPT_ZERO_TERMINATED); settings.zero_terminated = matches.is_present(options::ZERO_TERMINATED);
settings.merge = matches.is_present(OPT_MERGE); settings.merge = matches.is_present(options::MERGE);
settings.check = matches.is_present(OPT_CHECK); settings.check = matches.is_present(options::CHECK);
if matches.is_present(OPT_CHECK_SILENT) { if matches.is_present(options::CHECK_SILENT) {
settings.check_silent = matches.is_present(OPT_CHECK_SILENT); settings.check_silent = matches.is_present(options::CHECK_SILENT);
settings.check = true; settings.check = true;
}; };
settings.ignore_case = matches.is_present(OPT_IGNORE_CASE); settings.ignore_case = matches.is_present(options::IGNORE_CASE);
settings.ignore_blanks = matches.is_present(OPT_IGNORE_BLANKS); settings.ignore_blanks = matches.is_present(options::IGNORE_BLANKS);
settings.output_file = matches.value_of(OPT_OUTPUT).map(String::from); settings.output_file = matches.value_of(options::OUTPUT).map(String::from);
settings.reverse = matches.is_present(OPT_REVERSE); settings.reverse = matches.is_present(options::REVERSE);
settings.stable = matches.is_present(OPT_STABLE); settings.stable = matches.is_present(options::STABLE);
settings.unique = matches.is_present(OPT_UNIQUE); settings.unique = matches.is_present(options::UNIQUE);
if files.is_empty() { if files.is_empty() {
/* if no file, default to stdin */ /* if no file, default to stdin */
@ -1217,7 +1242,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
crash!(1, "extra operand `{}' not allowed with -c", files[1]) crash!(1, "extra operand `{}' not allowed with -c", files[1])
} }
if let Some(arg) = matches.args.get(OPT_SEPARATOR) { if let Some(arg) = matches.args.get(options::SEPARATOR) {
let separator = arg.vals[0].to_string_lossy(); let separator = arg.vals[0].to_string_lossy();
let separator = separator; let separator = separator;
if separator.len() != 1 { if separator.len() != 1 {
@ -1226,15 +1251,15 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
settings.separator = Some(separator.chars().next().unwrap()) settings.separator = Some(separator.chars().next().unwrap())
} }
if matches.is_present(OPT_KEY) { if matches.is_present(options::KEY) {
for key in &matches.args[OPT_KEY].vals { for key in &matches.args[options::KEY].vals {
settings settings
.selectors .selectors
.push(FieldSelector::parse(&key.to_string_lossy(), &settings)); .push(FieldSelector::parse(&key.to_string_lossy(), &settings));
} }
} }
if !matches.is_present(OPT_KEY) { if !matches.is_present(options::KEY) {
// add a default selector matching the whole line // add a default selector matching the whole line
let key_settings = KeySettings::from(&settings); let key_settings = KeySettings::from(&settings);
settings.selectors.push( settings.selectors.push(