Skip to content

Commit

Permalink
remove all clap-related code (#10)
Browse files Browse the repository at this point in the history
* remove all clap-related code

* builder pattern all the way through

* port example to builder pattern

* update readme

* s/description/help/g

* arg struct

* s/Man/Manual/

* more exit codes
  • Loading branch information
yoshuawuyts committed Aug 6, 2018
1 parent a6271b8 commit 16b74df
Show file tree
Hide file tree
Showing 16 changed files with 561 additions and 223 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ Generate structured man pages using
```rust
extern crate man;

use man::Man;
use man::prelude::*;

fn main() {
let page = Man::new("basic")
.description("A basic example")
.author("Alice", Some("alice@email.com"))
.author("Bob", Some("bob@email.com"))
.flag(Some("-d"), Some("--debug"), Some("Activate debug mode"))
.flag(Some("-v"), Some("--verbose"), Some("Verbose mode"));
.option(Some("-o"), Some("--output"), "output", None, "Output file");

let _string = page.to_string();
let page = Manual::new("basic")
.about("A basic example")
.author(Author::new("Alice Person").email("alice@person.com"))
.author(Author::new("Bob Human").email("bob@human.com"))
.flag(Flag::new().short("-d").long("--deubg").description("Enable debug mode"))
.flag(Flag::new().short("-v").long("--verbose").description("Enable verbose mode"))
.option(Opt::new("output").short("-o").long("--output").description("Output file"));

let _string = page.render();
}
```
Preview by running:
Expand Down
49 changes: 0 additions & 49 deletions examples/demo.rs

This file was deleted.

56 changes: 34 additions & 22 deletions examples/main.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
extern crate clap;
extern crate man;

use clap::{App, AppSettings, Arg, Man, SubCommand};
use man::Manual;
use man::prelude::*;

fn main() {
let a = App::new("testapp")
.about("Pointless application")
.setting(AppSettings::SubcommandRequiredElseHelp)
.author("Katharina Fey <kookie@spacekookie.de>")
// .author("Yosh Wuyts <y@w.s")
.long_about("Lorem Ipsum bla bla bla")
.arg(Arg::with_name("debug").short("d").help("Make program output debug messages"))
.arg(Arg::with_name("output").short("o").takes_value(true).help("Output File"))
.subcommand(SubCommand::with_name("foo").arg(Arg::with_name("bar").short("b").long("barr")));
let msg = Manual::new("auth-service")
.about("authorize & authenticate members".into())
.arg(Arg::new("path"))
.env(Env::new("PORT").help("The network port to listen to"))
.flag(
Flag::new()
.short("-h")
.long("--help")
.help("Prints help information."),
)
.flag(
Flag::new()
.short("-V")
.long("--version")
.help("Prints version information."),
)
.flag(
Flag::new()
.short("-v")
.long("--verbosity")
.help("Pass multiple times to print more information."),
)
.option(
Opt::new("port")
.short("-p")
.long("--port")
.help("The network port to listen to."),
)
.author(Author::new("Alice Person").email("alice@person.com"))
.author(Author::new("Bob Human").email("bob@human.com"))
.render();
// .option(Some("-o"), Some("--output"), "output", None, "Output file");

let manual = Manual::from_clap(&a);
println!("{:#?}", manual);

// let page = Man::new("basic")
// .description("A basic example")
// .author("Alice", Some("alice@email.com"))
// .author("Bob", Some("bob@email.com"))
// .flag(Some("-d"), Some("--debug"), Some("Activate debug mode"))
// .flag(Some("-v"), Some("--verbose"), Some("Verbose mode"));
// .option(Some("-o"), Some("--output"), "output", None, "Output file");
println!("{}", msg);
}
10 changes: 10 additions & 0 deletions src/arg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#[derive(Debug, Clone)]
pub struct Arg {
pub(crate) name: String,
}

impl Arg {
pub fn new(name: &str) -> Self {
Self { name: name.into() }
}
}
22 changes: 22 additions & 0 deletions src/author.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// An author entry.
#[derive(Debug, Clone)]
pub struct Author {
pub(crate) name: String,
pub(crate) email: Option<String>,
}

impl Author {
/// Create a new instance.
pub fn new(name: &str) -> Self {
Self {
name: name.into(),
email: None,
}
}

/// Set the email field.
pub fn email(mut self, email: &str) -> Self {
self.email = Some(email.into());
self
}
}
30 changes: 30 additions & 0 deletions src/environment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/// Command line environment variable representation.
#[derive(Debug, Clone)]
pub struct Env {
pub(crate) name: String,
pub(crate) default: Option<String>,
pub(crate) help: Option<String>,
}

impl Env {
/// Create a new instance.
pub fn new(name: &str) -> Self {
Self {
name: name.into(),
default: None,
help: None,
}
}

/// Set the default value.
pub fn default_value(mut self, default: &str) -> Self {
self.default = Some(default.into());
self
}

/// Set the help.
pub fn help(mut self, help: &str) -> Self {
self.help = Some(help.into());
self
}
}
36 changes: 36 additions & 0 deletions src/flag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/// Command line flag representation.
#[derive(Debug, Clone)]
pub struct Flag {
pub(crate) short: Option<String>,
pub(crate) long: Option<String>,
pub(crate) help: Option<String>,
}

impl Flag {
/// Create a new instance.
pub fn new() -> Self {
Self {
short: None,
long: None,
help: None,
}
}

/// Set the short value.
pub fn short(mut self, short: &str) -> Self {
self.short = Some(short.into());
self
}

/// Set the long value.
pub fn long(mut self, long: &str) -> Self {
self.long = Some(long.into());
self
}

/// Set the help value.
pub fn help(mut self, help: &str) -> Self {
self.help = Some(help.into());
self
}
}
108 changes: 12 additions & 96 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,104 +3,20 @@
#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
#![cfg_attr(test, deny(warnings))]

extern crate clap;
extern crate roff;

mod arg;
mod author;
mod environment;
mod flag;
mod man;
mod option;

use clap::{App, Arg, ArgSettings};
pub use man::*;
pub mod prelude;

/// Describe an argument or option
#[derive(Debug)]
pub struct ManualArg {
short: Option<char>,
long: Option<String>,
descr: Option<String>,
}

#[derive(Debug)]
pub struct Manual {
/// Optionally children of this app
children: Vec<(String, Manual)>,
/// Application name
name: Option<String>,
/// Type description
description: Option<String>,
/// Type authors
authors: Option<String>,
/// Type flags
flags: Vec<ManualArg>,
/// Type options
options: Vec<ManualArg>,
}

impl<'a, 'b, 'c> From<&'c Arg<'a, 'b>> for ManualArg {
fn from(s: &'c Arg) -> Self {
ManualArg {
short: s.short,
long: match s.long {
Some(s) => Some(s.into()),
_ => None,
},
descr: match s.help {
Some(s) => Some(s.into()),
_ => None,
},
}
}
}

impl Manual {
fn new() -> Self {
Manual {
children: Vec::new(),
name: None,
description: None,
authors: None,
flags: Vec::new(),
options: Vec::new(),
}
}

// TODO: Make this less awful
fn add_empty_child(&mut self, name: &str) -> &mut Manual {
self.children.push((name.into(), Manual::new()));
let (_, ref mut manual) = self.children.last_mut().unwrap();
manual
}

fn recursive(manual: &mut Manual, app: &App) {
manual.name = app.name.clone().into();
manual.description = app.about.map(Into::into);
manual.authors = app.author.map(Into::into);

let (flags, options): (Vec<ManualArg>, Vec<ManualArg>) = app
.args
.iter()
.fold((Vec::new(), Vec::new()), |(mut f, mut o), i: &Arg| {
if i.is_set(ArgSettings::TakesValue) {
f.push(i.into());
} else {
o.push(i.into());
}

(f, o)
});

manual.flags = flags;
manual.options = options;

app.subcommands.iter().for_each(|app| {
let _inner_name: String = app.name.clone();
let mut inner = manual.add_empty_child(&app.name);
Manual::recursive(&mut inner, app);
});
}

pub fn from_clap<'a, 'b>(app: &App<'a, 'b>) -> Manual {
let mut man = Manual::new();
Manual::recursive(&mut man, app);
man
}
}
pub use arg::Arg;
pub use author::Author;
pub use environment::Env;
pub use flag::Flag;
pub use man::Manual;
pub use option::Opt;
Loading

0 comments on commit 16b74df

Please sign in to comment.