mirror of
https://github.com/uutils/uutils-args.git
synced 2026-06-10 16:13:08 -07:00
Merge pull request #113 from BenWiederhake/dev-fallible-apply
Make Options::apply fallible
This commit is contained in:
@@ -67,11 +67,12 @@ struct Settings {
|
||||
// To implement `Options`, we only need to provide the `apply` method.
|
||||
// The `parse` method will be automatically generated.
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Caps => self.caps = true,
|
||||
Arg::ExclamationMarks(n) => self.exclamation_marks += n,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ uutils and when we opened as issue for it, it was discarded. This makes sense
|
||||
from `clap`'s perspective, but it shows that the priorities between `clap` and
|
||||
uutils diverge.
|
||||
|
||||
## Problem 6: It's stringly typed
|
||||
## Problem 7: It's stringly typed
|
||||
|
||||
`clap`'s arguments are identified by strings. This leads to code like this:
|
||||
|
||||
@@ -135,14 +135,14 @@ deal, but a bit annoying.
|
||||
|
||||
Of course, we wouldn't have this problem if we were able to use the derive API.
|
||||
|
||||
## Problem 7: Reading help string from a file
|
||||
## Problem 8: Reading help string from a file
|
||||
|
||||
In `uutils` our help strings can get quite long. Therefore, we like to extract
|
||||
those to an external file. With `clap` this means that we need to do some custom
|
||||
preprocessing on this file to extract the information for the several pieces of
|
||||
the help string that `clap` supports.
|
||||
|
||||
## Problem 8: No markdown support
|
||||
## Problem 9: No markdown support
|
||||
|
||||
Granted, this is not really a problem, but more of a nice-to-have. We have
|
||||
online documentation for the utils, based on the help strings and these are
|
||||
@@ -150,6 +150,16 @@ rendered from markdown. Ideally, our argument parser supports markdown too, so
|
||||
that we can have nicely rendered help strings which have (roughly) the same
|
||||
appearance in the terminal and online.
|
||||
|
||||
## Problem 10: No position-dependent argument-error prioritization
|
||||
|
||||
This is the question of which error to print if both `-A` and `-B` are given,
|
||||
and both are individually an error somehow. In case of the GNU tools, only the
|
||||
first error is printed, and then the program is aborted.
|
||||
|
||||
This also is not really a problem, but since it can be reasonably easily
|
||||
achieved by simply raising an error during argument application, this enables
|
||||
matching more closely the exact behavior of the GNU tools.
|
||||
|
||||
## Good things about `clap`
|
||||
|
||||
Alright, enough problems. Let's praise `clap` a bit, because it's an excellent
|
||||
|
||||
+11
-6
@@ -94,10 +94,11 @@ enum Arg {
|
||||
struct Settings { a: bool }
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::A => self.a = true,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,10 +138,11 @@ impl Default for Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::A => self.a = false,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,10 +177,11 @@ enum Arg {
|
||||
struct Settings { a: u8 }
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::A => self.a += 1,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,10 +218,11 @@ enum Arg {
|
||||
struct Settings { a: OsString }
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::A(s) => self.a = s,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,10 +259,11 @@ enum Arg {
|
||||
struct Settings { a: Vec<OsString> }
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::A(s) => self.a.push(s),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,4 +276,4 @@ let a = Settings::default().parse(std::env::args_os()).unwrap().0.a;
|
||||
[Up](super)
|
||||
[Next](next)
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+13
-7
@@ -59,10 +59,11 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Force => self.force = true,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,11 +101,12 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Force => self.force = true,
|
||||
Arg::NoForce => self.force = false,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,10 +162,11 @@ enum Arg {
|
||||
# }
|
||||
#
|
||||
# impl Options<Arg> for Settings {
|
||||
# fn apply(&mut self, arg: Arg) {
|
||||
# fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
# match arg {
|
||||
# Arg::Name(name) => self.name = name,
|
||||
# }
|
||||
# Ok(())
|
||||
# }
|
||||
# }
|
||||
#
|
||||
@@ -197,10 +200,11 @@ enum Arg {
|
||||
# }
|
||||
#
|
||||
# impl Options<Arg> for Settings {
|
||||
# fn apply(&mut self, arg: Arg) {
|
||||
# fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
# match arg {
|
||||
# Arg::Name(name) => self.name = name,
|
||||
# }
|
||||
# Ok(())
|
||||
# }
|
||||
# }
|
||||
#
|
||||
@@ -234,10 +238,11 @@ enum Arg {
|
||||
# }
|
||||
#
|
||||
# impl Options<Arg> for Settings {
|
||||
# fn apply(&mut self, arg: Arg) {
|
||||
# fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
# match arg {
|
||||
# Arg::Force(b) => self.force = b,
|
||||
# }
|
||||
# Ok(())
|
||||
# }
|
||||
# }
|
||||
#
|
||||
@@ -269,10 +274,11 @@ enum Arg {
|
||||
# }
|
||||
#
|
||||
# impl Options<Arg> for Settings {
|
||||
# fn apply(&mut self, arg: Arg) {
|
||||
# fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
# match arg {
|
||||
# Arg::Sort(s) => self.sort = s,
|
||||
# }
|
||||
# Ok(())
|
||||
# }
|
||||
# }
|
||||
#
|
||||
@@ -287,4 +293,4 @@ enum Arg {
|
||||
[Up](super)
|
||||
[Next](next)
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,18 +22,18 @@ enum Arg {
|
||||
// Completion is derived from the `Number` type, through the `Value` trait
|
||||
/// Give it a number!
|
||||
#[arg("-n N", "--number=N")]
|
||||
Number(Number),
|
||||
Number(#[allow(unused)] Number),
|
||||
|
||||
// Completion is derived from the `PathBuf` type
|
||||
/// Give it a path!
|
||||
#[arg("-p P", "--path=P")]
|
||||
Path(PathBuf),
|
||||
Path(#[allow(unused)] PathBuf),
|
||||
}
|
||||
|
||||
struct Settings;
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, _arg: Arg) {
|
||||
fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
panic!("Compile with the 'parse-is-complete' feature!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +34,12 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Min(n) => self.n1 = n,
|
||||
Arg::Plus(n) => self.n2 = n,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,12 +22,13 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Name(n) => self.name = n,
|
||||
Arg::Count(c) => self.count = c,
|
||||
Arg::Hidden => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -25,10 +25,11 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Color(c) => self.color = c,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -166,7 +166,7 @@ impl<T: Arguments> ArgumentIter<T> {
|
||||
/// call [`Options::apply`] on the result until the arguments are exhausted.
|
||||
pub trait Options<Arg: Arguments>: Sized {
|
||||
/// Apply a single argument to the options.
|
||||
fn apply(&mut self, arg: Arg);
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), Error>;
|
||||
|
||||
/// Parse an iterator of arguments into the options
|
||||
#[allow(unused_mut)]
|
||||
@@ -191,7 +191,7 @@ pub trait Options<Arg: Arguments>: Sized {
|
||||
{
|
||||
let mut iter = ArgumentIter::<Arg>::from_args(args);
|
||||
while let Some(arg) = iter.next_arg()? {
|
||||
self.apply(arg);
|
||||
self.apply(arg)?;
|
||||
}
|
||||
Ok((self, iter.positional_arguments))
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ mod cat;
|
||||
#[path = "coreutils/cksum.rs"]
|
||||
mod cksum;
|
||||
|
||||
#[path = "coreutils/date.rs"]
|
||||
mod date;
|
||||
|
||||
#[path = "coreutils/dd.rs"]
|
||||
mod dd;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Binary => self.binary = true,
|
||||
Arg::Check => self.check = true,
|
||||
@@ -57,6 +57,7 @@ impl Options<Arg> for Settings {
|
||||
Arg::Strict => self.strict = true,
|
||||
Arg::Warn => self.check_output = CheckOutput::Warn,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,13 +34,14 @@ impl Default for Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Decode => self.decode = true,
|
||||
Arg::IgnoreGarbage => self.ignore_garbage = true,
|
||||
Arg::Wrap(0) => self.wrap = None,
|
||||
Arg::Wrap(x) => self.wrap = Some(x),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Multiple => self.multiple = true,
|
||||
Arg::Suffix(s) => {
|
||||
@@ -35,6 +35,7 @@ impl Options<Arg> for Settings {
|
||||
}
|
||||
Arg::Zero => self.zero = true,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::ShowAll => {
|
||||
self.show_tabs = true;
|
||||
@@ -70,6 +70,7 @@ impl Options<Arg> for Settings {
|
||||
Arg::NumberNonblank => self.number = NumberingMode::NonEmpty,
|
||||
Arg::SqueezeBlank => self.squeeze_blank = true,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Binary => self.binary = Tristate::True,
|
||||
Arg::Text => self.binary = Tristate::False,
|
||||
@@ -47,6 +47,7 @@ impl Options<Arg> for Settings {
|
||||
self.tag = Tristate::False;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@ enum Arg {
|
||||
Bs(usize),
|
||||
|
||||
#[arg("cbs=BYTES")]
|
||||
Cbs(usize),
|
||||
Cbs(#[allow(unused)] usize),
|
||||
|
||||
#[arg("skip=BYTES", "iseek=BYTES")]
|
||||
Skip(u64),
|
||||
@@ -47,13 +47,13 @@ enum Arg {
|
||||
Status(StatusLevel),
|
||||
|
||||
#[arg("conv=CONVERSIONS")]
|
||||
Conv(String),
|
||||
Conv(#[allow(unused)] String),
|
||||
|
||||
#[arg("iflag=FLAGS")]
|
||||
Iflag(String),
|
||||
Iflag(#[allow(unused)] String),
|
||||
|
||||
#[arg("oflag=FLAGS")]
|
||||
Oflag(String),
|
||||
Oflag(#[allow(unused)] String),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
@@ -92,7 +92,7 @@ impl Default for Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Infile(f) => self.infile = Some(f),
|
||||
Arg::Outfile(f) => self.outfile = Some(f),
|
||||
@@ -111,6 +111,7 @@ impl Options<Arg> for Settings {
|
||||
Arg::Iflag(_f) => todo!(),
|
||||
Arg::Oflag(_f) => todo!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,12 +24,13 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::NoNewline => self.trailing_newline = false,
|
||||
Arg::EnableEscape => self.escape = true,
|
||||
Arg::DisableEscape => self.escape = false,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ struct Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::Bytes(n) => {
|
||||
self.mode = Mode::Bytes;
|
||||
@@ -202,6 +202,7 @@ impl Options<Arg> for Settings {
|
||||
Arg::Verbose => self.verbose = true,
|
||||
Arg::Zero => self.zero = true,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -360,7 +360,7 @@ impl Default for Settings {
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
|
||||
match arg {
|
||||
Arg::All => self.which_files = Files::All,
|
||||
Arg::AlmostAll => self.which_files = Files::AlmostAll,
|
||||
@@ -417,6 +417,7 @@ impl Options<Arg> for Settings {
|
||||
}
|
||||
Arg::GroupDirectoriesFirst => self.group_directories_first = true,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user