mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Merge pull request #5962 from wolimst/cut/fix/multiple-mode-args
cut: show error for multiple mode args (`-b`, `-c`, `-f`)
This commit is contained in:
commit
6adaf31d49
2 changed files with 48 additions and 7 deletions
|
@ -359,12 +359,25 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
|
||||||
let complement = matches.get_flag(options::COMPLEMENT);
|
let complement = matches.get_flag(options::COMPLEMENT);
|
||||||
|
|
||||||
|
// Only one, and only one of cutting mode arguments, i.e. `-b`, `-c`, `-f`,
|
||||||
|
// is expected. The number of those arguments is used for parsing a cutting
|
||||||
|
// mode and handling the error cases.
|
||||||
|
let mode_args_count = [
|
||||||
|
matches.indices_of(options::BYTES),
|
||||||
|
matches.indices_of(options::CHARACTERS),
|
||||||
|
matches.indices_of(options::FIELDS),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.map(|indices| indices.unwrap_or_default().count())
|
||||||
|
.sum();
|
||||||
|
|
||||||
let mode_parse = match (
|
let mode_parse = match (
|
||||||
|
mode_args_count,
|
||||||
matches.get_one::<String>(options::BYTES),
|
matches.get_one::<String>(options::BYTES),
|
||||||
matches.get_one::<String>(options::CHARACTERS),
|
matches.get_one::<String>(options::CHARACTERS),
|
||||||
matches.get_one::<String>(options::FIELDS),
|
matches.get_one::<String>(options::FIELDS),
|
||||||
) {
|
) {
|
||||||
(Some(byte_ranges), None, None) => list_to_ranges(byte_ranges, complement).map(|ranges| {
|
(1, Some(byte_ranges), None, None) => list_to_ranges(byte_ranges, complement).map(|ranges| {
|
||||||
Mode::Bytes(
|
Mode::Bytes(
|
||||||
ranges,
|
ranges,
|
||||||
Options {
|
Options {
|
||||||
|
@ -379,7 +392,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
(None, Some(char_ranges), None) => list_to_ranges(char_ranges, complement).map(|ranges| {
|
(1, None, Some(char_ranges), None) => list_to_ranges(char_ranges, complement).map(|ranges| {
|
||||||
Mode::Characters(
|
Mode::Characters(
|
||||||
ranges,
|
ranges,
|
||||||
Options {
|
Options {
|
||||||
|
@ -394,7 +407,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
(None, None, Some(field_ranges)) => {
|
(1, None, None, Some(field_ranges)) => {
|
||||||
list_to_ranges(field_ranges, complement).and_then(|ranges| {
|
list_to_ranges(field_ranges, complement).and_then(|ranges| {
|
||||||
let out_delim = match matches.get_one::<String>(options::OUTPUT_DELIMITER) {
|
let out_delim = match matches.get_one::<String>(options::OUTPUT_DELIMITER) {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
|
@ -461,7 +474,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(ref b, ref c, ref f) if b.is_some() || c.is_some() || f.is_some() => Err(
|
(2.., _, _, _) => Err(
|
||||||
"invalid usage: expects no more than one of --fields (-f), --chars (-c) or --bytes (-b)".into()
|
"invalid usage: expects no more than one of --fields (-f), --chars (-c) or --bytes (-b)".into()
|
||||||
),
|
),
|
||||||
_ => Err("invalid usage: expects one of --fields (-f), --chars (-c) or --bytes (-b)".into()),
|
_ => Err("invalid usage: expects one of --fields (-f), --chars (-c) or --bytes (-b)".into()),
|
||||||
|
@ -511,6 +524,13 @@ pub fn uu_app() -> Command {
|
||||||
.about(ABOUT)
|
.about(ABOUT)
|
||||||
.after_help(AFTER_HELP)
|
.after_help(AFTER_HELP)
|
||||||
.infer_long_args(true)
|
.infer_long_args(true)
|
||||||
|
// While `args_override_self(true)` for some arguments, such as `-d`
|
||||||
|
// and `--output-delimiter`, is consistent to the behavior of GNU cut,
|
||||||
|
// arguments related to cutting mode, i.e. `-b`, `-c`, `-f`, should
|
||||||
|
// cause an error when there is more than one of them, as described in
|
||||||
|
// the manual of GNU cut: "Use one, and only one of -b, -c or -f".
|
||||||
|
// `ArgAction::Append` is used on `-b`, `-c`, `-f` arguments, so that
|
||||||
|
// the occurrences of those could be counted and be handled accordingly.
|
||||||
.args_override_self(true)
|
.args_override_self(true)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::BYTES)
|
Arg::new(options::BYTES)
|
||||||
|
@ -518,7 +538,8 @@ pub fn uu_app() -> Command {
|
||||||
.long(options::BYTES)
|
.long(options::BYTES)
|
||||||
.help("filter byte columns from the input source")
|
.help("filter byte columns from the input source")
|
||||||
.allow_hyphen_values(true)
|
.allow_hyphen_values(true)
|
||||||
.value_name("LIST"),
|
.value_name("LIST")
|
||||||
|
.action(ArgAction::Append),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::CHARACTERS)
|
Arg::new(options::CHARACTERS)
|
||||||
|
@ -526,7 +547,8 @@ pub fn uu_app() -> Command {
|
||||||
.long(options::CHARACTERS)
|
.long(options::CHARACTERS)
|
||||||
.help("alias for character mode")
|
.help("alias for character mode")
|
||||||
.allow_hyphen_values(true)
|
.allow_hyphen_values(true)
|
||||||
.value_name("LIST"),
|
.value_name("LIST")
|
||||||
|
.action(ArgAction::Append),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::DELIMITER)
|
Arg::new(options::DELIMITER)
|
||||||
|
@ -548,7 +570,8 @@ pub fn uu_app() -> Command {
|
||||||
.long(options::FIELDS)
|
.long(options::FIELDS)
|
||||||
.help("filter field columns from the input source")
|
.help("filter field columns from the input source")
|
||||||
.allow_hyphen_values(true)
|
.allow_hyphen_values(true)
|
||||||
.value_name("LIST"),
|
.value_name("LIST")
|
||||||
|
.action(ArgAction::Append),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::COMPLEMENT)
|
Arg::new(options::COMPLEMENT)
|
||||||
|
|
|
@ -270,3 +270,21 @@ fn test_multiple() {
|
||||||
assert_eq!(result.stdout_str(), "b\n");
|
assert_eq!(result.stdout_str(), "b\n");
|
||||||
assert_eq!(result.stderr_str(), "");
|
assert_eq!(result.stderr_str(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiple_mode_args() {
|
||||||
|
for args in [
|
||||||
|
vec!["-b1", "-b2"],
|
||||||
|
vec!["-c1", "-c2"],
|
||||||
|
vec!["-f1", "-f2"],
|
||||||
|
vec!["-b1", "-c2"],
|
||||||
|
vec!["-b1", "-f2"],
|
||||||
|
vec!["-c1", "-f2"],
|
||||||
|
vec!["-b1", "-c2", "-f3"],
|
||||||
|
] {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&args)
|
||||||
|
.fails()
|
||||||
|
.stderr_is("cut: invalid usage: expects no more than one of --fields (-f), --chars (-c) or --bytes (-b)\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue