mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
Initial commit v0.0.3
This commit is contained in:
parent
959b5e9437
commit
2d546238a2
11 changed files with 407 additions and 0 deletions
4
Cargo.lock
generated
Normal file
4
Cargo.lock
generated
Normal file
|
@ -0,0 +1,4 @@
|
|||
[root]
|
||||
name = "clap"
|
||||
version = "0.0.1"
|
||||
|
5
Cargo.toml
Normal file
5
Cargo.toml
Normal file
|
@ -0,0 +1,5 @@
|
|||
[package]
|
||||
|
||||
name = "clap"
|
||||
version = "0.0.3"
|
||||
authors = ["Kevin K. <kbknapp@gmail.com>"]
|
226
src/app.rs
Normal file
226
src/app.rs
Normal file
|
@ -0,0 +1,226 @@
|
|||
use std::env;
|
||||
|
||||
use ArgMatches;
|
||||
use Arg;
|
||||
use args::OptArg;
|
||||
use args::FlagArg;
|
||||
use args::PosArg;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct App {
|
||||
name: &'static str,
|
||||
author: Option<&'static str>,
|
||||
version: Option<&'static str>,
|
||||
about: Option<&'static str>,
|
||||
raw_args: Vec<Arg>,
|
||||
flags: Vec<FlagArg>,
|
||||
opts: Vec<OptArg>,
|
||||
positionals: Vec<PosArg>
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(n: &'static str) -> App {
|
||||
App {
|
||||
name: n,
|
||||
author: None,
|
||||
about: None,
|
||||
version: None,
|
||||
raw_args: vec![],
|
||||
flags: vec![],
|
||||
opts: vec![],
|
||||
positionals: vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn author(&mut self, a: &'static str) -> &mut App {
|
||||
self.author = Some(a);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn about(&mut self, a: &'static str) -> &mut App {
|
||||
self.about = Some(a);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn version(&mut self, v: &'static str)-> &mut App {
|
||||
self.version = Some(v);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, a: &Arg) -> &mut App {
|
||||
if let Some(i) = a.index {
|
||||
self.positionals.push(PosArg {
|
||||
name: a.name,
|
||||
index: i,
|
||||
required: a.required,
|
||||
help: a.help,
|
||||
value: None
|
||||
|
||||
});
|
||||
} else if a.takes_value {
|
||||
self.opts.push(OptArg {
|
||||
name: a.name,
|
||||
short: a.short,
|
||||
long: a.long,
|
||||
help: a.help,
|
||||
required: a.required,
|
||||
value: None
|
||||
});
|
||||
} else {
|
||||
self.flags.push(FlagArg{
|
||||
name: a.name,
|
||||
short: a.short,
|
||||
long: a.long,
|
||||
help: a.help,
|
||||
});
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn get_matches(&mut self) -> ArgMatches {
|
||||
|
||||
let mut matches = ArgMatches {
|
||||
flags: vec![],
|
||||
opts: vec![],
|
||||
positionals: vec![],
|
||||
required: vec![],
|
||||
blacklist: vec![],
|
||||
about: self.about,
|
||||
name: self.name,
|
||||
author: self.author,
|
||||
version: self.version
|
||||
};
|
||||
|
||||
let mut needs_val = false;
|
||||
let mut needs_val_of = String::new();
|
||||
let mut pos_counter = 1;
|
||||
for a in env::args().collect::<Vec<String>>().tail() {
|
||||
let arg_slice = a.as_slice();
|
||||
if needs_val {
|
||||
for o in self.opts.iter() {
|
||||
if needs_val_of == o.name.to_string() {
|
||||
matches.opts.push(OptArg{
|
||||
name: o.name,
|
||||
short: o.short,
|
||||
long: o.long,
|
||||
help: o.help,
|
||||
required: o.required,
|
||||
value: Some(a.clone())
|
||||
});
|
||||
needs_val = false;
|
||||
needs_val_of.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if arg_slice.starts_with("--") {
|
||||
// Single flag, or option
|
||||
let mut p_arg = arg_slice.trim_left_matches(|c| c == '-');
|
||||
let mut found = false;
|
||||
for f in self.flags.iter() {
|
||||
if let Some(l) = f.long {
|
||||
if l == p_arg.as_slice() {
|
||||
matches.flags.push(f.clone());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if found { continue; }
|
||||
if p_arg.as_slice().contains("=") {
|
||||
let p_argv: Vec<&str> = p_arg.split_str("=").collect();
|
||||
p_arg = p_argv[0];
|
||||
for o in self.opts.iter() {
|
||||
if let Some(l) = o.long {
|
||||
if l == p_arg.as_slice() {
|
||||
found = true;
|
||||
matches.opts.push(OptArg{
|
||||
name: o.name,
|
||||
short: o.short,
|
||||
long: o.long,
|
||||
help: o.help,
|
||||
required: o.required,
|
||||
value: Some(p_argv[1].to_string().clone())
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for o in self.opts.iter() {
|
||||
if let Some(l) = o.long {
|
||||
if l == p_arg.as_slice() {
|
||||
found = true;
|
||||
needs_val = true;
|
||||
needs_val_of = o.name.to_string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ! found { panic!("Arg {} not valid", a); }
|
||||
continue;
|
||||
}
|
||||
} else if arg_slice.starts_with("-") {
|
||||
if arg_slice.len() > 2 {
|
||||
// Multiple flags using short i.e. -bgHlS
|
||||
let p_arg = arg_slice.trim_left_matches(|c| c == '-');
|
||||
let mut found = false;
|
||||
for c in p_arg.chars() {
|
||||
for f in self.flags.iter() {
|
||||
if let Some(s) = f.short {
|
||||
if c == s.char_at(0) {
|
||||
found = true;
|
||||
matches.flags.push(f.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ! found { panic!("Argument {} isn't valid.", arg_slice); }
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Short flag or opt
|
||||
let mut found = false;
|
||||
let p_arg = arg_slice.char_at(1);
|
||||
for f in self.flags.iter() {
|
||||
if let Some(s) = f.short {
|
||||
if p_arg == s.char_at(0) {
|
||||
found = true;
|
||||
matches.flags.push(f.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
for o in self.opts.iter() {
|
||||
if let Some(s) = o.short {
|
||||
if s.char_at(0) == p_arg {
|
||||
found = true;
|
||||
needs_val = true;
|
||||
needs_val_of = o.name.to_string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ! found { panic!("Argument {} isn't valid.", arg_slice); }
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Positional
|
||||
if self.positionals.is_empty() { panic!("Positional argument {} found but APP doesn't accept any", a); }
|
||||
for p in self.positionals.iter() {
|
||||
matches.positionals.push(PosArg{
|
||||
name: p.name,
|
||||
help: p.help,
|
||||
required: p.required,
|
||||
value: Some(a.clone()),
|
||||
index: pos_counter
|
||||
});
|
||||
pos_counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if needs_val { panic!("Value not provided for argument {}", needs_val_of); }
|
||||
|
||||
matches
|
||||
}
|
||||
}
|
57
src/arg.rs
Normal file
57
src/arg.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
#[derive(Clone)]
|
||||
pub struct Arg {
|
||||
pub name: &'static str,
|
||||
pub short: Option<&'static str>,
|
||||
pub long: Option<&'static str>,
|
||||
pub help: Option<&'static str>,
|
||||
pub required: bool,
|
||||
pub takes_value: bool,
|
||||
pub index: Option<i32>
|
||||
// allow_multiple: bool
|
||||
// exclusive_with
|
||||
// requires
|
||||
}
|
||||
|
||||
impl Arg {
|
||||
pub fn new(n: &'static str) -> Arg {
|
||||
Arg {
|
||||
name: n,
|
||||
short: None,
|
||||
long: None,
|
||||
help: None,
|
||||
required: false,
|
||||
takes_value: false,
|
||||
index: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn short(&mut self, s: &'static str) -> &mut Arg {
|
||||
self.short = Some(s);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn long(&mut self, l: &'static str) -> &mut Arg {
|
||||
self.long = Some(l);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn help(&mut self, h: &'static str) -> &mut Arg {
|
||||
self.help = Some(h);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn required(&mut self, r: bool) -> &mut Arg {
|
||||
self.required = r;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn takes_value(&mut self, tv: bool) -> &mut Arg {
|
||||
self.takes_value = tv;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn index(&mut self, i: i32) -> &mut Arg {
|
||||
self.index = Some(i);
|
||||
self
|
||||
}
|
||||
}
|
32
src/argmatches.rs
Normal file
32
src/argmatches.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use args::{ FlagArg, OptArg, PosArg };
|
||||
|
||||
pub struct ArgMatches {
|
||||
pub flags: Vec<FlagArg>,
|
||||
pub opts: Vec<OptArg>,
|
||||
pub positionals: Vec<PosArg>,
|
||||
pub required: Vec<&'static str>,
|
||||
pub blacklist: Vec<&'static str>,
|
||||
pub about: Option<&'static str>,
|
||||
pub name: &'static str,
|
||||
pub author: Option<&'static str>,
|
||||
pub version: Option<&'static str>
|
||||
}
|
||||
|
||||
impl ArgMatches {
|
||||
pub fn value_of(&self, name: &'static str) -> Option<String> {
|
||||
for o in self.opts.iter() {
|
||||
if o.name == name { return o.value.clone(); }
|
||||
}
|
||||
for p in self.opts.iter() {
|
||||
if p.name == name { return p.value.clone(); }
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn is_present(&self, name: &'static str) -> bool {
|
||||
for f in self.flags.iter() {
|
||||
if f.name == name { return true; }
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
8
src/args/flagarg.rs
Normal file
8
src/args/flagarg.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct FlagArg {
|
||||
pub name: &'static str,
|
||||
pub short: Option<&'static str>,
|
||||
pub long: Option<&'static str>,
|
||||
pub help: Option<&'static str>,
|
||||
}
|
7
src/args/mod.rs
Normal file
7
src/args/mod.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
pub use self::optarg::OptArg;
|
||||
pub use self::flagarg::FlagArg;
|
||||
pub use self::posarg::PosArg;
|
||||
|
||||
mod optarg;
|
||||
mod flagarg;
|
||||
mod posarg;
|
9
src/args/optarg.rs
Normal file
9
src/args/optarg.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
#[derive(Clone)]
|
||||
pub struct OptArg {
|
||||
pub name: &'static str,
|
||||
pub short: Option<&'static str>,
|
||||
pub long: Option<&'static str>,
|
||||
pub help: Option<&'static str>,
|
||||
pub required: bool,
|
||||
pub value: Option<String>
|
||||
}
|
9
src/args/posarg.rs
Normal file
9
src/args/posarg.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct PosArg {
|
||||
pub name: &'static str,
|
||||
pub help: Option<&'static str>,
|
||||
pub required: bool,
|
||||
pub value: Option<String>,
|
||||
pub index: i32
|
||||
}
|
12
src/lib.rs
Normal file
12
src/lib.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
pub use argmatches::ArgMatches;
|
||||
pub use arg::Arg;
|
||||
pub use app::App;
|
||||
|
||||
mod app;
|
||||
mod argmatches;
|
||||
mod arg;
|
||||
mod args;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
}
|
38
src/main.rs
Normal file
38
src/main.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
extern crate clap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
|
||||
fn main() {
|
||||
let matches = App::new("MyApp")
|
||||
.version("1.0")
|
||||
.author("Jostmon <jostmon2@gmail.com>")
|
||||
.about("Does awesome things")
|
||||
.arg(Arg::new("config")
|
||||
.short("c")
|
||||
.long("config")
|
||||
.required(true)
|
||||
.help("Sets a custom config file")
|
||||
.takes_value(true))
|
||||
.arg(Arg::new("output")
|
||||
.short("o")
|
||||
.long("output")
|
||||
.help("Sets an optional output file")
|
||||
.takes_value(true))
|
||||
.arg(Arg::new("debug")
|
||||
.short("d")
|
||||
.help("Turn debugging information on"))
|
||||
.get_matches();
|
||||
|
||||
if let Some(o) = matches.value_of("output") {
|
||||
println!("Value for output: {}", o);
|
||||
}
|
||||
|
||||
println!("Config file: {}", matches.value_of("config").unwrap());
|
||||
|
||||
if matches.is_present("debug") {
|
||||
println!("Debug mode on");
|
||||
}
|
||||
|
||||
println!("App is running...");
|
||||
println!("Done.");
|
||||
}
|
Loading…
Reference in a new issue