Skip to content

Commit 60474b1

Browse files
committed
Update help and usage handling in rust-argparse
Modify how usage and help messages are printed, so help text more closely matches the help and usage texts from the original binaries. These changes also ensure we use the same flags as the original utilitiles in an effort to maintain compatibility with the original efivar tools.
1 parent 12d3d0d commit 60474b1

File tree

2 files changed

+60
-11
lines changed

2 files changed

+60
-11
lines changed

src/lib/rust-argparse/LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Copyright (c) 2014-2015 Paul Colomiets
2+
Copyright (c) 2023 Nicholas Vinson
23

34
Permission is hereby granted, free of charge, to any person obtaining a copy
45
of this software and associated documentation files (the "Software"), to deal

src/lib/rust-argparse/src/parser.rs

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use action::IFlagAction;
3030
use self::ArgumentKind::{Positional, ShortOption, LongOption, Delimiter};
3131

3232

33-
static OPTION_WIDTH: usize = 24;
33+
static OPTION_WIDTH: usize = 36;
3434
static TOTAL_WIDTH: usize = 79;
3535

3636

@@ -613,11 +613,13 @@ pub struct ArgumentParser<'parser> {
613613
options: Vec<Rc<GenericOption<'parser>>>,
614614
arguments: Vec<Rc<GenericArgument<'parser>>>,
615615
env_vars: Vec<Rc<EnvVar<'parser>>>,
616+
error_message_before_usage: bool,
616617
catchall_argument: Option<Rc<GenericArgument<'parser>>>,
617618
short_options: HashMap<char, Rc<GenericOption<'parser>>>,
618619
long_options: HashMap<String, Rc<GenericOption<'parser>>>,
619620
stop_on_first_argument: bool,
620621
silence_double_dash: bool,
622+
usage_is_help: bool,
621623
}
622624

623625

@@ -631,16 +633,20 @@ impl<'parser> ArgumentParser<'parser> {
631633
description: "",
632634
vars: Vec::new(),
633635
env_vars: Vec::new(),
636+
error_message_before_usage: false,
634637
arguments: Vec::new(),
635638
catchall_argument: None,
636639
options: Vec::new(),
637640
short_options: HashMap::new(),
638641
long_options: HashMap::new(),
639642
stop_on_first_argument: false,
640643
silence_double_dash: true,
644+
usage_is_help: false,
641645
};
642-
ap.add_option_for(None, &["-h", "--help"], Flag(Box::new(HelpAction)),
643-
"Show this help message and exit");
646+
ap.add_option_for(None, &["-?", "--help"], Flag(Box::new(HelpAction)),
647+
"show this help message");
648+
ap.add_option_for(None, &["--usage"], Flag(Box::new(HelpAction)),
649+
"display brief usage message");
644650
return ap;
645651
}
646652

@@ -716,6 +722,20 @@ impl<'parser> ArgumentParser<'parser> {
716722
self.options.push(opt);
717723
}
718724

725+
/// Set Print Error Before Usage
726+
///
727+
/// Always print the error message before printing usage.
728+
pub fn set_error_before_usage(&mut self) {
729+
self.error_message_before_usage = true;
730+
}
731+
732+
/// Set Help as Usage
733+
///
734+
/// Always print full help text when usage is needed.
735+
pub fn set_help_as_usage(&mut self) {
736+
self.usage_is_help = true;
737+
}
738+
719739
/// Print help
720740
///
721741
/// Usually command-line option is used for printing help,
@@ -760,8 +780,13 @@ impl<'parser> ArgumentParser<'parser> {
760780
/// Only needed if you like to do some argument validation that is out
761781
/// of scope of the argparse
762782
pub fn error(&self, command: &str, message: &str, writer: &mut dyn Write) {
763-
self.print_usage(command, writer).unwrap();
764-
writeln!(writer, "{}: {}", command, message).ok();
783+
if self.error_message_before_usage {
784+
writeln!(writer, "{}: {}", command, message).ok();
785+
self.print_usage(command, writer).unwrap();
786+
} else {
787+
self.print_usage(command, writer).unwrap();
788+
writeln!(writer, "{}: {}", command, message).ok();
789+
}
765790
}
766791

767792
/// Configure parser to ignore options when first non-option argument is
@@ -822,7 +847,7 @@ impl<'a, 'b> HelpFormatter<'a, 'b> {
822847
-> IoResult<()>
823848
{
824849
return HelpFormatter { parser: parser, name: name, buf: writer }
825-
.write_usage();
850+
.write_usage(parser.usage_is_help);
826851
}
827852

828853
pub fn print_help(parser: &ArgumentParser, name: &str, writer: &mut dyn Write)
@@ -857,18 +882,25 @@ impl<'a, 'b> HelpFormatter<'a, 'b> {
857882
let mut num = 2;
858883
write!(self.buf, " ")?;
859884
let mut niter = opt.names.iter();
885+
if opt.names.len() == 1 {
886+
num += 4;
887+
write!(self.buf, " ")?;
888+
}
889+
860890
let name = niter.next().unwrap();
861891
write!(self.buf, "{}", name)?;
862892
num += name.len();
893+
863894
for name in niter {
864-
write!(self.buf, ",")?;
895+
write!(self.buf, ", ")?;
865896
write!(self.buf, "{}", name)?;
866-
num += name.len() + 1;
897+
num += name.len() + 2;
867898
}
899+
868900
match opt.action {
869901
Flag(_) => {}
870902
Single(_) | Push(_) | Many(_) => {
871-
write!(self.buf, " ")?;
903+
write!(self.buf, "=")?;
872904
let var = &self.parser.vars[opt.varid.unwrap()];
873905
write!(self.buf, "{}", &var.metavar[..])?;
874906
num += var.metavar.len() + 1;
@@ -890,7 +922,7 @@ impl<'a, 'b> HelpFormatter<'a, 'b> {
890922
}
891923

892924
fn write_help(&mut self) -> IoResult<()> {
893-
self.write_usage()?;
925+
self.write_usage(false)?;
894926
write!(self.buf, "\n")?;
895927
if !self.parser.description.is_empty() {
896928
wrap_text(self.buf, self.parser.description,TOTAL_WIDTH, 0)?;
@@ -914,14 +946,30 @@ impl<'a, 'b> HelpFormatter<'a, 'b> {
914946
|| !self.parser.long_options.is_empty()
915947
{
916948
write!(self.buf, "\nOptional arguments:\n")?;
949+
let mut help_options: Vec<&GenericOption<'_>> = Vec::new();
917950
for opt in self.parser.options.iter() {
951+
match &opt.action {
952+
Flag(action) => {
953+
match action.parse_flag() {
954+
Help => help_options.push(&**opt),
955+
_ => self.print_option(&**opt)?,
956+
}
957+
},
958+
_ => self.print_option(&**opt)?,
959+
}
960+
}
961+
write!(self.buf, "\nHelp options:\n")?;
962+
for opt in help_options.iter() {
918963
self.print_option(&**opt)?;
919964
}
920965
}
921966
return Ok(());
922967
}
923968

924-
fn write_usage(&mut self) -> IoResult<()> {
969+
fn write_usage(&mut self, usage_is_help: bool) -> IoResult<()> {
970+
if usage_is_help {
971+
return self.write_help();
972+
}
925973
write!(self.buf, "Usage:\n ")?;
926974
write!(self.buf, "{}", self.name)?;
927975
if !self.parser.options.is_empty() {

0 commit comments

Comments
 (0)