mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
feat(multicall): Stablize multicall
`multicall` allows you to have one binary expose itself as multiple programs, like busybox does. This also works well for user clap for parsing REPLs. Fixes #2861
This commit is contained in:
parent
1a2b7acd60
commit
686b0379ce
12 changed files with 15 additions and 55 deletions
|
@ -64,7 +64,7 @@ default = [
|
|||
"suggestions",
|
||||
]
|
||||
debug = ["clap_derive/debug", "backtrace"] # Enables debug messages
|
||||
unstable-doc = ["derive", "cargo", "wrap_help", "yaml", "env", "unicode", "regex", "unstable-replace", "unstable-multicall", "unstable-grouped"] # for docs.rs
|
||||
unstable-doc = ["derive", "cargo", "wrap_help", "yaml", "env", "unicode", "regex", "unstable-replace", "unstable-grouped"] # for docs.rs
|
||||
|
||||
# Used in default
|
||||
std = ["indexmap/std"] # support for no_std in a backwards-compatible way
|
||||
|
@ -81,7 +81,6 @@ unicode = ["textwrap/unicode-width", "unicase"] # Support for unicode character
|
|||
|
||||
# In-work features
|
||||
unstable-replace = []
|
||||
unstable-multicall = []
|
||||
unstable-grouped = []
|
||||
# note: this will always enable clap_derive, change this to `clap_derive?/unstable-v4` when MSRV is bigger than 1.60
|
||||
unstable-v4 = ["clap_derive/unstable-v4"]
|
||||
|
@ -178,17 +177,14 @@ required-features = ["derive"]
|
|||
[[example]]
|
||||
name = "busybox"
|
||||
path = "examples/multicall-busybox.rs"
|
||||
required-features = ["unstable-multicall"]
|
||||
|
||||
[[example]]
|
||||
name = "hostname"
|
||||
path = "examples/multicall-hostname.rs"
|
||||
required-features = ["unstable-multicall"]
|
||||
|
||||
[[example]]
|
||||
name = "repl"
|
||||
path = "examples/repl.rs"
|
||||
required-features = ["unstable-multicall"]
|
||||
|
||||
[[example]]
|
||||
name = "01_quick"
|
||||
|
|
4
Makefile
4
Makefile
|
@ -15,8 +15,8 @@ MSRV?=1.56.0
|
|||
_FEATURES = minimal default wasm full debug release
|
||||
_FEATURES_minimal = --no-default-features --features "std"
|
||||
_FEATURES_default =
|
||||
_FEATURES_wasm = --features "derive cargo env unicode yaml regex unstable-replace unstable-multicall unstable-grouped"
|
||||
_FEATURES_full = --features "derive cargo env unicode yaml regex unstable-replace unstable-multicall unstable-grouped wrap_help"
|
||||
_FEATURES_wasm = --features "derive cargo env unicode yaml regex unstable-replace unstable-grouped"
|
||||
_FEATURES_full = --features "derive cargo env unicode yaml regex unstable-replace unstable-grouped wrap_help"
|
||||
_FEATURES_next = ${_FEATURES_full} --features unstable-v4
|
||||
_FEATURES_debug = ${_FEATURES_full} --features debug
|
||||
_FEATURES_release = ${_FEATURES_full} --release
|
||||
|
|
|
@ -152,7 +152,6 @@ Why use the procedural [Builder API](https://github.com/clap-rs/clap/blob/v3.1.1
|
|||
**Warning:** These may contain breaking changes between minor releases.
|
||||
|
||||
* **unstable-replace**: Enable [`Command::replace`](https://github.com/clap-rs/clap/issues/2836)
|
||||
* **unstable-multicall**: Enable [`Command::multicall`](https://github.com/clap-rs/clap/issues/2861)
|
||||
* **unstable-grouped**: Enable [`ArgMatches::grouped_values_of`](https://github.com/clap-rs/clap/issues/2924)
|
||||
* **unstable-v4**: Preview features which will be stable on the v4.0 release
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// Note: this requires the `unstable-multicall` feature
|
||||
|
||||
use std::process::exit;
|
||||
|
||||
use clap::{Arg, Command};
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// Note: this requires the `unstable-multicall` feature
|
||||
|
||||
use clap::Command;
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// Note: this requires the `unstable-multicall` feature
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use clap::Command;
|
||||
|
|
|
@ -153,7 +153,6 @@ pub enum AppSettings {
|
|||
since = "3.1.0",
|
||||
note = "Replaced with `Command::multicall` and `Command::is_multicall_set`"
|
||||
)]
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
Multicall,
|
||||
|
||||
/// Deprecated, replaced with [`Command::allow_invalid_utf8_for_external_subcommands`] and [`Command::is_allow_invalid_utf8_for_external_subcommands_set`]
|
||||
|
@ -466,7 +465,6 @@ bitflags! {
|
|||
const USE_LONG_FORMAT_FOR_HELP_SC = 1 << 42;
|
||||
const INFER_LONG_ARGS = 1 << 43;
|
||||
const IGNORE_ERRORS = 1 << 44;
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
const MULTICALL = 1 << 45;
|
||||
const NO_OP = 0;
|
||||
}
|
||||
|
@ -533,7 +531,6 @@ impl_settings! { AppSettings, AppFlags,
|
|||
=> Flags::HELP_REQUIRED,
|
||||
Hidden
|
||||
=> Flags::HIDDEN,
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
Multicall
|
||||
=> Flags::MULTICALL,
|
||||
NoAutoHelp
|
||||
|
|
|
@ -637,7 +637,6 @@ impl<'help> App<'help> {
|
|||
let mut raw_args = clap_lex::RawArgs::new(itr.into_iter());
|
||||
let mut cursor = raw_args.cursor();
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
if self.settings.is_set(AppSettings::Multicall) {
|
||||
if let Some(argv0) = raw_args.next_os(&mut cursor) {
|
||||
let argv0 = Path::new(&argv0);
|
||||
|
@ -3062,7 +3061,6 @@ impl<'help> App<'help> {
|
|||
/// [`App::subcommand_value_name`]: crate::Command::subcommand_value_name
|
||||
/// [`App::subcommand_help_heading`]: crate::Command::subcommand_help_heading
|
||||
#[inline]
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
pub fn multicall(self, yes: bool) -> Self {
|
||||
if yes {
|
||||
self.setting(AppSettings::Multicall)
|
||||
|
@ -3715,15 +3713,9 @@ impl<'help> App<'help> {
|
|||
}
|
||||
|
||||
/// Report whether [`Command::multicall`] is set
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
pub fn is_multicall_set(&self) -> bool {
|
||||
self.is_set(AppSettings::Multicall)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unstable-multicall"))]
|
||||
fn is_multicall_set(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Deprecated
|
||||
|
@ -4109,13 +4101,10 @@ impl<'help> App<'help> {
|
|||
// Make sure all the globally set flags apply to us as well
|
||||
self.settings = self.settings | self.g_settings;
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
{
|
||||
if self.is_multicall_set() {
|
||||
self.settings.insert(AppSettings::SubcommandRequired.into());
|
||||
self.settings.insert(AppSettings::DisableHelpFlag.into());
|
||||
self.settings.insert(AppSettings::DisableVersionFlag.into());
|
||||
}
|
||||
if self.is_multicall_set() {
|
||||
self.settings.insert(AppSettings::SubcommandRequired.into());
|
||||
self.settings.insert(AppSettings::DisableHelpFlag.into());
|
||||
self.settings.insert(AppSettings::DisableVersionFlag.into());
|
||||
}
|
||||
|
||||
self._propagate();
|
||||
|
@ -4180,7 +4169,7 @@ impl<'help> App<'help> {
|
|||
mid_string.push(' ');
|
||||
}
|
||||
}
|
||||
let is_multicall_set = cfg!(feature = "unstable-multicall") && self.is_multicall_set();
|
||||
let is_multicall_set = self.is_multicall_set();
|
||||
|
||||
let sc = self.subcommands.iter_mut().find(|s| s.name == name)?;
|
||||
|
||||
|
@ -4263,7 +4252,7 @@ impl<'help> App<'help> {
|
|||
mid_string.push(' ');
|
||||
}
|
||||
}
|
||||
let is_multicall_set = cfg!(feature = "unstable-multicall") && self.is_multicall_set();
|
||||
let is_multicall_set = self.is_multicall_set();
|
||||
|
||||
let self_bin_name = if is_multicall_set {
|
||||
self.bin_name.as_deref().unwrap_or("")
|
||||
|
|
|
@ -60,15 +60,12 @@ pub(crate) fn assert_app(cmd: &Command) {
|
|||
for arg in cmd.get_arguments() {
|
||||
assert_arg(arg);
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
{
|
||||
assert!(
|
||||
!cmd.is_multicall_set(),
|
||||
"Command {}: Arguments like {} cannot be set on a multicall command",
|
||||
cmd.get_name(),
|
||||
arg.name
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!cmd.is_multicall_set(),
|
||||
"Command {}: Arguments like {} cannot be set on a multicall command",
|
||||
cmd.get_name(),
|
||||
arg.name
|
||||
);
|
||||
|
||||
if let Some(s) = arg.short.as_ref() {
|
||||
short_flags.push(Flag::Arg(format!("-{}", s), &*arg.name));
|
||||
|
@ -467,7 +464,6 @@ fn assert_app_flags(cmd: &Command) {
|
|||
}
|
||||
|
||||
checker!(is_allow_invalid_utf8_for_external_subcommands_set requires is_allow_external_subcommands_set);
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
checker!(is_multicall_set conflicts is_no_binary_name_set);
|
||||
}
|
||||
|
||||
|
|
|
@ -494,7 +494,6 @@ For more information try --help
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
#[test]
|
||||
fn busybox_like_multicall() {
|
||||
fn applet_commands() -> [Command<'static>; 2] {
|
||||
|
@ -520,7 +519,6 @@ fn busybox_like_multicall() {
|
|||
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnrecognizedSubcommand);
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
#[test]
|
||||
fn hostname_like_multicall() {
|
||||
let mut cmd = Command::new("hostname")
|
||||
|
@ -550,7 +548,6 @@ fn hostname_like_multicall() {
|
|||
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
#[test]
|
||||
fn bad_multicall_command_error() {
|
||||
let cmd = Command::new("repl")
|
||||
|
@ -606,7 +603,6 @@ For more information try help
|
|||
assert_eq!(err.kind(), ErrorKind::DisplayVersion);
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
#[test]
|
||||
#[should_panic = "Command repl: Arguments like oh-no cannot be set on a multicall command"]
|
||||
fn cant_have_args_with_multicall() {
|
||||
|
@ -620,7 +616,6 @@ fn cant_have_args_with_multicall() {
|
|||
cmd.build();
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
#[test]
|
||||
fn multicall_help_flag() {
|
||||
static EXPECTED: &str = "\
|
||||
|
@ -644,7 +639,6 @@ OPTIONS:
|
|||
utils::assert_output(cmd, "foo bar --help", EXPECTED, false);
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
#[test]
|
||||
fn multicall_help_subcommand() {
|
||||
static EXPECTED: &str = "\
|
||||
|
@ -668,7 +662,6 @@ OPTIONS:
|
|||
utils::assert_output(cmd, "help foo bar", EXPECTED, false);
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
#[test]
|
||||
fn multicall_render_help() {
|
||||
static EXPECTED: &str = "\
|
||||
|
|
|
@ -22,8 +22,6 @@ fn example_tests() {
|
|||
"wrap_help",
|
||||
#[cfg(feature = "unstable-replace")]
|
||||
"unstable-replace",
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
"unstable-multicall",
|
||||
#[cfg(feature = "unstable-grouped")]
|
||||
"unstable-grouped",
|
||||
]
|
||||
|
|
|
@ -22,8 +22,6 @@ fn ui_tests() {
|
|||
"wrap_help",
|
||||
#[cfg(feature = "unstable-replace")]
|
||||
"unstable-replace",
|
||||
#[cfg(feature = "unstable-multicall")]
|
||||
"unstable-multicall",
|
||||
#[cfg(feature = "unstable-grouped")]
|
||||
"unstable-grouped",
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue