Pull help querying and getting an iterator over options into a public methods

This commit is contained in:
2025-11-05 05:06:59 +11:00
parent b11c55a1ee
commit b0072855bc
4 changed files with 31 additions and 11 deletions

View File

@@ -140,7 +140,7 @@ impl<ID: 'static> Opts<ID> {
// Ensure that all required arguments have been provided
let mut required_flag_idx = 0;
for (i, option) in self.options.iter().enumerate() {
for (i, option) in self.iter().enumerate() {
match option.r#type {
OptType::Positional => if i >= state.positional_index && option.is_required() {
error(program_name, ParseError::RequiredPositional(option.first_name()));
@@ -192,7 +192,7 @@ impl<ID: 'static> Opts<ID> {
let mut required_idx = 0;
// Match a suitable option by name (ignoring the first flag character & skipping positional arguments)
let (name, option) = self.options.iter()
let (name, option) = self.iter()
.filter(|opt| matches!(opt.r#type, OptType::Flag | OptType::Value)).find_map(|opt| {
if let Some(name) = opt.match_name(option_str, 1) {
Some((name, opt))

View File

@@ -23,7 +23,7 @@ impl<ID: 'static> core::fmt::Display for StandardShortUsageWriter<'_, ID> {
write!(f, "Usage: {}", self.0.program_name)?;
// Write option parameter arguments
for option in self.0.options.options.iter()
for option in self.0.options.iter()
.filter(|o| matches!(o.r#type, OptType::Value | OptType::Flag)) {
write!(f, " {}", if option.is_required() { '<' } else { '[' })?;
match (option.first_short_name(), option.first_long_name()) {
@@ -39,7 +39,7 @@ impl<ID: 'static> core::fmt::Display for StandardShortUsageWriter<'_, ID> {
}
// Write positional arguments
for option in self.0.options.options.iter()
for option in self.0.options.iter()
.filter(|o| matches!(o.r#type, OptType::Positional)) {
let name = option.first_name();
match option.is_required() {
@@ -100,7 +100,7 @@ impl<ID> core::fmt::Display for StandardFullHelpWriter<'_, ID> {
}
// Write positional arguments
for option in self.0.options.options.iter()
for option in self.0.options.iter()
.filter(|o| matches!(o.r#type, OptType::Positional)) {
let name = option.first_name();
match option.is_required() {
@@ -124,12 +124,12 @@ impl<ID> core::fmt::Display for StandardFullHelpWriter<'_, ID> {
}
// Determine the alignment width from the longest option parameter
let align_width = 2 + self.0.options.options.iter()
let align_width = 2 + self.0.options.iter()
.map(|o| calculate_left_pad(o)).max().unwrap_or(0);
// Write positional argument descriptions
first = true;
for option in self.0.options.options.iter()
for option in self.0.options.iter()
.filter(|o| matches!(o.r#type, OptType::Positional)) {
if first {
// Write separator and positional section header
@@ -149,7 +149,7 @@ impl<ID> core::fmt::Display for StandardFullHelpWriter<'_, ID> {
// Write option parameter argument descriptions
first = true;
for option in self.0.options.options.iter()
for option in self.0.options.iter()
.filter(|o| matches!(o.r#type, OptType::Flag | OptType::Value)) {
if first {
// Write separator and options section header

View File

@@ -40,15 +40,35 @@ impl<ID: 'static> Opts<ID> {
}
}
/// Set the recognised flag/option characters.
/// Sets the recognised flag/option characters.
#[inline]
pub const fn with_flag_chars(mut self, flag_chars: &'static str) -> Self {
self.flag_chars = flag_chars;
self
}
/// Set the description of the program, available to help writers.
/// Sets the description of the program, available to help writers.
#[inline]
pub const fn with_description(mut self, description: &'static str) -> Self {
self.description = Some(description);
self
}
/// Gets the first available help option if one exists.
pub const fn help_option(&self) -> Option<&'static Opt<ID>> {
let mut i = 0;
while i < self.options.len() {
if self.options[i].is_help() {
return Some(&self.options[i]);
}
i += 1;
}
None
}
/// Gets an iterator over the parser's options.
#[inline]
pub fn iter(&self) -> core::slice::Iter<'static, Opt<ID>> {
self.options.iter()
}
}

View File

@@ -56,7 +56,7 @@ impl<ID: 'static> Opts<ID> {
fn easy_error(&self, program_name: &str, err: ParseError) {
eprintln!("{program_name}: {err}");
self.eprint_help::<StandardShortUsageWriter<'_, ID>>(program_name);
if let Some(help_option) = self.options.iter().find(|o| o.is_help()) {
if let Some(help_option) = self.help_option() {
eprintln!("Run '{program_name} {help}' to view all available options.",
help = help_option.first_long_name().unwrap_or(help_option.first_name()));
}