-
Notifications
You must be signed in to change notification settings - Fork 6
Open
Description
The many-to-many relationship of arguments and settings is currently handled entirely in the struct, but we could take some of the heavy lifting into the arguments. This will prevent that we forget to handle arguments in the struct.
My proposal is that arguments can imply other arguments, which will be added to the iterator after the initial argument. This allows us to rewrite some arguments with multiple effects as expanding into multiple smaller arguments. Take this set of arguments from cat
for example:
#[derive(Clone, Arguments)]
enum Arg {
#[arg("-A", "--show-all")]
ShowAll,
#[arg("-e")]
ShowNonPrintingEnds,
#[arg("-E")]
ShowEnds,
#[arg("-t")]
ShowNonPrintingTabs,
#[arg("-T", "--show-tabs")]
ShowTabs,
#[arg("-v", "--show-nonprinting")]
ShowNonPrinting,
}
#[derive(Initial)]
struct Settings {
show_tabs: bool,
show_ends: bool,
show_nonprinting: bool,
}
impl Options for Settings {
type Arg = Arg;
fn apply(&mut self, arg: Arg) {
if let Arg::ShowAll | Arg::ShowNonPrintingTabs | Arg::ShowTabs = arg {
self.show_tabs = true;
}
if let Arg::ShowAll | Arg::ShowNonPrintingEnds | Arg::ShowEnds = arg {
self.show_ends = true;
}
if let Arg::ShowAll | Arg::ShowNonPrintingTabs | Arg::ShowNonPrintingEnds | Arg::ShowNonPrinting = arg {
self.show_non_printing = true;
}
}
}
This could be rewritten as:
#[derive(Clone, Arguments)]
enum Arg {
#[option("-A", "--show-all", implies = [Arg::ShowEnds, Arg::ShowTabs, Arg::ShowNonPrinting])]
ShowAll,
#[option("-e", implies = [Arg::ShowEnds, Arg::ShowNonPrinting])]
ShowNonPrintingEnds,
#[option("-E")]
ShowEnds,
#[option("-t", implies = [Arg::ShowEnds, Arg::ShowNonPrinting])]
ShowNonPrintingTabs,
#[option("-T", "--show-tabs")]
ShowTabs,
#[option("-v", "--show-nonprinting")]
ShowNonPrinting,
}
#[derive(Initial)]
struct Settings {
show_tabs: bool,
show_ends: bool,
show_nonprinting: bool,
}
impl Options for Settings {
type Arg = Arg;
fn apply(&mut self, arg: Arg) {
match arg {
Arg::ShowTabs => self.show_tabs = true,
Arg::ShowEnds => self.show_ends = true,
Arg::ShowNonPrinting => self.show_nonprinting = true,
}
}
}
Open questions:
- Should this be applied recursively? E.g. could
ShowAll
haveimplies = [Arg::ShowNonPrintingEnds, Arg::ShowTabs]
. I think it shouldn't to prevent loops and to keep the implementation simpler. - Should the original argument be preserved?
Use cases:
-A
,-e
and-t
incat
.--zero
,-o
,-g
,-n
inls
-s
inbasename
-d
and-a
incp
-F
intail
-a
inuname
-a
inwho
Metadata
Metadata
Assignees
Labels
No labels