mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
Consistently wrap help and subcommand messages(with refactoring)
This commit is contained in:
parent
04fd3369d3
commit
a19bfa1c35
2 changed files with 381 additions and 276 deletions
|
@ -48,8 +48,6 @@ pub(crate) struct Help<'help, 'app, 'parser, 'writer> {
|
||||||
next_line_help: bool,
|
next_line_help: bool,
|
||||||
hide_pv: bool,
|
hide_pv: bool,
|
||||||
term_w: usize,
|
term_w: usize,
|
||||||
longest: usize,
|
|
||||||
force_next_line: bool,
|
|
||||||
use_long: bool,
|
use_long: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +69,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
|
|
||||||
/// Create a new `Help` instance.
|
/// Create a new `Help` instance.
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
w: HelpWriter<'writer>,
|
writer: HelpWriter<'writer>,
|
||||||
parser: &'parser Parser<'help, 'app>,
|
parser: &'parser Parser<'help, 'app>,
|
||||||
use_long: bool,
|
use_long: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -87,17 +85,15 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let nlh = parser.is_set(AppSettings::NextLineHelp);
|
let next_line_help = parser.is_set(AppSettings::NextLineHelp);
|
||||||
let hide_pv = parser.is_set(AppSettings::HidePossibleValuesInHelp);
|
let hide_pv = parser.is_set(AppSettings::HidePossibleValuesInHelp);
|
||||||
|
|
||||||
Help {
|
Help {
|
||||||
writer: w,
|
writer,
|
||||||
parser,
|
parser,
|
||||||
next_line_help: nlh,
|
next_line_help,
|
||||||
hide_pv,
|
hide_pv,
|
||||||
term_w,
|
term_w,
|
||||||
longest: 0,
|
|
||||||
force_next_line: false,
|
|
||||||
use_long,
|
use_long,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,15 +137,6 @@ macro_rules! write_method {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! write_nspaces {
|
|
||||||
($_self:ident, $num:expr) => {{
|
|
||||||
debug!("Help::write_nspaces!: num={}", $num);
|
|
||||||
for _ in 0..$num {
|
|
||||||
$_self.none(" ")?;
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods to write Arg help.
|
// Methods to write Arg help.
|
||||||
impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
fn good<T: Into<String> + AsRef<[u8]>>(&mut self, msg: T) -> io::Result<()> {
|
fn good<T: Into<String> + AsRef<[u8]>>(&mut self, msg: T) -> io::Result<()> {
|
||||||
|
@ -164,28 +151,32 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
write_method!(self, msg, none)
|
write_method!(self, msg, none)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spaces(&mut self, n: usize) -> io::Result<()> {
|
||||||
|
self.none(" ".repeat(n))
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes help for each argument in the order they were declared to the wrapped stream.
|
/// Writes help for each argument in the order they were declared to the wrapped stream.
|
||||||
fn write_args_unsorted(&mut self, args: &[&Arg<'help>]) -> io::Result<()> {
|
fn write_args_unsorted(&mut self, args: &[&Arg<'help>]) -> io::Result<()> {
|
||||||
debug!("Help::write_args_unsorted");
|
debug!("Help::write_args_unsorted");
|
||||||
// The shortest an arg can legally be is 2 (i.e. '-x')
|
// The shortest an arg can legally be is 2 (i.e. '-x')
|
||||||
self.longest = 2;
|
let mut longest = 2;
|
||||||
let mut arg_v = Vec::with_capacity(10);
|
let mut arg_v = Vec::with_capacity(10);
|
||||||
let use_long = self.use_long;
|
|
||||||
for arg in args.iter().filter(|arg| should_show_arg(use_long, *arg)) {
|
for arg in args
|
||||||
|
.iter()
|
||||||
|
.filter(|arg| should_show_arg(self.use_long, *arg))
|
||||||
|
{
|
||||||
if arg.longest_filter() {
|
if arg.longest_filter() {
|
||||||
self.longest = cmp::max(self.longest, str_width(arg.to_string().as_str()));
|
longest = longest.max(str_width(arg.to_string().as_str()));
|
||||||
}
|
}
|
||||||
arg_v.push(arg)
|
arg_v.push(arg)
|
||||||
}
|
}
|
||||||
let mut first = true;
|
|
||||||
let arg_c = arg_v.len();
|
let next_line_help = self.will_args_wrap(args, longest);
|
||||||
|
|
||||||
|
let argc = arg_v.len();
|
||||||
for (i, arg) in arg_v.iter().enumerate() {
|
for (i, arg) in arg_v.iter().enumerate() {
|
||||||
if first {
|
self.write_arg(arg, i + 1 == argc, next_line_help, longest)?;
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
self.none("\n")?;
|
|
||||||
}
|
|
||||||
self.write_arg(arg, i < arg_c)?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -194,20 +185,20 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
fn write_args(&mut self, args: &[&Arg<'help>]) -> io::Result<()> {
|
fn write_args(&mut self, args: &[&Arg<'help>]) -> io::Result<()> {
|
||||||
debug!("Help::write_args");
|
debug!("Help::write_args");
|
||||||
// The shortest an arg can legally be is 2 (i.e. '-x')
|
// The shortest an arg can legally be is 2 (i.e. '-x')
|
||||||
self.longest = 2;
|
let mut longest = 2;
|
||||||
let mut ord_m = VecMap::new();
|
let mut ord_m = VecMap::new();
|
||||||
let use_long = self.use_long;
|
|
||||||
// Determine the longest
|
// Determine the longest
|
||||||
for arg in args.iter().filter(|arg| {
|
for arg in args.iter().filter(|arg| {
|
||||||
// If it's NextLineHelp we don't care to compute how long it is because it may be
|
// If it's NextLineHelp we don't care to compute how long it is because it may be
|
||||||
// NextLineHelp on purpose simply *because* it's so long and would throw off all other
|
// NextLineHelp on purpose simply *because* it's so long and would throw off all other
|
||||||
// args alignment
|
// args alignment
|
||||||
should_show_arg(use_long, *arg)
|
should_show_arg(self.use_long, *arg)
|
||||||
}) {
|
}) {
|
||||||
if arg.longest_filter() {
|
if arg.longest_filter() {
|
||||||
debug!("Help::write_args: Current Longest...{}", self.longest);
|
debug!("Help::write_args: Current Longest...{}", longest);
|
||||||
self.longest = cmp::max(self.longest, str_width(arg.to_string().as_str()));
|
longest = longest.max(str_width(arg.to_string().as_str()));
|
||||||
debug!("Help::write_args: New Longest...{}", self.longest);
|
debug!("Help::write_args: New Longest...{}", longest);
|
||||||
}
|
}
|
||||||
let btm = ord_m.entry(arg.disp_ord).or_insert(BTreeMap::new());
|
let btm = ord_m.entry(arg.disp_ord).or_insert(BTreeMap::new());
|
||||||
|
|
||||||
|
@ -232,27 +223,39 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
};
|
};
|
||||||
btm.insert(key, arg);
|
btm.insert(key, arg);
|
||||||
}
|
}
|
||||||
let mut first = true;
|
|
||||||
for btm in ord_m.values() {
|
let next_line_help = self.will_args_wrap(args, longest);
|
||||||
for arg in btm.values() {
|
|
||||||
if first {
|
let num_ord_m = ord_m.len();
|
||||||
first = false;
|
for (i, btm) in ord_m.values().enumerate() {
|
||||||
} else {
|
let last_btm = i + 1 == num_ord_m;
|
||||||
self.none("\n")?;
|
let num_args = btm.len();
|
||||||
}
|
for (i, arg) in btm.values().enumerate() {
|
||||||
self.write_arg(arg, false)?;
|
let last_arg = last_btm && i + 1 == num_args;
|
||||||
|
self.write_arg(arg, last_arg, next_line_help, longest)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes help for an argument to the wrapped stream.
|
/// Writes help for an argument to the wrapped stream.
|
||||||
fn write_arg(&mut self, arg: &Arg<'help>, prevent_nlh: bool) -> io::Result<()> {
|
fn write_arg(
|
||||||
debug!("Help::write_arg");
|
&mut self,
|
||||||
self.short(arg)?;
|
arg: &Arg<'help>,
|
||||||
self.long(arg)?;
|
last_arg: bool,
|
||||||
let spec_vals = self.val(arg)?;
|
next_line_help: bool,
|
||||||
self.help(arg, &*spec_vals, prevent_nlh)?;
|
longest: usize,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let spec_vals = &self.spec_vals(arg);
|
||||||
|
|
||||||
|
self.write_arg_inner(arg, spec_vals, next_line_help, longest)?;
|
||||||
|
|
||||||
|
if !last_arg {
|
||||||
|
self.none("\n")?;
|
||||||
|
if next_line_help {
|
||||||
|
self.none("\n")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +304,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes argument's possible values to the wrapped stream.
|
/// Writes argument's possible values to the wrapped stream.
|
||||||
fn val(&mut self, arg: &Arg) -> Result<String, io::Error> {
|
fn val(&mut self, arg: &Arg<'help>, next_line_help: bool, longest: usize) -> io::Result<()> {
|
||||||
debug!("Help::val: arg={}", arg.name);
|
debug!("Help::val: arg={}", arg.name);
|
||||||
let mult =
|
let mult =
|
||||||
arg.is_set(ArgSettings::MultipleValues) || arg.is_set(ArgSettings::MultipleOccurrences);
|
arg.is_set(ArgSettings::MultipleValues) || arg.is_set(ArgSettings::MultipleOccurrences);
|
||||||
|
@ -344,36 +347,17 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let spec_vals = self.spec_vals(arg);
|
|
||||||
let h = arg.about.unwrap_or("");
|
|
||||||
let h_w = str_width(h) + str_width(&*spec_vals);
|
|
||||||
let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp);
|
|
||||||
let taken = self.longest + 12;
|
|
||||||
self.force_next_line = !nlh
|
|
||||||
&& self.term_w >= taken
|
|
||||||
&& (taken as f32 / self.term_w as f32) > 0.40
|
|
||||||
&& h_w > (self.term_w - taken);
|
|
||||||
|
|
||||||
debug!("Help::val: Has switch...");
|
debug!("Help::val: Has switch...");
|
||||||
if self.use_long {
|
if self.use_long {
|
||||||
// long help prints messages on the next line so it don't need to align text
|
// long help prints messages on the next line so it don't need to align text
|
||||||
debug!("Help::val: printing long help so skip alignment");
|
debug!("Help::val: printing long help so skip alignment");
|
||||||
} else if arg.has_switch() {
|
} else if arg.has_switch() {
|
||||||
debug!("Yes");
|
debug!("Yes");
|
||||||
debug!("Help::val: force_next_line...{:?}", self.force_next_line);
|
debug!("Help::val: nlh...{:?}", next_line_help);
|
||||||
debug!("Help::val: nlh...{:?}", nlh);
|
if !next_line_help {
|
||||||
debug!("Help::val: taken...{}", taken);
|
|
||||||
debug!(
|
|
||||||
"val: help_width > (width - taken)...{} > ({} - {})",
|
|
||||||
h_w, self.term_w, taken
|
|
||||||
);
|
|
||||||
debug!("Help::val: longest...{}", self.longest);
|
|
||||||
debug!("Help::val: next_line...");
|
|
||||||
if !(nlh || self.force_next_line) {
|
|
||||||
debug!("No");
|
|
||||||
let self_len = str_width(arg.to_string().as_str());
|
let self_len = str_width(arg.to_string().as_str());
|
||||||
// subtract ourself
|
// subtract ourself
|
||||||
let mut spcs = self.longest - self_len;
|
let mut spcs = longest - self_len;
|
||||||
// Since we're writing spaces from the tab point we first need to know if we
|
// Since we're writing spaces from the tab point we first need to know if we
|
||||||
// had a long and short, or just short
|
// had a long and short, or just short
|
||||||
if arg.long.is_some() {
|
if arg.long.is_some() {
|
||||||
|
@ -384,87 +368,86 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
spcs += 8;
|
spcs += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_nspaces!(self, spcs);
|
self.spaces(spcs)?;
|
||||||
} else {
|
|
||||||
debug!("Yes");
|
|
||||||
}
|
}
|
||||||
} else if !(nlh || self.force_next_line) {
|
} else if !next_line_help {
|
||||||
debug!("No, and not next_line");
|
debug!("No, and not next_line");
|
||||||
write_nspaces!(
|
self.spaces(longest + 4 - str_width(&arg.to_string()))?;
|
||||||
self,
|
|
||||||
self.longest + 4 - (str_width(arg.to_string().as_str()))
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
debug!("No");
|
debug!("No");
|
||||||
}
|
}
|
||||||
Ok(spec_vals)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_before_after_help(&mut self, h: &str) -> io::Result<()> {
|
fn write_before_help(&mut self) -> io::Result<()> {
|
||||||
debug!("Help::write_before_after_help");
|
debug!("Help::write_before_help");
|
||||||
let mut help = String::from(h);
|
let before_help = if self.use_long {
|
||||||
// determine if our help fits or needs to wrap
|
self.parser
|
||||||
debug!(
|
.app
|
||||||
"Help::write_before_after_help: Term width...{}",
|
.before_long_help
|
||||||
self.term_w
|
.or(self.parser.app.before_help)
|
||||||
);
|
|
||||||
let too_long = str_width(h) >= self.term_w;
|
|
||||||
|
|
||||||
debug!("Help::write_before_after_help: Too long...");
|
|
||||||
if too_long {
|
|
||||||
debug!("Yes");
|
|
||||||
debug!("Help::write_before_after_help: help: {}", help);
|
|
||||||
debug!(
|
|
||||||
"Help::write_before_after_help: help width: {}",
|
|
||||||
str_width(&*help)
|
|
||||||
);
|
|
||||||
// Determine how many newlines we need to insert
|
|
||||||
debug!(
|
|
||||||
"Help::write_before_after_help: Usable space: {}",
|
|
||||||
self.term_w
|
|
||||||
);
|
|
||||||
help = wrap_help(&help, self.term_w);
|
|
||||||
} else {
|
} else {
|
||||||
debug!("No");
|
self.parser.app.before_help
|
||||||
|
};
|
||||||
|
if let Some(output) = before_help {
|
||||||
|
self.none(text_wrapper(output, self.term_w))?;
|
||||||
|
self.none("\n\n")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_after_help(&mut self) -> io::Result<()> {
|
||||||
|
debug!("Help::write_after_help");
|
||||||
|
let after_help = if self.use_long {
|
||||||
|
self.parser
|
||||||
|
.app
|
||||||
|
.after_long_help
|
||||||
|
.or(self.parser.app.after_help)
|
||||||
|
} else {
|
||||||
|
self.parser.app.after_help
|
||||||
|
};
|
||||||
|
if let Some(output) = after_help {
|
||||||
|
self.none("\n\n")?;
|
||||||
|
self.none(text_wrapper(output, self.term_w))?;
|
||||||
}
|
}
|
||||||
self.none(&help)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes argument's help to the wrapped stream.
|
/// Writes argument's help to the wrapped stream.
|
||||||
fn help(&mut self, arg: &Arg, spec_vals: &str, prevent_nlh: bool) -> io::Result<()> {
|
fn help(
|
||||||
|
&mut self,
|
||||||
|
has_switch: bool,
|
||||||
|
about: &str,
|
||||||
|
spec_vals: &str,
|
||||||
|
next_line_help: bool,
|
||||||
|
longest: usize,
|
||||||
|
) -> io::Result<()> {
|
||||||
debug!("Help::help");
|
debug!("Help::help");
|
||||||
let h = if self.use_long {
|
let mut help = String::from(about) + spec_vals;
|
||||||
arg.long_about.unwrap_or_else(|| arg.about.unwrap_or(""))
|
debug!("Help::help: Next Line...{:?}", next_line_help);
|
||||||
} else {
|
|
||||||
arg.about.unwrap_or_else(|| arg.long_about.unwrap_or(""))
|
|
||||||
};
|
|
||||||
let mut help = String::from(h) + spec_vals;
|
|
||||||
let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp) || self.use_long;
|
|
||||||
debug!("Help::help: Next Line...{:?}", nlh);
|
|
||||||
|
|
||||||
let spcs = if nlh || self.force_next_line {
|
let spaces = if next_line_help {
|
||||||
12 // "tab" * 3
|
12 // "tab" * 3
|
||||||
} else {
|
} else {
|
||||||
self.longest + 12
|
longest + 12
|
||||||
};
|
};
|
||||||
|
|
||||||
let too_long = spcs + str_width(h) + str_width(&*spec_vals) >= self.term_w;
|
let too_long = spaces + str_width(about) + str_width(spec_vals) >= self.term_w;
|
||||||
|
|
||||||
// Is help on next line, if so then indent
|
// Is help on next line, if so then indent
|
||||||
if nlh || self.force_next_line {
|
if next_line_help {
|
||||||
self.none(&format!("\n{}{}{}", TAB, TAB, TAB))?;
|
self.none(&format!("\n{}{}{}", TAB, TAB, TAB))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Help::help: Too long...");
|
debug!("Help::help: Too long...");
|
||||||
if too_long && spcs <= self.term_w {
|
if too_long && spaces <= self.term_w {
|
||||||
debug!("Yes");
|
debug!("Yes");
|
||||||
debug!("Help::help: help...{}", help);
|
debug!("Help::help: help...{}", help);
|
||||||
debug!("Help::help: help width...{}", str_width(&*help));
|
debug!("Help::help: help width...{}", str_width(&help));
|
||||||
// Determine how many newlines we need to insert
|
// Determine how many newlines we need to insert
|
||||||
let avail_chars = self.term_w - spcs;
|
let avail_chars = self.term_w - spaces;
|
||||||
debug!("Help::help: Usable space...{}", avail_chars);
|
debug!("Help::help: Usable space...{}", avail_chars);
|
||||||
help = wrap_help(&help, avail_chars);
|
help = text_wrapper(&help, avail_chars);
|
||||||
} else {
|
} else {
|
||||||
debug!("No");
|
debug!("No");
|
||||||
}
|
}
|
||||||
|
@ -473,21 +456,65 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
for part in help.lines().skip(1) {
|
for part in help.lines().skip(1) {
|
||||||
self.none("\n")?;
|
self.none("\n")?;
|
||||||
if nlh || self.force_next_line {
|
if next_line_help {
|
||||||
self.none(&format!("{}{}{}", TAB, TAB, TAB))?;
|
self.none(&format!("{}{}{}", TAB, TAB, TAB))?;
|
||||||
} else if arg.has_switch() {
|
} else if has_switch {
|
||||||
write_nspaces!(self, self.longest + 12);
|
self.spaces(longest + 12)?;
|
||||||
} else {
|
} else {
|
||||||
write_nspaces!(self, self.longest + 8);
|
self.spaces(longest + 8)?;
|
||||||
}
|
}
|
||||||
self.none(part)?;
|
self.none(part)?;
|
||||||
}
|
}
|
||||||
if !prevent_nlh && (nlh || self.force_next_line) {
|
|
||||||
self.none("\n")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
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, next_line_help, longest)?;
|
||||||
|
|
||||||
|
let about = if self.use_long {
|
||||||
|
arg.long_about.unwrap_or_else(|| arg.about.unwrap_or(""))
|
||||||
|
} else {
|
||||||
|
arg.about.unwrap_or_else(|| arg.long_about.unwrap_or(""))
|
||||||
|
};
|
||||||
|
|
||||||
|
self.help(arg.has_switch(), 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()
|
||||||
|
.filter(|arg| should_show_arg(self.use_long, *arg))
|
||||||
|
.any(|arg| {
|
||||||
|
let spec_vals = &self.spec_vals(arg);
|
||||||
|
self.arg_next_line_help(arg, spec_vals, longest)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arg_next_line_help(&self, arg: &Arg<'help>, spec_vals: &str, longest: usize) -> bool {
|
||||||
|
if self.next_line_help || arg.is_set(ArgSettings::NextLineHelp) || self.use_long {
|
||||||
|
// setting_next_line
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
// force_next_line
|
||||||
|
let h = arg.about.unwrap_or("");
|
||||||
|
let h_w = str_width(h) + str_width(spec_vals);
|
||||||
|
let taken = longest + 12;
|
||||||
|
self.term_w >= taken
|
||||||
|
&& (taken as f32 / self.term_w as f32) > 0.40
|
||||||
|
&& h_w > (self.term_w - taken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn spec_vals(&self, a: &Arg) -> String {
|
fn spec_vals(&self, a: &Arg) -> String {
|
||||||
debug!("Help::spec_vals: a={}", a);
|
debug!("Help::spec_vals: a={}", a);
|
||||||
let mut spec_vals = vec![];
|
let mut spec_vals = vec![];
|
||||||
|
@ -599,35 +626,54 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
};
|
};
|
||||||
prefix.to_string() + &spec_vals.join(" ")
|
prefix.to_string() + &spec_vals.join(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_about(&mut self, new_line: bool) -> io::Result<()> {
|
||||||
|
let about = if self.use_long {
|
||||||
|
self.parser.app.long_about.or(self.parser.app.about)
|
||||||
|
} else {
|
||||||
|
self.parser.app.about
|
||||||
|
};
|
||||||
|
if let Some(output) = about {
|
||||||
|
self.none(text_wrapper(output, self.term_w))?;
|
||||||
|
if new_line {
|
||||||
|
self.none("\n")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_author(&mut self, new_line: bool) -> io::Result<()> {
|
||||||
|
if let Some(author) = self.parser.app.author {
|
||||||
|
self.none(text_wrapper(author, self.term_w))?;
|
||||||
|
if new_line {
|
||||||
|
self.none("\n")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Methods to write a single subcommand
|
/// Methods to write a single subcommand
|
||||||
impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
fn write_subcommand(&mut self, sc_str: &str, app: &App<'help>) -> io::Result<()> {
|
fn write_subcommand(
|
||||||
|
&mut self,
|
||||||
|
sc_str: &str,
|
||||||
|
app: &App<'help>,
|
||||||
|
next_line_help: bool,
|
||||||
|
longest: usize,
|
||||||
|
) -> io::Result<()> {
|
||||||
debug!("Help::write_subcommand");
|
debug!("Help::write_subcommand");
|
||||||
self.none(TAB)?;
|
|
||||||
self.good(sc_str)?;
|
|
||||||
let spec_vals = self.sc_val(sc_str, app)?;
|
|
||||||
self.sc_help(app, &*spec_vals)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sc_val(&mut self, sc_str: &str, app: &App) -> Result<String, io::Error> {
|
let spec_vals = &self.sc_spec_vals(app);
|
||||||
debug!("Help::sc_val: app={}", app.name);
|
|
||||||
let spec_vals = self.sc_spec_vals(app);
|
|
||||||
let h = app.about.unwrap_or("");
|
|
||||||
let h_w = str_width(h) + str_width(&*spec_vals);
|
|
||||||
let nlh = self.next_line_help;
|
|
||||||
let taken = self.longest + 12;
|
|
||||||
self.force_next_line = !nlh
|
|
||||||
&& self.term_w >= taken
|
|
||||||
&& (taken as f32 / self.term_w as f32) > 0.40
|
|
||||||
&& h_w > (self.term_w - taken);
|
|
||||||
|
|
||||||
if !(nlh || self.force_next_line) {
|
let about = if self.use_long {
|
||||||
write_nspaces!(self, self.longest + 4 - (str_width(sc_str)));
|
app.long_about.unwrap_or_else(|| app.about.unwrap_or(""))
|
||||||
}
|
} else {
|
||||||
Ok(spec_vals)
|
app.about.unwrap_or_else(|| app.long_about.unwrap_or(""))
|
||||||
|
};
|
||||||
|
|
||||||
|
self.subcmd(sc_str, next_line_help, longest)?;
|
||||||
|
self.help(false, about, spec_vals, next_line_help, longest)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sc_spec_vals(&self, a: &App) -> String {
|
fn sc_spec_vals(&self, a: &App) -> String {
|
||||||
|
@ -658,56 +704,28 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
spec_vals.join(" ")
|
spec_vals.join(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sc_help(&mut self, app: &App<'help>, spec_vals: &str) -> io::Result<()> {
|
fn subcommand_next_line_help(&self, app: &App<'help>, spec_vals: &str, longest: usize) -> bool {
|
||||||
debug!("Help::sc_help");
|
if self.next_line_help | self.use_long {
|
||||||
let h = if self.use_long {
|
// setting_next_line
|
||||||
app.long_about.unwrap_or_else(|| app.about.unwrap_or(""))
|
true
|
||||||
} else {
|
} else {
|
||||||
app.about.unwrap_or_else(|| app.long_about.unwrap_or(""))
|
// force_next_line
|
||||||
};
|
let h = app.about.unwrap_or("");
|
||||||
let mut help = String::from(h) + spec_vals;
|
let h_w = str_width(h) + str_width(spec_vals);
|
||||||
let nlh = self.next_line_help || self.use_long;
|
let taken = longest + 12;
|
||||||
debug!("Help::sc_help: Next Line...{:?}", nlh);
|
self.term_w >= taken
|
||||||
|
&& (taken as f32 / self.term_w as f32) > 0.40
|
||||||
let spcs = if nlh || self.force_next_line {
|
&& h_w > (self.term_w - taken)
|
||||||
12 // "tab" * 3
|
|
||||||
} else {
|
|
||||||
self.longest + 12
|
|
||||||
};
|
|
||||||
|
|
||||||
let too_long = spcs + str_width(h) + str_width(&*spec_vals) >= self.term_w;
|
|
||||||
|
|
||||||
// Is help on next line, if so then indent
|
|
||||||
if nlh || self.force_next_line {
|
|
||||||
self.none(&format!("\n{}{}{}", TAB, TAB, TAB))?;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debug!("Help::sc_help: Too long...");
|
/// Writes subcommand to the wrapped stream.
|
||||||
if too_long && spcs <= self.term_w {
|
fn subcmd(&mut self, sc_str: &str, next_line_help: bool, longest: usize) -> io::Result<()> {
|
||||||
debug!("Yes");
|
self.none(TAB)?;
|
||||||
debug!("Help::sc_help: help...{}", help);
|
self.good(sc_str)?;
|
||||||
debug!("Help::sc_help: help width...{}", str_width(&*help));
|
if !next_line_help {
|
||||||
// Determine how many newlines we need to insert
|
let width = str_width(sc_str);
|
||||||
let avail_chars = self.term_w - spcs;
|
self.spaces(width.max(longest + 4) - width)?;
|
||||||
debug!("Help::sc_help: Usable space...{}", avail_chars);
|
|
||||||
help = wrap_help(&help, avail_chars);
|
|
||||||
} else {
|
|
||||||
debug!("No");
|
|
||||||
}
|
|
||||||
if let Some(part) = help.lines().next() {
|
|
||||||
self.none(part)?;
|
|
||||||
}
|
|
||||||
for part in help.lines().skip(1) {
|
|
||||||
self.none("\n")?;
|
|
||||||
if nlh || self.force_next_line {
|
|
||||||
self.none(&format!("{}{}{}", TAB, TAB, TAB))?;
|
|
||||||
} else {
|
|
||||||
write_nspaces!(self, self.longest + 8);
|
|
||||||
}
|
|
||||||
self.none(part)?;
|
|
||||||
}
|
|
||||||
if !help.contains('\n') && (nlh || self.force_next_line) {
|
|
||||||
self.none("\n")?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -744,6 +762,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
.collect::<IndexSet<_>>();
|
.collect::<IndexSet<_>>();
|
||||||
|
|
||||||
let mut first = if pos {
|
let mut first = if pos {
|
||||||
|
// Write positional args if any
|
||||||
self.warning("ARGS:\n")?;
|
self.warning("ARGS:\n")?;
|
||||||
self.write_args_unsorted(&self.parser.app.get_positionals().collect::<Vec<_>>())?;
|
self.write_args_unsorted(&self.parser.app.get_positionals().collect::<Vec<_>>())?;
|
||||||
false
|
false
|
||||||
|
@ -825,27 +844,48 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Will use next line help on writing subcommands.
|
||||||
|
fn will_subcommands_wrap(&self, subcommands: &[App<'help>], longest: usize) -> bool {
|
||||||
|
subcommands
|
||||||
|
.iter()
|
||||||
|
.filter(|&subcommand| should_show_subcommand(subcommand))
|
||||||
|
.any(|subcommand| {
|
||||||
|
let spec_vals = &self.sc_spec_vals(subcommand);
|
||||||
|
self.subcommand_next_line_help(subcommand, spec_vals, longest)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes help for subcommands of a Parser Object to the wrapped stream.
|
/// Writes help for subcommands of a Parser Object to the wrapped stream.
|
||||||
fn write_subcommands(&mut self, app: &App<'help>) -> io::Result<()> {
|
fn write_subcommands(&mut self, app: &App<'help>) -> io::Result<()> {
|
||||||
debug!("Help::write_subcommands");
|
debug!("Help::write_subcommands");
|
||||||
// The shortest an arg can legally be is 2 (i.e. '-x')
|
// The shortest an arg can legally be is 2 (i.e. '-x')
|
||||||
self.longest = 2;
|
let mut longest = 2;
|
||||||
let mut ord_m = VecMap::new();
|
let mut ord_m = VecMap::new();
|
||||||
for sc in app
|
for subcommand in app
|
||||||
.subcommands
|
.subcommands
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|s| !s.is_set(AppSettings::Hidden))
|
.filter(|subcommand| should_show_subcommand(subcommand))
|
||||||
{
|
{
|
||||||
let btm = ord_m.entry(sc.disp_ord).or_insert(BTreeMap::new());
|
let btm = ord_m.entry(subcommand.disp_ord).or_insert(BTreeMap::new());
|
||||||
let mut sc_str = String::new();
|
let mut sc_str = String::new();
|
||||||
sc_str.push_str(&sc.short_flag.map_or(String::new(), |c| format!("-{}, ", c)));
|
sc_str.push_str(
|
||||||
sc_str.push_str(&sc.long_flag.map_or(String::new(), |c| format!("--{}, ", c)));
|
&subcommand
|
||||||
sc_str.push_str(&sc.name);
|
.short_flag
|
||||||
self.longest = cmp::max(self.longest, str_width(&sc_str));
|
.map_or(String::new(), |c| format!("-{}, ", c)),
|
||||||
btm.insert(sc_str, sc.clone());
|
);
|
||||||
|
sc_str.push_str(
|
||||||
|
&subcommand
|
||||||
|
.long_flag
|
||||||
|
.map_or(String::new(), |c| format!("--{}, ", c)),
|
||||||
|
);
|
||||||
|
sc_str.push_str(&subcommand.name);
|
||||||
|
longest = longest.max(str_width(&sc_str));
|
||||||
|
btm.insert(sc_str, subcommand.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Help::write_subcommands longest = {}", self.longest);
|
debug!("Help::write_subcommands longest = {}", longest);
|
||||||
|
|
||||||
|
let next_line_help = self.will_subcommands_wrap(&app.subcommands, longest);
|
||||||
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for btm in ord_m.values() {
|
for btm in ord_m.values() {
|
||||||
|
@ -855,7 +895,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
} else {
|
} else {
|
||||||
self.none("\n")?;
|
self.none("\n")?;
|
||||||
}
|
}
|
||||||
self.write_subcommand(sc_str, sc)?;
|
self.write_subcommand(sc_str, sc, next_line_help, longest)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -864,22 +904,18 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
/// Writes binary name of a Parser Object to the wrapped stream.
|
/// Writes binary name of a Parser Object to the wrapped stream.
|
||||||
fn write_bin_name(&mut self) -> io::Result<()> {
|
fn write_bin_name(&mut self) -> io::Result<()> {
|
||||||
debug!("Help::write_bin_name");
|
debug!("Help::write_bin_name");
|
||||||
let term_w = self.term_w;
|
|
||||||
macro_rules! write_name {
|
let bin_name = if let Some(bn) = self.parser.app.bin_name.as_ref() {
|
||||||
() => {{
|
|
||||||
self.good(&*wrap_help(&self.parser.app.name, term_w))?;
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
if let Some(bn) = self.parser.app.bin_name.as_ref() {
|
|
||||||
if bn.contains(' ') {
|
if bn.contains(' ') {
|
||||||
// In case we're dealing with subcommands i.e. git mv is translated to git-mv
|
// In case we're dealing with subcommands i.e. git mv is translated to git-mv
|
||||||
self.good(&bn.replace(" ", "-"))?
|
bn.replace(" ", "-")
|
||||||
} else {
|
} else {
|
||||||
write_name!();
|
text_wrapper(&self.parser.app.name, self.term_w)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
write_name!();
|
text_wrapper(&self.parser.app.name, self.term_w)
|
||||||
}
|
};
|
||||||
|
self.good(&bin_name)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -941,36 +977,16 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"author" => {
|
"author" => {
|
||||||
if let Some(s) = self.parser.app.author {
|
self.write_author(false)?;
|
||||||
self.none(&wrap_help(s, self.term_w))?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"author-with-newline" => {
|
"author-with-newline" => {
|
||||||
if let Some(s) = self.parser.app.author {
|
self.write_author(true)?;
|
||||||
self.none(&wrap_help(s, self.term_w))?;
|
|
||||||
self.none("\n")?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"about" => {
|
"about" => {
|
||||||
let about = if self.use_long {
|
self.write_about(false)?;
|
||||||
self.parser.app.long_about.or(self.parser.app.about)
|
|
||||||
} else {
|
|
||||||
self.parser.app.about
|
|
||||||
};
|
|
||||||
if let Some(output) = about {
|
|
||||||
self.none(wrap_help(output, self.term_w))?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"about-with-newline" => {
|
"about-with-newline" => {
|
||||||
let about = if self.use_long {
|
self.write_about(true)?;
|
||||||
self.parser.app.long_about.or(self.parser.app.about)
|
|
||||||
} else {
|
|
||||||
self.parser.app.about
|
|
||||||
};
|
|
||||||
if let Some(output) = about {
|
|
||||||
self.none(wrap_help(output, self.term_w))?;
|
|
||||||
self.none("\n")?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"usage-heading" => {
|
"usage-heading" => {
|
||||||
self.warning("USAGE:")?;
|
self.warning("USAGE:")?;
|
||||||
|
@ -1005,32 +1021,10 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
self.write_subcommands(self.parser.app)?;
|
self.write_subcommands(self.parser.app)?;
|
||||||
}
|
}
|
||||||
"after-help" => {
|
"after-help" => {
|
||||||
let after_help = if self.use_long {
|
self.write_after_help()?;
|
||||||
self.parser
|
|
||||||
.app
|
|
||||||
.after_long_help
|
|
||||||
.or(self.parser.app.after_help)
|
|
||||||
} else {
|
|
||||||
self.parser.app.after_help
|
|
||||||
};
|
|
||||||
if let Some(output) = after_help {
|
|
||||||
self.none("\n\n")?;
|
|
||||||
self.write_before_after_help(output)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"before-help" => {
|
"before-help" => {
|
||||||
let before_help = if self.use_long {
|
self.write_before_help()?;
|
||||||
self.parser
|
|
||||||
.app
|
|
||||||
.before_long_help
|
|
||||||
.or(self.parser.app.before_help)
|
|
||||||
} else {
|
|
||||||
self.parser.app.before_help
|
|
||||||
};
|
|
||||||
if let Some(output) = before_help {
|
|
||||||
self.write_before_after_help(output)?;
|
|
||||||
self.none("\n\n")?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1050,8 +1044,12 @@ fn should_show_arg(use_long: bool, arg: &Arg) -> bool {
|
||||||
|| arg.is_set(ArgSettings::NextLineHelp)
|
|| arg.is_set(ArgSettings::NextLineHelp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_help(help: &str, avail_chars: usize) -> String {
|
fn should_show_subcommand(subcommand: &App) -> bool {
|
||||||
let wrapper = textwrap::Wrapper::new(avail_chars).break_words(false);
|
!subcommand.is_set(AppSettings::Hidden)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn text_wrapper(help: &str, width: usize) -> String {
|
||||||
|
let wrapper = textwrap::Wrapper::new(width).break_words(false);
|
||||||
help.lines()
|
help.lines()
|
||||||
.map(|line| wrapper.fill(line))
|
.map(|line| wrapper.fill(line))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
|
@ -1060,11 +1058,11 @@ fn wrap_help(help: &str, avail_chars: usize) -> String {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::wrap_help;
|
use super::text_wrapper;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wrap_help_last_word() {
|
fn wrap_help_last_word() {
|
||||||
let help = String::from("foo bar baz");
|
let help = String::from("foo bar baz");
|
||||||
assert_eq!(wrap_help(&help, 5), "foo\nbar\nbaz");
|
assert_eq!(text_wrapper(&help, 5), "foo\nbar\nbaz");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
109
tests/help.rs
109
tests/help.rs
|
@ -117,7 +117,6 @@ FLAGS:
|
||||||
-V, --version
|
-V, --version
|
||||||
Prints version information
|
Prints version information
|
||||||
|
|
||||||
|
|
||||||
some longer text that comes after the help";
|
some longer text that comes after the help";
|
||||||
|
|
||||||
static HIDDEN_ARGS: &str = "prog 1.0
|
static HIDDEN_ARGS: &str = "prog 1.0
|
||||||
|
@ -887,6 +886,114 @@ fn no_wrap_default_help() {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "wrap_help")]
|
||||||
|
fn wrapped_help() {
|
||||||
|
static WRAPPED_HELP: &str = "test
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
rust_test.exe [FLAGS]
|
||||||
|
|
||||||
|
FLAGS:
|
||||||
|
-a, --all
|
||||||
|
Also do versioning for private crates (will not be
|
||||||
|
published)
|
||||||
|
|
||||||
|
--exact
|
||||||
|
Specify inter dependency version numbers exactly with
|
||||||
|
`=`
|
||||||
|
|
||||||
|
-h, --help
|
||||||
|
Prints help information
|
||||||
|
|
||||||
|
--no-git-commit
|
||||||
|
Do not commit version changes
|
||||||
|
|
||||||
|
--no-git-push
|
||||||
|
Do not push generated commit and tags to git remote
|
||||||
|
|
||||||
|
-V, --version
|
||||||
|
Prints version information";
|
||||||
|
let app = App::new("test")
|
||||||
|
.term_width(67)
|
||||||
|
.arg(
|
||||||
|
Arg::new("all")
|
||||||
|
.short('a')
|
||||||
|
.long("all")
|
||||||
|
.about("Also do versioning for private crates (will not be published)"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("exact")
|
||||||
|
.long("exact")
|
||||||
|
.about("Specify inter dependency version numbers exactly with `=`"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("no_git_commit")
|
||||||
|
.long("no-git-commit")
|
||||||
|
.about("Do not commit version changes"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("no_git_push")
|
||||||
|
.long("no-git-push")
|
||||||
|
.about("Do not push generated commit and tags to git remote"),
|
||||||
|
);
|
||||||
|
assert!(utils::compare_output(
|
||||||
|
app,
|
||||||
|
"test --help",
|
||||||
|
WRAPPED_HELP,
|
||||||
|
false
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "wrap_help")]
|
||||||
|
fn unwrapped_help() {
|
||||||
|
static UNWRAPPED_HELP: &str = "test
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
rust_test.exe [FLAGS]
|
||||||
|
|
||||||
|
FLAGS:
|
||||||
|
-a, --all Also do versioning for private crates
|
||||||
|
(will not be published)
|
||||||
|
--exact Specify inter dependency version numbers
|
||||||
|
exactly with `=`
|
||||||
|
-h, --help Prints help information
|
||||||
|
--no-git-commit Do not commit version changes
|
||||||
|
--no-git-push Do not push generated commit and tags to
|
||||||
|
git remote
|
||||||
|
-V, --version Prints version information";
|
||||||
|
let app = App::new("test")
|
||||||
|
.term_width(68)
|
||||||
|
.arg(
|
||||||
|
Arg::new("all")
|
||||||
|
.short('a')
|
||||||
|
.long("all")
|
||||||
|
.about("Also do versioning for private crates (will not be published)"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("exact")
|
||||||
|
.long("exact")
|
||||||
|
.about("Specify inter dependency version numbers exactly with `=`"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("no_git_commit")
|
||||||
|
.long("no-git-commit")
|
||||||
|
.about("Do not commit version changes"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("no_git_push")
|
||||||
|
.long("no-git-push")
|
||||||
|
.about("Do not push generated commit and tags to git remote"),
|
||||||
|
);
|
||||||
|
assert!(utils::compare_output(
|
||||||
|
app,
|
||||||
|
"test --help",
|
||||||
|
UNWRAPPED_HELP,
|
||||||
|
false
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn complex_subcommand_help_output() {
|
fn complex_subcommand_help_output() {
|
||||||
let a = utils::complex_app();
|
let a = utils::complex_app();
|
||||||
|
|
Loading…
Reference in a new issue