-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Arguments imply other arguments #15
Comments
In fact, this could go even further. For example: enum Arg {
#[arg("--sort=SORT")]
Sort(Sort),
#[arg("-t", implies = [Arg::Sort(Sort::Time)])]
SortTime,
} |
On second thought, I wonder how we could do this without additional enum variants, i.e. have multiple arguments mapped to a single variant, which would be really nice for the sort option for instance: enum Arg {
/// Set the sorting method
#[arg("--sort=SORT")]
#[arg("-t", default = Sort::Time, help = "Sort by time")]
Sort(Sort),
} For the enum Arg {
#[combined("-e", [Arg::ShowEnds, Arg::ShowNonPrinting], help = "...")
#[arg("-E")]
ShowEnds,
#[arg("-v")]
ShowNonPrinting,
} |
Here's another approach that's currently possible, but requires some boilerplate. There might be some crates that could take the boilerplate away. #[derive(Default)]
struct Show {
tabs: bool,
ends: bool,
nonprinting: bool,
}
impl Show {
const TABS: Self = Self {
tabs: true,
ends: false,
nonprinting: false,
};
const ENDS: Self = Self {
tabs: false,
ends: true,
nonprinting: false,
};
const NONPRINTING: Self = Self {
tabs: false,
ends: false,
nonprinting: true,
};
}
impl BitOr for Show {
type Output = Self;
fn bitor(self, other: Self) -> Self {
Self {
tabs: self.tabs | other.tabs,
ends: self.ends | other.ends,
nonprinting: self.nonprinting | other.nonprinting,
}
}
}
#[derive(Arguments)]
enum Arg {
#[arg("-A", "--show-all", default = Show::TABS | Show::ENDS | Show::NONPRINTING)]
#[arg("-E", "--show-ends", default = Show::ENDS)]
#[arg("-T", "--show-tabs", default = Show::TABS)]
#[arg("-v", "--show-nonprinting", default = Show::NONPRINTING)]
#[arg("-e", default = Show::ENDS | Show::NONPRINTING)]
#[arg("-t", default = Show::TABS | Show::NONPRINTING)]
Show(Show),
}
impl Options for Settings {
type Arg = Arg;
fn apply(&mut self, arg: Arg) {
match arg {
Arg::Show(s) => self.show = self.show | s,
}
} |
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:This could be rewritten as:
Open questions:
ShowAll
haveimplies = [Arg::ShowNonPrintingEnds, Arg::ShowTabs]
. I think it shouldn't to prevent loops and to keep the implementation simpler.Use cases:
-A
,-e
and-t
incat
.--zero
,-o
,-g
,-n
inls
-s
inbasename
-d
and-a
incp
-F
intail
-a
inuname
-a
inwho
The text was updated successfully, but these errors were encountered: