mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37: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<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let args = args.collect_lossy();
|
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
|
// Argument parsing
|
||||||
//
|
//
|
||||||
let matches = uu_app().try_get_matches_from(args)?;
|
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 line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO));
|
||||||
|
|
||||||
let opt_suffix = matches.get_one::<String>(options::SUFFIX).is_some();
|
let mut name_args = matches
|
||||||
let opt_multiple = matches.get_flag(options::MULTIPLE);
|
|
||||||
let multiple_paths = opt_suffix || opt_multiple;
|
|
||||||
let name_args_count = matches
|
|
||||||
.get_many::<String>(options::NAME)
|
.get_many::<String>(options::NAME)
|
||||||
.map(|n| n.len())
|
.unwrap_or_default()
|
||||||
.unwrap_or(0);
|
.collect::<Vec<_>>();
|
||||||
|
if name_args.is_empty() {
|
||||||
// too many arguments
|
return Err(UUsageError::new(1, "missing operand".to_string()));
|
||||||
if !multiple_paths && name_args_count > 2 {
|
}
|
||||||
|
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(
|
return Err(UUsageError::new(
|
||||||
1,
|
1,
|
||||||
format!(
|
format!("extra operand {}", name_args[2].quote(),),
|
||||||
"extra operand {}",
|
|
||||||
matches
|
|
||||||
.get_many::<String>(options::NAME)
|
|
||||||
.unwrap()
|
|
||||||
.nth(2)
|
|
||||||
.unwrap()
|
|
||||||
.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
|
// Main Program Processing
|
||||||
//
|
//
|
||||||
|
|
||||||
let paths: Vec<_> = if multiple_paths {
|
for path in name_args {
|
||||||
matches.get_many::<String>(options::NAME).unwrap().collect()
|
print!("{}{}", basename(path, &suffix), line_ending);
|
||||||
} else {
|
|
||||||
matches
|
|
||||||
.get_many::<String>(options::NAME)
|
|
||||||
.unwrap()
|
|
||||||
.take(1)
|
|
||||||
.collect()
|
|
||||||
};
|
|
||||||
|
|
||||||
for path in paths {
|
|
||||||
print!("{}{}", basename(path, suffix), line_ending);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -123,27 +85,31 @@ pub fn uu_app() -> Command {
|
||||||
.short('a')
|
.short('a')
|
||||||
.long(options::MULTIPLE)
|
.long(options::MULTIPLE)
|
||||||
.help("support multiple arguments and treat each as a NAME")
|
.help("support multiple arguments and treat each as a NAME")
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue)
|
||||||
|
.overrides_with(options::MULTIPLE),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::NAME)
|
Arg::new(options::NAME)
|
||||||
.action(clap::ArgAction::Append)
|
.action(clap::ArgAction::Append)
|
||||||
.value_hint(clap::ValueHint::AnyPath)
|
.value_hint(clap::ValueHint::AnyPath)
|
||||||
.hide(true),
|
.hide(true)
|
||||||
|
.trailing_var_arg(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::SUFFIX)
|
Arg::new(options::SUFFIX)
|
||||||
.short('s')
|
.short('s')
|
||||||
.long(options::SUFFIX)
|
.long(options::SUFFIX)
|
||||||
.value_name("SUFFIX")
|
.value_name("SUFFIX")
|
||||||
.help("remove a trailing SUFFIX; implies -a"),
|
.help("remove a trailing SUFFIX; implies -a")
|
||||||
|
.overrides_with(options::SUFFIX),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::ZERO)
|
Arg::new(options::ZERO)
|
||||||
.short('z')
|
.short('z')
|
||||||
.long(options::ZERO)
|
.long(options::ZERO)
|
||||||
.help("end each output line with NUL, not newline")
|
.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);
|
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]
|
#[test]
|
||||||
fn test_zero_does_not_imply_multiple() {
|
fn test_zero_does_not_imply_multiple() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue