mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
parent
a6cb2e65bc
commit
6079a871a0
5 changed files with 83 additions and 57 deletions
|
@ -82,6 +82,7 @@ MSRV is now 1.60.0
|
|||
- *(assert)* Ensure subcommand names are not duplicated
|
||||
- *(help)* Use `Command::display_name` in the help title rather than `Command::bin_name`
|
||||
- *(help)* Show when a flag is `ArgAction::Count` by adding an `...`
|
||||
- *(help)* Use a more neutral palette for coloring
|
||||
- *(version)* Use `Command::display_name` rather than `Command::bin_name`
|
||||
- *(parser)* Assert on unknown args when using external subcommands (#3703)
|
||||
- *(parser)* Always fill in `""` argument for external subcommands (#3263)
|
||||
|
|
|
@ -3979,11 +3979,11 @@ impl Arg {
|
|||
let mut styled = StyledStr::new();
|
||||
// Write the name such --long or -l
|
||||
if let Some(l) = self.get_long() {
|
||||
styled.none("--");
|
||||
styled.none(l);
|
||||
styled.literal("--");
|
||||
styled.literal(l);
|
||||
} else if let Some(s) = self.get_short() {
|
||||
styled.none("-");
|
||||
styled.none(s);
|
||||
styled.literal("-");
|
||||
styled.literal(s);
|
||||
}
|
||||
styled.extend(self.stylize_arg_suffix().into_iter());
|
||||
styled
|
||||
|
@ -3995,29 +3995,28 @@ impl Arg {
|
|||
let mut need_closing_bracket = false;
|
||||
if self.is_takes_value_set() && !self.is_positional() {
|
||||
let is_optional_val = self.get_min_vals() == 0;
|
||||
let sep = if self.is_require_equals_set() {
|
||||
if self.is_require_equals_set() {
|
||||
if is_optional_val {
|
||||
need_closing_bracket = true;
|
||||
"[="
|
||||
styled.placeholder("[=");
|
||||
} else {
|
||||
"="
|
||||
styled.literal("=");
|
||||
}
|
||||
} else if is_optional_val {
|
||||
need_closing_bracket = true;
|
||||
" ["
|
||||
styled.placeholder(" [");
|
||||
} else {
|
||||
" "
|
||||
};
|
||||
styled.good(sep);
|
||||
styled.placeholder(" ");
|
||||
}
|
||||
}
|
||||
if self.is_takes_value_set() || self.is_positional() {
|
||||
let arg_val = self.render_arg_val();
|
||||
styled.good(arg_val);
|
||||
styled.placeholder(arg_val);
|
||||
} else if matches!(*self.get_action(), ArgAction::Count) {
|
||||
styled.good("...");
|
||||
styled.placeholder("...");
|
||||
}
|
||||
if need_closing_bracket {
|
||||
styled.none("]");
|
||||
styled.placeholder("]");
|
||||
}
|
||||
|
||||
styled
|
||||
|
|
|
@ -13,6 +13,18 @@ impl StyledStr {
|
|||
Self { pieces: Vec::new() }
|
||||
}
|
||||
|
||||
pub(crate) fn header(&mut self, msg: impl Into<String>) {
|
||||
self.stylize_(Some(Style::Header), msg.into());
|
||||
}
|
||||
|
||||
pub(crate) fn literal(&mut self, msg: impl Into<String>) {
|
||||
self.stylize_(Some(Style::Literal), msg.into());
|
||||
}
|
||||
|
||||
pub(crate) fn placeholder(&mut self, msg: impl Into<String>) {
|
||||
self.stylize_(Some(Style::Placeholder), msg.into());
|
||||
}
|
||||
|
||||
pub(crate) fn good(&mut self, msg: impl Into<String>) {
|
||||
self.stylize_(Some(Style::Good), msg.into());
|
||||
}
|
||||
|
@ -137,6 +149,16 @@ impl StyledStr {
|
|||
for (style, content) in &self.pieces {
|
||||
let mut color = termcolor::ColorSpec::new();
|
||||
match style {
|
||||
Some(Style::Header) => {
|
||||
color.set_bold(true);
|
||||
color.set_underline(true);
|
||||
}
|
||||
Some(Style::Literal) => {
|
||||
color.set_bold(true);
|
||||
}
|
||||
Some(Style::Placeholder) => {
|
||||
color.set_dimmed(true);
|
||||
}
|
||||
Some(Style::Good) => {
|
||||
color.set_fg(Some(termcolor::Color::Green));
|
||||
}
|
||||
|
@ -212,6 +234,9 @@ impl std::fmt::Display for StyledStr {
|
|||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum Style {
|
||||
Header,
|
||||
Literal,
|
||||
Placeholder,
|
||||
Good,
|
||||
Warning,
|
||||
Error,
|
||||
|
|
|
@ -155,7 +155,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
self.write_about(true, true);
|
||||
}
|
||||
"usage-heading" => {
|
||||
self.warning("USAGE:");
|
||||
self.header("USAGE:");
|
||||
}
|
||||
"usage" => {
|
||||
self.writer
|
||||
|
@ -215,7 +215,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
.replace("{n}", "\n"),
|
||||
self.term_w,
|
||||
);
|
||||
self.good(&display_name);
|
||||
self.none(&display_name);
|
||||
}
|
||||
|
||||
/// Writes binary name of a Parser Object to the wrapped stream.
|
||||
|
@ -232,7 +232,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
} else {
|
||||
wrap(&self.cmd.get_name().replace("{n}", "\n"), self.term_w)
|
||||
};
|
||||
self.good(&bin_name);
|
||||
self.none(&bin_name);
|
||||
}
|
||||
|
||||
fn write_version(&mut self) {
|
||||
|
@ -340,7 +340,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
|
||||
let mut first = if !pos.is_empty() {
|
||||
// Write positional args if any
|
||||
self.warning("ARGS:\n");
|
||||
self.header("ARGS:\n");
|
||||
self.write_args(&pos, "ARGS", positional_sort_key);
|
||||
false
|
||||
} else {
|
||||
|
@ -351,7 +351,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
if !first {
|
||||
self.none("\n\n");
|
||||
}
|
||||
self.warning("OPTIONS:\n");
|
||||
self.header("OPTIONS:\n");
|
||||
self.write_args(&non_pos, "OPTIONS", option_sort_key);
|
||||
first = false;
|
||||
}
|
||||
|
@ -373,7 +373,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
if !first {
|
||||
self.none("\n\n");
|
||||
}
|
||||
self.warning(format!("{}:\n", heading));
|
||||
self.header(format!("{}:\n", heading));
|
||||
self.write_args(&args, heading, option_sort_key);
|
||||
first = false
|
||||
}
|
||||
|
@ -386,12 +386,12 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
}
|
||||
|
||||
let default_help_heading = Str::from("SUBCOMMANDS");
|
||||
self.warning(
|
||||
self.header(
|
||||
self.cmd
|
||||
.get_subcommand_help_heading()
|
||||
.unwrap_or(&default_help_heading),
|
||||
);
|
||||
self.warning(":\n");
|
||||
self.header(":\n");
|
||||
|
||||
self.write_subcommands(self.cmd);
|
||||
}
|
||||
|
@ -465,7 +465,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
debug!("Help::short");
|
||||
|
||||
if let Some(s) = arg.get_short() {
|
||||
self.good(format!("-{}", s));
|
||||
self.literal(format!("-{}", s));
|
||||
} else if arg.get_long().is_some() {
|
||||
self.none(TAB)
|
||||
}
|
||||
|
@ -478,7 +478,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
if arg.short.is_some() {
|
||||
self.none(", ");
|
||||
}
|
||||
self.good(format!("--{}", long));
|
||||
self.literal(format!("--{}", long));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,7 +622,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
self.none("\n");
|
||||
self.spaces(spaces);
|
||||
self.none("- ");
|
||||
self.good(pv.get_name());
|
||||
self.literal(pv.get_name());
|
||||
if let Some(help) = pv.get_help() {
|
||||
debug!("Help::help: Possible Value help");
|
||||
|
||||
|
@ -775,12 +775,12 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
self.writer.extend(msg.iter());
|
||||
}
|
||||
|
||||
fn good<T: Into<String>>(&mut self, msg: T) {
|
||||
self.writer.good(msg);
|
||||
fn header<T: Into<String>>(&mut self, msg: T) {
|
||||
self.writer.header(msg);
|
||||
}
|
||||
|
||||
fn warning<T: Into<String>>(&mut self, msg: T) {
|
||||
self.writer.warning(msg);
|
||||
fn literal<T: Into<String>>(&mut self, msg: T) {
|
||||
self.writer.literal(msg);
|
||||
}
|
||||
|
||||
fn none<T: Into<String>>(&mut self, msg: T) {
|
||||
|
@ -915,7 +915,7 @@ impl<'cmd, 'writer> Help<'cmd, 'writer> {
|
|||
/// Writes subcommand to the wrapped stream.
|
||||
fn subcmd(&mut self, sc_str: &str, next_line_help: bool, longest: usize) {
|
||||
self.none(TAB);
|
||||
self.good(sc_str);
|
||||
self.literal(sc_str);
|
||||
if !next_line_help {
|
||||
let width = display_width(sc_str);
|
||||
self.spaces(width.max(longest + 4) - width);
|
||||
|
|
|
@ -32,7 +32,7 @@ impl<'cmd> Usage<'cmd> {
|
|||
pub(crate) fn create_usage_with_title(&self, used: &[Id]) -> StyledStr {
|
||||
debug!("Usage::create_usage_with_title");
|
||||
let mut styled = StyledStr::new();
|
||||
styled.none("USAGE:\n ");
|
||||
styled.header("USAGE:\n ");
|
||||
styled.extend(self.create_usage_no_title(used).into_iter());
|
||||
styled
|
||||
}
|
||||
|
@ -58,10 +58,10 @@ impl<'cmd> Usage<'cmd> {
|
|||
.get_usage_name()
|
||||
.or_else(|| self.cmd.get_bin_name())
|
||||
.unwrap_or_else(|| self.cmd.get_name());
|
||||
styled.none(name);
|
||||
styled.literal(name);
|
||||
|
||||
if self.needs_options_tag() {
|
||||
styled.none(" [OPTIONS]");
|
||||
styled.placeholder(" [OPTIONS]");
|
||||
}
|
||||
|
||||
let allow_missing_positional = self.cmd.is_allow_missing_positional_set();
|
||||
|
@ -80,15 +80,15 @@ impl<'cmd> Usage<'cmd> {
|
|||
&& !(self.cmd.has_visible_subcommands() || self.cmd.is_allow_external_subcommands_set())
|
||||
&& !has_last
|
||||
{
|
||||
styled.none(" [--]");
|
||||
styled.placeholder(" [--]");
|
||||
}
|
||||
let not_req_or_hidden =
|
||||
|p: &Arg| (!p.is_required_set() || p.is_last_set()) && !p.is_hide_set();
|
||||
if self.cmd.get_positionals().any(not_req_or_hidden) {
|
||||
if let Some(args_tag) = self.get_args_tag(incl_reqs) {
|
||||
styled.none(&*args_tag);
|
||||
styled.placeholder(&*args_tag);
|
||||
} else {
|
||||
styled.none(" [ARGS]");
|
||||
styled.placeholder(" [ARGS]");
|
||||
}
|
||||
if has_last && incl_reqs {
|
||||
let pos = self
|
||||
|
@ -102,17 +102,18 @@ impl<'cmd> Usage<'cmd> {
|
|||
);
|
||||
let req = pos.is_required_set();
|
||||
if req && self.cmd.get_positionals().any(|p| !p.is_required_set()) {
|
||||
styled.none(" -- <");
|
||||
styled.literal(" -- ");
|
||||
styled.placeholder("<");
|
||||
} else if req {
|
||||
styled.none(" [--] <");
|
||||
styled.placeholder(" [--] <");
|
||||
} else {
|
||||
styled.none(" [-- <");
|
||||
styled.placeholder(" [-- <");
|
||||
}
|
||||
styled.none(&*pos.name_no_brackets());
|
||||
styled.none('>');
|
||||
styled.none(pos.multiple_str());
|
||||
styled.placeholder(&*pos.name_no_brackets());
|
||||
styled.placeholder('>');
|
||||
styled.placeholder(pos.multiple_str());
|
||||
if !req {
|
||||
styled.none(']');
|
||||
styled.placeholder(']');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,19 +137,19 @@ impl<'cmd> Usage<'cmd> {
|
|||
if !self.cmd.is_args_conflicts_with_subcommands_set() {
|
||||
styled.extend(self.create_help_usage(false).into_iter());
|
||||
} else {
|
||||
styled.none(name);
|
||||
styled.literal(name);
|
||||
}
|
||||
styled.none(" <");
|
||||
styled.none(placeholder);
|
||||
styled.none(">");
|
||||
styled.placeholder(" <");
|
||||
styled.placeholder(placeholder);
|
||||
styled.placeholder(">");
|
||||
} else if self.cmd.is_subcommand_required_set() {
|
||||
styled.none(" <");
|
||||
styled.none(placeholder);
|
||||
styled.none(">");
|
||||
styled.placeholder(" <");
|
||||
styled.placeholder(placeholder);
|
||||
styled.placeholder(">");
|
||||
} else {
|
||||
styled.none(" [");
|
||||
styled.none(placeholder);
|
||||
styled.none("]");
|
||||
styled.placeholder(" [");
|
||||
styled.placeholder(placeholder);
|
||||
styled.placeholder("]");
|
||||
}
|
||||
}
|
||||
styled.trim();
|
||||
|
@ -162,7 +163,7 @@ impl<'cmd> Usage<'cmd> {
|
|||
debug!("Usage::create_smart_usage");
|
||||
let mut styled = StyledStr::new();
|
||||
|
||||
styled.none(
|
||||
styled.literal(
|
||||
self.cmd
|
||||
.get_usage_name()
|
||||
.or_else(|| self.cmd.get_bin_name())
|
||||
|
@ -172,13 +173,13 @@ impl<'cmd> Usage<'cmd> {
|
|||
self.write_required_usage_from(used, None, true, &mut styled);
|
||||
|
||||
if self.cmd.is_subcommand_required_set() {
|
||||
styled.none(" <");
|
||||
styled.none(
|
||||
styled.placeholder(" <");
|
||||
styled.placeholder(
|
||||
self.cmd
|
||||
.get_subcommand_value_name()
|
||||
.unwrap_or(DEFAULT_SUB_VALUE_NAME),
|
||||
);
|
||||
styled.none(">");
|
||||
styled.placeholder(">");
|
||||
}
|
||||
styled
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue