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
|
||||
* Builder Pattern
|
||||
* Yaml
|
||||
|
||||
To build an `Arg` there are four:
|
||||
|
||||
* Derive Macros
|
||||
* Builder Pattern
|
||||
* Usage Strings
|
||||
* Yaml
|
||||
|
||||
### 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)
|
||||
1. [Using Derive Macros](#using-derive-macros)
|
||||
2. [Using Builder Pattern](#using-builder-pattern)
|
||||
3. [Using YAML](#using-yaml)
|
||||
4. [Running it](#running-it)
|
||||
3. [Running it](#running-it)
|
||||
5. [Try it!](#try-it)
|
||||
1. [Pre-Built Test](#pre-built-test)
|
||||
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`)
|
||||
- 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
|
||||
* **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
|
||||
- Can be required by default
|
||||
- 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
|
||||
|
||||
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")]
|
||||
#[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 {
|
||||
#![allow(deprecated)]
|
||||
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.
|
||||
let (mut a, yaml, err) = if let Some(name) = y["name"].as_str() {
|
||||
|
|
|
@ -349,16 +349,12 @@ impl<'help> Arg<'help> {
|
|||
Self::new(n)
|
||||
}
|
||||
|
||||
/// Creates a new instance of [`Arg`] from a .yaml (YAML) file.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use clap::{Arg, load_yaml};
|
||||
/// let yaml = load_yaml!("arg.yaml");
|
||||
/// let arg = Arg::from(yaml);
|
||||
/// ```
|
||||
/// Deprecated in Issue #9, maybe clap::Parser would fit your use case?
|
||||
#[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 {
|
||||
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.
|
||||
|
|
|
@ -114,9 +114,12 @@ impl<'help> ArgGroup<'help> {
|
|||
Self::new(n)
|
||||
}
|
||||
|
||||
/// Deprecated, see [`ArgGroup::from`]
|
||||
/// Deprecated in Issue #9, maybe clap::Parser would fit your use case?
|
||||
#[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 {
|
||||
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")]
|
||||
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 {
|
||||
let b = y.as_hash().expect("ArgGroup::from::<Yaml> expects a table");
|
||||
// We WANT this to panic on error...so expect() is good.
|
||||
|
|
|
@ -77,9 +77,14 @@ impl SubCommand {
|
|||
App::new(name)
|
||||
}
|
||||
|
||||
/// TODO
|
||||
/// Deprecated in Issue #9, maybe clap::Parser would fit your use case?
|
||||
#[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 {
|
||||
#![allow(deprecated)]
|
||||
App::from_yaml(yaml)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,7 @@ use std::fs;
|
|||
use std::process::{Command, Output};
|
||||
|
||||
fn run_example<S: AsRef<str>>(name: S, args: &[&str]) -> Output {
|
||||
let mut all_args = vec![
|
||||
"run",
|
||||
"--example",
|
||||
name.as_ref(),
|
||||
"--features",
|
||||
"yaml",
|
||||
"--",
|
||||
];
|
||||
let mut all_args = vec!["run", "--example", name.as_ref(), "--"];
|
||||
all_args.extend_from_slice(args);
|
||||
|
||||
Command::new(env!("CARGO"))
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#![cfg(feature = "yaml")]
|
||||
#![allow(deprecated)]
|
||||
|
||||
use clap::{load_yaml, App, Arg, ErrorKind, ValueHint};
|
||||
|
||||
|
|
Loading…
Reference in a new issue