Skip to content

Commit

Permalink
Merge pull request google#132 from sadmac7000/master
Browse files Browse the repository at this point in the history
Document dynamic commands and bump version
  • Loading branch information
sadmac7000 authored Jun 26, 2022
2 parents bd37ed1 + c96d491 commit b9296f0
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 10 deletions.
6 changes: 3 additions & 3 deletions argh/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "argh"
version = "0.1.7"
version = "0.1.8"
authors = ["Taylor Cramer <[email protected]>", "Benjamin Brittain <[email protected]>", "Erick Tryzelaar <[email protected]>"]
edition = "2018"
keywords = ["args", "arguments", "derive", "cli"]
Expand All @@ -10,8 +10,8 @@ repository = "https://github.com/google/argh"
readme = "README.md"

[dependencies]
argh_shared = { version = "0.1.7", path = "../argh_shared" }
argh_derive = { version = "0.1.7", path = "../argh_derive" }
argh_shared = { version = "0.1.8", path = "../argh_shared" }
argh_derive = { version = "0.1.8", path = "../argh_derive" }

[dev-dependencies]
once_cell = "1.10.0"
115 changes: 111 additions & 4 deletions argh/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,102 @@
//! fooey: bool,
//! }
//! ```
//!
//! You can also discover subcommands dynamically at runtime. To do this,
//! declare subcommands as usual and add a variant to the enum with the
//! `dynamic` attribute. Instead of deriving `FromArgs`, the value inside the
//! dynamic variant should implement `DynamicSubCommand`.
//!
//! ```rust
//! # use argh::CommandInfo;
//! # use argh::DynamicSubCommand;
//! # use argh::EarlyExit;
//! # use argh::FromArgs;
//! # use once_cell::sync::OnceCell;
//!
//! #[derive(FromArgs, PartialEq, Debug)]
//! /// Top-level command.
//! struct TopLevel {
//! #[argh(subcommand)]
//! nested: MySubCommandEnum,
//! }
//!
//! #[derive(FromArgs, PartialEq, Debug)]
//! #[argh(subcommand)]
//! enum MySubCommandEnum {
//! Normal(NormalSubCommand),
//! #[argh(dynamic)]
//! Dynamic(Dynamic),
//! }
//!
//! #[derive(FromArgs, PartialEq, Debug)]
//! /// Normal subcommand.
//! #[argh(subcommand, name = "normal")]
//! struct NormalSubCommand {
//! #[argh(option)]
//! /// how many x
//! x: usize,
//! }
//!
//! /// Dynamic subcommand.
//! #[derive(PartialEq, Debug)]
//! struct Dynamic {
//! name: String
//! }
//!
//! impl DynamicSubCommand for Dynamic {
//! fn commands() -> &'static [&'static CommandInfo] {
//! static RET: OnceCell<Vec<&'static CommandInfo>> = OnceCell::new();
//! RET.get_or_init(|| {
//! let mut commands = Vec::new();
//!
//! // argh needs the `CommandInfo` structs we generate to be valid
//! // for the static lifetime. We can allocate the structures on
//! // the heap with `Box::new` and use `Box::leak` to get a static
//! // reference to them. We could also just use a constant
//! // reference, but only because this is a synthetic example; the
//! // point of using dynamic commands is to have commands you
//! // don't know about until runtime!
//! commands.push(&*Box::leak(Box::new(CommandInfo {
//! name: "dynamic_command",
//! description: "A dynamic command",
//! })));
//!
//! commands
//! })
//! }
//!
//! fn try_redact_arg_values(
//! command_name: &[&str],
//! args: &[&str],
//! ) -> Option<Result<Vec<String>, EarlyExit>> {
//! for command in Self::commands() {
//! if command_name.last() == Some(&command.name) {
//! // Process arguments and redact values here.
//! if !args.is_empty() {
//! return Some(Err("Our example dynamic command never takes arguments!"
//! .to_string().into()));
//! }
//! return Some(Ok(Vec::new()))
//! }
//! }
//! None
//! }
//!
//! fn try_from_args(command_name: &[&str], args: &[&str]) -> Option<Result<Self, EarlyExit>> {
//! for command in Self::commands() {
//! if command_name.last() == Some(&command.name) {
//! if !args.is_empty() {
//! return Some(Err("Our example dynamic command never takes arguments!"
//! .to_string().into()));
//! }
//! return Some(Ok(Dynamic { name: command.name.to_string() }))
//! }
//! }
//! None
//! }
//! }
//! ```
#![deny(missing_docs)]

Expand Down Expand Up @@ -465,15 +561,26 @@ pub trait DynamicSubCommand: Sized {
/// Info about supported subcommands.
fn commands() -> &'static [&'static CommandInfo];

/// Perform the function of `FromArgs::redact_arg_values` for this dynamic command. If the
/// command being processed is not recognized return `None`.
/// Perform the function of `FromArgs::redact_arg_values` for this dynamic
/// command.
///
/// The full list of subcommands, ending with the subcommand that should be
/// dynamically recognized, is passed in `command_name`. If the command
/// passed is not recognized, this function should return `None`. Otherwise
/// it should return `Some`, and the value within the `Some` has the same
/// semantics as the return of `FromArgs::redact_arg_values`.
fn try_redact_arg_values(
command_name: &[&str],
args: &[&str],
) -> Option<Result<Vec<String>, EarlyExit>>;

/// Perform the function of `FromArgs::from_args` for this dynamic command. If the command being
/// processed is not recognized return `None`.
/// Perform the function of `FromArgs::from_args` for this dynamic command.
///
/// The full list of subcommands, ending with the subcommand that should be
/// dynamically recognized, is passed in `command_name`. If the command
/// passed is not recognized, this function should return `None`. Otherwise
/// it should return `Some`, and the value within the `Some` has the same
/// semantics as the return of `FromArgs::from_args`.
fn try_from_args(command_name: &[&str], args: &[&str]) -> Option<Result<Self, EarlyExit>>;
}

Expand Down
4 changes: 2 additions & 2 deletions argh_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "argh_derive"
version = "0.1.7"
version = "0.1.8"
authors = ["Taylor Cramer <[email protected]>", "Benjamin Brittain <[email protected]>", "Erick Tryzelaar <[email protected]>"]
edition = "2018"
license = "BSD-3-Clause"
Expand All @@ -16,4 +16,4 @@ heck = "0.3.1"
proc-macro2 = "1.0"
quote = "1.0"
syn = "1.0"
argh_shared = { version = "0.1.7", path = "../argh_shared" }
argh_shared = { version = "0.1.8", path = "../argh_shared" }
2 changes: 1 addition & 1 deletion argh_shared/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "argh_shared"
version = "0.1.7"
version = "0.1.8"
authors = ["Taylor Cramer <[email protected]>", "Benjamin Brittain <[email protected]>", "Erick Tryzelaar <[email protected]>"]
edition = "2018"
license = "BSD-3-Clause"
Expand Down

0 comments on commit b9296f0

Please sign in to comment.