mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42:33 +00:00
Merge pull request #3381 from epage/parser
refactor: Minor progress on reducing Parser's visibility
This commit is contained in:
commit
8efee8a671
5 changed files with 146 additions and 177 deletions
|
@ -678,9 +678,10 @@ impl<'help> App<'help> {
|
||||||
self._build();
|
self._build();
|
||||||
let color = self.get_color();
|
let color = self.get_color();
|
||||||
|
|
||||||
let p = Parser::new(self);
|
|
||||||
let mut c = Colorizer::new(false, color);
|
let mut c = Colorizer::new(false, color);
|
||||||
Help::new(HelpWriter::Buffer(&mut c), &p, false).write_help()?;
|
let parser = Parser::new(self);
|
||||||
|
let usage = Usage::new(parser.app, &parser.required);
|
||||||
|
Help::new(HelpWriter::Buffer(&mut c), parser.app, &usage, false).write_help()?;
|
||||||
c.print()
|
c.print()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,9 +704,10 @@ impl<'help> App<'help> {
|
||||||
self._build();
|
self._build();
|
||||||
let color = self.get_color();
|
let color = self.get_color();
|
||||||
|
|
||||||
let p = Parser::new(self);
|
|
||||||
let mut c = Colorizer::new(false, color);
|
let mut c = Colorizer::new(false, color);
|
||||||
Help::new(HelpWriter::Buffer(&mut c), &p, true).write_help()?;
|
let parser = Parser::new(self);
|
||||||
|
let usage = Usage::new(parser.app, &parser.required);
|
||||||
|
Help::new(HelpWriter::Buffer(&mut c), parser.app, &usage, true).write_help()?;
|
||||||
c.print()
|
c.print()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,8 +730,9 @@ impl<'help> App<'help> {
|
||||||
pub fn write_help<W: Write>(&mut self, w: &mut W) -> io::Result<()> {
|
pub fn write_help<W: Write>(&mut self, w: &mut W) -> io::Result<()> {
|
||||||
self._build();
|
self._build();
|
||||||
|
|
||||||
let p = Parser::new(self);
|
let parser = Parser::new(self);
|
||||||
Help::new(HelpWriter::Normal(w), &p, false).write_help()?;
|
let usage = Usage::new(parser.app, &parser.required);
|
||||||
|
Help::new(HelpWriter::Normal(w), parser.app, &usage, false).write_help()?;
|
||||||
w.flush()
|
w.flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,8 +755,9 @@ impl<'help> App<'help> {
|
||||||
pub fn write_long_help<W: Write>(&mut self, w: &mut W) -> io::Result<()> {
|
pub fn write_long_help<W: Write>(&mut self, w: &mut W) -> io::Result<()> {
|
||||||
self._build();
|
self._build();
|
||||||
|
|
||||||
let p = Parser::new(self);
|
let parser = Parser::new(self);
|
||||||
Help::new(HelpWriter::Normal(w), &p, true).write_help()?;
|
let usage = Usage::new(parser.app, &parser.required);
|
||||||
|
Help::new(HelpWriter::Normal(w), parser.app, &usage, true).write_help()?;
|
||||||
w.flush()
|
w.flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,9 +824,8 @@ impl<'help> App<'help> {
|
||||||
// before parsing incase we run into a subcommand
|
// before parsing incase we run into a subcommand
|
||||||
self._build();
|
self._build();
|
||||||
|
|
||||||
let mut parser = Parser::new(self);
|
let parser = Parser::new(self);
|
||||||
parser._build();
|
Usage::new(parser.app, &parser.required).create_usage_with_title(&[])
|
||||||
Usage::new(&parser).create_usage_with_title(&[])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ use std::{
|
||||||
use crate::{
|
use crate::{
|
||||||
build::{arg::display_arg_val, App, AppSettings, Arg, ArgSettings},
|
build::{arg::display_arg_val, App, AppSettings, Arg, ArgSettings},
|
||||||
output::{fmt::Colorizer, Usage},
|
output::{fmt::Colorizer, Usage},
|
||||||
parse::Parser,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Third party
|
// Third party
|
||||||
|
@ -21,9 +20,10 @@ use textwrap::core::display_width;
|
||||||
/// `clap` Help Writer.
|
/// `clap` Help Writer.
|
||||||
///
|
///
|
||||||
/// Wraps a writer stream providing different methods to generate help for `clap` objects.
|
/// Wraps a writer stream providing different methods to generate help for `clap` objects.
|
||||||
pub(crate) struct Help<'help, 'app, 'parser, 'writer> {
|
pub(crate) struct Help<'help, 'app, 'writer> {
|
||||||
writer: HelpWriter<'writer>,
|
writer: HelpWriter<'writer>,
|
||||||
parser: &'parser Parser<'help, 'app>,
|
app: &'app App<'help>,
|
||||||
|
usage: &'app Usage<'help, 'app>,
|
||||||
next_line_help: bool,
|
next_line_help: bool,
|
||||||
hide_pv: bool,
|
hide_pv: bool,
|
||||||
term_w: usize,
|
term_w: usize,
|
||||||
|
@ -31,7 +31,7 @@ pub(crate) struct Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public Functions
|
// Public Functions
|
||||||
impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
impl<'help, 'app, 'writer> Help<'help, 'app, 'writer> {
|
||||||
const DEFAULT_TEMPLATE: &'static str = "\
|
const DEFAULT_TEMPLATE: &'static str = "\
|
||||||
{before-help}{bin} {version}\n\
|
{before-help}{bin} {version}\n\
|
||||||
{author-with-newline}{about-with-newline}\n\
|
{author-with-newline}{about-with-newline}\n\
|
||||||
|
@ -49,27 +49,29 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
/// Create a new `Help` instance.
|
/// Create a new `Help` instance.
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
writer: HelpWriter<'writer>,
|
writer: HelpWriter<'writer>,
|
||||||
parser: &'parser Parser<'help, 'app>,
|
app: &'app App<'help>,
|
||||||
|
usage: &'app Usage<'help, 'app>,
|
||||||
use_long: bool,
|
use_long: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
debug!("Help::new");
|
debug!("Help::new");
|
||||||
let term_w = match parser.app.term_w {
|
let term_w = match app.term_w {
|
||||||
Some(0) => usize::MAX,
|
Some(0) => usize::MAX,
|
||||||
Some(w) => w,
|
Some(w) => w,
|
||||||
None => cmp::min(
|
None => cmp::min(
|
||||||
dimensions().map_or(100, |(w, _)| w),
|
dimensions().map_or(100, |(w, _)| w),
|
||||||
match parser.app.max_w {
|
match app.max_w {
|
||||||
None | Some(0) => usize::MAX,
|
None | Some(0) => usize::MAX,
|
||||||
Some(mw) => mw,
|
Some(mw) => mw,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let next_line_help = parser.is_set(AppSettings::NextLineHelp);
|
let next_line_help = app.is_set(AppSettings::NextLineHelp);
|
||||||
let hide_pv = parser.is_set(AppSettings::HidePossibleValues);
|
let hide_pv = app.is_set(AppSettings::HidePossibleValues);
|
||||||
|
|
||||||
Help {
|
Help {
|
||||||
writer,
|
writer,
|
||||||
parser,
|
app,
|
||||||
|
usage,
|
||||||
next_line_help,
|
next_line_help,
|
||||||
hide_pv,
|
hide_pv,
|
||||||
term_w,
|
term_w,
|
||||||
|
@ -81,22 +83,20 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
pub(crate) fn write_help(&mut self) -> io::Result<()> {
|
pub(crate) fn write_help(&mut self) -> io::Result<()> {
|
||||||
debug!("Help::write_help");
|
debug!("Help::write_help");
|
||||||
|
|
||||||
if let Some(h) = self.parser.app.help_str {
|
if let Some(h) = self.app.help_str {
|
||||||
self.none(h)?;
|
self.none(h)?;
|
||||||
} else if let Some(tmpl) = self.parser.app.template {
|
} else if let Some(tmpl) = self.app.template {
|
||||||
self.write_templated_help(tmpl)?;
|
self.write_templated_help(tmpl)?;
|
||||||
} else {
|
} else {
|
||||||
let pos = self
|
let pos = self
|
||||||
.parser
|
|
||||||
.app
|
.app
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.any(|arg| should_show_arg(self.use_long, arg));
|
.any(|arg| should_show_arg(self.use_long, arg));
|
||||||
let non_pos = self
|
let non_pos = self
|
||||||
.parser
|
|
||||||
.app
|
.app
|
||||||
.get_non_positionals()
|
.get_non_positionals()
|
||||||
.any(|arg| should_show_arg(self.use_long, arg));
|
.any(|arg| should_show_arg(self.use_long, arg));
|
||||||
let subcmds = self.parser.app.has_visible_subcommands();
|
let subcmds = self.app.has_visible_subcommands();
|
||||||
|
|
||||||
if non_pos || pos || subcmds {
|
if non_pos || pos || subcmds {
|
||||||
self.write_templated_help(Self::DEFAULT_TEMPLATE)?;
|
self.write_templated_help(Self::DEFAULT_TEMPLATE)?;
|
||||||
|
@ -124,7 +124,7 @@ macro_rules! write_method {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods to write Arg help.
|
// Methods to write Arg help.
|
||||||
impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
impl<'help, 'app, 'writer> Help<'help, 'app, 'writer> {
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn good<T: Into<String> + AsRef<[u8]>>(&mut self, msg: T) -> io::Result<()> {
|
fn good<T: Into<String> + AsRef<[u8]>>(&mut self, msg: T) -> io::Result<()> {
|
||||||
write_method!(self, msg, good)
|
write_method!(self, msg, good)
|
||||||
|
@ -356,12 +356,9 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
fn write_before_help(&mut self) -> io::Result<()> {
|
fn write_before_help(&mut self) -> io::Result<()> {
|
||||||
debug!("Help::write_before_help");
|
debug!("Help::write_before_help");
|
||||||
let before_help = if self.use_long {
|
let before_help = if self.use_long {
|
||||||
self.parser
|
self.app.before_long_help.or(self.app.before_help)
|
||||||
.app
|
|
||||||
.before_long_help
|
|
||||||
.or(self.parser.app.before_help)
|
|
||||||
} else {
|
} else {
|
||||||
self.parser.app.before_help
|
self.app.before_help
|
||||||
};
|
};
|
||||||
if let Some(output) = before_help {
|
if let Some(output) = before_help {
|
||||||
self.none(text_wrapper(&output.replace("{n}", "\n"), self.term_w))?;
|
self.none(text_wrapper(&output.replace("{n}", "\n"), self.term_w))?;
|
||||||
|
@ -373,12 +370,9 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
fn write_after_help(&mut self) -> io::Result<()> {
|
fn write_after_help(&mut self) -> io::Result<()> {
|
||||||
debug!("Help::write_after_help");
|
debug!("Help::write_after_help");
|
||||||
let after_help = if self.use_long {
|
let after_help = if self.use_long {
|
||||||
self.parser
|
self.app.after_long_help.or(self.app.after_help)
|
||||||
.app
|
|
||||||
.after_long_help
|
|
||||||
.or(self.parser.app.after_help)
|
|
||||||
} else {
|
} else {
|
||||||
self.parser.app.after_help
|
self.app.after_help
|
||||||
};
|
};
|
||||||
if let Some(output) = after_help {
|
if let Some(output) = after_help {
|
||||||
self.none("\n\n")?;
|
self.none("\n\n")?;
|
||||||
|
@ -618,9 +612,9 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
|
|
||||||
fn write_about(&mut self, before_new_line: bool, after_new_line: bool) -> io::Result<()> {
|
fn write_about(&mut self, before_new_line: bool, after_new_line: bool) -> io::Result<()> {
|
||||||
let about = if self.use_long {
|
let about = if self.use_long {
|
||||||
self.parser.app.long_about.or(self.parser.app.about)
|
self.app.long_about.or(self.app.about)
|
||||||
} else {
|
} else {
|
||||||
self.parser.app.about
|
self.app.about
|
||||||
};
|
};
|
||||||
if let Some(output) = about {
|
if let Some(output) = about {
|
||||||
if before_new_line {
|
if before_new_line {
|
||||||
|
@ -635,7 +629,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_author(&mut self, before_new_line: bool, after_new_line: bool) -> io::Result<()> {
|
fn write_author(&mut self, before_new_line: bool, after_new_line: bool) -> io::Result<()> {
|
||||||
if let Some(author) = self.parser.app.author {
|
if let Some(author) = self.app.author {
|
||||||
if before_new_line {
|
if before_new_line {
|
||||||
self.none("\n")?;
|
self.none("\n")?;
|
||||||
}
|
}
|
||||||
|
@ -648,7 +642,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_version(&mut self) -> io::Result<()> {
|
fn write_version(&mut self) -> io::Result<()> {
|
||||||
let version = self.parser.app.version.or(self.parser.app.long_version);
|
let version = self.app.version.or(self.app.long_version);
|
||||||
if let Some(output) = version {
|
if let Some(output) = version {
|
||||||
self.none(text_wrapper(output, self.term_w))?;
|
self.none(text_wrapper(output, self.term_w))?;
|
||||||
}
|
}
|
||||||
|
@ -657,7 +651,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Methods to write a single subcommand
|
/// Methods to write a single subcommand
|
||||||
impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
impl<'help, 'app, 'writer> Help<'help, 'app, 'writer> {
|
||||||
fn write_subcommand(
|
fn write_subcommand(
|
||||||
&mut self,
|
&mut self,
|
||||||
sc_str: &str,
|
sc_str: &str,
|
||||||
|
@ -731,27 +725,24 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods to write Parser help.
|
// Methods to write Parser help.
|
||||||
impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
impl<'help, 'app, 'writer> Help<'help, 'app, 'writer> {
|
||||||
/// Writes help for all arguments (options, flags, args, subcommands)
|
/// Writes help for all arguments (options, flags, args, subcommands)
|
||||||
/// including titles of a Parser Object to the wrapped stream.
|
/// including titles of a Parser Object to the wrapped stream.
|
||||||
pub(crate) fn write_all_args(&mut self) -> io::Result<()> {
|
pub(crate) fn write_all_args(&mut self) -> io::Result<()> {
|
||||||
debug!("Help::write_all_args");
|
debug!("Help::write_all_args");
|
||||||
let pos = self
|
let pos = self
|
||||||
.parser
|
|
||||||
.app
|
.app
|
||||||
.get_positionals_with_no_heading()
|
.get_positionals_with_no_heading()
|
||||||
.filter(|arg| should_show_arg(self.use_long, arg))
|
.filter(|arg| should_show_arg(self.use_long, arg))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let non_pos = self
|
let non_pos = self
|
||||||
.parser
|
|
||||||
.app
|
.app
|
||||||
.get_non_positionals_with_no_heading()
|
.get_non_positionals_with_no_heading()
|
||||||
.filter(|arg| should_show_arg(self.use_long, arg))
|
.filter(|arg| should_show_arg(self.use_long, arg))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let subcmds = self.parser.app.has_visible_subcommands();
|
let subcmds = self.app.has_visible_subcommands();
|
||||||
|
|
||||||
let custom_headings = self
|
let custom_headings = self
|
||||||
.parser
|
|
||||||
.app
|
.app
|
||||||
.args
|
.args
|
||||||
.args()
|
.args()
|
||||||
|
@ -778,7 +769,6 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
if !custom_headings.is_empty() {
|
if !custom_headings.is_empty() {
|
||||||
for heading in custom_headings {
|
for heading in custom_headings {
|
||||||
let args = self
|
let args = self
|
||||||
.parser
|
|
||||||
.app
|
.app
|
||||||
.args
|
.args
|
||||||
.args()
|
.args()
|
||||||
|
@ -807,10 +797,10 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
self.none("\n\n")?;
|
self.none("\n\n")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.warning(self.parser.app.subcommand_heading.unwrap_or("SUBCOMMANDS"))?;
|
self.warning(self.app.subcommand_heading.unwrap_or("SUBCOMMANDS"))?;
|
||||||
self.warning(":\n")?;
|
self.warning(":\n")?;
|
||||||
|
|
||||||
self.write_subcommands(self.parser.app)?;
|
self.write_subcommands(self.app)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -871,15 +861,15 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
fn write_bin_name(&mut self) -> io::Result<()> {
|
fn write_bin_name(&mut self) -> io::Result<()> {
|
||||||
debug!("Help::write_bin_name");
|
debug!("Help::write_bin_name");
|
||||||
|
|
||||||
let bin_name = if let Some(bn) = self.parser.app.bin_name.as_ref() {
|
let bin_name = if let Some(bn) = self.app.bin_name.as_ref() {
|
||||||
if bn.contains(' ') {
|
if bn.contains(' ') {
|
||||||
// In case we're dealing with subcommands i.e. git mv is translated to git-mv
|
// In case we're dealing with subcommands i.e. git mv is translated to git-mv
|
||||||
bn.replace(' ', "-")
|
bn.replace(' ', "-")
|
||||||
} else {
|
} else {
|
||||||
text_wrapper(&self.parser.app.name.replace("{n}", "\n"), self.term_w)
|
text_wrapper(&self.app.name.replace("{n}", "\n"), self.term_w)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
text_wrapper(&self.parser.app.name.replace("{n}", "\n"), self.term_w)
|
text_wrapper(&self.app.name.replace("{n}", "\n"), self.term_w)
|
||||||
};
|
};
|
||||||
self.good(&bin_name)?;
|
self.good(&bin_name)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -887,7 +877,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods to write Parser help using templates.
|
// Methods to write Parser help using templates.
|
||||||
impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
impl<'help, 'app, 'writer> Help<'help, 'app, 'writer> {
|
||||||
/// Write help to stream for the parser in the format defined by the template.
|
/// Write help to stream for the parser in the format defined by the template.
|
||||||
///
|
///
|
||||||
/// For details about the template language see [`App::help_template`].
|
/// For details about the template language see [`App::help_template`].
|
||||||
|
@ -962,7 +952,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
self.warning("USAGE:")?;
|
self.warning("USAGE:")?;
|
||||||
}
|
}
|
||||||
"usage" => {
|
"usage" => {
|
||||||
self.none(Usage::new(self.parser).create_usage_no_title(&[]))?;
|
self.none(self.usage.create_usage_no_title(&[]))?;
|
||||||
}
|
}
|
||||||
"all-args" => {
|
"all-args" => {
|
||||||
self.write_all_args()?;
|
self.write_all_args()?;
|
||||||
|
@ -970,13 +960,13 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> {
|
||||||
"options" => {
|
"options" => {
|
||||||
// Include even those with a heading as we don't have a good way of
|
// Include even those with a heading as we don't have a good way of
|
||||||
// handling help_heading in the template.
|
// handling help_heading in the template.
|
||||||
self.write_args(&self.parser.app.get_non_positionals().collect::<Vec<_>>())?;
|
self.write_args(&self.app.get_non_positionals().collect::<Vec<_>>())?;
|
||||||
}
|
}
|
||||||
"positionals" => {
|
"positionals" => {
|
||||||
self.write_args(&self.parser.app.get_positionals().collect::<Vec<_>>())?;
|
self.write_args(&self.app.get_positionals().collect::<Vec<_>>())?;
|
||||||
}
|
}
|
||||||
"subcommands" => {
|
"subcommands" => {
|
||||||
self.write_subcommands(self.parser.app)?;
|
self.write_subcommands(self.app)?;
|
||||||
}
|
}
|
||||||
"after-help" => {
|
"after-help" => {
|
||||||
self.write_after_help()?;
|
self.write_after_help()?;
|
||||||
|
|
|
@ -3,19 +3,20 @@ use indexmap::IndexSet;
|
||||||
// Internal
|
// Internal
|
||||||
use crate::{
|
use crate::{
|
||||||
build::AppSettings as AS,
|
build::AppSettings as AS,
|
||||||
build::{Arg, ArgSettings},
|
build::{App, Arg, ArgSettings},
|
||||||
parse::{ArgMatcher, Parser},
|
parse::ArgMatcher,
|
||||||
util::Id,
|
util::{ChildGraph, Id},
|
||||||
INTERNAL_ERROR_MSG,
|
INTERNAL_ERROR_MSG,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) struct Usage<'help, 'app, 'parser> {
|
pub(crate) struct Usage<'help, 'app> {
|
||||||
p: &'parser Parser<'help, 'app>,
|
app: &'app App<'help>,
|
||||||
|
required: &'app ChildGraph<Id>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
impl<'help, 'app> Usage<'help, 'app> {
|
||||||
pub(crate) fn new(p: &'parser Parser<'help, 'app>) -> Self {
|
pub(crate) fn new(app: &'app App<'help>, required: &'app ChildGraph<Id>) -> Self {
|
||||||
Usage { p }
|
Usage { app, required }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a usage string for display. This happens just after all arguments were parsed, but before
|
// Creates a usage string for display. This happens just after all arguments were parsed, but before
|
||||||
|
@ -31,7 +32,7 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
// Creates a usage string (*without title*) if one was not provided by the user manually.
|
// Creates a usage string (*without title*) if one was not provided by the user manually.
|
||||||
pub(crate) fn create_usage_no_title(&self, used: &[Id]) -> String {
|
pub(crate) fn create_usage_no_title(&self, used: &[Id]) -> String {
|
||||||
debug!("Usage::create_usage_no_title");
|
debug!("Usage::create_usage_no_title");
|
||||||
if let Some(u) = self.p.app.usage_str {
|
if let Some(u) = self.app.usage_str {
|
||||||
String::from(&*u)
|
String::from(&*u)
|
||||||
} else if used.is_empty() {
|
} else if used.is_empty() {
|
||||||
self.create_help_usage(true)
|
self.create_help_usage(true)
|
||||||
|
@ -45,12 +46,11 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
debug!("Usage::create_help_usage; incl_reqs={:?}", incl_reqs);
|
debug!("Usage::create_help_usage; incl_reqs={:?}", incl_reqs);
|
||||||
let mut usage = String::with_capacity(75);
|
let mut usage = String::with_capacity(75);
|
||||||
let name = self
|
let name = self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.usage
|
.usage
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.or_else(|| self.p.app.bin_name.as_ref())
|
.or_else(|| self.app.bin_name.as_ref())
|
||||||
.unwrap_or(&self.p.app.name);
|
.unwrap_or(&self.app.name);
|
||||||
usage.push_str(&*name);
|
usage.push_str(&*name);
|
||||||
let req_string = if incl_reqs {
|
let req_string = if incl_reqs {
|
||||||
self.get_required_usage_from(&[], None, false)
|
self.get_required_usage_from(&[], None, false)
|
||||||
|
@ -64,30 +64,27 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
usage.push_str(" [OPTIONS]");
|
usage.push_str(" [OPTIONS]");
|
||||||
}
|
}
|
||||||
|
|
||||||
let allow_missing_positional = self.p.app.is_set(AS::AllowMissingPositional);
|
let allow_missing_positional = self.app.is_set(AS::AllowMissingPositional);
|
||||||
if !allow_missing_positional {
|
if !allow_missing_positional {
|
||||||
usage.push_str(&req_string);
|
usage.push_str(&req_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
let has_last = self
|
let has_last = self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.any(|p| p.is_set(ArgSettings::Last));
|
.any(|p| p.is_set(ArgSettings::Last));
|
||||||
// places a '--' in the usage string if there are args and options
|
// places a '--' in the usage string if there are args and options
|
||||||
// supporting multiple values
|
// supporting multiple values
|
||||||
if self
|
if self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.get_non_positionals()
|
.get_non_positionals()
|
||||||
.any(|o| o.is_set(ArgSettings::MultipleValues))
|
.any(|o| o.is_set(ArgSettings::MultipleValues))
|
||||||
&& self
|
&& self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.any(|p| !p.is_set(ArgSettings::Required))
|
.any(|p| !p.is_set(ArgSettings::Required))
|
||||||
&& !(self.p.app.has_visible_subcommands()
|
&& !(self.app.has_visible_subcommands()
|
||||||
|| self.p.is_set(AS::AllowExternalSubcommands))
|
|| self.app.is_set(AS::AllowExternalSubcommands))
|
||||||
&& !has_last
|
&& !has_last
|
||||||
{
|
{
|
||||||
usage.push_str(" [--]");
|
usage.push_str(" [--]");
|
||||||
|
@ -96,7 +93,7 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
(!p.is_set(ArgSettings::Required) || p.is_set(ArgSettings::Last))
|
(!p.is_set(ArgSettings::Required) || p.is_set(ArgSettings::Last))
|
||||||
&& !p.is_set(ArgSettings::Hidden)
|
&& !p.is_set(ArgSettings::Hidden)
|
||||||
};
|
};
|
||||||
if self.p.app.get_positionals().any(not_req_or_hidden) {
|
if self.app.get_positionals().any(not_req_or_hidden) {
|
||||||
if let Some(args_tag) = self.get_args_tag(incl_reqs) {
|
if let Some(args_tag) = self.get_args_tag(incl_reqs) {
|
||||||
usage.push_str(&*args_tag);
|
usage.push_str(&*args_tag);
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,7 +101,6 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
}
|
}
|
||||||
if has_last && incl_reqs {
|
if has_last && incl_reqs {
|
||||||
let pos = self
|
let pos = self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.find(|p| p.is_set(ArgSettings::Last))
|
.find(|p| p.is_set(ArgSettings::Last))
|
||||||
|
@ -113,7 +109,6 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
let req = pos.is_set(ArgSettings::Required);
|
let req = pos.is_set(ArgSettings::Required);
|
||||||
if req
|
if req
|
||||||
&& self
|
&& self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.any(|p| !p.is_set(ArgSettings::Required))
|
.any(|p| !p.is_set(ArgSettings::Required))
|
||||||
|
@ -138,14 +133,15 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// incl_reqs is only false when this function is called recursively
|
// incl_reqs is only false when this function is called recursively
|
||||||
if self.p.app.has_visible_subcommands() && incl_reqs
|
if self.app.has_visible_subcommands() && incl_reqs
|
||||||
|| self.p.is_set(AS::AllowExternalSubcommands)
|
|| self.app.is_set(AS::AllowExternalSubcommands)
|
||||||
{
|
{
|
||||||
let placeholder = self.p.app.subcommand_value_name.unwrap_or("SUBCOMMAND");
|
let placeholder = self.app.subcommand_value_name.unwrap_or("SUBCOMMAND");
|
||||||
if self.p.is_set(AS::SubcommandsNegateReqs) || self.p.is_set(AS::ArgsNegateSubcommands)
|
if self.app.is_set(AS::SubcommandsNegateReqs)
|
||||||
|
|| self.app.is_set(AS::ArgsNegateSubcommands)
|
||||||
{
|
{
|
||||||
usage.push_str("\n ");
|
usage.push_str("\n ");
|
||||||
if !self.p.is_set(AS::ArgsNegateSubcommands) {
|
if !self.app.is_set(AS::ArgsNegateSubcommands) {
|
||||||
usage.push_str(&*self.create_help_usage(false));
|
usage.push_str(&*self.create_help_usage(false));
|
||||||
} else {
|
} else {
|
||||||
usage.push_str(&*name);
|
usage.push_str(&*name);
|
||||||
|
@ -153,8 +149,8 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
usage.push_str(" <");
|
usage.push_str(" <");
|
||||||
usage.push_str(placeholder);
|
usage.push_str(placeholder);
|
||||||
usage.push('>');
|
usage.push('>');
|
||||||
} else if self.p.is_set(AS::SubcommandRequired)
|
} else if self.app.is_set(AS::SubcommandRequired)
|
||||||
|| self.p.is_set(AS::SubcommandRequiredElseHelp)
|
|| self.app.is_set(AS::SubcommandRequiredElseHelp)
|
||||||
{
|
{
|
||||||
usage.push_str(" <");
|
usage.push_str(" <");
|
||||||
usage.push_str(placeholder);
|
usage.push_str(placeholder);
|
||||||
|
@ -183,17 +179,16 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
|
|
||||||
usage.push_str(
|
usage.push_str(
|
||||||
&self
|
&self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.usage
|
.usage
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.or_else(|| self.p.app.bin_name.as_ref())
|
.or_else(|| self.app.bin_name.as_ref())
|
||||||
.unwrap_or(&self.p.app.name)[..],
|
.unwrap_or(&self.app.name)[..],
|
||||||
);
|
);
|
||||||
usage.push_str(&*r_string);
|
usage.push_str(&*r_string);
|
||||||
if self.p.is_set(AS::SubcommandRequired) {
|
if self.app.is_set(AS::SubcommandRequired) {
|
||||||
usage.push_str(" <");
|
usage.push_str(" <");
|
||||||
usage.push_str(self.p.app.subcommand_value_name.unwrap_or("SUBCOMMAND"));
|
usage.push_str(self.app.subcommand_value_name.unwrap_or("SUBCOMMAND"));
|
||||||
usage.push('>');
|
usage.push('>');
|
||||||
}
|
}
|
||||||
usage.shrink_to_fit();
|
usage.shrink_to_fit();
|
||||||
|
@ -205,7 +200,6 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
debug!("Usage::get_args_tag; incl_reqs = {:?}", incl_reqs);
|
debug!("Usage::get_args_tag; incl_reqs = {:?}", incl_reqs);
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
for pos in self
|
for pos in self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||||
|
@ -213,11 +207,10 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
||||||
{
|
{
|
||||||
debug!("Usage::get_args_tag:iter:{}", pos.name);
|
debug!("Usage::get_args_tag:iter:{}", pos.name);
|
||||||
let required = self.p.app.groups_for_arg(&pos.id).any(|grp_s| {
|
let required = self.app.groups_for_arg(&pos.id).any(|grp_s| {
|
||||||
debug!("Usage::get_args_tag:iter:{:?}:iter:{:?}", pos.name, grp_s);
|
debug!("Usage::get_args_tag:iter:{:?}:iter:{:?}", pos.name, grp_s);
|
||||||
// if it's part of a required group we don't want to count it
|
// if it's part of a required group we don't want to count it
|
||||||
self.p
|
self.app
|
||||||
.app
|
|
||||||
.groups
|
.groups
|
||||||
.iter()
|
.iter()
|
||||||
.any(|g| g.required && (g.id == grp_s))
|
.any(|g| g.required && (g.id == grp_s))
|
||||||
|
@ -231,25 +224,23 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.p.is_set(AS::DontCollapseArgsInUsage) && count > 1 {
|
if !self.app.is_set(AS::DontCollapseArgsInUsage) && count > 1 {
|
||||||
debug!("Usage::get_args_tag:iter: More than one, returning [ARGS]");
|
debug!("Usage::get_args_tag:iter: More than one, returning [ARGS]");
|
||||||
|
|
||||||
// [ARGS]
|
// [ARGS]
|
||||||
None
|
None
|
||||||
} else if count == 1 && incl_reqs {
|
} else if count == 1 && incl_reqs {
|
||||||
let pos = self
|
let pos = self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.find(|pos| {
|
.find(|pos| {
|
||||||
!pos.is_set(ArgSettings::Required)
|
!pos.is_set(ArgSettings::Required)
|
||||||
&& !pos.is_set(ArgSettings::Hidden)
|
&& !pos.is_set(ArgSettings::Hidden)
|
||||||
&& !pos.is_set(ArgSettings::Last)
|
&& !pos.is_set(ArgSettings::Last)
|
||||||
&& !self.p.app.groups_for_arg(&pos.id).any(|grp_s| {
|
&& !self.app.groups_for_arg(&pos.id).any(|grp_s| {
|
||||||
debug!("Usage::get_args_tag:iter:{:?}:iter:{:?}", pos.name, grp_s);
|
debug!("Usage::get_args_tag:iter:{:?}:iter:{:?}", pos.name, grp_s);
|
||||||
// if it's part of a required group we don't want to count it
|
// if it's part of a required group we don't want to count it
|
||||||
self.p
|
self.app
|
||||||
.app
|
|
||||||
.groups
|
.groups
|
||||||
.iter()
|
.iter()
|
||||||
.any(|g| g.required && (g.id == grp_s))
|
.any(|g| g.required && (g.id == grp_s))
|
||||||
|
@ -267,14 +258,13 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
pos.name_no_brackets(),
|
pos.name_no_brackets(),
|
||||||
pos.multiple_str()
|
pos.multiple_str()
|
||||||
))
|
))
|
||||||
} else if self.p.is_set(AS::DontCollapseArgsInUsage)
|
} else if self.app.is_set(AS::DontCollapseArgsInUsage)
|
||||||
&& self.p.app.has_positionals()
|
&& self.app.has_positionals()
|
||||||
&& incl_reqs
|
&& incl_reqs
|
||||||
{
|
{
|
||||||
debug!("Usage::get_args_tag:iter: Don't collapse returning all");
|
debug!("Usage::get_args_tag:iter: Don't collapse returning all");
|
||||||
Some(
|
Some(
|
||||||
self.p
|
self.app
|
||||||
.app
|
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||||
|
@ -286,7 +276,6 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
} else if !incl_reqs {
|
} else if !incl_reqs {
|
||||||
debug!("Usage::get_args_tag:iter: incl_reqs=false, building secondary usage string");
|
debug!("Usage::get_args_tag:iter: incl_reqs=false, building secondary usage string");
|
||||||
let highest_req_pos = self
|
let highest_req_pos = self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.filter_map(|pos| {
|
.filter_map(|pos| {
|
||||||
|
@ -297,10 +286,9 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or_else(|| Some(self.p.app.get_positionals().count()));
|
.unwrap_or_else(|| Some(self.app.get_positionals().count()));
|
||||||
Some(
|
Some(
|
||||||
self.p
|
self.app
|
||||||
.app
|
|
||||||
.get_positionals()
|
.get_positionals()
|
||||||
.filter(|pos| pos.index <= highest_req_pos)
|
.filter(|pos| pos.index <= highest_req_pos)
|
||||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||||
|
@ -318,7 +306,7 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
// Determines if we need the `[OPTIONS]` tag in the usage string
|
// Determines if we need the `[OPTIONS]` tag in the usage string
|
||||||
fn needs_options_tag(&self) -> bool {
|
fn needs_options_tag(&self) -> bool {
|
||||||
debug!("Usage::needs_options_tag");
|
debug!("Usage::needs_options_tag");
|
||||||
'outer: for f in self.p.app.get_non_positionals() {
|
'outer: for f in self.app.get_non_positionals() {
|
||||||
debug!("Usage::needs_options_tag:iter: f={}", f.name);
|
debug!("Usage::needs_options_tag:iter: f={}", f.name);
|
||||||
|
|
||||||
// Don't print `[OPTIONS]` just for help or version
|
// Don't print `[OPTIONS]` just for help or version
|
||||||
|
@ -335,15 +323,9 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
debug!("Usage::needs_options_tag:iter Option is required");
|
debug!("Usage::needs_options_tag:iter Option is required");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for grp_s in self.p.app.groups_for_arg(&f.id) {
|
for grp_s in self.app.groups_for_arg(&f.id) {
|
||||||
debug!("Usage::needs_options_tag:iter:iter: grp_s={:?}", grp_s);
|
debug!("Usage::needs_options_tag:iter:iter: grp_s={:?}", grp_s);
|
||||||
if self
|
if self.app.groups.iter().any(|g| g.id == grp_s && g.required) {
|
||||||
.p
|
|
||||||
.app
|
|
||||||
.groups
|
|
||||||
.iter()
|
|
||||||
.any(|g| g.id == grp_s && g.required)
|
|
||||||
{
|
|
||||||
debug!("Usage::needs_options_tag:iter:iter: Group is required");
|
debug!("Usage::needs_options_tag:iter:iter: Group is required");
|
||||||
continue 'outer;
|
continue 'outer;
|
||||||
}
|
}
|
||||||
|
@ -377,9 +359,9 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
|
|
||||||
let mut unrolled_reqs = IndexSet::new();
|
let mut unrolled_reqs = IndexSet::new();
|
||||||
|
|
||||||
for a in self.p.required.iter() {
|
for a in self.required.iter() {
|
||||||
if let Some(m) = matcher {
|
if let Some(m) = matcher {
|
||||||
for aa in self.p.app.unroll_requirements_for_arg(a, m) {
|
for aa in self.app.unroll_requirements_for_arg(a, m) {
|
||||||
// if we don't check for duplicates here this causes duplicate error messages
|
// if we don't check for duplicates here this causes duplicate error messages
|
||||||
// see https://github.com/clap-rs/clap/issues/2770
|
// see https://github.com/clap-rs/clap/issues/2770
|
||||||
unrolled_reqs.insert(aa);
|
unrolled_reqs.insert(aa);
|
||||||
|
@ -396,35 +378,33 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let args_in_groups = self
|
let args_in_groups = self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.groups
|
.groups
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|gn| self.p.required.contains(&gn.id))
|
.filter(|gn| self.required.contains(&gn.id))
|
||||||
.flat_map(|g| self.p.app.unroll_args_in_group(&g.id))
|
.flat_map(|g| self.app.unroll_args_in_group(&g.id))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for a in unrolled_reqs
|
for a in unrolled_reqs
|
||||||
.iter()
|
.iter()
|
||||||
.chain(incls.iter())
|
.chain(incls.iter())
|
||||||
.filter(|name| !self.p.app.get_positionals().any(|p| &&p.id == name))
|
.filter(|name| !self.app.get_positionals().any(|p| &&p.id == name))
|
||||||
.filter(|name| !self.p.app.groups.iter().any(|g| &&g.id == name))
|
.filter(|name| !self.app.groups.iter().any(|g| &&g.id == name))
|
||||||
.filter(|name| !args_in_groups.contains(name))
|
.filter(|name| !args_in_groups.contains(name))
|
||||||
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(name)))
|
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(name)))
|
||||||
{
|
{
|
||||||
debug!("Usage::get_required_usage_from:iter:{:?}", a);
|
debug!("Usage::get_required_usage_from:iter:{:?}", a);
|
||||||
let arg = self.p.app.find(a).expect(INTERNAL_ERROR_MSG).to_string();
|
let arg = self.app.find(a).expect(INTERNAL_ERROR_MSG).to_string();
|
||||||
ret_val.push(arg);
|
ret_val.push(arg);
|
||||||
}
|
}
|
||||||
let mut g_vec: Vec<String> = vec![];
|
let mut g_vec: Vec<String> = vec![];
|
||||||
for g in unrolled_reqs
|
for g in unrolled_reqs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|n| self.p.app.groups.iter().any(|g| g.id == **n))
|
.filter(|n| self.app.groups.iter().any(|g| g.id == **n))
|
||||||
{
|
{
|
||||||
// don't print requirement for required groups that have an arg.
|
// don't print requirement for required groups that have an arg.
|
||||||
if let Some(m) = matcher {
|
if let Some(m) = matcher {
|
||||||
let have_group_entry = self
|
let have_group_entry = self
|
||||||
.p
|
|
||||||
.app
|
.app
|
||||||
.unroll_args_in_group(g)
|
.unroll_args_in_group(g)
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -434,7 +414,7 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem = self.p.app.format_group(g);
|
let elem = self.app.format_group(g);
|
||||||
if !g_vec.contains(&elem) {
|
if !g_vec.contains(&elem) {
|
||||||
g_vec.push(elem);
|
g_vec.push(elem);
|
||||||
}
|
}
|
||||||
|
@ -444,9 +424,9 @@ impl<'help, 'app, 'parser> Usage<'help, 'app, 'parser> {
|
||||||
let mut pvec = unrolled_reqs
|
let mut pvec = unrolled_reqs
|
||||||
.iter()
|
.iter()
|
||||||
.chain(incls.iter())
|
.chain(incls.iter())
|
||||||
.filter(|a| self.p.app.get_positionals().any(|p| &&p.id == a))
|
.filter(|a| self.app.get_positionals().any(|p| &&p.id == a))
|
||||||
.filter(|&pos| matcher.map_or(true, |m| !m.contains(pos)))
|
.filter(|&pos| matcher.map_or(true, |m| !m.contains(pos)))
|
||||||
.filter_map(|pos| self.p.app.find(pos))
|
.filter_map(|pos| self.app.find(pos))
|
||||||
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
|
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
|
||||||
.filter(|pos| !args_in_groups.contains(&pos.id))
|
.filter(|pos| !args_in_groups.contains(&pos.id))
|
||||||
.map(|pos| (pos.index.unwrap(), pos))
|
.map(|pos| (pos.index.unwrap(), pos))
|
||||||
|
|
|
@ -28,13 +28,13 @@ pub(crate) struct Parser<'help, 'app> {
|
||||||
pub(crate) app: &'app mut App<'help>,
|
pub(crate) app: &'app mut App<'help>,
|
||||||
pub(crate) required: ChildGraph<Id>,
|
pub(crate) required: ChildGraph<Id>,
|
||||||
pub(crate) overridden: RefCell<Vec<Id>>,
|
pub(crate) overridden: RefCell<Vec<Id>>,
|
||||||
pub(crate) seen: Vec<Id>,
|
seen: Vec<Id>,
|
||||||
pub(crate) cur_idx: Cell<usize>,
|
cur_idx: Cell<usize>,
|
||||||
/// Index of the previous flag subcommand in a group of flags.
|
/// Index of the previous flag subcommand in a group of flags.
|
||||||
pub(crate) flag_subcmd_at: Option<usize>,
|
flag_subcmd_at: Option<usize>,
|
||||||
/// Counter indicating the number of items to skip
|
/// Counter indicating the number of items to skip
|
||||||
/// when revisiting the group of flags which includes the flag subcommand.
|
/// when revisiting the group of flags which includes the flag subcommand.
|
||||||
pub(crate) flag_subcmd_skip: usize,
|
flag_subcmd_skip: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializing Methods
|
// Initializing Methods
|
||||||
|
@ -48,6 +48,14 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
{
|
{
|
||||||
reqs.insert(a.id.clone());
|
reqs.insert(a.id.clone());
|
||||||
}
|
}
|
||||||
|
for group in &app.groups {
|
||||||
|
if group.required {
|
||||||
|
let idx = reqs.insert(group.id.clone());
|
||||||
|
for a in &group.requires {
|
||||||
|
reqs.insert_child(idx, a.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Parser {
|
Parser {
|
||||||
app,
|
app,
|
||||||
|
@ -60,20 +68,6 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does all the initializing and prepares the parser
|
|
||||||
pub(crate) fn _build(&mut self) {
|
|
||||||
debug!("Parser::_build");
|
|
||||||
|
|
||||||
for group in &self.app.groups {
|
|
||||||
if group.required {
|
|
||||||
let idx = self.required.insert(group.id.clone());
|
|
||||||
for a in &group.requires {
|
|
||||||
self.required.insert_child(idx, a.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should we color the help?
|
// Should we color the help?
|
||||||
pub(crate) fn color_help(&self) -> ColorChoice {
|
pub(crate) fn color_help(&self) -> ColorChoice {
|
||||||
#[cfg(feature = "color")]
|
#[cfg(feature = "color")]
|
||||||
|
@ -96,7 +90,6 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
) -> ClapResult<()> {
|
) -> ClapResult<()> {
|
||||||
debug!("Parser::get_matches_with");
|
debug!("Parser::get_matches_with");
|
||||||
// Verify all positional assertions pass
|
// Verify all positional assertions pass
|
||||||
self._build();
|
|
||||||
|
|
||||||
let mut subcmd_name: Option<String> = None;
|
let mut subcmd_name: Option<String> = None;
|
||||||
let mut keep_state = false;
|
let mut keep_state = false;
|
||||||
|
@ -264,7 +257,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
return Err(ClapError::no_equals(
|
return Err(ClapError::no_equals(
|
||||||
self.app,
|
self.app,
|
||||||
arg,
|
arg,
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ParseResult::NoMatchingArg { arg } => {
|
ParseResult::NoMatchingArg { arg } => {
|
||||||
|
@ -279,7 +272,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
self.app,
|
self.app,
|
||||||
rest,
|
rest,
|
||||||
arg,
|
arg,
|
||||||
Usage::new(self).create_usage_no_title(&used),
|
Usage::new(self.app, &self.required).create_usage_no_title(&used),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
ParseResult::HelpFlag => {
|
ParseResult::HelpFlag => {
|
||||||
|
@ -353,7 +346,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
return Err(ClapError::no_equals(
|
return Err(ClapError::no_equals(
|
||||||
self.app,
|
self.app,
|
||||||
arg,
|
arg,
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
ParseResult::NoMatchingArg { arg } => {
|
ParseResult::NoMatchingArg { arg } => {
|
||||||
|
@ -361,7 +354,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
self.app,
|
self.app,
|
||||||
arg,
|
arg,
|
||||||
None,
|
None,
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ParseResult::HelpFlag => {
|
ParseResult::HelpFlag => {
|
||||||
|
@ -406,7 +399,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
self.app,
|
self.app,
|
||||||
arg_os.to_str_lossy().into_owned(),
|
arg_os.to_str_lossy().into_owned(),
|
||||||
None,
|
None,
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,7 +440,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
None => {
|
None => {
|
||||||
return Err(ClapError::invalid_utf8(
|
return Err(ClapError::invalid_utf8(
|
||||||
self.app,
|
self.app,
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -461,7 +454,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
if !allow_invalid_utf8 && v.to_str().is_none() {
|
if !allow_invalid_utf8 && v.to_str().is_none() {
|
||||||
return Err(ClapError::invalid_utf8(
|
return Err(ClapError::invalid_utf8(
|
||||||
self.app,
|
self.app,
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
sc_m.add_val_to(
|
sc_m.add_val_to(
|
||||||
|
@ -506,7 +499,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
return Err(ClapError::missing_subcommand(
|
return Err(ClapError::missing_subcommand(
|
||||||
self.app,
|
self.app,
|
||||||
bn.to_string(),
|
bn.to_string(),
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
} else if self.is_set(AS::SubcommandRequiredElseHelp) {
|
} else if self.is_set(AS::SubcommandRequiredElseHelp) {
|
||||||
debug!("Parser::get_matches_with: SubcommandRequiredElseHelp=true");
|
debug!("Parser::get_matches_with: SubcommandRequiredElseHelp=true");
|
||||||
|
@ -534,7 +527,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
return ClapError::unnecessary_double_dash(
|
return ClapError::unnecessary_double_dash(
|
||||||
self.app,
|
self.app,
|
||||||
arg_os.to_str_lossy().into_owned(),
|
arg_os.to_str_lossy().into_owned(),
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,7 +548,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(&self.app.name)
|
.unwrap_or(&self.app.name)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// If the argument must be a subcommand.
|
// If the argument must be a subcommand.
|
||||||
|
@ -574,7 +567,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
self.app,
|
self.app,
|
||||||
arg_os.to_str_lossy().into_owned(),
|
arg_os.to_str_lossy().into_owned(),
|
||||||
None,
|
None,
|
||||||
Usage::new(self).create_usage_with_title(&[]),
|
Usage::new(self.app, &self.required).create_usage_with_title(&[]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,7 +714,8 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
let mut mid_string = String::from(" ");
|
let mut mid_string = String::from(" ");
|
||||||
|
|
||||||
if !self.is_set(AS::SubcommandsNegateReqs) {
|
if !self.is_set(AS::SubcommandsNegateReqs) {
|
||||||
let reqs = Usage::new(self).get_required_usage_from(&[], None, true); // maybe Some(m)
|
let reqs =
|
||||||
|
Usage::new(self.app, &self.required).get_required_usage_from(&[], None, true); // maybe Some(m)
|
||||||
|
|
||||||
for s in &reqs {
|
for s in &reqs {
|
||||||
mid_string.push_str(s);
|
mid_string.push_str(s);
|
||||||
|
@ -1563,13 +1557,14 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
self.app,
|
self.app,
|
||||||
format!("--{}", arg),
|
format!("--{}", arg),
|
||||||
did_you_mean,
|
did_you_mean,
|
||||||
Usage::new(self).create_usage_with_title(&*used),
|
Usage::new(self.app, &self.required).create_usage_with_title(&*used),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn write_help_err(&self) -> ClapResult<Colorizer> {
|
pub(crate) fn write_help_err(&self) -> ClapResult<Colorizer> {
|
||||||
|
let usage = Usage::new(self.app, &self.required);
|
||||||
let mut c = Colorizer::new(true, self.color_help());
|
let mut c = Colorizer::new(true, self.color_help());
|
||||||
Help::new(HelpWriter::Buffer(&mut c), self, false).write_help()?;
|
Help::new(HelpWriter::Buffer(&mut c), self.app, &usage, false).write_help()?;
|
||||||
Ok(c)
|
Ok(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1580,9 +1575,10 @@ impl<'help, 'app> Parser<'help, 'app> {
|
||||||
);
|
);
|
||||||
|
|
||||||
use_long = use_long && self.use_long_help();
|
use_long = use_long && self.use_long_help();
|
||||||
|
let usage = Usage::new(self.app, &self.required);
|
||||||
let mut c = Colorizer::new(false, self.color_help());
|
let mut c = Colorizer::new(false, self.color_help());
|
||||||
|
|
||||||
match Help::new(HelpWriter::Buffer(&mut c), self, use_long).write_help() {
|
match Help::new(HelpWriter::Buffer(&mut c), self.app, &usage, use_long).write_help() {
|
||||||
Err(e) => e.into(),
|
Err(e) => e.into(),
|
||||||
_ => ClapError::for_app(self.app, c, ErrorKind::DisplayHelp, vec![]),
|
_ => ClapError::for_app(self.app, c, ErrorKind::DisplayHelp, vec![]),
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
return Err(Error::empty_value(
|
return Err(Error::empty_value(
|
||||||
self.p.app,
|
self.p.app,
|
||||||
o,
|
o,
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
);
|
);
|
||||||
return Err(Error::invalid_utf8(
|
return Err(Error::invalid_utf8(
|
||||||
self.p.app,
|
self.p.app,
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if !arg.possible_vals.is_empty() {
|
if !arg.possible_vals.is_empty() {
|
||||||
|
@ -122,7 +122,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
.filter_map(PossibleValue::get_visible_name)
|
.filter_map(PossibleValue::get_visible_name)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
arg,
|
arg,
|
||||||
Usage::new(self.p).create_usage_with_title(&used),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&used),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
return Err(Error::empty_value(
|
return Err(Error::empty_value(
|
||||||
self.p.app,
|
self.p.app,
|
||||||
arg,
|
arg,
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
self.p.app,
|
self.p.app,
|
||||||
arg,
|
arg,
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
.chain(used_filtered.iter())
|
.chain(used_filtered.iter())
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
Usage::new(self.p).create_usage_with_title(&required)
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&required)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_requirements(&mut self, matcher: &ArgMatcher) {
|
fn gather_requirements(&mut self, matcher: &ArgMatcher) {
|
||||||
|
@ -317,7 +317,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
return Err(Error::unexpected_multiple_usage(
|
return Err(Error::unexpected_multiple_usage(
|
||||||
self.p.app,
|
self.p.app,
|
||||||
a,
|
a,
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Some(max_occurs) = a.max_occurs {
|
if let Some(max_occurs) = a.max_occurs {
|
||||||
|
@ -332,7 +332,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
a,
|
a,
|
||||||
max_occurs,
|
max_occurs,
|
||||||
occurs,
|
occurs,
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,7 +361,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
} else {
|
} else {
|
||||||
total_num
|
total_num
|
||||||
},
|
},
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
.expect(INVALID_UTF8)
|
.expect(INVALID_UTF8)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
a.to_string(),
|
a.to_string(),
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
a,
|
a,
|
||||||
num,
|
num,
|
||||||
ma.num_vals(),
|
ma.num_vals(),
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
num == 0
|
num == 0
|
||||||
|
@ -404,7 +404,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
return Err(Error::empty_value(
|
return Err(Error::empty_value(
|
||||||
self.p.app,
|
self.p.app,
|
||||||
a,
|
a,
|
||||||
Usage::new(self.p).create_usage_with_title(&[]),
|
Usage::new(self.p.app, &self.p.required).create_usage_with_title(&[]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -514,7 +514,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
||||||
self.p.required
|
self.p.required
|
||||||
);
|
);
|
||||||
|
|
||||||
let usg = Usage::new(self.p);
|
let usg = Usage::new(self.p.app, &self.p.required);
|
||||||
|
|
||||||
let req_args = usg.get_required_usage_from(&incl, Some(matcher), true);
|
let req_args = usg.get_required_usage_from(&incl, Some(matcher), true);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue