Skip to content

Commit bf9fd5e

Browse files
authored
Merge pull request #113 from BenWiederhake/dev-fallible-apply
Make Options::apply fallible
2 parents e50cf46 + e3f0b52 commit bf9fd5e

27 files changed

+848
-73
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,12 @@ struct Settings {
6767
// To implement `Options`, we only need to provide the `apply` method.
6868
// The `parse` method will be automatically generated.
6969
impl Options<Arg> for Settings {
70-
fn apply(&mut self, arg: Arg) {
70+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
7171
match arg {
7272
Arg::Caps => self.caps = true,
7373
Arg::ExclamationMarks(n) => self.exclamation_marks += n,
7474
}
75+
Ok(())
7576
}
7677
}
7778

docs/design/problems_with_clap.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ uutils and when we opened as issue for it, it was discarded. This makes sense
108108
from `clap`'s perspective, but it shows that the priorities between `clap` and
109109
uutils diverge.
110110

111-
## Problem 6: It's stringly typed
111+
## Problem 7: It's stringly typed
112112

113113
`clap`'s arguments are identified by strings. This leads to code like this:
114114

@@ -135,21 +135,31 @@ deal, but a bit annoying.
135135

136136
Of course, we wouldn't have this problem if we were able to use the derive API.
137137

138-
## Problem 7: Reading help string from a file
138+
## Problem 8: Reading help string from a file
139139

140140
In `uutils` our help strings can get quite long. Therefore, we like to extract
141141
those to an external file. With `clap` this means that we need to do some custom
142142
preprocessing on this file to extract the information for the several pieces of
143143
the help string that `clap` supports.
144144

145-
## Problem 8: No markdown support
145+
## Problem 9: No markdown support
146146

147147
Granted, this is not really a problem, but more of a nice-to-have. We have
148148
online documentation for the utils, based on the help strings and these are
149149
rendered from markdown. Ideally, our argument parser supports markdown too, so
150150
that we can have nicely rendered help strings which have (roughly) the same
151151
appearance in the terminal and online.
152152

153+
## Problem 10: No position-dependent argument-error prioritization
154+
155+
This is the question of which error to print if both `-A` and `-B` are given,
156+
and both are individually an error somehow. In case of the GNU tools, only the
157+
first error is printed, and then the program is aborted.
158+
159+
This also is not really a problem, but since it can be reasonably easily
160+
achieved by simply raising an error during argument application, this enables
161+
matching more closely the exact behavior of the GNU tools.
162+
153163
## Good things about `clap`
154164

155165
Alright, enough problems. Let's praise `clap` a bit, because it's an excellent

docs/guide/port.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,11 @@ enum Arg {
9494
struct Settings { a: bool }
9595

9696
impl Options<Arg> for Settings {
97-
fn apply(&mut self, arg: Arg) {
97+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
9898
match arg {
9999
Arg::A => self.a = true,
100100
}
101+
Ok(())
101102
}
102103
}
103104

@@ -137,10 +138,11 @@ impl Default for Settings {
137138
}
138139

139140
impl Options<Arg> for Settings {
140-
fn apply(&mut self, arg: Arg) {
141+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
141142
match arg {
142143
Arg::A => self.a = false,
143144
}
145+
Ok(())
144146
}
145147
}
146148

@@ -175,10 +177,11 @@ enum Arg {
175177
struct Settings { a: u8 }
176178

177179
impl Options<Arg> for Settings {
178-
fn apply(&mut self, arg: Arg) {
180+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
179181
match arg {
180182
Arg::A => self.a += 1,
181183
}
184+
Ok(())
182185
}
183186
}
184187

@@ -215,10 +218,11 @@ enum Arg {
215218
struct Settings { a: OsString }
216219

217220
impl Options<Arg> for Settings {
218-
fn apply(&mut self, arg: Arg) {
221+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
219222
match arg {
220223
Arg::A(s) => self.a = s,
221224
}
225+
Ok(())
222226
}
223227
}
224228

@@ -255,10 +259,11 @@ enum Arg {
255259
struct Settings { a: Vec<OsString> }
256260

257261
impl Options<Arg> for Settings {
258-
fn apply(&mut self, arg: Arg) {
262+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
259263
match arg {
260264
Arg::A(s) => self.a.push(s),
261265
}
266+
Ok(())
262267
}
263268
}
264269

@@ -271,4 +276,4 @@ let a = Settings::default().parse(std::env::args_os()).unwrap().0.a;
271276
[Up](super)
272277
[Next](next)
273278

274-
</div>
279+
</div>

docs/guide/quick.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,11 @@ struct Settings {
5959
}
6060

6161
impl Options<Arg> for Settings {
62-
fn apply(&mut self, arg: Arg) {
62+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
6363
match arg {
6464
Arg::Force => self.force = true,
6565
}
66+
Ok(())
6667
}
6768
}
6869

@@ -100,11 +101,12 @@ struct Settings {
100101
}
101102

102103
impl Options<Arg> for Settings {
103-
fn apply(&mut self, arg: Arg) {
104+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
104105
match arg {
105106
Arg::Force => self.force = true,
106107
Arg::NoForce => self.force = false,
107108
}
109+
Ok(())
108110
}
109111
}
110112

@@ -160,10 +162,11 @@ enum Arg {
160162
# }
161163
#
162164
# impl Options<Arg> for Settings {
163-
# fn apply(&mut self, arg: Arg) {
165+
# fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
164166
# match arg {
165167
# Arg::Name(name) => self.name = name,
166168
# }
169+
# Ok(())
167170
# }
168171
# }
169172
#
@@ -197,10 +200,11 @@ enum Arg {
197200
# }
198201
#
199202
# impl Options<Arg> for Settings {
200-
# fn apply(&mut self, arg: Arg) {
203+
# fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
201204
# match arg {
202205
# Arg::Name(name) => self.name = name,
203206
# }
207+
# Ok(())
204208
# }
205209
# }
206210
#
@@ -234,10 +238,11 @@ enum Arg {
234238
# }
235239
#
236240
# impl Options<Arg> for Settings {
237-
# fn apply(&mut self, arg: Arg) {
241+
# fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
238242
# match arg {
239243
# Arg::Force(b) => self.force = b,
240244
# }
245+
# Ok(())
241246
# }
242247
# }
243248
#
@@ -269,10 +274,11 @@ enum Arg {
269274
# }
270275
#
271276
# impl Options<Arg> for Settings {
272-
# fn apply(&mut self, arg: Arg) {
277+
# fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
273278
# match arg {
274279
# Arg::Sort(s) => self.sort = s,
275280
# }
281+
# Ok(())
276282
# }
277283
# }
278284
#
@@ -287,4 +293,4 @@ enum Arg {
287293
[Up](super)
288294
[Next](next)
289295

290-
</div>
296+
</div>

examples/completion.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,18 @@ enum Arg {
2222
// Completion is derived from the `Number` type, through the `Value` trait
2323
/// Give it a number!
2424
#[arg("-n N", "--number=N")]
25-
Number(Number),
25+
Number(#[allow(unused)] Number),
2626

2727
// Completion is derived from the `PathBuf` type
2828
/// Give it a path!
2929
#[arg("-p P", "--path=P")]
30-
Path(PathBuf),
30+
Path(#[allow(unused)] PathBuf),
3131
}
3232

3333
struct Settings;
3434

3535
impl Options<Arg> for Settings {
36-
fn apply(&mut self, _arg: Arg) {
36+
fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> {
3737
panic!("Compile with the 'parse-is-complete' feature!")
3838
}
3939
}

examples/deprecated.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ struct Settings {
3434
}
3535

3636
impl Options<Arg> for Settings {
37-
fn apply(&mut self, arg: Arg) {
37+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
3838
match arg {
3939
Arg::Min(n) => self.n1 = n,
4040
Arg::Plus(n) => self.n2 = n,
4141
}
42+
Ok(())
4243
}
4344
}
4445

examples/hello_world.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ struct Settings {
2222
}
2323

2424
impl Options<Arg> for Settings {
25-
fn apply(&mut self, arg: Arg) {
25+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
2626
match arg {
2727
Arg::Name(n) => self.name = n,
2828
Arg::Count(c) => self.count = c,
2929
Arg::Hidden => {}
3030
}
31+
Ok(())
3132
}
3233
}
3334

examples/value.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ struct Settings {
2525
}
2626

2727
impl Options<Arg> for Settings {
28-
fn apply(&mut self, arg: Arg) {
28+
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
2929
match arg {
3030
Arg::Color(c) => self.color = c,
3131
}
32+
Ok(())
3233
}
3334
}
3435

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl<T: Arguments> ArgumentIter<T> {
166166
/// call [`Options::apply`] on the result until the arguments are exhausted.
167167
pub trait Options<Arg: Arguments>: Sized {
168168
/// Apply a single argument to the options.
169-
fn apply(&mut self, arg: Arg);
169+
fn apply(&mut self, arg: Arg) -> Result<(), Error>;
170170

171171
/// Parse an iterator of arguments into the options
172172
#[allow(unused_mut)]
@@ -191,7 +191,7 @@ pub trait Options<Arg: Arguments>: Sized {
191191
{
192192
let mut iter = ArgumentIter::<Arg>::from_args(args);
193193
while let Some(arg) = iter.next_arg()? {
194-
self.apply(arg);
194+
self.apply(arg)?;
195195
}
196196
Ok((self, iter.positional_arguments))
197197
}

tests/coreutils.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ mod cat;
1616
#[path = "coreutils/cksum.rs"]
1717
mod cksum;
1818

19+
#[path = "coreutils/date.rs"]
20+
mod date;
21+
1922
#[path = "coreutils/dd.rs"]
2023
mod dd;
2124

0 commit comments

Comments
 (0)