Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V3 master #510

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

name = "clap"
version = "2.5.1"
version = "3.0.0"
authors = ["Kevin K. <[email protected]>"]
exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"]
description = "A simple to use, efficient, and full featured Command Line Argument Parser"
Expand Down
10 changes: 5 additions & 5 deletions examples/13a_enum_values_automatic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// trait which is very straight forward. There are three ways to do this, for simple enums
// meaning those that don't require 'pub' or any '#[derive()]' directives you can use clas's
// simple_enum! macro. For those that require 'pub' or any '#[derive()]'s you can use clap's
// arg_enum! macro. The third way is to implement std::str::FromStr manually.
// arg_values! macro. The third way is to implement std::str::FromStr manually.
//
// In most circumstances using either simple_enum! or arg_enum! is fine.
// In most circumstances using either simple_enum! or arg_values! is fine.
//
// In the following example we will create two enums using macros, assign a positional argument
// that accepts only one of those values, and use clap to parse the argument.
Expand All @@ -15,10 +15,10 @@ extern crate clap;

use clap::{App, Arg};

// Using arg_enum! is more like traditional enum declarations
// Using arg_values! is more like traditional enum declarations
//
// **NOTE:** Only bare variants are supported
arg_enum!{
arg_values!{
#[derive(Debug)]
pub enum Oof {
Rab,
Expand All @@ -27,7 +27,7 @@ arg_enum!{
}
}

arg_enum!{
arg_values!{
#[derive(Debug)]
enum Foo {
Bar,
Expand Down
14 changes: 11 additions & 3 deletions examples/16_app_settings.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
#[macro_use]
extern crate clap;

use clap::{App, AppSettings, SubCommand};

subcommands!{
enum MyApp {
Test => "test"
}
}

fn main() {
use MyApp::*;
// You can use AppSettings to change the application level behavior of clap. .setting() function
// of App struct takes AppSettings enum as argument. There is also .settings() function which
// takes slice of AppSettings enum. You can learn more about AppSettings in the documentation,
Expand All @@ -19,7 +27,7 @@ fn main() {
// Required positional argument called input. This
// will be only required if subcommand is not present.

.subcommand(SubCommand::with_name("test")
.subcommand(SubCommand::with_name(Test)
.about("does some testing"))
// if program is invoked with subcommand, you do not
// need to specify the <input> argument anymore due to
Expand All @@ -35,7 +43,7 @@ fn main() {
}

match matches.subcommand() {
("test", _) => println!("The 'test' subcommand was used"),
_ => unreachable!()
Some((Test, _)) => println!("The 'test' subcommand was used"),
None => println!("No subcommand was used"),
}
}
54 changes: 54 additions & 0 deletions examples/21a_enums_for_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// There are multiple ways in which to use enums as the "Keys" to access args. This has the benefit
// of not being "stringly-typed" and is *far* less error prone. It also allows one to take full
// advantage of auto-completion with tools like Racer (https://github.com/phildawes/racer). It also
// lets rustc do the error checking for you when you decide to change arugment names and such.

// This first method we'll look at is the most simple version, where enum variants are used
// literally as the arg keys. For args like positional arguments, this means one must either make
// the variants how they'd like them to be displayed in help messages and such. This can be at odds
// with Rust best practices for style guides, so in other examples we'll look at other ways use
// enums with Args.

// On to the code...

// First we import the clap macros
#[macro_use]
extern crate clap;
use clap::{App, Arg};

// Next we declare the "keys" we'll use to access the arguments
//
// NOTE: The enums support use of `pub` or `#[meta]` style attributes (like derive(), or cfg()
// attributes), or any combinations of those two elements
args!{
enum MyProg {
Verbose,
Config
}
}

fn main() {
// We declare the App struct like normal. We could also use a use statement such as
// `use MyProg::*;` to save a few key-strokes, but for this simple example we'll leave
// that out.
let m = App::new("myprog")
.arg(Arg::with_name(MyProg::Verbose)
.short("v")
.help("print verbose output"))
.arg(Arg::with_name(MyProg::Config)
.long("config")
.value_name("FILE")
.help("use a custom config file"))
.get_matches();

// Now to access the args we use the enum variants
if m.is_present(MyProg::Verbose) {
println!("Printing verbosely...");
}

//println!("Verbose used {} times", m.occurrences_of(MyProg::Verbos)) // ERROR typo! (Mising E)

if let Some(file) = m.value_of(MyProg::Config) {
println!("Using config file: {}", file);
}
}
32 changes: 32 additions & 0 deletions examples/21b_enums_for_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This next method we'll look at an instance where we'll want the arg to be displayed differently
// from the enum variant itself

// We import the clap macros
#[macro_use]
extern crate clap;
use clap::{App, Arg};

// Next we declare the "keys" we'll use to access the arguments associated a display version
// The downside to using this form is that it's all or othing, either all args use a "display"
// version or are used literally. The next example shows one way we can get around this...
args!{
enum MyProg {
Config => "FILE"
}
}

fn main() {
use MyProg::*;
let m = App::new("myprog")
.arg(Arg::with_name(Config)
.takes_value(true)
.required(true)
.help("The custom config file to use"))
.get_matches();

// Run this program with --help to see that `Config` appears as "FILE"

if let Some(file) = m.value_of(Config) {
println!("Using config file: {}", file);
}
}
44 changes: 44 additions & 0 deletions examples/21c_enums_for_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// In this method we go back to the original, but find a way to get the desired affect without
// having to give a "display" version for all args

// We import the clap macros
#[macro_use]
extern crate clap;
use clap::{App, Arg, SubCommand};

// Everything starts out normal, we declare the enums just like before.
//
// Notice we can also put multiple enums into a single `args!` macro. This is useful if we're using
// subcommands.
args!{
enum MyProgArgs {
Config
}
enum TestArgs {
Verbose,
SomeFlag
}
}

fn main() {
use MyProgArgs::*;
use TestArgs::*;

let m = App::new("myprog")
.arg(Arg::with_name(Config)
.usage("<FILE> 'The custom config file to use'")) // Here we use a usage method which
// allows setting all the normal
// usage style settings (Same as
// Arg::from_usage), but with the
// added benefit of "renaming" the
// display version of this arg. In
// this example, "FILE"
.subcommand(SubCommand::with_name("test")
.arg(Arg::with_name(Verbose)
.usage("-v, --verbose 'print verbose output'")))
.arg(Arg::with_name(SomeFlag)
.usage("--some-flag 'some imaginary flag'")))
.get_matches();

// more logic here...
}
64 changes: 64 additions & 0 deletions examples/22a_enums_for_subcommands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// There are multiple ways in which to use enums as the "Keys" to access subcommands. This has the
// benefit of not being "stringly-typed" and is *far* less error prone. It also allows one to take
// full advantage of auto-completion with tools like Racer (https://github.com/phildawes/racer). It
// also lets rustc do the error checking for you when you decide to change arugment names and such.
// Finally, but certainly not least, it allows rustc to check against all possible variants when
// pattern matching, and complain about NonExaustive matches when one adds a new subcommand but
// forgets to check for it!
//
// This first method we'll look at is the most simple version, where enum variants are used
// literally as the subcommand keys and displayed to the user as such. This can be at odds
// with Rust best practices for style guides, so in other examples we'll look at other ways use
// enums with subcommands.
//
// Pro Tip: It's a good idea to name your enum after the parent command that the subcommands belong
// to. This avoids massive collisions and typos, and allows pattern matching against variants.

// On to the code...

// First we import the clap macros
#[macro_use]
extern crate clap;
use clap::{App, SubCommand};

// Next we declare the "keys"/"subcommands" we'll use to access the arguments. Notice, we use
// lowercase, non-camell-case variants so that users don't have to type "Clone" to access this
// subcommand. We'll need to use the allow(non_camel_case_types) to silence the warning. In another
// example we'll see how to get arounds this, and keep the compiler happy.
//
// NOTE: The enums support use of `pub` or `#[meta]` style attributes (like derive(), allow(), or
// cfg() attributes), or any combinations of those two elements
//
// NOTE 2: Just like the args! macro, one can declare multiple enums inside the same args! block
subcommands!{
#[allow(non_camel_case_types)]
enum Git {
clone,
push,
pull
}
}

fn main() {
// We declare the App struct like normal. We could also use a use statement such as
// `use MyProg::*;` to save a few key-strokes, but for this simple example we'll leave
// that out.
let m = App::new("git")
.subcommand(SubCommand::with_name(Git::clone))
.subcommand(SubCommand::with_name(Git::push))
.subcommand(SubCommand::with_name(Git::pull))
.get_matches();

// Now to access the subcommands we can pattern match against the variants
//
// Note, the tuple is (Variant, ArgMatches), but we're not using the ArgMatches here, so we
// just throw them away with _
match m.subcommand() {
Some((Git::clone, _)) => println!("Clone was used"),
Some((Git::push, _)) => println!("Push was used"),
Some((Git::pull, _)) => println!("Pull was used"), // <-- commment out this line to see the
// compiler complain about NonExaustive
// matches. Yay for no more strings! :)
None => println!("No subcommand was used... :("),
}
}
42 changes: 42 additions & 0 deletions examples/22b_enums_for_subcommands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Next we'll look at how we can have sane subcommands, or ones with hyphens, and still make the
// compiler happy about camel_case_types

// First we import the clap macros
#[macro_use]
extern crate clap;
use clap::{App, SubCommand};

// Now we declare the variants, and their associated display/usage version
subcommands!{
enum Git {
Clone => "clone",
Push = "push",
Pull => "pull",
DoStuff => "do-stuff"
}
}

fn main() {
use Git::*;

let m = App::new("git")
.subcommand(SubCommand::with_name(Clone))
.subcommand(SubCommand::with_name(Push))
.subcommand(SubCommand::with_name(Pull))
.subcommand(SubCommand::with_name(DoStuff))
.get_matches();

// Now to access the subcommands we can pattern match against the variants
//
// Note, the tuple is (Variant, ArgMatches), but we're not using the ArgMatches here, so we
// just throw them away with _
match m.subcommand() {
Some((Clone, _)) => println!("clone was used"),
Some((Push, _)) => println!("push was used"),
Some((Pull, _)) => println!("pull was used"), // <-- commment out this line to see the
// compiler complain about NonExaustive
// matches. Yay for no more strings! :)
Some((DoStuff, _)) => println!("do-stuff was used"),
None => println!("No subcommand was used... :("),
}
}
45 changes: 45 additions & 0 deletions examples/22c_enums_for_subcommands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Now we'll see how we can support external subcommands. These should be used with caution, as
// they silence certain circumstances that would otherwise be and error. These conditions must be
// checked manually. The specific cases are when someone uses a "potential" external subcommand,
// i.e. something that wasn't defined at compile time, but it turns out no external subcommand for
// that exists. One must then check for, and inform the user of the error manually.

// First we import the clap macros
#[macro_use]
extern crate clap;
use clap::{App, SubCommand};

// The only thing we need to do differently from the previous two examples is make the **FIRST**
// variant "External", and clap will generate all the necessary code.
//
// Note: All the previous version are still supported, such as pub/#[meta] items, and the basic or
// this alternate version
subcommands!{
enum Git {
External,
Clone => "clone",
Push => "push",
Pull => "pull"
}
}

fn main() {
use Git::*;

let m = App::new("git")
.subcommand(SubCommand::with_name(Clone))
.subcommand(SubCommand::with_name(Push))
.subcommand(SubCommand::with_name(Pull))
.get_matches();

// Now to access the subcommands we can pattern match against the variants like normal. the
// difference is now clap has generated an `External(Vec<OsString>)` variant that contains the
// args along with the subcommand that was used.
match m.subcommand() {
Some((Clone, _)) => println!("Clone was used"),
Some((Push, _)) => println!("Push was used"),
Some((Pull, _)) => println!("Pull was used"),
Some((External(ref args), _)) => println!("An external subcommand was used: {:?}", args),
None => println!("No subcommand was used... :("),
}
}
Loading