From 150964c4e7124d54476c9d9b4b3f2406f0fd00e5 Mon Sep 17 00:00:00 2001 From: Kevin K Date: Sat, 27 Aug 2016 20:20:46 -0400 Subject: [PATCH] imp(Help): automatically moves help text to the next line and wraps when term width is determined to be too small, or help text is too long Now `clap` will check if it should automatically place long help messages on the next line after the flag/option. This is determined by checking to see if the space taken by flag/option plus spaces and values doesn't leave enough room for the entirety of the help message, with the single exception of of if the flag/option/spaces/values is less than 25% of the width. Closes #597 --- src/app/help.rs | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/app/help.rs b/src/app/help.rs index 4e7d0c80833..f52260d8ede 100644 --- a/src/app/help.rs +++ b/src/app/help.rs @@ -339,8 +339,16 @@ impl<'a> Help<'a> { } else { try!(color!(self, "{}", arg, good)); } + + let spec_vals = self.spec_vals(arg); + let h = arg.help().unwrap_or(""); + let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp); + let width = self.term_w; + let taken = (longest + 12) + str_width(&*spec_vals); + let force_next_line = !nlh && width >= taken && str_width(h) > (width - taken) && (taken as f32 / width as f32) > 0.25; + if arg.has_switch() { - if !(self.next_line_help || arg.is_set(ArgSettings::NextLineHelp)) { + if !(nlh || force_next_line) { let self_len = arg.to_string().len(); // subtract ourself let mut spcs = longest - self_len; @@ -356,7 +364,7 @@ impl<'a> Help<'a> { write_nspaces!(self.writer, spcs); } - } else if !(self.next_line_help || arg.is_set(ArgSettings::NextLineHelp)) { + } else if !(nlh || force_next_line) { write_nspaces!(self.writer, longest + 4 - (arg.to_string().len())); } Ok(()) @@ -416,19 +424,30 @@ impl<'a> Help<'a> { let spec_vals = self.spec_vals(arg); let mut help = String::new(); let h = arg.help().unwrap_or(""); - let spcs = if self.next_line_help || arg.is_set(ArgSettings::NextLineHelp) { + let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp); + debugln!("Next Line...{:?}", nlh); + + // determine if our help fits or needs to wrap + let width = self.term_w; + debugln!("Term width...{}", width); + + // We calculate with longest+12 since if it's already NLH we don't care + let taken = (longest + 12) + str_width(&*spec_vals); + let force_next_line = !nlh && width >= taken && str_width(h) > (width - taken) && (taken as f32 / width as f32) > 0.25; + debugln!("Force Next Line...{:?}", force_next_line); + debugln!("Force Next Line math (help_len > (width - flags/opts/spcs))...{} > ({} - {})", str_width(h), width, taken); + + let spcs = if nlh || force_next_line { 8 // "tab" + "tab" } else { longest + 12 }; - // determine if our help fits or needs to wrap - let width = self.term_w; - debugln!("Term width...{}", width); + let too_long = spcs + str_width(h) + str_width(&*spec_vals) >= width; debugln!("Spaces: {}", spcs); // Is help on next line, if so newline + 2x tab - if self.next_line_help || arg.is_set(ArgSettings::NextLineHelp) { + if nlh || force_next_line { try!(write!(self.writer, "\n{}{}", TAB, TAB)); } @@ -470,7 +489,7 @@ impl<'a> Help<'a> { } for part in help.split("{n}").skip(1) { try!(write!(self.writer, "\n")); - if self.next_line_help || arg.is_set(ArgSettings::NextLineHelp) { + if nlh || force_next_line { try!(write!(self.writer, "{}{}", TAB, TAB)); } else if arg.has_switch() { write_nspaces!(self.writer, longest + 12);