Skip to content

Commit

Permalink
v0.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ksk001100 committed Feb 15, 2020
1 parent 98e6a53 commit 555c557
Show file tree
Hide file tree
Showing 12 changed files with 446 additions and 39 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "seahorse"
version = "0.3.1"
version = "0.4.0"
authors = ["ksk001100 <[email protected]>"]
edition = "2018"
keywords = ["cli"]
Expand Down
73 changes: 64 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,60 @@ A minimal CLI framework written in Rust

```toml
[dependencies]
seahorse = "0.3.1"
seahorse = "0.4.0"
```

## Example

### Multiple action app
```rust
use std::env;
use seahorse::{App, Action, Command, color};
use seahorse::{
App,
Action,
Command,
Context,
Flag,
FlagType,
color
};

fn main() {
let args: Vec<String> = env::args().collect();
let action: Action = |v: Vec<String>| println!("Hello, {:?}", v);
let action: Action = |c: &Context| {
let name = &c.args[2];
if c.bool_flag("bye") {
println!("Bye, {}", name);
} else {
println!("Hello, {}", name);
}

match c.string_flag("other") {
Some(val) => println!("{}", val),
_ => println!("Not other...")
}

match c.int_flag("age") {
Some(val) => println!("{} is {} years old", name, val),
_ => println!("I don't know how old {} is...", name)
}
};
let display_name = color::magenta("
██████╗██╗ ██╗
██╔════╝██║ ██║
██║ ██║ ██║
██║ ██║ ██║
╚██████╗███████╗██║
╚═════╝╚══════╝╚═╝");
let command = Command::new("hello", "cli_tool hello user", action);
let command = Command::new()
.name("hello")
.usage("cli_tool hello [name]")
.action(action)
.flags(vec![
Flag::new("bye", "cli_tool hello [name] --bye", FlagType::Bool),
Flag::new("other", "cli_tool hello [name] --other [string]", FlagType::String),
Flag::new("age", "cli_tool hello [name] --age [int]", FlagType::Int),
]);

let app = App::new()
.name("cli_tool")
Expand All @@ -45,17 +78,28 @@ fn main() {
}
```

![](images/screen_shot1.png)
![](images/screen_shot2.png)
```bash
$ cli_tool hello John --age 10 --other test
Hello, John
test
John is 10 years old
```

### Single action app
```rust
use std::env;
use seahorse::{SingleApp, Action, color};
use seahorse::{SingleApp, Action, color, Context, Flag, FlagType};

fn main() {
let args: Vec<String> = env::args().collect();
let action: Action = |v: Vec<String>| println!("Hello, {:?}", v);
let action: Action = |c: &Context| {
let name = &c.args[0];
if c.bool_flag("bye") {
println!("Bye, {:?}", name);
} else {
println!("Hello, {:?}", name);
}
};
let display_name = color::magenta("
██████╗██╗ ██╗
██╔════╝██║ ██║
Expand All @@ -69,8 +113,19 @@ fn main() {
.display_name(display_name)
.usage("cli_tool [args]")
.version(env!("CARGO_PKG_VERSION"))
.action(action);
.action(action)
.flags(vec![
Flag::new("bye", "cli_tool args --bye", FlagType::Bool),
]);

app.run(args);
}
```

```bash
$ cli_tool John
Hello, "John"

$ cli_tool John --bye
Bye, "John"
```
33 changes: 29 additions & 4 deletions example/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,49 @@
use std::env;
use seahorse::{App, Action, Command, color};
use seahorse::{App, Action, Command, color, Flag, FlagType, Context};

