Skip to content

Commit

Permalink
feat(help): 'usage' feature flag for auto-genned usage
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Sep 19, 2022
1 parent 80f616a commit b13ec5c
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 10 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ default = [
"std",
"color",
"help",
"usage",
"error-context",
"suggestions",
]
Expand All @@ -68,6 +69,7 @@ unstable-doc = ["derive", "cargo", "wrap_help", "env", "unicode", "string", "uns
std = [] # support for no_std in a backwards-compatible way
color = ["dep:atty", "dep:termcolor"]
help = []
usage = []
error-context = []
suggestions = ["dep:strsim", "error-context"]

Expand Down
1 change: 1 addition & 0 deletions src/_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,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
//! * **usage**: Auto-generate usage
//! * **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.
//!
Expand Down
7 changes: 7 additions & 0 deletions src/builder/command.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg_attr(not(feature = "usage"), allow(unused_mut))]

// Std
use std::env;
use std::ffi::OsString;
Expand Down Expand Up @@ -3142,6 +3144,7 @@ impl Command {
/// # Reflection
impl Command {
#[inline]
#[cfg(feature = "usage")]
pub(crate) fn get_usage_name(&self) -> Option<&str> {
self.usage_name.as_deref()
}
Expand Down Expand Up @@ -3851,6 +3854,7 @@ impl Command {
use std::fmt::Write;

let mut mid_string = String::from(" ");
#[cfg(feature = "usage")]
if !self.is_subcommand_negates_reqs_set() && !self.is_args_conflicts_with_subcommands_set()
{
let reqs = Usage::new(self).get_required_usage_from(&[], None, true); // maybe Some(m)
Expand Down Expand Up @@ -3936,6 +3940,7 @@ impl Command {

if !self.is_set(AppSettings::BinNameBuilt) {
let mut mid_string = String::from(" ");
#[cfg(feature = "usage")]
if !self.is_subcommand_negates_reqs_set()
&& !self.is_args_conflicts_with_subcommands_set()
{
Expand Down Expand Up @@ -4290,6 +4295,7 @@ impl<'a, T> Captures<'a> for T {}
// Internal Query Methods
impl Command {
/// Iterate through the *flags* & *options* arguments.
#[cfg(any(feature = "usage", feature = "help"))]
pub(crate) fn get_non_positionals(&self) -> impl Iterator<Item = &Arg> {
self.get_arguments().filter(|a| !a.is_positional())
}
Expand Down Expand Up @@ -4318,6 +4324,7 @@ impl Command {
self.get_positionals().next().is_some()
}

#[cfg(any(feature = "usage", feature = "help"))]
pub(crate) fn has_visible_subcommands(&self) -> bool {
self.subcommands
.iter()
Expand Down
35 changes: 26 additions & 9 deletions src/output/usage.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#![cfg_attr(not(feature = "usage"), allow(unused_imports))]
#![cfg_attr(not(feature = "usage"), allow(unused_variables))]
#![cfg_attr(not(feature = "usage"), allow(clippy::manual_map))]
#![cfg_attr(not(feature = "usage"), allow(dead_code))]

// Internal
use crate::builder::StyledStr;
use crate::builder::{ArgPredicate, Command};
Expand Down Expand Up @@ -44,13 +49,26 @@ impl<'cmd> Usage<'cmd> {
debug!("Usage::create_usage_no_title");
if let Some(u) = self.cmd.get_override_usage() {
Some(u.clone())
} else if used.is_empty() {
Some(self.create_help_usage(true))
} else {
Some(self.create_smart_usage(used))
#[cfg(feature = "usage")]
{
if used.is_empty() {
Some(self.create_help_usage(true))
} else {
Some(self.create_smart_usage(used))
}
}

#[cfg(not(feature = "usage"))]
{
None
}
}
}
}

#[cfg(feature = "usage")]
impl<'cmd> Usage<'cmd> {
// Creates a usage string for display in help messages (i.e. not for errors)
fn create_help_usage(&self, incl_reqs: bool) -> StyledStr {
debug!("Usage::create_help_usage; incl_reqs={:?}", incl_reqs);
Expand Down Expand Up @@ -177,7 +195,7 @@ impl<'cmd> Usage<'cmd> {
}

pub(crate) fn get_args(&self, incls: &[Id], force_optional: bool) -> Vec<StyledStr> {
debug!("Usage::get_required_usage_from: incls={:?}", incls,);
debug!("Usage::get_args: incls={:?}", incls,);

let required_owned;
let required = if let Some(required) = self.required {
Expand Down Expand Up @@ -206,10 +224,7 @@ impl<'cmd> Usage<'cmd> {
// by unroll_requirements_for_arg.
unrolled_reqs.push(a.clone());
}
debug!(
"Usage::get_required_usage_from: unrolled_reqs={:?}",
unrolled_reqs
);
debug!("Usage::get_args: unrolled_reqs={:?}", unrolled_reqs);

let mut required_groups_members = FlatSet::new();
let mut required_groups = FlatSet::new();
Expand Down Expand Up @@ -294,10 +309,12 @@ impl<'cmd> Usage<'cmd> {
ret_val.push(pos);
}

debug!("Usage::get_required_usage_from: ret_val={:?}", ret_val);
debug!("Usage::get_args: ret_val={:?}", ret_val);
ret_val
}
}

impl<'cmd> Usage<'cmd> {
pub(crate) fn get_required_usage_from(
&self,
incls: &[Id],
Expand Down
1 change: 1 addition & 0 deletions tests/builder/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::redundant_clone)]
#![cfg(feature = "help")]
#![cfg(feature = "usage")]

mod action;
mod app_settings;
Expand Down
3 changes: 2 additions & 1 deletion tests/derive/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![cfg(feature = "help")]
#![cfg(feature = "derive")]
#![cfg(feature = "help")]
#![cfg(feature = "usage")]

mod app_name;
mod arguments;
Expand Down
1 change: 1 addition & 0 deletions tests/examples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#[test]
#[cfg(feature = "help")]
#[cfg(feature = "error-context")]
#[cfg(feature = "usage")]
fn example_tests() {
let t = trycmd::TestCases::new();
let features = [
Expand Down
1 change: 1 addition & 0 deletions tests/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#[test]
#[cfg(feature = "help")]
#[cfg(feature = "error-context")]
#[cfg(feature = "usage")]
fn ui_tests() {
let t = trycmd::TestCases::new();
let features = [
Expand Down

0 comments on commit b13ec5c

Please sign in to comment.