Initial commit v0.0.3

This commit is contained in:
Kevin K 2015-02-25 08:37:25 -05:00
parent 959b5e9437
commit 2d546238a2
11 changed files with 407 additions and 0 deletions

4
Cargo.lock generated Normal file
View file

@ -0,0 +1,4 @@
[root]
name = "clap"
version = "0.0.1"

5
Cargo.toml Normal file
View file

@ -0,0 +1,5 @@
[package]
name = "clap"
version = "0.0.3"
authors = ["Kevin K. <kbknapp@gmail.com>"]

226
src/app.rs Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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.");
}