feat: Open the door for user styling in the future

This added about 10 KiB to the `.text` which I cannot explain why
This commit is contained in:
Ed Page 2022-08-24 10:24:15 -05:00
parent 2e2b63fa5c
commit c6155f62d5
18 changed files with 215 additions and 111 deletions

View file

@ -1,5 +1,6 @@
use std::io::Write;
use clap::builder::StyledStr;
use clap::*;
use crate::generator::{utils, Generator};
@ -59,9 +60,9 @@ fn escape_string(string: &str) -> String {
string.replace('\'', "''")
}
fn get_tooltip<T: ToString>(help: Option<&str>, data: T) -> String {
fn get_tooltip<T: ToString>(help: Option<&StyledStr>, data: T) -> String {
match help {
Some(help) => escape_string(help),
Some(help) => escape_string(&help.to_string()),
_ => data.to_string(),
}
}

View file

@ -93,7 +93,7 @@ fn gen_fish_inner(
}
if let Some(data) = option.get_help() {
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
template.push_str(format!(" -d '{}'", escape_string(&data.to_string())).as_str());
}
template.push_str(value_completion(option).as_str());
@ -118,7 +118,7 @@ fn gen_fish_inner(
}
if let Some(data) = flag.get_help() {
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
template.push_str(format!(" -d '{}'", escape_string(&data.to_string())).as_str());
}
buffer.push_str(template.as_str());
@ -132,7 +132,7 @@ fn gen_fish_inner(
template.push_str(format!(" -a \"{}\"", &subcommand.get_name()).as_str());
if let Some(data) = subcommand.get_about() {
template.push_str(format!(" -d '{}'", escape_string(data)).as_str())
template.push_str(format!(" -d '{}'", escape_string(&data.to_string())).as_str())
}
buffer.push_str(template.as_str());
@ -164,7 +164,7 @@ fn value_completion(option: &Arg) -> String {
Some(format!(
"{}\t{}",
escape_string(value.get_name()).as_str(),
escape_string(value.get_help().unwrap_or_default()).as_str()
escape_string(&value.get_help().unwrap_or_default().to_string())
))
})
.collect::<Vec<_>>()

View file

@ -1,5 +1,6 @@
use std::io::Write;
use clap::builder::StyledStr;
use clap::*;
use crate::generator::{utils, Generator};
@ -64,9 +65,9 @@ fn escape_string(string: &str) -> String {
string.replace('\'', "''")
}
fn get_tooltip<T: ToString>(help: Option<&str>, data: T) -> String {
fn get_tooltip<T: ToString>(help: Option<&StyledStr>, data: T) -> String {
match help {
Some(help) => escape_string(help),
Some(help) => escape_string(&help.to_string()),
_ => data.to_string(),
}
}

View file

@ -153,7 +153,7 @@ fn subcommands_of(p: &Command) -> String {
let text = format!(
"'{name}:{help}' \\",
name = name,
help = escape_help(subcommand.get_about().unwrap_or_default())
help = escape_help(&subcommand.get_about().unwrap_or_default().to_string())
);
if !text.is_empty() {
@ -372,7 +372,8 @@ fn value_completion(arg: &Arg) -> Option<String> {
Some(format!(
r#"{name}\:"{tooltip}""#,
name = escape_value(value.get_name()),
tooltip = value.get_help().map(escape_help).unwrap_or_default()
tooltip =
escape_help(&value.get_help().unwrap_or_default().to_string()),
))
}
})
@ -445,7 +446,7 @@ fn write_opts_of(p: &Command, p_global: Option<&Command>) -> String {
for o in p.get_opts() {
debug!("write_opts_of:iter: o={}", o.get_id());
let help = o.get_help().map(escape_help).unwrap_or_default();
let help = escape_help(&o.get_help().unwrap_or_default().to_string());
let conflicts = arg_conflicts(p, o, p_global);
let multiple = "*";
@ -541,7 +542,7 @@ fn write_flags_of(p: &Command, p_global: Option<&Command>) -> String {
for f in utils::flags(p) {
debug!("write_flags_of:iter: f={}", f.get_id());
let help = f.get_help().map(escape_help).unwrap_or_default();
let help = escape_help(&f.get_help().unwrap_or_default().to_string());
let conflicts = arg_conflicts(p, &f, p_global);
let multiple = "*";
@ -634,7 +635,8 @@ fn write_positionals_of(p: &Command) -> String {
name = arg.get_id(),
help = arg
.get_help()
.map_or("".to_owned(), |v| " -- ".to_owned() + v)
.map(|s| s.to_string())
.map_or("".to_owned(), |v| " -- ".to_owned() + &v)
.replace('[', "\\[")
.replace(']', "\\]")
.replace('\'', "'\\''")

View file

@ -28,7 +28,7 @@ impl Generator for Fig {
write!(
&mut buffer,
" description: \"{}\",\n",
escape_string(cmd.get_about().unwrap_or_default())
escape_string(&cmd.get_about().unwrap_or_default().to_string())
)
.unwrap();
@ -101,7 +101,7 @@ fn gen_fig_inner(
buffer,
"{:indent$}description: \"{}\",\n",
"",
escape_string(data),
escape_string(&data.to_string()),
indent = indent + 4
)
.unwrap();
@ -205,7 +205,7 @@ fn gen_options(cmd: &Command, indent: usize) -> String {
&mut buffer,
"{:indent$}description: \"{}\",\n",
"",
escape_string(data),
escape_string(&data.to_string()),
indent = indent + 4
)
.unwrap();
@ -314,7 +314,7 @@ fn gen_options(cmd: &Command, indent: usize) -> String {
&mut buffer,
"{:indent$}description: \"{}\",\n",
"",
escape_string(data).as_str(),
escape_string(&data.to_string()).as_str(),
indent = indent + 4
)
.unwrap();
@ -426,7 +426,7 @@ fn gen_args(arg: &Arg, indent: usize) -> String {
&mut buffer,
"{:indent$}description: \"{}\",\n",
"",
escape_string(help),
escape_string(&help.to_string()),
indent = indent + 6
)
.unwrap();

View file

@ -17,7 +17,7 @@ pub(crate) fn about(roff: &mut Roff, cmd: &clap::Command) {
pub(crate) fn description(roff: &mut Roff, cmd: &clap::Command) {
if let Some(about) = cmd.get_long_about().or_else(|| cmd.get_about()) {
for line in about.lines() {
for line in about.to_string().lines() {
if line.trim().is_empty() {
roff.control("PP", []);
} else {
@ -110,7 +110,7 @@ pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) {
let mut arg_help_written = false;
if let Some(help) = opt.get_long_help().or_else(|| opt.get_help()) {
arg_help_written = true;
body.push(roman(help));
body.push(roman(help.to_string()));
}
roff.control("TP", []);
@ -224,7 +224,7 @@ pub(crate) fn subcommands(roff: &mut Roff, cmd: &clap::Command, section: &str) {
roff.text([roman(&name)]);
if let Some(about) = sub.get_about().or_else(|| sub.get_long_about()) {
for line in about.lines() {
for line in about.to_string().lines() {
roff.text([roman(line)]);
}
}
@ -242,7 +242,7 @@ pub(crate) fn version(cmd: &clap::Command) -> String {
pub(crate) fn after_help(roff: &mut Roff, cmd: &clap::Command) {
if let Some(about) = cmd.get_after_long_help().or_else(|| cmd.get_after_help()) {
for line in about.lines() {
for line in about.to_string().lines() {
roff.text([roman(line)]);
}
}

View file

@ -17,6 +17,7 @@ use crate::builder::IntoResettable;
use crate::builder::OsStr;
use crate::builder::PossibleValue;
use crate::builder::Str;
use crate::builder::StyledStr;
use crate::builder::ValueRange;
use crate::ArgAction;
use crate::Id;
@ -54,8 +55,8 @@ use crate::INTERNAL_ERROR_MSG;
#[derive(Default, Clone)]
pub struct Arg {
pub(crate) id: Id,
pub(crate) help: Option<Str>,
pub(crate) long_help: Option<Str>,
pub(crate) help: Option<StyledStr>,
pub(crate) long_help: Option<StyledStr>,
pub(crate) action: Option<ArgAction>,
pub(crate) value_parser: Option<super::ValueParser>,
pub(crate) blacklist: Vec<Id>,
@ -1900,7 +1901,7 @@ impl Arg {
/// [`Arg::long_help`]: Arg::long_help()
#[inline]
#[must_use]
pub fn help(mut self, h: impl IntoResettable<Str>) -> Self {
pub fn help(mut self, h: impl IntoResettable<StyledStr>) -> Self {
self.help = h.into_resettable().into_option();
self
}
@ -1962,7 +1963,7 @@ impl Arg {
/// [`Arg::help`]: Arg::help()
#[inline]
#[must_use]
pub fn long_help(mut self, h: impl IntoResettable<Str>) -> Self {
pub fn long_help(mut self, h: impl IntoResettable<StyledStr>) -> Self {
self.long_help = h.into_resettable().into_option();
self
}
@ -3539,8 +3540,8 @@ impl Arg {
/// Get the help specified for this argument, if any
#[inline]
pub fn get_help(&self) -> Option<&str> {
self.help.as_deref()
pub fn get_help(&self) -> Option<&StyledStr> {
self.help.as_ref()
}
/// Get the long help specified for this argument, if any
@ -3550,12 +3551,12 @@ impl Arg {
/// ```rust
/// # use clap::Arg;
/// let arg = Arg::new("foo").long_help("long help");
/// assert_eq!(Some("long help"), arg.get_long_help());
/// assert_eq!(Some("long help".to_owned()), arg.get_long_help().map(|s| s.to_string()));
/// ```
///
#[inline]
pub fn get_long_help(&self) -> Option<&str> {
self.long_help.as_deref()
pub fn get_long_help(&self) -> Option<&StyledStr> {
self.long_help.as_ref()
}
/// Get the help heading specified for this argument, if any

View file

@ -75,22 +75,22 @@ pub struct Command {
author: Option<Str>,
version: Option<Str>,
long_version: Option<Str>,
about: Option<Str>,
long_about: Option<Str>,
before_help: Option<Str>,
before_long_help: Option<Str>,
after_help: Option<Str>,
after_long_help: Option<Str>,
about: Option<StyledStr>,
long_about: Option<StyledStr>,
before_help: Option<StyledStr>,
before_long_help: Option<StyledStr>,
after_help: Option<StyledStr>,
after_long_help: Option<StyledStr>,
aliases: Vec<(Str, bool)>, // (name, visible)
short_flag_aliases: Vec<(char, bool)>, // (name, visible)
long_flag_aliases: Vec<(Str, bool)>, // (name, visible)
usage_str: Option<Str>,
usage_str: Option<StyledStr>,
usage_name: Option<String>,
help_str: Option<Str>,
help_str: Option<StyledStr>,
disp_ord: Option<usize>,
term_w: Option<usize>,
max_w: Option<usize>,
template: Option<Str>,
template: Option<StyledStr>,
settings: AppFlags,
g_settings: AppFlags,
args: MKeyMap,
@ -1442,7 +1442,7 @@ impl Command {
/// # ;
/// ```
#[must_use]
pub fn about(mut self, about: impl IntoResettable<Str>) -> Self {
pub fn about(mut self, about: impl IntoResettable<StyledStr>) -> Self {
self.about = about.into_resettable().into_option();
self
}
@ -1467,7 +1467,7 @@ impl Command {
/// ```
/// [`Command::about`]: Command::about()
#[must_use]
pub fn long_about(mut self, long_about: impl IntoResettable<Str>) -> Self {
pub fn long_about(mut self, long_about: impl IntoResettable<StyledStr>) -> Self {
self.long_about = long_about.into_resettable().into_option();
self
}
@ -1489,7 +1489,7 @@ impl Command {
/// ```
///
#[must_use]
pub fn after_help(mut self, help: impl Into<Str>) -> Self {
pub fn after_help(mut self, help: impl Into<StyledStr>) -> Self {
self.after_help = Some(help.into());
self
}
@ -1511,7 +1511,7 @@ impl Command {
/// # ;
/// ```
#[must_use]
pub fn after_long_help(mut self, help: impl Into<Str>) -> Self {
pub fn after_long_help(mut self, help: impl Into<StyledStr>) -> Self {
self.after_long_help = Some(help.into());
self
}
@ -1531,7 +1531,7 @@ impl Command {
/// # ;
/// ```
#[must_use]
pub fn before_help(mut self, help: impl Into<Str>) -> Self {
pub fn before_help(mut self, help: impl Into<StyledStr>) -> Self {
self.before_help = Some(help.into());
self
}
@ -1551,7 +1551,7 @@ impl Command {
/// # ;
/// ```
#[must_use]
pub fn before_long_help(mut self, help: impl Into<Str>) -> Self {
pub fn before_long_help(mut self, help: impl Into<StyledStr>) -> Self {
self.before_long_help = Some(help.into());
self
}
@ -1645,7 +1645,7 @@ impl Command {
///
/// [`ArgMatches::usage`]: ArgMatches::usage()
#[must_use]
pub fn override_usage(mut self, usage: impl Into<Str>) -> Self {
pub fn override_usage(mut self, usage: impl Into<StyledStr>) -> Self {
self.usage_str = Some(usage.into());
self
}
@ -1682,7 +1682,7 @@ impl Command {
/// # ;
/// ```
#[must_use]
pub fn override_help(mut self, help: impl Into<Str>) -> Self {
pub fn override_help(mut self, help: impl Into<StyledStr>) -> Self {
self.help_str = Some(help.into());
self
}
@ -1732,7 +1732,7 @@ impl Command {
/// [`Command::before_help`]: Command::before_help()
/// [`Command::before_long_help`]: Command::before_long_help()
#[must_use]
pub fn help_template(mut self, s: impl Into<Str>) -> Self {
pub fn help_template(mut self, s: impl Into<StyledStr>) -> Self {
self.template = Some(s.into());
self
}
@ -3242,16 +3242,16 @@ impl Command {
///
/// [`Command::about`]: Command::about()
#[inline]
pub fn get_about(&self) -> Option<&str> {
self.about.as_deref()
pub fn get_about(&self) -> Option<&StyledStr> {
self.about.as_ref()
}
/// Get the help message specified via [`Command::long_about`].
///
/// [`Command::long_about`]: Command::long_about()
#[inline]
pub fn get_long_about(&self) -> Option<&str> {
self.long_about.as_deref()
pub fn get_long_about(&self) -> Option<&StyledStr> {
self.long_about.as_ref()
}
/// Get the custom section heading specified via [`Command::next_help_heading`].
@ -3364,26 +3364,26 @@ impl Command {
/// Returns the help heading for listing subcommands.
#[inline]
pub fn get_before_help(&self) -> Option<&str> {
self.before_help.as_deref()
pub fn get_before_help(&self) -> Option<&StyledStr> {
self.before_help.as_ref()
}
/// Returns the help heading for listing subcommands.
#[inline]
pub fn get_before_long_help(&self) -> Option<&str> {
self.before_long_help.as_deref()
pub fn get_before_long_help(&self) -> Option<&StyledStr> {
self.before_long_help.as_ref()
}
/// Returns the help heading for listing subcommands.
#[inline]
pub fn get_after_help(&self) -> Option<&str> {
self.after_help.as_deref()
pub fn get_after_help(&self) -> Option<&StyledStr> {
self.after_help.as_ref()
}
/// Returns the help heading for listing subcommands.
#[inline]
pub fn get_after_long_help(&self) -> Option<&str> {
self.after_long_help.as_deref()
pub fn get_after_long_help(&self) -> Option<&StyledStr> {
self.after_long_help.as_ref()
}
/// Find subcommand such that its name or one of aliases equals `name`.
@ -3667,16 +3667,16 @@ impl Command {
// Internally used only
impl Command {
pub(crate) fn get_override_usage(&self) -> Option<&str> {
self.usage_str.as_deref()
pub(crate) fn get_override_usage(&self) -> Option<&StyledStr> {
self.usage_str.as_ref()
}
pub(crate) fn get_override_help(&self) -> Option<&str> {
self.help_str.as_deref()
pub(crate) fn get_override_help(&self) -> Option<&StyledStr> {
self.help_str.as_ref()
}
pub(crate) fn get_help_template(&self) -> Option<&str> {
self.template.as_deref()
pub(crate) fn get_help_template(&self) -> Option<&StyledStr> {
self.template.as_ref()
}
pub(crate) fn get_term_width(&self) -> Option<usize> {

View file

@ -339,13 +339,13 @@ pub(crate) fn assert_app(cmd: &Command) {
if let Some(help_template) = cmd.get_help_template() {
assert!(
!help_template.contains("{flags}"),
!help_template.to_string().contains("{flags}"),
"Command {}: {}",
cmd.get_name(),
"`{flags}` template variable was removed in clap3, they are now included in `{options}`",
);
assert!(
!help_template.contains("{unified}"),
!help_template.to_string().contains("{unified}"),
"Command {}: {}",
cmd.get_name(),
"`{unified}` template variable was removed in clap3, use `{options}` instead"

View file

@ -1,6 +1,7 @@
use std::{borrow::Cow, iter};
use crate::builder::Str;
use crate::builder::StyledStr;
use crate::util::eq_ignore_case;
/// A possible value of an argument.
@ -30,7 +31,7 @@ use crate::util::eq_ignore_case;
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct PossibleValue {
name: Str,
help: Option<Str>,
help: Option<StyledStr>,
aliases: Vec<Str>, // (name, visible)
hide: bool,
}
@ -75,7 +76,7 @@ impl PossibleValue {
/// ```
#[inline]
#[must_use]
pub fn help(mut self, help: impl Into<Str>) -> Self {
pub fn help(mut self, help: impl Into<StyledStr>) -> Self {
self.help = Some(help.into());
self
}
@ -144,16 +145,16 @@ impl PossibleValue {
/// Get the help specified for this argument, if any
#[inline]
pub fn get_help(&self) -> Option<&str> {
self.help.as_deref()
pub fn get_help(&self) -> Option<&StyledStr> {
self.help.as_ref()
}
/// Get the help specified for this argument, if any and the argument
/// value is not hidden
#[inline]
pub(crate) fn get_visible_help(&self) -> Option<&str> {
pub(crate) fn get_visible_help(&self) -> Option<&StyledStr> {
if !self.hide {
self.help.as_deref()
self.get_help()
} else {
None
}

View file

@ -3,6 +3,7 @@
use crate::builder::OsStr;
use crate::builder::Str;
use crate::builder::StyledStr;
/// Clearable builder value
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -43,6 +44,15 @@ pub trait IntoResettable<T> {
fn into_resettable(self) -> Resettable<T>;
}
impl IntoResettable<StyledStr> for Option<&'static str> {
fn into_resettable(self) -> Resettable<StyledStr> {
match self {
Some(s) => Resettable::Value(s.into()),
None => Resettable::Reset,
}
}
}
impl IntoResettable<OsStr> for Option<&'static str> {
fn into_resettable(self) -> Resettable<OsStr> {
match self {
@ -67,6 +77,12 @@ impl<T> IntoResettable<T> for Resettable<T> {
}
}
impl<I: Into<StyledStr>> IntoResettable<StyledStr> for I {
fn into_resettable(self) -> Resettable<StyledStr> {
Resettable::Value(self.into())
}
}
impl<I: Into<OsStr>> IntoResettable<OsStr> for I {
fn into_resettable(self) -> Resettable<OsStr> {
Resettable::Value(self.into())

View file

@ -32,7 +32,41 @@ impl StyledStr {
}
fn stylize(&mut self, style: Option<Style>, msg: String) {
self.pieces.push((style, msg));
if !msg.is_empty() {
self.pieces.push((style, msg));
}
}
/// HACK: Until call sites are updated to handle formatted text, extract the unformatted
#[track_caller]
pub(crate) fn unwrap_none(&self) -> &str {
match self.pieces.len() {
0 => "",
1 => {
if self.pieces[0].0 != None {
panic!("{}", crate::INTERNAL_ERROR_MSG)
}
self.pieces[0].1.as_str()
}
_ => panic!("{}", crate::INTERNAL_ERROR_MSG),
}
}
pub(crate) fn is_empty(&self) -> bool {
self.pieces.is_empty()
}
pub(crate) fn iter(&self) -> impl Iterator<Item = (Option<Style>, &str)> {
self.pieces.iter().map(|(s, c)| (*s, c.as_str()))
}
pub(crate) fn extend(
&mut self,
other: impl IntoIterator<Item = (impl Into<Option<Style>>, impl Into<String>)>,
) {
for (style, content) in other {
self.stylize(style.into(), content.into());
}
}
#[cfg(feature = "color")]
@ -68,6 +102,13 @@ impl StyledStr {
}
}
impl Default for &'_ StyledStr {
fn default() -> Self {
static DEFAULT: StyledStr = StyledStr::new();
&DEFAULT
}
}
impl From<std::string::String> for StyledStr {
fn from(name: std::string::String) -> Self {
let mut styled = StyledStr::new();

View file

@ -80,9 +80,9 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
debug!("Help::write_help");
if let Some(h) = self.cmd.get_override_help() {
self.none(h);
self.extend(h);
} else if let Some(tmpl) = self.cmd.get_help_template() {
self.write_templated_help(tmpl);
self.write_templated_help(tmpl.unwrap_none());
} else {
let pos = self
.cmd
@ -107,6 +107,10 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
// Methods to write Arg help.
impl<'cmd, 'writer> Help<'cmd, 'writer> {
fn extend(&mut self, msg: &StyledStr) {
self.writer.extend(msg.iter());
}
fn good<T: Into<String>>(&mut self, msg: T) {
self.writer.good(msg);
}
@ -353,7 +357,10 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
self.cmd.get_before_help()
};
if let Some(output) = before_help {
self.none(text_wrapper(&output.replace("{n}", "\n"), self.term_w));
self.none(text_wrapper(
&output.unwrap_none().replace("{n}", "\n"),
self.term_w,
));
self.none("\n\n");
}
}
@ -369,7 +376,10 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
};
if let Some(output) = after_help {
self.none("\n\n");
self.none(text_wrapper(&output.replace("{n}", "\n"), self.term_w));
self.none(text_wrapper(
&output.unwrap_none().replace("{n}", "\n"),
self.term_w,
));
}
}
@ -377,13 +387,13 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
fn help(
&mut self,
arg: Option<&Arg>,
about: &str,
about: &StyledStr,
spec_vals: &str,
next_line_help: bool,
longest: usize,
) {
debug!("Help::help");
let mut help = String::from(about) + spec_vals;
let mut help = String::from(about.unwrap_none()) + spec_vals;
debug!("Help::help: Next Line...{:?}", next_line_help);
let spaces = if next_line_help {
@ -451,7 +461,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
.expect("Only called with possible value");
let help_longest = possible_vals
.iter()
.filter_map(|f| f.get_visible_help().map(display_width))
.filter_map(|f| f.get_visible_help().map(|h| display_width(h.unwrap_none())))
.max()
.expect("Only called with possible value with help");
// should new line
@ -490,7 +500,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
usize::MAX
};
let help = text_wrapper(help, avail_chars);
let help = text_wrapper(help.unwrap_none(), avail_chars);
let mut help = help.lines();
self.none(help.next().unwrap_or_default());
@ -522,7 +532,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
} else {
// force_next_line
let h = arg.get_help().unwrap_or_default();
let h_w = display_width(h) + display_width(spec_vals);
let h_w = display_width(h.unwrap_none()) + display_width(spec_vals);
let taken = longest + 12;
self.term_w >= taken
&& (taken as f32 / self.term_w as f32) > 0.40
@ -649,7 +659,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
if before_new_line {
self.none("\n");
}
self.none(text_wrapper(output, self.term_w));
self.none(text_wrapper(output.unwrap_none(), self.term_w));
if after_new_line {
self.none("\n");
}
@ -739,7 +749,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
} else {
// force_next_line
let h = cmd.get_about().unwrap_or_default();
let h_w = display_width(h) + display_width(spec_vals);
let h_w = display_width(h.unwrap_none()) + display_width(spec_vals);
let taken = longest + 12;
self.term_w >= taken
&& (taken as f32 / self.term_w as f32) > 0.40

View file

@ -40,7 +40,7 @@ impl<'cmd> Usage<'cmd> {
pub(crate) fn create_usage_no_title(&self, used: &[Id]) -> String {
debug!("Usage::create_usage_no_title");
if let Some(u) = self.cmd.get_override_usage() {
u.to_owned()
u.to_string()
} else if used.is_empty() {
self.create_help_usage(true)
} else {

View file

@ -450,7 +450,11 @@ fn mut_subcommand_with_alias_resolve() {
let mut cmd =
Command::new("foo").subcommand(Command::new("bar").alias("baz").about("test subcmd"));
assert_eq!(
cmd.find_subcommand("baz").unwrap().get_about().unwrap(),
cmd.find_subcommand("baz")
.unwrap()
.get_about()
.unwrap()
.to_string(),
"test subcmd"
);
@ -459,7 +463,11 @@ fn mut_subcommand_with_alias_resolve() {
cmd = cmd.mut_subcommand(&*true_name, |subcmd| subcmd.about("modified about"));
assert_eq!(
cmd.find_subcommand("baz").unwrap().get_about().unwrap(),
cmd.find_subcommand("baz")
.unwrap()
.get_about()
.unwrap()
.to_string(),
"modified about"
);
}

View file

@ -233,7 +233,10 @@ fn doc_comment_about_handles_both_abouts() {
}
let cmd = Opts::command();
assert_eq!(cmd.get_about(), Some("Opts doc comment summary"));
assert_eq!(
cmd.get_about().map(|s| s.to_string()),
Some("Opts doc comment summary".to_owned())
);
// clap will fallback to `about` on `None`. The main care about is not providing a `Sub` doc
// comment.
assert_eq!(cmd.get_long_about(), None);

View file

@ -94,7 +94,11 @@ fn inferred_help() {
let mut cmd = Opt::command();
cmd.build();
let arg = cmd.get_arguments().find(|a| a.get_id() == "help").unwrap();
assert_eq!(arg.get_help(), Some("Foo"), "Incorrect help");
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("Foo".to_owned()),
"Incorrect help"
);
assert!(matches!(arg.get_action(), clap::ArgAction::Help));
}
@ -114,7 +118,11 @@ fn inferred_version() {
.get_arguments()
.find(|a| a.get_id() == "version")
.unwrap();
assert_eq!(arg.get_help(), Some("Foo"), "Incorrect help");
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("Foo".to_owned()),
"Incorrect help"
);
assert!(matches!(arg.get_action(), clap::ArgAction::Version));
}

View file

@ -46,7 +46,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -'b');
assert_eq!(arg.get_id(), "foo");
@ -54,7 +54,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b ...);
assert_eq!(arg.get_id(), "foo");
@ -62,7 +62,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Count));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b "How to use it");
assert_eq!(arg.get_id(), "foo");
@ -70,7 +70,10 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), Some("How to use it"));
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("How to use it".to_owned())
);
}
#[test]
@ -82,7 +85,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -'b' --hello);
assert_eq!(arg.get_id(), "foo");
@ -91,7 +94,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b --hello ...);
assert_eq!(arg.get_id(), "foo");
@ -100,7 +103,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Count));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b --hello "How to use it");
assert_eq!(arg.get_id(), "foo");
@ -109,7 +112,10 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), Some("How to use it"));
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("How to use it".to_owned())
);
}
#[test]
@ -186,7 +192,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -'b' <NUM>);
assert_eq!(arg.get_id(), "foo");
@ -194,7 +200,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b <NUM> ...);
assert_eq!(arg.get_id(), "foo");
@ -202,7 +208,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Append));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b <NUM> "How to use it");
assert_eq!(arg.get_id(), "foo");
@ -210,7 +216,10 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), Some("How to use it"));
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("How to use it".to_owned())
);
}
#[test]
@ -221,7 +230,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!([NUM]);
assert_eq!(arg.get_id(), "NUM");
@ -229,7 +238,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(<NUM>);
assert_eq!(arg.get_id(), "NUM");
@ -237,7 +246,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: <NUM>);
assert_eq!(arg.get_id(), "foo");
@ -245,7 +254,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(<NUM> ...);
assert_eq!(arg.get_id(), "NUM");
@ -253,7 +262,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Append));
assert_eq!(arg.get_num_args(), Some((1..).into()));
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(<NUM> "How to use it");
assert_eq!(arg.get_id(), "NUM");
@ -261,7 +270,10 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), Some("How to use it"));
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("How to use it".to_owned())
);
}
#[test]