mirror of
https://github.com/clap-rs/clap
synced 2024-12-12 13:52:34 +00:00
feat(help): Break out help feature flag
This removes auto-generated help, saving about 50 KiB.
This commit is contained in:
parent
6ea5d46300
commit
7a5dad89ff
21 changed files with 100 additions and 38 deletions
|
@ -57,6 +57,7 @@ pre-release-replacements = [
|
|||
default = [
|
||||
"std",
|
||||
"color",
|
||||
"help",
|
||||
"error-context",
|
||||
"suggestions",
|
||||
]
|
||||
|
@ -66,6 +67,7 @@ unstable-doc = ["derive", "cargo", "wrap_help", "env", "unicode", "string", "uns
|
|||
# Used in default
|
||||
std = [] # support for no_std in a backwards-compatible way
|
||||
color = ["dep:atty", "dep:termcolor"]
|
||||
help = []
|
||||
error-context = []
|
||||
suggestions = ["dep:strsim", "error-context"]
|
||||
|
||||
|
@ -153,6 +155,7 @@ path = "examples/multicall-hostname.rs"
|
|||
[[example]]
|
||||
name = "repl"
|
||||
path = "examples/repl.rs"
|
||||
required-features = ["help"]
|
||||
|
||||
[[example]]
|
||||
name = "01_quick"
|
||||
|
|
|
@ -11,7 +11,7 @@ publish = false
|
|||
release = false
|
||||
|
||||
[dev-dependencies]
|
||||
clap = { path = "../", version = "4.0.0-alpha.0", default-features = false, features = ["std"] }
|
||||
clap = { path = "../", version = "4.0.0-alpha.0", default-features = false, features = ["std", "help"] }
|
||||
criterion = "0.3.2"
|
||||
lazy_static = "1"
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ unicode-xid = { version = "0.2.2", optional = true }
|
|||
snapbox = { version = "0.3", features = ["diff"] }
|
||||
# Cutting out `filesystem` feature
|
||||
trycmd = { version = "0.13", default-features = false, features = ["color-auto", "diff", "examples"] }
|
||||
clap = { path = "../", version = "4.0.0-alpha.0", default-features = false, features = ["std", "derive"] }
|
||||
clap = { path = "../", version = "4.0.0-alpha.0", default-features = false, features = ["std", "derive", "help"] }
|
||||
|
||||
[[example]]
|
||||
name = "dynamic"
|
||||
|
|
|
@ -44,3 +44,4 @@ clap_complete = { path = "../clap_complete", version = "4.0.0-alpha.0" }
|
|||
|
||||
[dev-dependencies]
|
||||
snapbox = { version = "0.3", features = ["diff"] }
|
||||
clap = { path = "../", version = "4.0.0-alpha.0", default-features = false, features = ["std", "help"] }
|
||||
|
|
|
@ -45,7 +45,7 @@ clap = { path = "../", version = "4.0.0-alpha.0", default-features = false, feat
|
|||
|
||||
[dev-dependencies]
|
||||
snapbox = { version = "0.3", features = ["diff"] }
|
||||
clap = { path = "../", version = "4.0.0-alpha.0", default-features = false, features = ["std"] }
|
||||
clap = { path = "../", version = "4.0.0-alpha.0", default-features = false, features = ["std", "help"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
//!
|
||||
//! * **std**: _Not Currently Used._ Placeholder for supporting `no_std` environments in a backwards compatible manner.
|
||||
//! * **color**: Turns on colored error messages.
|
||||
//! * **help**: Auto-generate help output
|
||||
//! * **error-context**: Include contextual information for errors (which arg failed, etc)
|
||||
//! * **suggestions**: Turns on the `Did you mean '--myoption'?` feature for when users make typos.
|
||||
//!
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::Command;
|
||||
/// # use clap::Arg;
|
||||
/// let cmd = Command::new("mycmd")
|
||||
|
@ -211,7 +212,8 @@ pub enum ArgAction {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::Command;
|
||||
/// # use clap::Arg;
|
||||
/// let cmd = Command::new("mycmd")
|
||||
|
|
|
@ -1107,7 +1107,8 @@ impl Arg {
|
|||
/// # ;
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("config")
|
||||
|
@ -1168,7 +1169,8 @@ impl Arg {
|
|||
/// .value_names(["fast", "slow"]);
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("io")
|
||||
|
@ -1991,7 +1993,8 @@ impl Arg {
|
|||
/// Setting `help` displays a short message to the side of the argument when the user passes
|
||||
/// `-h` or `--help` (by default).
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("cfg")
|
||||
|
@ -2040,7 +2043,8 @@ impl Arg {
|
|||
/// Setting `help` displays a short message to the side of the argument when the user passes
|
||||
/// `-h` or `--help` (by default).
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("cfg")
|
||||
|
@ -2096,7 +2100,8 @@ impl Arg {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg, ArgAction};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("a") // Typically args are grouped alphabetically by name.
|
||||
|
@ -2162,7 +2167,8 @@ impl Arg {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg, ArgAction};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("opt")
|
||||
|
@ -2212,7 +2218,8 @@ impl Arg {
|
|||
///
|
||||
/// Setting `Hidden` will hide the argument when displaying help text
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("cfg")
|
||||
|
@ -2385,7 +2392,8 @@ impl Arg {
|
|||
///
|
||||
/// Setting `hide_short_help(true)` will hide the argument when displaying short help text
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("cfg")
|
||||
|
@ -2411,7 +2419,8 @@ impl Arg {
|
|||
///
|
||||
/// However, when --help is called
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("cfg")
|
||||
|
@ -2456,7 +2465,8 @@ impl Arg {
|
|||
///
|
||||
/// Setting `hide_long_help(true)` will hide the argument when displaying long help text
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("cfg")
|
||||
|
@ -2482,7 +2492,8 @@ impl Arg {
|
|||
///
|
||||
/// However, when -h is called
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg};
|
||||
/// let m = Command::new("prog")
|
||||
/// .arg(Arg::new("cfg")
|
||||
|
@ -4196,6 +4207,7 @@ impl Arg {
|
|||
self.is_multiple_values_set() || matches!(*self.get_action(), ArgAction::Append)
|
||||
}
|
||||
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn get_display_order(&self) -> usize {
|
||||
self.disp_ord.unwrap_or(999)
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ pub struct Command {
|
|||
disp_ord: Option<usize>,
|
||||
term_w: Option<usize>,
|
||||
max_w: Option<usize>,
|
||||
#[cfg(feature = "help")]
|
||||
template: Option<StyledStr>,
|
||||
settings: AppFlags,
|
||||
g_settings: AppFlags,
|
||||
|
@ -1727,6 +1728,7 @@ impl Command {
|
|||
/// [`Command::before_help`]: Command::before_help()
|
||||
/// [`Command::before_long_help`]: Command::before_long_help()
|
||||
#[must_use]
|
||||
#[cfg(feature = "help")]
|
||||
pub fn help_template(mut self, s: impl IntoResettable<StyledStr>) -> Self {
|
||||
self.template = s.into_resettable().into_option();
|
||||
self
|
||||
|
@ -2536,7 +2538,8 @@ impl Command {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, };
|
||||
/// let m = Command::new("cust-ord")
|
||||
/// .subcommand(Command::new("alpha") // typically subcommands are grouped
|
||||
|
@ -3661,14 +3664,17 @@ impl Command {
|
|||
self.help_str.as_ref()
|
||||
}
|
||||
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn get_help_template(&self) -> Option<&StyledStr> {
|
||||
self.template.as_ref()
|
||||
}
|
||||
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn get_term_width(&self) -> Option<usize> {
|
||||
self.term_w
|
||||
}
|
||||
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn get_max_term_width(&self) -> Option<usize> {
|
||||
self.max_w
|
||||
}
|
||||
|
@ -3753,6 +3759,11 @@ impl Command {
|
|||
self.settings.insert(AppSettings::DisableHelpFlag.into());
|
||||
self.settings.insert(AppSettings::DisableVersionFlag.into());
|
||||
}
|
||||
if !cfg!(feature = "help") && self.get_override_help().is_none() {
|
||||
self.settings.insert(AppSettings::DisableHelpFlag.into());
|
||||
self.settings
|
||||
.insert(AppSettings::DisableHelpSubcommand.into());
|
||||
}
|
||||
if self.is_set(AppSettings::ArgsNegateSubcommands) {
|
||||
self.settings
|
||||
.insert(AppSettings::SubcommandsNegateReqs.into());
|
||||
|
@ -4461,6 +4472,7 @@ impl Command {
|
|||
.map(|sc| sc.get_name())
|
||||
}
|
||||
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn get_display_order(&self) -> usize {
|
||||
self.disp_ord.unwrap_or(999)
|
||||
}
|
||||
|
@ -4553,6 +4565,7 @@ impl Default for Command {
|
|||
disp_ord: Default::default(),
|
||||
term_w: Default::default(),
|
||||
max_w: Default::default(),
|
||||
#[cfg(feature = "help")]
|
||||
template: Default::default(),
|
||||
settings: Default::default(),
|
||||
g_settings: Default::default(),
|
||||
|
|
|
@ -337,6 +337,7 @@ pub(crate) fn assert_app(cmd: &Command) {
|
|||
|
||||
_verify_positionals(cmd);
|
||||
|
||||
#[cfg(feature = "help")]
|
||||
if let Some(help_template) = cmd.get_help_template() {
|
||||
assert!(
|
||||
!help_template.to_string().contains("{flags}"),
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::{borrow::Cow, iter};
|
||||
|
||||
use crate::builder::IntoResettable;
|
||||
use crate::builder::Str;
|
||||
use crate::builder::StyledStr;
|
||||
|
@ -157,6 +155,7 @@ impl PossibleValue {
|
|||
/// Get the help specified for this argument, if any and the argument
|
||||
/// value is not hidden
|
||||
#[inline]
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn get_visible_help(&self) -> Option<&StyledStr> {
|
||||
if !self.hide {
|
||||
self.get_help()
|
||||
|
@ -178,7 +177,8 @@ impl PossibleValue {
|
|||
|
||||
/// Get the name if argument value is not hidden, `None` otherwise,
|
||||
/// but wrapped in quotes if it contains whitespace
|
||||
pub(crate) fn get_visible_quoted_name(&self) -> Option<Cow<'_, str>> {
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn get_visible_quoted_name(&self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
if !self.hide {
|
||||
Some(if self.name.contains(char::is_whitespace) {
|
||||
format!("{:?}", self.name).into()
|
||||
|
@ -194,7 +194,7 @@ impl PossibleValue {
|
|||
///
|
||||
/// Namely the name and all aliases.
|
||||
pub fn get_name_and_aliases(&self) -> impl Iterator<Item = &str> + '_ {
|
||||
iter::once(self.get_name()).chain(self.aliases.iter().map(|s| s.as_str()))
|
||||
std::iter::once(self.get_name()).chain(self.aliases.iter().map(|s| s.as_str()))
|
||||
}
|
||||
|
||||
/// Tests if the value is valid for this argument value
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
use crate::output::display_width;
|
||||
use crate::output::textwrap;
|
||||
|
||||
/// Terminal-styling container
|
||||
#[derive(Clone, Default, Debug, PartialEq, Eq)]
|
||||
pub struct StyledStr {
|
||||
|
@ -86,6 +83,7 @@ impl StyledStr {
|
|||
self.pieces = self.pieces.trim_end().to_owned();
|
||||
}
|
||||
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn indent(&mut self, initial: &str, trailing: &str) {
|
||||
if let Some((_, first)) = self.iter_mut().next() {
|
||||
first.insert_str(0, initial);
|
||||
|
@ -97,8 +95,9 @@ impl StyledStr {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn wrap(&mut self, hard_width: usize) {
|
||||
let mut wrapper = textwrap::wrap_algorithms::LineWrapper::new(hard_width);
|
||||
let mut wrapper = crate::output::textwrap::wrap_algorithms::LineWrapper::new(hard_width);
|
||||
for (_, content) in self.iter_mut() {
|
||||
let mut total = Vec::new();
|
||||
for (i, line) in content.split_inclusive('\n').enumerate() {
|
||||
|
@ -106,8 +105,8 @@ impl StyledStr {
|
|||
// start of a section does not imply newline
|
||||
wrapper.reset();
|
||||
}
|
||||
let line =
|
||||
textwrap::word_separators::find_words_ascii_space(line).collect::<Vec<_>>();
|
||||
let line = crate::output::textwrap::word_separators::find_words_ascii_space(line)
|
||||
.collect::<Vec<_>>();
|
||||
total.extend(wrapper.wrap(line));
|
||||
}
|
||||
let total = total.join("");
|
||||
|
@ -130,14 +129,16 @@ impl StyledStr {
|
|||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn display_width(&self) -> usize {
|
||||
let mut width = 0;
|
||||
for (_, c) in self.iter() {
|
||||
width += display_width(c);
|
||||
width += crate::output::display_width(c);
|
||||
}
|
||||
width
|
||||
}
|
||||
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
self.pieces.is_empty()
|
||||
}
|
||||
|
|
|
@ -250,7 +250,8 @@ pub enum ErrorKind {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "help"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "help", doc = " ```")]
|
||||
/// # use clap::{Command, Arg, error::ErrorKind};
|
||||
/// let result = Command::new("prog")
|
||||
/// .try_get_matches_from(vec!["prog", "--help"]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![cfg_attr(not(feature = "help"), allow(unused_variables))]
|
||||
|
||||
// Internal
|
||||
use super::AutoHelp;
|
||||
use super::HelpTemplate;
|
||||
use crate::builder::Command;
|
||||
use crate::builder::StyledStr;
|
||||
use crate::output::Usage;
|
||||
|
@ -11,10 +11,16 @@ pub(crate) fn write_help(writer: &mut StyledStr, cmd: &Command, usage: &Usage<'_
|
|||
|
||||
if let Some(h) = cmd.get_override_help() {
|
||||
writer.extend(h.iter());
|
||||
} else if let Some(tmpl) = cmd.get_help_template() {
|
||||
} else {
|
||||
#[cfg(feature = "help")]
|
||||
{
|
||||
use super::AutoHelp;
|
||||
use super::HelpTemplate;
|
||||
if let Some(tmpl) = cmd.get_help_template() {
|
||||
for (style, content) in tmpl.iter() {
|
||||
if style == None {
|
||||
HelpTemplate::new(writer, cmd, usage, use_long).write_templated_help(content);
|
||||
HelpTemplate::new(writer, cmd, usage, use_long)
|
||||
.write_templated_help(content);
|
||||
} else {
|
||||
writer.stylize(style, content);
|
||||
}
|
||||
|
@ -22,6 +28,13 @@ pub(crate) fn write_help(writer: &mut StyledStr, cmd: &Command, usage: &Usage<'_
|
|||
} else {
|
||||
AutoHelp::new(writer, cmd, usage, use_long).write_help();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "help"))]
|
||||
{
|
||||
debug!("write_help: no help, `Command::override_help` and `help` is missing");
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any extra lines caused by book keeping
|
||||
writer.trim();
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
mod help;
|
||||
#[cfg(feature = "help")]
|
||||
mod help_template;
|
||||
mod usage;
|
||||
|
||||
pub(crate) mod fmt;
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) mod textwrap;
|
||||
|
||||
pub(crate) use self::help::write_help;
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) use self::help_template::AutoHelp;
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) use self::help_template::HelpTemplate;
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) use self::textwrap::core::display_width;
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) use self::textwrap::wrap;
|
||||
pub(crate) use self::usage::Usage;
|
||||
|
||||
pub(crate) const TAB: &str = " ";
|
||||
#[cfg(feature = "help")]
|
||||
pub(crate) const TAB_WIDTH: usize = TAB.len();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![cfg(feature = "help")]
|
||||
|
||||
use clap::{arg, builder::PossibleValue, error::ErrorKind, Arg, ArgAction, ArgGroup, Command};
|
||||
|
||||
use super::utils;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(clippy::bool_assert_comparison)]
|
||||
#![allow(clippy::redundant_clone)]
|
||||
#![cfg(feature = "help")]
|
||||
|
||||
mod action;
|
||||
mod app_settings;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![cfg(feature = "help")]
|
||||
#![cfg(feature = "derive")]
|
||||
|
||||
mod app_name;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![cfg(not(tarpaulin))]
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "help")]
|
||||
#[cfg(feature = "error-context")]
|
||||
fn example_tests() {
|
||||
let t = trycmd::TestCases::new();
|
||||
|
|
|
@ -277,6 +277,7 @@ mod arg {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "help")]
|
||||
fn optional_value() {
|
||||
let mut cmd = clap::Command::new("test").arg(clap::arg!(port: -p [NUM]));
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![cfg(not(tarpaulin))]
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "help")]
|
||||
#[cfg(feature = "error-context")]
|
||||
fn ui_tests() {
|
||||
let t = trycmd::TestCases::new();
|
||||
|
|
Loading…
Reference in a new issue