Skip to content

Commit

Permalink
Merge pull request #1235 from stevepentland/hide-help
Browse files Browse the repository at this point in the history
Add option to hide help based on long/short
  • Loading branch information
kbknapp authored Apr 2, 2018
2 parents 245c179 + 69400cb commit d51d35d
Show file tree
Hide file tree
Showing 5 changed files with 350 additions and 7 deletions.
15 changes: 13 additions & 2 deletions src/app/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,9 @@ impl<'a> Help<'a> {
// The shortest an arg can legally be is 2 (i.e. '-x')
self.longest = 2;
let mut arg_v = Vec::with_capacity(10);
let use_long = self.use_long;
for arg in args.filter(|arg| {
!(arg.is_set(ArgSettings::Hidden)) || arg.is_set(ArgSettings::NextLineHelp)
should_show_arg(use_long, *arg)
}) {
if arg.longest_filter() {
self.longest = cmp::max(self.longest, str_width(arg.to_string().as_str()));
Expand Down Expand Up @@ -231,12 +232,13 @@ impl<'a> Help<'a> {
// The shortest an arg can legally be is 2 (i.e. '-x')
self.longest = 2;
let mut ord_m = VecMap::new();
let use_long = self.use_long;
// Determine the longest
for arg in args.filter(|arg| {
// If it's NextLineHelp, but we don't care to compute how long because it may be
// NextLineHelp on purpose *because* it's so long and would throw off all other
// args alignment
!arg.is_set(ArgSettings::Hidden) || arg.is_set(ArgSettings::NextLineHelp)
should_show_arg(use_long, *arg)
}) {
if arg.longest_filter() {
debugln!("Help::write_args: Current Longest...{}", self.longest);
Expand Down Expand Up @@ -565,6 +567,15 @@ impl<'a> Help<'a> {
}
}

fn should_show_arg(use_long: bool, arg: &ArgWithOrder) -> bool {
if arg.is_set(ArgSettings::Hidden) {
return false;
}

(!arg.is_set(ArgSettings::HiddenLongHelp) && use_long) ||
(!arg.is_set(ArgSettings::HiddenShortHelp) && !use_long) ||
arg.is_set(ArgSettings::NextLineHelp)
}

// Methods to write Parser help.
impl<'a> Help<'a> {
Expand Down
19 changes: 15 additions & 4 deletions src/app/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1499,14 +1499,25 @@ where
}

fn use_long_help(&self) -> bool {
self.meta.long_about.is_some() || self.flags.iter().any(|f| f.b.long_help.is_some())
|| self.opts.iter().any(|o| o.b.long_help.is_some())
|| self.positionals.values().any(|p| p.b.long_help.is_some())
// In this case, both must be checked. This allows the retention of
// original formatting, but also ensures that the actual -h or --help
// specified by the user is sent through. If HiddenShortHelp is not included,
// then items specified with hidden_short_help will also be hidden.
let should_long = |v: &Base| {
v.long_help.is_some() ||
v.is_set(ArgSettings::HiddenLongHelp) ||
v.is_set(ArgSettings::HiddenShortHelp)
};

self.meta.long_about.is_some()
|| self.flags.iter().any(|f| should_long(&f.b))
|| self.opts.iter().any(|o| should_long(&o.b))
|| self.positionals.values().any(|p| should_long(&p.b))
|| self.subcommands
.iter()
.any(|s| s.p.meta.long_about.is_some())
}

fn _help(&self, mut use_long: bool) -> Error {
debugln!("Parser::_help: use_long={:?}", use_long);
use_long = use_long && self.use_long_help();
Expand Down
159 changes: 159 additions & 0 deletions src/args/arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2299,6 +2299,9 @@ impl<'a, 'b> Arg<'a, 'b> {

/// Hides an argument from help message output.
///
/// **NOTE:** Implicitly sets [`Arg::hidden_short_help(true)`] and [`Arg::hidden_long_help(true)`]
/// when set to true
///
/// **NOTE:** This does **not** hide the argument from usage strings on error
///
/// # Examples
Expand Down Expand Up @@ -2335,6 +2338,8 @@ impl<'a, 'b> Arg<'a, 'b> {
/// -h, --help Prints help information
/// -V, --version Prints version information
/// ```
/// [`Arg::hidden_short_help(true)`]: ./struct.Arg.html#method.hidden_short_help
/// [`Arg::hidden_long_help(true)`]: ./struct.Arg.html#method.hidden_long_help
pub fn hidden(self, h: bool) -> Self {
if h {
self.set(ArgSettings::Hidden)
Expand Down Expand Up @@ -3735,6 +3740,160 @@ impl<'a, 'b> Arg<'a, 'b> {
self.multiple(raw).allow_hyphen_values(raw).last(raw)
}

/// Hides an argument from short help message output.
///
/// **NOTE:** This does **not** hide the argument from usage strings on error
///
/// **NOTE:** Setting this option will cause next-line-help output style to be used
/// when long help (`--help`) is called.
///
/// # Examples
///
/// ```rust
/// # use clap::{App, Arg};
/// Arg::with_name("debug")
/// .hidden_short_help(true)
/// # ;
/// ```
/// Setting `hidden_short_help(true)` will hide the argument when displaying short help text
///
/// ```rust
/// # use clap::{App, Arg};
/// let m = App::new("prog")
/// .arg(Arg::with_name("cfg")
/// .long("config")
/// .hidden_short_help(true)
/// .help("Some help text describing the --config arg"))
/// .get_matches_from(vec![
/// "prog", "-h"
/// ]);
/// ```
///
/// The above example displays
///
/// ```notrust
/// helptest
///
/// USAGE:
/// helptest [FLAGS]
///
/// FLAGS:
/// -h, --help Prints help information
/// -V, --version Prints version information
/// ```
///
/// However, when --help is called
///
/// ```rust
/// # use clap::{App, Arg};
/// let m = App::new("prog")
/// .arg(Arg::with_name("cfg")
/// .long("config")
/// .hidden_short_help(true)
/// .help("Some help text describing the --config arg"))
/// .get_matches_from(vec![
/// "prog", "--help"
/// ]);
/// ```
///
/// Then the following would be displayed
///
/// ```notrust
/// helptest
///
/// USAGE:
/// helptest [FLAGS]
///
/// FLAGS:
/// --config Some help text describing the --config arg
/// -h, --help Prints help information
/// -V, --version Prints version information
/// ```
pub fn hidden_short_help(self, hide: bool) -> Self {
if hide {
self.set(ArgSettings::HiddenShortHelp)
} else {
self.unset(ArgSettings::HiddenShortHelp)
}
}

/// Hides an argument from long help message output.
///
/// **NOTE:** This does **not** hide the argument from usage strings on error
///
/// **NOTE:** Setting this option will cause next-line-help output style to be used
/// when long help (`--help`) is called.
///
/// # Examples
///
/// ```rust
/// # use clap::{App, Arg};
/// Arg::with_name("debug")
/// .hidden_long_help(true)
/// # ;
/// ```
/// Setting `hidden_long_help(true)` will hide the argument when displaying long help text
///
/// ```rust
/// # use clap::{App, Arg};
/// let m = App::new("prog")
/// .arg(Arg::with_name("cfg")
/// .long("config")
/// .hidden_long_help(true)
/// .help("Some help text describing the --config arg"))
/// .get_matches_from(vec![
/// "prog", "--help"
/// ]);
/// ```
///
/// The above example displays
///
/// ```notrust
/// helptest
///
/// USAGE:
/// helptest [FLAGS]
///
/// FLAGS:
/// -h, --help Prints help information
/// -V, --version Prints version information
/// ```
///
/// However, when -h is called
///
/// ```rust
/// # use clap::{App, Arg};
/// let m = App::new("prog")
/// .arg(Arg::with_name("cfg")
/// .long("config")
/// .hidden_long_help(true)
/// .help("Some help text describing the --config arg"))
/// .get_matches_from(vec![
/// "prog", "-h"
/// ]);
/// ```
///
/// Then the following would be displayed
///
/// ```notrust
/// helptest
///
/// USAGE:
/// helptest [FLAGS]
///
/// FLAGS:
/// --config Some help text describing the --config arg
/// -h, --help Prints help information
/// -V, --version Prints version information
/// ```
pub fn hidden_long_help(self, hide: bool) -> Self {
if hide {
self.set(ArgSettings::HiddenLongHelp)
} else {
self.unset(ArgSettings::HiddenLongHelp)
}
}

/// Checks if one of the [`ArgSettings`] settings is set for the argument
/// [`ArgSettings`]: ./enum.ArgSettings.html
pub fn is_set(&self, s: ArgSettings) -> bool {
Expand Down
20 changes: 19 additions & 1 deletion src/args/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ bitflags! {
const HIDE_DEFAULT_VAL = 1 << 15;
const CASE_INSENSITIVE = 1 << 16;
const HIDE_ENV_VALS = 1 << 17;
const HIDDEN_SHORT_H = 1 << 18;
const HIDDEN_LONG_H = 1 << 19;
}
}

Expand Down Expand Up @@ -51,7 +53,9 @@ impl ArgFlags {
Last => Flags::LAST,
CaseInsensitive => Flags::CASE_INSENSITIVE,
HideEnvValues => Flags::HIDE_ENV_VALS,
HideDefaultValue => Flags::HIDE_DEFAULT_VAL
HideDefaultValue => Flags::HIDE_DEFAULT_VAL,
HiddenShortHelp => Flags::HIDDEN_SHORT_H,
HiddenLongHelp => Flags::HIDDEN_LONG_H
}
}

Expand Down Expand Up @@ -101,6 +105,10 @@ pub enum ArgSettings {
CaseInsensitive,
/// Hides ENV values in the help message
HideEnvValues,
/// The argument should **not** be shown in short help text
HiddenShortHelp,
/// The argument should **not** be shown in long help text
HiddenLongHelp,
#[doc(hidden)] RequiredUnlessAll,
#[doc(hidden)] ValueDelimiterNotSet,
}
Expand All @@ -127,6 +135,8 @@ impl FromStr for ArgSettings {
"hidedefaultvalue" => Ok(ArgSettings::HideDefaultValue),
"caseinsensitive" => Ok(ArgSettings::CaseInsensitive),
"hideenvvalues" => Ok(ArgSettings::HideEnvValues),
"hiddenshorthelp" => Ok(ArgSettings::HiddenShortHelp),
"hiddenlonghelp" => Ok(ArgSettings::HiddenLongHelp),
_ => Err("unknown ArgSetting, cannot convert from str".to_owned()),
}
}
Expand Down Expand Up @@ -207,6 +217,14 @@ mod test {
"hideenvvalues".parse::<ArgSettings>().unwrap(),
ArgSettings::HideEnvValues
);
assert_eq!(
"hiddenshorthelp".parse::<ArgSettings>().unwrap(),
ArgSettings::HiddenShortHelp
);
assert_eq!(
"hiddenlonghelp".parse::<ArgSettings>().unwrap(),
ArgSettings::HiddenLongHelp
);
assert!("hahahaha".parse::<ArgSettings>().is_err());
}
}
Loading

0 comments on commit d51d35d

Please sign in to comment.