mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 14:54:15 +00:00
parent
88fff13e71
commit
6ce9714e2b
10 changed files with 27 additions and 241 deletions
2
FAQ.md
2
FAQ.md
|
@ -73,14 +73,12 @@ To build an `App` there are three:
|
||||||
|
|
||||||
* Derive Macros
|
* Derive Macros
|
||||||
* Builder Pattern
|
* Builder Pattern
|
||||||
* Yaml
|
|
||||||
|
|
||||||
To build an `Arg` there are four:
|
To build an `Arg` there are four:
|
||||||
|
|
||||||
* Derive Macros
|
* Derive Macros
|
||||||
* Builder Pattern
|
* Builder Pattern
|
||||||
* Usage Strings
|
* Usage Strings
|
||||||
* Yaml
|
|
||||||
|
|
||||||
### Why is there a default subcommand of help?
|
### Why is there a default subcommand of help?
|
||||||
|
|
||||||
|
|
70
README.md
70
README.md
|
@ -27,8 +27,7 @@ We are currently hard at work trying to release `3.0`. We have a `3.0.0-beta.5`
|
||||||
4. [Quick Example](#quick-example)
|
4. [Quick Example](#quick-example)
|
||||||
1. [Using Derive Macros](#using-derive-macros)
|
1. [Using Derive Macros](#using-derive-macros)
|
||||||
2. [Using Builder Pattern](#using-builder-pattern)
|
2. [Using Builder Pattern](#using-builder-pattern)
|
||||||
3. [Using YAML](#using-yaml)
|
3. [Running it](#running-it)
|
||||||
4. [Running it](#running-it)
|
|
||||||
5. [Try it!](#try-it)
|
5. [Try it!](#try-it)
|
||||||
1. [Pre-Built Test](#pre-built-test)
|
1. [Pre-Built Test](#pre-built-test)
|
||||||
2. [Build Your Own Binary](#build-your-own-binary)
|
2. [Build Your Own Binary](#build-your-own-binary)
|
||||||
|
@ -92,7 +91,6 @@ Below are a few of the features which `clap` supports, full descriptions and usa
|
||||||
* **Sub-Commands** (i.e. `git add <file>` where `add` is a sub-command of `git`)
|
* **Sub-Commands** (i.e. `git add <file>` where `add` is a sub-command of `git`)
|
||||||
- Support their own sub-arguments, and sub-sub-commands independent of the parent
|
- Support their own sub-arguments, and sub-sub-commands independent of the parent
|
||||||
- Get their own auto-generated Help, Version, and Usage independent of parent
|
- Get their own auto-generated Help, Version, and Usage independent of parent
|
||||||
* **Support for building CLIs from YAML** - This keeps your Rust source nice and tidy and makes supporting localized translation very simple!
|
|
||||||
* **Requirement Rules**: Arguments can define the following types of requirement rules
|
* **Requirement Rules**: Arguments can define the following types of requirement rules
|
||||||
- Can be required by default
|
- Can be required by default
|
||||||
- Can be required only if certain arguments are present
|
- Can be required only if certain arguments are present
|
||||||
|
@ -304,72 +302,6 @@ fn main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Using YAML
|
|
||||||
|
|
||||||
This third method shows how you can use a YAML file to build your CLI and keep your Rust source tidy
|
|
||||||
or support multiple localized translations by having different YAML files for each localization.
|
|
||||||
|
|
||||||
First, create the `cli.yaml` file to hold your CLI options, but it could be called anything we like:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
name: myapp
|
|
||||||
version: "1.0"
|
|
||||||
author: Kevin K. <kbknapp@gmail.com>
|
|
||||||
about: Does awesome things
|
|
||||||
args:
|
|
||||||
- config:
|
|
||||||
short: c
|
|
||||||
long: config
|
|
||||||
value_name: FILE
|
|
||||||
help: Sets a custom config file
|
|
||||||
takes_value: true
|
|
||||||
- INPUT:
|
|
||||||
help: Sets the input file to use
|
|
||||||
required: true
|
|
||||||
index: 1
|
|
||||||
- verbose:
|
|
||||||
short: v
|
|
||||||
multiple_occurrences: true
|
|
||||||
help: Sets the level of verbosity
|
|
||||||
subcommands:
|
|
||||||
- test:
|
|
||||||
about: controls testing features
|
|
||||||
version: "1.3"
|
|
||||||
author: Someone E. <someone_else@other.com>
|
|
||||||
args:
|
|
||||||
- debug:
|
|
||||||
short: d
|
|
||||||
long: debug
|
|
||||||
help: Print debug information
|
|
||||||
```
|
|
||||||
|
|
||||||
Since this feature requires additional dependencies that not everyone may want, it is *not* compiled in by default and we need to enable a feature flag in Cargo.toml:
|
|
||||||
|
|
||||||
Simply add the `yaml` feature flag to your `Cargo.toml`.
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[dependencies]
|
|
||||||
clap = { version = "3.0.0-beta.5", features = ["yaml"] }
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally we create our `main.rs` file just like we would have with the previous two examples:
|
|
||||||
|
|
||||||
```rust,ignore
|
|
||||||
// (Full example with detailed comments in examples/17_yaml.rs)
|
|
||||||
//
|
|
||||||
// This example demonstrates clap's building from YAML style of creating arguments which is far
|
|
||||||
// more clean, but takes a very small performance hit compared to the other two methods.
|
|
||||||
use clap::{App, load_yaml};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// The YAML file is found relative to the current file, similar to how modules are found
|
|
||||||
let yaml = load_yaml!("cli.yaml");
|
|
||||||
let matches = App::from(yaml).get_matches();
|
|
||||||
|
|
||||||
// Same as previous examples...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Running it
|
#### Running it
|
||||||
|
|
||||||
If you were to compile any of the above programs and run them with the flag `--help` or `-h` (or `help` subcommand, since we defined `test` as a subcommand) the following would be output (except the first example where the help message sort of explains the Rust code).
|
If you were to compile any of the above programs and run them with the flag `--help` or `-h` (or `help` subcommand, since we defined `test` as a subcommand) the following would be output (except the first example where the help message sort of explains the Rust code).
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
// In order to use YAML to define your CLI you must compile clap with the "yaml" feature because
|
|
||||||
// it's **not** included by default.
|
|
||||||
//
|
|
||||||
// In order to do this, ensure your Cargo.toml looks like one of the following:
|
|
||||||
//
|
|
||||||
// [dependencies.clap]
|
|
||||||
// features = ["yaml"]
|
|
||||||
//
|
|
||||||
// __OR__
|
|
||||||
//
|
|
||||||
// [dependencies]
|
|
||||||
// clap = { features = ["yaml"] }
|
|
||||||
|
|
||||||
// Using yaml requires calling a clap macro `load_yaml!()`.
|
|
||||||
// Note: If you're using clap as a dependency and don't have a feature for your users called
|
|
||||||
// "yaml", you'll need to remove the #[cfg(feature = "yaml")] conditional compilation attribute
|
|
||||||
#[cfg(feature = "yaml")]
|
|
||||||
fn main() {
|
|
||||||
use clap::{load_yaml, App};
|
|
||||||
|
|
||||||
// To load a yaml file containing our CLI definition such as the example '17_yaml.yaml' we can
|
|
||||||
// use the convenience macro which loads the file at compile relative to the current file
|
|
||||||
// similar to how modules are found.
|
|
||||||
//
|
|
||||||
// Then we pass that yaml object to App to build the CLI.
|
|
||||||
//
|
|
||||||
// Finally we call get_matches() to start the parsing process. We use the matches just as we
|
|
||||||
// normally would
|
|
||||||
let yaml = load_yaml!("17_yaml.yaml");
|
|
||||||
let m = App::from_yaml(yaml).get_matches();
|
|
||||||
|
|
||||||
// Because the example 17_yaml.yaml is rather large we'll just look a single arg so you can
|
|
||||||
// see that it works...
|
|
||||||
if let Some(mode) = m.value_of("mode") {
|
|
||||||
match mode {
|
|
||||||
"vi" => println!("You are using vi"),
|
|
||||||
"emacs" => println!("You are using emacs..."),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("--mode <MODE> wasn't used...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "yaml"))]
|
|
||||||
fn main() {
|
|
||||||
// As stated above, if clap is not compiled with the YAML feature, it is disabled.
|
|
||||||
println!("YAML feature is disabled.");
|
|
||||||
println!("Pass --features yaml to cargo when trying this example.");
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
name: yaml_app
|
|
||||||
version: "1.0"
|
|
||||||
about: an example using a .yaml file to build a CLI
|
|
||||||
author: Kevin K. <kbknapp@gmail.com>
|
|
||||||
|
|
||||||
# AppSettings can be defined as a list and are **not** ascii case sensitive
|
|
||||||
settings:
|
|
||||||
- ArgRequiredElseHelp
|
|
||||||
|
|
||||||
# All Args must be defined in the 'args:' list where the name of the arg, is the
|
|
||||||
# key to a Hash object
|
|
||||||
args:
|
|
||||||
# The name of this argument, is 'opt' which will be used to access the value
|
|
||||||
# later in your Rust code
|
|
||||||
- opt:
|
|
||||||
help: example option argument from yaml
|
|
||||||
short: o
|
|
||||||
long: option
|
|
||||||
multiple_occurrences: true
|
|
||||||
takes_value: true
|
|
||||||
- pos:
|
|
||||||
help: example positional argument from yaml
|
|
||||||
index: 1
|
|
||||||
# A list of possible values can be defined as a list
|
|
||||||
possible_values:
|
|
||||||
- fast
|
|
||||||
- slow
|
|
||||||
- flag:
|
|
||||||
help: demo flag argument
|
|
||||||
short: F
|
|
||||||
multiple_occurrences: true
|
|
||||||
takes_value: true
|
|
||||||
global: true
|
|
||||||
# Conflicts, mutual overrides, and requirements can all be defined as a
|
|
||||||
# list, where the key is the name of the other argument
|
|
||||||
conflicts_with:
|
|
||||||
- opt
|
|
||||||
requires:
|
|
||||||
- pos
|
|
||||||
- mode:
|
|
||||||
long: mode
|
|
||||||
help: shows an option with specific values
|
|
||||||
# possible_values can also be defined in this list format
|
|
||||||
possible_values: [ vi, emacs ]
|
|
||||||
takes_value: true
|
|
||||||
- mvals:
|
|
||||||
long: mult-vals
|
|
||||||
help: demos an option which has two named values
|
|
||||||
# value names can be described in a list, where the help will be shown
|
|
||||||
# --mult-vals <one> <two>
|
|
||||||
value_names:
|
|
||||||
- one
|
|
||||||
- two
|
|
||||||
- minvals:
|
|
||||||
long: min-vals
|
|
||||||
multiple_values: true
|
|
||||||
help: you must supply at least two values to satisfy me
|
|
||||||
min_values: 2
|
|
||||||
- maxvals:
|
|
||||||
long: max-vals
|
|
||||||
multiple_values: true
|
|
||||||
help: you can only supply a max of 3 values for me!
|
|
||||||
max_values: 3
|
|
||||||
|
|
||||||
# All subcommands must be listed in the 'subcommand:' object, where the key to
|
|
||||||
# the list is the name of the subcommand, and all settings for that command are
|
|
||||||
# are part of a Hash object
|
|
||||||
subcommands:
|
|
||||||
# The name of this subcommand will be 'subcmd' which can be accessed in your
|
|
||||||
# Rust code later
|
|
||||||
- subcmd:
|
|
||||||
about: demos subcommands from yaml
|
|
||||||
version: "0.1"
|
|
||||||
author: Kevin K. <kbknapp@gmail.com>
|
|
||||||
# Subcommand args are exactly like App args
|
|
||||||
args:
|
|
||||||
- scopt:
|
|
||||||
short: B
|
|
||||||
multiple_occurrences: true
|
|
||||||
help: example subcommand option
|
|
||||||
takes_value: true
|
|
||||||
- scpos1:
|
|
||||||
help: example subcommand positional
|
|
||||||
index: 1
|
|
||||||
|
|
||||||
# ArgGroups are supported as well, and must be specified in the 'groups:'
|
|
||||||
# object of this file
|
|
||||||
groups:
|
|
||||||
# the name of the ArgGoup is specified here
|
|
||||||
- min-max-vals:
|
|
||||||
# All args and groups that are a part of this group are set here
|
|
||||||
args:
|
|
||||||
- minvals
|
|
||||||
- maxvals
|
|
||||||
# setting conflicts is done the same manner as setting 'args:'
|
|
||||||
#
|
|
||||||
# to make this group required, you could set 'required: true' but for
|
|
||||||
# this example we won't do that.
|
|
|
@ -398,9 +398,14 @@ impl<'help> App<'help> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Deprecated in Issue #9, maybe clap::Parser would fit your use case?
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
|
#[deprecated(
|
||||||
|
since = "3.0.0",
|
||||||
|
note = "Deprecated in Issue #9, maybe clap::Parser would fit your use case?"
|
||||||
|
)]
|
||||||
pub fn from_yaml(y: &'help Yaml) -> Self {
|
pub fn from_yaml(y: &'help Yaml) -> Self {
|
||||||
|
#![allow(deprecated)]
|
||||||
let yaml_file_hash = y.as_hash().expect("YAML file must be a hash");
|
let yaml_file_hash = y.as_hash().expect("YAML file must be a hash");
|
||||||
// We WANT this to panic on error...so expect() is good.
|
// We WANT this to panic on error...so expect() is good.
|
||||||
let (mut a, yaml, err) = if let Some(name) = y["name"].as_str() {
|
let (mut a, yaml, err) = if let Some(name) = y["name"].as_str() {
|
||||||
|
|
|
@ -349,16 +349,12 @@ impl<'help> Arg<'help> {
|
||||||
Self::new(n)
|
Self::new(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new instance of [`Arg`] from a .yaml (YAML) file.
|
/// Deprecated in Issue #9, maybe clap::Parser would fit your use case?
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// use clap::{Arg, load_yaml};
|
|
||||||
/// let yaml = load_yaml!("arg.yaml");
|
|
||||||
/// let arg = Arg::from(yaml);
|
|
||||||
/// ```
|
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
|
#[deprecated(
|
||||||
|
since = "3.0.0",
|
||||||
|
note = "Deprecated in Issue #9, maybe clap::Parser would fit your use case?"
|
||||||
|
)]
|
||||||
pub fn from_yaml(y: &'help Yaml) -> Self {
|
pub fn from_yaml(y: &'help Yaml) -> Self {
|
||||||
let yaml_file_hash = y.as_hash().expect("YAML file must be a hash");
|
let yaml_file_hash = y.as_hash().expect("YAML file must be a hash");
|
||||||
// We WANT this to panic on error...so expect() is good.
|
// We WANT this to panic on error...so expect() is good.
|
||||||
|
|
|
@ -114,9 +114,12 @@ impl<'help> ArgGroup<'help> {
|
||||||
Self::new(n)
|
Self::new(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated, see [`ArgGroup::from`]
|
/// Deprecated in Issue #9, maybe clap::Parser would fit your use case?
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
#[deprecated(since = "3.0.0", note = "Replaced with `ArgGroup::from`")]
|
#[deprecated(
|
||||||
|
since = "3.0.0",
|
||||||
|
note = "Deprecated in Issue #9, maybe clap::Parser would fit your use case?"
|
||||||
|
)]
|
||||||
pub fn from_yaml(yaml: &'help Yaml) -> Self {
|
pub fn from_yaml(yaml: &'help Yaml) -> Self {
|
||||||
Self::from(yaml)
|
Self::from(yaml)
|
||||||
}
|
}
|
||||||
|
@ -436,9 +439,10 @@ impl<'help> From<&'_ ArgGroup<'help>> for ArgGroup<'help> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deprecated in Issue #9, maybe clap::Parser would fit your use case?
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
impl<'help> From<&'help Yaml> for ArgGroup<'help> {
|
impl<'help> From<&'help Yaml> for ArgGroup<'help> {
|
||||||
/// TODO
|
/// Deprecated in Issue #9, maybe clap::Parser would fit your use case?
|
||||||
fn from(y: &'help Yaml) -> Self {
|
fn from(y: &'help Yaml) -> Self {
|
||||||
let b = y.as_hash().expect("ArgGroup::from::<Yaml> expects a table");
|
let b = y.as_hash().expect("ArgGroup::from::<Yaml> expects a table");
|
||||||
// We WANT this to panic on error...so expect() is good.
|
// We WANT this to panic on error...so expect() is good.
|
||||||
|
|
|
@ -77,9 +77,14 @@ impl SubCommand {
|
||||||
App::new(name)
|
App::new(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Deprecated in Issue #9, maybe clap::Parser would fit your use case?
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
|
#[deprecated(
|
||||||
|
since = "3.0.0",
|
||||||
|
note = "Deprecated in Issue #9, maybe clap::Parser would fit your use case?"
|
||||||
|
)]
|
||||||
pub fn from_yaml(yaml: &yaml_rust::Yaml) -> App {
|
pub fn from_yaml(yaml: &yaml_rust::Yaml) -> App {
|
||||||
|
#![allow(deprecated)]
|
||||||
App::from_yaml(yaml)
|
App::from_yaml(yaml)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,7 @@ use std::fs;
|
||||||
use std::process::{Command, Output};
|
use std::process::{Command, Output};
|
||||||
|
|
||||||
fn run_example<S: AsRef<str>>(name: S, args: &[&str]) -> Output {
|
fn run_example<S: AsRef<str>>(name: S, args: &[&str]) -> Output {
|
||||||
let mut all_args = vec![
|
let mut all_args = vec!["run", "--example", name.as_ref(), "--"];
|
||||||
"run",
|
|
||||||
"--example",
|
|
||||||
name.as_ref(),
|
|
||||||
"--features",
|
|
||||||
"yaml",
|
|
||||||
"--",
|
|
||||||
];
|
|
||||||
all_args.extend_from_slice(args);
|
all_args.extend_from_slice(args);
|
||||||
|
|
||||||
Command::new(env!("CARGO"))
|
Command::new(env!("CARGO"))
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![cfg(feature = "yaml")]
|
#![cfg(feature = "yaml")]
|
||||||
|
#![allow(deprecated)]
|
||||||
|
|
||||||
use clap::{load_yaml, App, Arg, ErrorKind, ValueHint};
|
use clap::{load_yaml, App, Arg, ErrorKind, ValueHint};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue