mirror of
https://github.com/gay-pizza/jaarg.git
synced 2025-12-18 23:10:17 +00:00
Move help text and required flag to with chain, make help text optional
This commit is contained in:
@@ -203,11 +203,11 @@ pub fn main() -> ExitCode {
|
||||
// Read & parse arguments from the command line, store results into the above structure
|
||||
enum Arg { Out, Bin, Txt, Whitespace, Help }
|
||||
const OPTIONS: Opts<Arg> = Opts::new(&[
|
||||
Opt::help_flag(Arg::Help, &["--help", "-h"], "Show this help message and exit"),
|
||||
Opt::positional_required(Arg::Out, "out", "Path to generated header file"),
|
||||
Opt::value(Arg::Bin, &["--bin", "-b"], "data.bin", "Add a binary file"),
|
||||
Opt::value(Arg::Txt, &["--txt", "-t"], "text.txt", "Add a text file"),
|
||||
Opt::value(Arg::Whitespace, &["--whitespace"], "\" \"", "Emitted indentation (Default: \"\\t\")"),
|
||||
Opt::help_flag(Arg::Help, &["--help", "-h"]).help_text("Show this help message and exit"),
|
||||
Opt::positional(Arg::Out, "out").help_text("Path to generated header file").required(),
|
||||
Opt::value(Arg::Bin, &["--bin", "-b"], "data.bin").help_text("Add a binary file"),
|
||||
Opt::value(Arg::Txt, &["--txt", "-t"], "text.txt").help_text("Add a text file"),
|
||||
Opt::value(Arg::Whitespace, &["--whitespace"], "\" \"").help_text("Emitted indentation (Default: \"\\t\")"),
|
||||
]);
|
||||
match OPTIONS.parse_easy(|program_name, id, _opt, _name, arg| {
|
||||
match id {
|
||||
|
||||
@@ -8,10 +8,10 @@ use std::process::ExitCode;
|
||||
|
||||
fn main() -> ExitCode {
|
||||
const OPTIONS: Opts<&'static str> = Opts::new(&[
|
||||
Opt::help_flag("help", &["--help"], "Show this help"),
|
||||
Opt::positional("positional", "positional", "Positional argument"),
|
||||
Opt::value("value", &["-v", "--value"], "string", "Value option"),
|
||||
Opt::flag("flag", &["-f", "--flag"], "Flag option"),
|
||||
Opt::help_flag("help", &["--help"]).help_text("Show this help"),
|
||||
Opt::positional("positional", "positional").help_text("Positional argument"),
|
||||
Opt::value("value", &["-v", "--value"], "string").help_text("Value option"),
|
||||
Opt::flag("flag", &["-f", "--flag"]).help_text("Flag option"),
|
||||
]);
|
||||
|
||||
let map = match OPTIONS.parse_map_easy() {
|
||||
|
||||
18
src/help.rs
18
src/help.rs
@@ -134,10 +134,12 @@ impl<ID> core::fmt::Display for StandardFullHelpWriter<'_, ID> {
|
||||
}
|
||||
|
||||
// Write positional argument line
|
||||
writeln!(f, " {name} {:.<width$} {help_text}", "",
|
||||
name = option.first_name(),
|
||||
help_text = option.help_string,
|
||||
width = align_width - calculate_left_pad(option))?;
|
||||
write!(f, " {name}", name = option.first_name())?;
|
||||
if let Some(help_text) = option.help_string {
|
||||
write!(f, " {:.<width$} {help_text}", "",
|
||||
width = align_width - calculate_left_pad(option))?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
}
|
||||
|
||||
// Write option parameter argument descriptions
|
||||
@@ -167,9 +169,11 @@ impl<ID> core::fmt::Display for StandardFullHelpWriter<'_, ID> {
|
||||
}
|
||||
|
||||
// Write padding and help text
|
||||
writeln!(f, " {:.<width$} {help_text}", "",
|
||||
help_text = option.help_string,
|
||||
width = align_width - calculate_left_pad(option))?;
|
||||
if let Some(help_text) = option.help_string {
|
||||
write!(f, " {:.<width$} {help_text}", "",
|
||||
width = align_width - calculate_left_pad(option))?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -22,7 +22,7 @@ pub struct Opt<ID> {
|
||||
id: ID,
|
||||
names: OptIdentifier,
|
||||
value_name: Option<&'static str>,
|
||||
help_string: &'static str,
|
||||
help_string: Option<&'static str>,
|
||||
r#type: OptType,
|
||||
flags: OptFlag,
|
||||
}
|
||||
@@ -40,50 +40,47 @@ impl OptFlag {
|
||||
// TODO: Improve this interface by making the name field take AsOptIdentifier when const traits are stabilised
|
||||
impl<ID> Opt<ID> {
|
||||
#[inline]
|
||||
const fn new(id: ID, names: OptIdentifier, value_name: Option<&'static str>, help_string: &'static str, r#type: OptType) -> Self {
|
||||
const fn new(id: ID, names: OptIdentifier, value_name: Option<&'static str>, r#type: OptType) -> Self {
|
||||
assert!(match names {
|
||||
OptIdentifier::Single(_) => true,
|
||||
OptIdentifier::Multi(names) => !names.is_empty(),
|
||||
}, "Option names cannot be an empty slice");
|
||||
Self { id, names, value_name, help_string, r#type, flags: OptFlag::NONE }
|
||||
Self { id, names, value_name, help_string: None, r#type, flags: OptFlag::NONE }
|
||||
}
|
||||
|
||||
/// A positional argument that is parsed sequentially without being invoked by an option flag
|
||||
pub const fn positional(id: ID, name: &'static str, help_string: &'static str) -> Self {
|
||||
Self::new(id, OptIdentifier::Single(name), None, help_string, OptType::Positional)
|
||||
}
|
||||
/// A required positional argument that is parsed sequentially without being invoked by an option flag
|
||||
pub const fn positional_required(id: ID, name: &'static str, help_string: &'static str) -> Self {
|
||||
Self::new(id, OptIdentifier::Single(name), None, help_string, OptType::Positional).with_required()
|
||||
pub const fn positional(id: ID, name: &'static str) -> Self {
|
||||
Self::new(id, OptIdentifier::Single(name), None, OptType::Positional)
|
||||
}
|
||||
/// A flag-type option that serves as the interface's help flag
|
||||
pub const fn help_flag(id: ID, names: &'static[&'static str], help_string: &'static str) -> Self {
|
||||
Self::new(id, OptIdentifier::Multi(names), None, help_string, OptType::Flag).with_help_flag()
|
||||
pub const fn help_flag(id: ID, names: &'static[&'static str]) -> Self {
|
||||
Self::new(id, OptIdentifier::Multi(names), None, OptType::Flag)
|
||||
.with_help_flag()
|
||||
}
|
||||
/// A flag-type option that takes no value
|
||||
pub const fn flag(id: ID, names: &'static[&'static str], help_string: &'static str) -> Self {
|
||||
Self::new(id, OptIdentifier::Multi(names), None, help_string, OptType::Flag)
|
||||
}
|
||||
/// A required flag-type option that takes no value
|
||||
pub const fn flag_required(id: ID, names: &'static[&'static str], help_string: &'static str) -> Self {
|
||||
Self::new(id, OptIdentifier::Multi(names), None, help_string, OptType::Flag).with_required()
|
||||
/// A flag-type option, takes no value
|
||||
pub const fn flag(id: ID, names: &'static[&'static str]) -> Self {
|
||||
Self::new(id, OptIdentifier::Multi(names), None, OptType::Flag)
|
||||
}
|
||||
/// An option argument that takes a value
|
||||
pub const fn value(id: ID, names: &'static[&'static str], value_name: &'static str, help_string: &'static str) -> Self {
|
||||
Self::new(id, OptIdentifier::Multi(names), Some(value_name), help_string, OptType::Value)
|
||||
}
|
||||
/// A required option argument that takes a value
|
||||
pub const fn value_required(id: ID, names: &'static[&'static str], value_name: &'static str, help_string: &'static str) -> Self {
|
||||
Self::new(id, OptIdentifier::Multi(names), Some(value_name), help_string, OptType::Value).with_required()
|
||||
pub const fn value(id: ID, names: &'static[&'static str], value_name: &'static str) -> Self {
|
||||
Self::new(id, OptIdentifier::Multi(names), Some(value_name), OptType::Value)
|
||||
}
|
||||
|
||||
/// This option is required, ie; parsing will fail if it is not specified.
|
||||
#[inline]
|
||||
const fn with_required(mut self) -> Self {
|
||||
pub const fn required(mut self) -> Self {
|
||||
assert!(!self.is_help(), "Help flag cannot be made required");
|
||||
self.flags.0 |= OptFlag::REQUIRED.0;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the help string for an option.
|
||||
#[inline]
|
||||
pub const fn help_text(mut self, help_string: &'static str) -> Self {
|
||||
self.help_string = Some(help_string);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
const fn with_help_flag(mut self) -> Self {
|
||||
assert!(matches!(self.r#type, OptType::Flag), "Only flags are allowed to be help options");
|
||||
|
||||
Reference in New Issue
Block a user