mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Merge pull request #5989 from BenWiederhake/dev-shuf-echo-anywhere
shuf: treat -e as a flag, not as a multi-value arg
This commit is contained in:
commit
69ea02d9b0
2 changed files with 97 additions and 17 deletions
|
@ -12,7 +12,7 @@ use rand::RngCore;
|
|||
use std::fs::File;
|
||||
use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write};
|
||||
use uucore::display::Quotable;
|
||||
use uucore::error::{FromIo, UResult, USimpleError};
|
||||
use uucore::error::{FromIo, UResult, USimpleError, UUsageError};
|
||||
use uucore::{format_usage, help_about, help_usage};
|
||||
|
||||
mod rand_read_adapter;
|
||||
|
@ -42,15 +42,21 @@ mod options {
|
|||
pub static RANDOM_SOURCE: &str = "random-source";
|
||||
pub static REPEAT: &str = "repeat";
|
||||
pub static ZERO_TERMINATED: &str = "zero-terminated";
|
||||
pub static FILE: &str = "file";
|
||||
pub static FILE_OR_ARGS: &str = "file-or-args";
|
||||
}
|
||||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
let mode = if let Some(args) = matches.get_many::<String>(options::ECHO) {
|
||||
Mode::Echo(args.map(String::from).collect())
|
||||
let mode = if matches.get_flag(options::ECHO) {
|
||||
Mode::Echo(
|
||||
matches
|
||||
.get_many::<String>(options::FILE_OR_ARGS)
|
||||
.unwrap_or_default()
|
||||
.map(String::from)
|
||||
.collect(),
|
||||
)
|
||||
} else if let Some(range) = matches.get_one::<String>(options::INPUT_RANGE) {
|
||||
match parse_range(range) {
|
||||
Ok(m) => Mode::InputRange(m),
|
||||
|
@ -59,13 +65,17 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Mode::Default(
|
||||
matches
|
||||
.get_one::<String>(options::FILE)
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or("-")
|
||||
.to_string(),
|
||||
)
|
||||
let mut operands = matches
|
||||
.get_many::<String>(options::FILE_OR_ARGS)
|
||||
.unwrap_or_default();
|
||||
let file = operands.next().cloned().unwrap_or("-".into());
|
||||
if let Some(second_file) = operands.next() {
|
||||
return Err(UUsageError::new(
|
||||
1,
|
||||
format!("unexpected argument '{second_file}' found"),
|
||||
));
|
||||
};
|
||||
Mode::Default(file)
|
||||
};
|
||||
|
||||
let options = Options {
|
||||
|
@ -124,11 +134,9 @@ pub fn uu_app() -> Command {
|
|||
Arg::new(options::ECHO)
|
||||
.short('e')
|
||||
.long(options::ECHO)
|
||||
.value_name("ARG")
|
||||
.help("treat each ARG as an input line")
|
||||
.use_value_delimiter(false)
|
||||
.num_args(0..)
|
||||
.action(clap::ArgAction::Append)
|
||||
.action(clap::ArgAction::SetTrue)
|
||||
.overrides_with(options::ECHO)
|
||||
.conflicts_with(options::INPUT_RANGE),
|
||||
)
|
||||
.arg(
|
||||
|
@ -137,7 +145,7 @@ pub fn uu_app() -> Command {
|
|||
.long(options::INPUT_RANGE)
|
||||
.value_name("LO-HI")
|
||||
.help("treat each number LO through HI as an input line")
|
||||
.conflicts_with(options::FILE),
|
||||
.conflicts_with(options::FILE_OR_ARGS),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::HEAD_COUNT)
|
||||
|
@ -178,7 +186,11 @@ pub fn uu_app() -> Command {
|
|||
.action(ArgAction::SetTrue)
|
||||
.overrides_with(options::ZERO_TERMINATED),
|
||||
)
|
||||
.arg(Arg::new(options::FILE).value_hint(clap::ValueHint::FilePath))
|
||||
.arg(
|
||||
Arg::new(options::FILE_OR_ARGS)
|
||||
.action(clap::ArgAction::Append)
|
||||
.value_hint(clap::ValueHint::FilePath),
|
||||
)
|
||||
}
|
||||
|
||||
fn read_input_file(filename: &str) -> UResult<Vec<u8>> {
|
||||
|
|
|
@ -32,6 +32,28 @@ fn test_output_is_random_permutation() {
|
|||
assert_eq!(result_seq, input_seq, "Output is not a permutation");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_explicit_stdin_file() {
|
||||
let input_seq = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
let input = input_seq
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
|
||||
let result = new_ucmd!().arg("-").pipe_in(input.as_bytes()).succeeds();
|
||||
result.no_stderr();
|
||||
|
||||
let mut result_seq: Vec<i32> = result
|
||||
.stdout_str()
|
||||
.split('\n')
|
||||
.filter(|x| !x.is_empty())
|
||||
.map(|x| x.parse().unwrap())
|
||||
.collect();
|
||||
result_seq.sort_unstable();
|
||||
assert_eq!(result_seq, input_seq, "Output is not a permutation");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_termination() {
|
||||
let input_seq = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
|
@ -116,6 +138,36 @@ fn test_echo_multi() {
|
|||
assert_eq!(result_seq, ["a", "b", "c"], "Output is not a permutation");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_echo_postfix() {
|
||||
let result = new_ucmd!().arg("a").arg("b").arg("c").arg("-e").succeeds();
|
||||
result.no_stderr();
|
||||
|
||||
let mut result_seq: Vec<String> = result
|
||||
.stdout_str()
|
||||
.split('\n')
|
||||
.filter(|x| !x.is_empty())
|
||||
.map(|x| x.into())
|
||||
.collect();
|
||||
result_seq.sort_unstable();
|
||||
assert_eq!(result_seq, ["a", "b", "c"], "Output is not a permutation");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_echo_short_collapsed_zero() {
|
||||
let result = new_ucmd!().arg("-ez").arg("a").arg("b").arg("c").succeeds();
|
||||
result.no_stderr();
|
||||
|
||||
let mut result_seq: Vec<String> = result
|
||||
.stdout_str()
|
||||
.split('\0')
|
||||
.filter(|x| !x.is_empty())
|
||||
.map(|x| x.parse().unwrap())
|
||||
.collect();
|
||||
result_seq.sort_unstable();
|
||||
assert_eq!(result_seq, ["a", "b", "c"], "Output is not a permutation");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_head_count() {
|
||||
let repeat_limit = 5;
|
||||
|
@ -365,6 +417,22 @@ fn test_shuf_multiple_outputs() {
|
|||
.stderr_contains("cannot be used multiple times");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shuf_two_input_files() {
|
||||
new_ucmd!()
|
||||
.args(&["file_a", "file_b"])
|
||||
.fails()
|
||||
.stderr_contains("unexpected argument 'file_b' found");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shuf_three_input_files() {
|
||||
new_ucmd!()
|
||||
.args(&["file_a", "file_b", "file_c"])
|
||||
.fails()
|
||||
.stderr_contains("unexpected argument 'file_b' found");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shuf_invalid_input_line_count() {
|
||||
new_ucmd!()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue