mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
basename: implement and test repeated flags and arguments
Note in particular that `args_override_self` would *NOT* work here, since it would in all cases cause `options::NAME` to override itself, or interfere with `trailing_var_arg`.
This commit is contained in:
parent
9441806a23
commit
f905d9ce41
2 changed files with 81 additions and 67 deletions
|
@ -27,86 +27,48 @@ pub mod options {
|
|||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_lossy();
|
||||
|
||||
// Since options have to go before names,
|
||||
// if the first argument is not an option, then there is no option,
|
||||
// and that implies there is exactly one name (no option => no -a option),
|
||||
// so simple format is used
|
||||
if args.len() > 1 && !args[1].starts_with('-') {
|
||||
if args.len() > 3 {
|
||||
return Err(UUsageError::new(
|
||||
1,
|
||||
format!("extra operand {}", args[3].to_string().quote()),
|
||||
));
|
||||
}
|
||||
let suffix = if args.len() > 2 { args[2].as_ref() } else { "" };
|
||||
println!("{}", basename(&args[1], suffix));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
//
|
||||
// Argument parsing
|
||||
//
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
|
||||
// too few arguments
|
||||
if !matches.contains_id(options::NAME) {
|
||||
return Err(UUsageError::new(1, "missing operand".to_string()));
|
||||
}
|
||||
|
||||
let line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO));
|
||||
|
||||
let opt_suffix = matches.get_one::<String>(options::SUFFIX).is_some();
|
||||
let opt_multiple = matches.get_flag(options::MULTIPLE);
|
||||
let multiple_paths = opt_suffix || opt_multiple;
|
||||
let name_args_count = matches
|
||||
let mut name_args = matches
|
||||
.get_many::<String>(options::NAME)
|
||||
.map(|n| n.len())
|
||||
.unwrap_or(0);
|
||||
|
||||
// too many arguments
|
||||
if !multiple_paths && name_args_count > 2 {
|
||||
.unwrap_or_default()
|
||||
.collect::<Vec<_>>();
|
||||
if name_args.is_empty() {
|
||||
return Err(UUsageError::new(1, "missing operand".to_string()));
|
||||
}
|
||||
let multiple_paths =
|
||||
matches.get_one::<String>(options::SUFFIX).is_some() || matches.get_flag(options::MULTIPLE);
|
||||
let suffix = if multiple_paths {
|
||||
matches
|
||||
.get_one::<String>(options::SUFFIX)
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
// "simple format"
|
||||
match name_args.len() {
|
||||
0 => panic!("already checked"),
|
||||
1 => String::default(),
|
||||
2 => name_args.pop().unwrap().clone(),
|
||||
_ => {
|
||||
return Err(UUsageError::new(
|
||||
1,
|
||||
format!(
|
||||
"extra operand {}",
|
||||
matches
|
||||
.get_many::<String>(options::NAME)
|
||||
.unwrap()
|
||||
.nth(2)
|
||||
.unwrap()
|
||||
.quote()
|
||||
),
|
||||
format!("extra operand {}", name_args[2].quote(),),
|
||||
));
|
||||
}
|
||||
|
||||
let suffix = if opt_suffix {
|
||||
matches.get_one::<String>(options::SUFFIX).unwrap()
|
||||
} else if !opt_multiple && name_args_count > 1 {
|
||||
matches
|
||||
.get_many::<String>(options::NAME)
|
||||
.unwrap()
|
||||
.nth(1)
|
||||
.unwrap()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Main Program Processing
|
||||
//
|
||||
|
||||
let paths: Vec<_> = if multiple_paths {
|
||||
matches.get_many::<String>(options::NAME).unwrap().collect()
|
||||
} else {
|
||||
matches
|
||||
.get_many::<String>(options::NAME)
|
||||
.unwrap()
|
||||
.take(1)
|
||||
.collect()
|
||||
};
|
||||
|
||||
for path in paths {
|
||||
print!("{}{}", basename(path, suffix), line_ending);
|
||||
for path in name_args {
|
||||
print!("{}{}", basename(path, &suffix), line_ending);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -123,27 +85,31 @@ pub fn uu_app() -> Command {
|
|||
.short('a')
|
||||
.long(options::MULTIPLE)
|
||||
.help("support multiple arguments and treat each as a NAME")
|
||||
.action(ArgAction::SetTrue),
|
||||
.action(ArgAction::SetTrue)
|
||||
.overrides_with(options::MULTIPLE),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::NAME)
|
||||
.action(clap::ArgAction::Append)
|
||||
.value_hint(clap::ValueHint::AnyPath)
|
||||
.hide(true),
|
||||
.hide(true)
|
||||
.trailing_var_arg(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::SUFFIX)
|
||||
.short('s')
|
||||
.long(options::SUFFIX)
|
||||
.value_name("SUFFIX")
|
||||
.help("remove a trailing SUFFIX; implies -a"),
|
||||
.help("remove a trailing SUFFIX; implies -a")
|
||||
.overrides_with(options::SUFFIX),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::ZERO)
|
||||
.short('z')
|
||||
.long(options::ZERO)
|
||||
.help("end each output line with NUL, not newline")
|
||||
.action(ArgAction::SetTrue),
|
||||
.action(ArgAction::SetTrue)
|
||||
.overrides_with(options::ZERO),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -202,6 +202,54 @@ fn test_invalid_arg() {
|
|||
new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeated_multiple() {
|
||||
new_ucmd!()
|
||||
.args(&["-aa", "-a", "foo"])
|
||||
.succeeds()
|
||||
.stdout_is("foo\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeated_multiple_many() {
|
||||
new_ucmd!()
|
||||
.args(&["-aa", "-a", "1/foo", "q/bar", "x/y/baz"])
|
||||
.succeeds()
|
||||
.stdout_is("foo\nbar\nbaz\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeated_suffix_last() {
|
||||
new_ucmd!()
|
||||
.args(&["-s", ".h", "-s", ".c", "foo.c"])
|
||||
.succeeds()
|
||||
.stdout_is("foo\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeated_suffix_not_first() {
|
||||
new_ucmd!()
|
||||
.args(&["-s", ".h", "-s", ".c", "foo.h"])
|
||||
.succeeds()
|
||||
.stdout_is("foo.h\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeated_suffix_multiple() {
|
||||
new_ucmd!()
|
||||
.args(&["-as", ".h", "-a", "-s", ".c", "foo.c", "bar.c", "bar.h"])
|
||||
.succeeds()
|
||||
.stdout_is("foo\nbar\nbar.h\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeated_zero() {
|
||||
new_ucmd!()
|
||||
.args(&["-zz", "-z", "foo/bar"])
|
||||
.succeeds()
|
||||
.stdout_is("bar\0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_does_not_imply_multiple() {
|
||||
new_ucmd!()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue