Skip to content
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

fix(help): Improve debug output for help #3836

Merged
merged 3 commits into from Jun 15, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
118 changes: 60 additions & 58 deletions src/output/help.rs
Expand Up @@ -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)
}
Expand All @@ -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();
Expand All @@ -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:
Expand Down Expand Up @@ -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")?;
Expand Down Expand Up @@ -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(())
}
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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() {
Expand All @@ -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
}
}
Expand Down Expand Up @@ -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)?;
Expand Down