fn main() {
let args: Vec<String> = env::args().collect();
let action: Action = |v: Vec<String>| println!("Hello, {:?}", v);
let display_name = color::magenta("
██████╗██╗ ██╗
██╔════╝██║ ██║
██║ ██║ ██║
██║ ██║ ██║
╚██████╗███████╗██║
╚═════╝╚══════╝╚═╝");
let command = Command::new("hello", "cli_tool hello user", action);

let app = App::new()
.name("cli_tool")
.display_name(display_name)
.usage("cli_tool [command] [arg]")
.version(env!("CARGO_PKG_VERSION"))
.commands(vec![command]);
.commands(vec![command()]);

app.run(args);
}

fn action(c: &Context) {
let name = &c.args[2];
if c.bool_flag("bool") {
println!("true");
} else {
println!("false");
}

match c.string_flag("string") {
Some(s) => println!("{}", s),
None => println!("string none...")
}

println!("Hello, {}", name);
}

fn command() -> Command {
Command::new()
.name("hello")
.usage("cli_tool hello [name]")
.action(action)
.flags(vec![
Flag::new("bool", "cli_tool hello [name] --bool", FlagType::Bool),
Flag::new("string", "cli_tool hello [name] --string [string]", FlagType::String),
])
}
Binary file removed images/screen_shot1.png
Binary file not shown.
Binary file removed images/screen_shot2.png
Binary file not shown.
4 changes: 3 additions & 1 deletion src/action.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pub type Action = fn(Vec<String>);
use crate::Context;

pub type Action = fn(&Context);
45 changes: 37 additions & 8 deletions src/app/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ impl App {
}

match self.select_command(&cmd) {
Some(command) => (command.action)(args_v.to_vec()),
Some(command) => {
command.run(args);
}
None => self.help(),
}
}
Expand Down Expand Up @@ -95,12 +97,35 @@ impl App {

#[cfg(test)]
mod tests {
use crate::{Action, App, Command};
use crate::{Action, App, Command, Context, Flag, FlagType};

#[test]
fn app_test() {
let a: Action = |v: Vec<String>| println!("Hello, {:?}", v);
let c = Command::new("hello", "test hello user", a);
let a: Action = |c: &Context| {
assert_eq!(true, c.bool_flag("bool"));
match c.string_flag("string") {
Some(flag) => assert_eq!("string".to_string(), flag),
None => assert!(false, "string test false...")
}
match c.int_flag("int") {
Some(flag) => assert_eq!(100, flag),
None => assert!(false, "int test false...")
}
match c.float_flag("float") {
Some(flag) => assert_eq!(1.23, flag),
None => assert!(false, "float test false...")
}
};
let c = Command::new()
.name("hello")
.usage("test hello args")
.action(a)
.flags(vec![
Flag::new("bool", "test hello [args] --bool", FlagType::Bool),
Flag::new("string", "test hello [args] --int [int value]", FlagType::String),
Flag::new("int", "test hello [args] --int [int value]", FlagType::Int),
Flag::new("float", "test hello [args] --int [int value]", FlagType::Float),
]);
let app = App::new()
.name("test")
.usage("test [command] [arg]")
Expand All @@ -110,10 +135,14 @@ mod tests {
app.run(vec![
"test".to_string(),
"hello".to_string(),
"arg1".to_string(),
"arg2".to_string(),
"arg3".to_string(),
"arg4".to_string(),
"args".to_string(),
"--bool".to_string(),
"--string".to_string(),
"string".to_string(),
"--int".to_string(),
"100".to_string(),
"--float".to_string(),
"1.23".to_string(),
]);

assert_eq!(app.name, "test".to_string());
Expand Down
34 changes: 27 additions & 7 deletions src/app/single_app.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::Action;
use crate::{Action, Context, Flag};

pub struct SingleApp {
pub name: String,
pub display_name: String,
pub usage: String,
pub version: String,
pub action: Action,
pub flags: Option<Vec<Flag>>
}

impl Default for SingleApp {
Expand All @@ -15,7 +16,8 @@ impl Default for SingleApp {
display_name: "".to_string(),
usage: "".to_string(),
version: "".to_string(),
action: |v: Vec<String>| println!("{:?}", v),
action: |c: &Context| println!("{:?}", c.args),
flags: None,
}
}
}
Expand Down Expand Up @@ -50,10 +52,15 @@ impl SingleApp {
self
}

pub fn flags(mut self, flags: Vec<Flag>) -> Self {
self.flags = Some(flags);
self
}

pub fn run(&self, args: Vec<String>) {
match args.len() {
1 => self.help(),
_ => (self.action)(args[1..].to_vec()),
_ => (self.action)(&Context::new(args[1..].to_vec(), self.flags.clone()))
}
}

Expand All @@ -70,18 +77,31 @@ impl SingleApp {

#[cfg(test)]
mod tests {
use crate::{Action, SingleApp};
use crate::{Action, Context, SingleApp, Flag, FlagType};

#[test]
fn single_app_test() {
let a: Action = |v: Vec<String>| println!("Hello, {:?}", v);
let a: Action = |c: &Context| {
if c.bool_flag("bool") {
assert!(true, "bool test true");
} else {
assert!(false, "bool test false");
}
};
let app = SingleApp::new()
.name("test")
.usage("test [url]")
.version("0.0.1")
.action(a);
.action(a)
.flags(vec![
Flag::new("bool", "test [url] --bool", FlagType::Bool)
]);

app.run(vec!["test".to_string(), "http://google.com".to_string()]);
app.run(vec![
"test".to_string(),
"http://google.com".to_string(),
"--bool".to_string()
]);

assert_eq!(app.name, "test".to_string());
assert_eq!(app.usage, "test [url]".to_string());
Expand Down
Loading

0 comments on commit 555c557

Please sign in to comment.