Merge pull request #3836 from epage/help

fix(help): Improve debug output for help
This commit is contained in:
Ed Page 2022-06-15 10:43:06 -05:00 committed by GitHub
commit 82fd204ab5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -174,7 +174,12 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
.filter(|arg| should_show_arg(self.use_long, *arg))
{
if arg.longest_filter() {
longest = longest.max(display_width(arg.to_string().as_str()));
longest = longest.max(display_width(&arg.to_string()));
debug!(
"Help::write_args_unsorted: arg={:?} longest={}",
arg.get_id(),
longest
);
}
arg_v.push(arg)
}
@ -189,8 +194,8 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
/// Sorts arguments by length and display order and write their help to the wrapped stream.
fn write_args(&mut self, args: &[&Arg<'help>]) -> io::Result<()> {
debug!("Help::write_args");
fn write_args(&mut self, args: &[&Arg<'help>], _category: &str) -> io::Result<()> {
debug!("Help::write_args {}", _category);
// The shortest an arg can legally be is 2 (i.e. '-x')
let mut longest = 2;
let mut ord_v = Vec::new();
@ -203,9 +208,12 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
should_show_arg(self.use_long, *arg)
}) {
if arg.longest_filter() {
debug!("Help::write_args: Current Longest...{}", longest);
longest = longest.max(display_width(arg.to_string().as_str()));
debug!("Help::write_args: New Longest...{}", longest);
longest = longest.max(display_width(&arg.to_string()));
debug!(
"Help::write_args: arg={:?} longest={}",
arg.get_id(),
longest
);
}
// Formatting key like this to ensure that:
@ -250,7 +258,18 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
) -> io::Result<()> {
let spec_vals = &self.spec_vals(arg);
self.write_arg_inner(arg, spec_vals, next_line_help, longest)?;
self.short(arg)?;
self.long(arg)?;
self.val(arg)?;
self.align_to_about(arg, next_line_help, longest)?;
let about = if self.use_long {
arg.long_help.or(arg.help).unwrap_or("")
} else {
arg.help.or(arg.long_help).unwrap_or("")
};
self.help(Some(arg), about, spec_vals, next_line_help, longest)?;
if !last_arg {
self.none("\n")?;
@ -330,35 +349,41 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
next_line_help: bool,
longest: usize,
) -> io::Result<()> {
debug!("Help::align_to_about: arg={}", arg.name);
debug!("Help::align_to_about: Has switch...");
if self.use_long {
debug!(
"Help::align_to_about: arg={}, next_line_help={}, longest={}",
arg.name, next_line_help, longest
);
if self.use_long || next_line_help {
// long help prints messages on the next line so it doesn't need to align text
debug!("Help::align_to_about: printing long help so skip alignment");
} else if !arg.is_positional() {
debug!("Yes");
debug!("Help::align_to_about: nlh...{:?}", next_line_help);
if !next_line_help {
let self_len = display_width(arg.to_string().as_str());
// subtract ourself
let mut spcs = longest - self_len;
// Since we're writing spaces from the tab point we first need to know if we
// had a long and short, or just short
if arg.long.is_some() {
// Only account 4 after the val
spcs += 4;
} else {
// Only account for ', --' + 4 after the val
spcs += 8;
}
let self_len = display_width(&arg.to_string());
// Since we're writing spaces from the tab point we first need to know if we
// had a long and short, or just short
let padding = if arg.long.is_some() {
// Only account 4 after the val
4
} else {
// Only account for ', --' + 4 after the val
8
};
let spcs = longest + padding - self_len;
debug!(
"Help::align_to_about: positional=false arg_len={}, spaces={}",
self_len, spcs
);
self.spaces(spcs)?;
}
} else if !next_line_help {
debug!("No, and not next_line");
self.spaces(longest + 4 - display_width(&arg.to_string()))?;
self.spaces(spcs)?;
} else {
debug!("No");
let self_len = display_width(&arg.to_string());
let padding = 4;
let spcs = longest + padding - self_len;
debug!(
"Help::align_to_about: positional=true arg_len={}, spaces={}",
self_len, spcs
);
self.spaces(spcs)?;
}
Ok(())
}
@ -529,29 +554,6 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
Ok(())
}
/// Writes help for an argument to the wrapped stream.
fn write_arg_inner(
&mut self,
arg: &Arg<'help>,
spec_vals: &str,
next_line_help: bool,
longest: usize,
) -> io::Result<()> {
self.short(arg)?;
self.long(arg)?;
self.val(arg)?;
self.align_to_about(arg, next_line_help, longest)?;
let about = if self.use_long {
arg.long_help.or(arg.help).unwrap_or("")
} else {
arg.help.or(arg.long_help).unwrap_or("")
};
self.help(Some(arg), about, spec_vals, next_line_help, longest)?;
Ok(())
}
/// Will use next line help on writing args.
fn will_args_wrap(&self, args: &[&Arg<'help>], longest: usize) -> bool {
args.iter()
@ -854,7 +856,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
self.none("\n\n")?;
}
self.warning("OPTIONS:\n")?;
self.write_args(&non_pos)?;
self.write_args(&non_pos, "OPTIONS")?;
first = false;
}
if !custom_headings.is_empty() {
@ -876,7 +878,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
self.none("\n\n")?;
}
self.warning(format!("{}:\n", heading))?;
self.write_args(&args)?;
self.write_args(&args, heading)?;
first = false
}
}
@ -1079,10 +1081,10 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
"options" => {
// Include even those with a heading as we don't have a good way of
// handling help_heading in the template.
self.write_args(&self.cmd.get_non_positionals().collect::<Vec<_>>())?;
self.write_args(&self.cmd.get_non_positionals().collect::<Vec<_>>(), "options")?;
}
"positionals" => {
self.write_args(&self.cmd.get_positionals().collect::<Vec<_>>())?;
self.write_args(&self.cmd.get_positionals().collect::<Vec<_>>(), "positionals")?;
}
"subcommands" => {
self.write_subcommands(self.cmd)?;