Skip to content
This repository has been archived by the owner on Feb 8, 2020. It is now read-only.

[wip] man page generation #1

Merged
merged 4 commits into from
Feb 3, 2020
Merged
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
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ description = """
A shell completion script and manpage generation library used with clap
"""

[package.metadata.docs.rs]
features = ["doc"]

[badges]
travis-ci = { repository = "clap-rs/clap_generate" }
appveyor = { repository = "clap-rs/clap_generate" }
Expand All @@ -48,6 +51,7 @@ maintenance = {status = "actively-developed"}
[dependencies]
clap = {git = "https://github.com/kbknapp/clap-rs", branch = "v3-master", default-features = false}
clippy = { version = "~0.0.166", optional = true }
man = {git = "https://github.com/rust-clique/man" }

[dev-dependencies]
version-sync = "0.5"
Expand Down Expand Up @@ -94,6 +98,3 @@ rpath = false
lto = true
debug-assertions = false
codegen-units = 1

[package.metadata.docs.rs]
features = ["doc"]
28 changes: 28 additions & 0 deletions examples/man.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
extern crate clap;
extern crate clap_generate;

use clap::{App, Arg};
use clap_generate::gen_manuals;

fn main() {
let app = App::new("testapp")
.about("Pointless application")
.author("Alice Person <[email protected]>\nBob Human <[email protected]>")
.arg(Arg::with_name("dir").index(1))
.arg(
Arg::with_name("debug")
.short('d')
.help("Make program output debug messages"),
)
.arg(
Arg::with_name("output")
.short('o')
.long("out")
.takes_value(true)
.help("Output File"),
);

for manual in gen_manuals(&app) {
println!("{}", manual.render());
}
}
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#![cfg_attr(feature = "lints", allow(explicit_iter_loop))]

extern crate clap as _clap;
extern crate man;

// Re-Export of clap
mod clap {
Expand All @@ -40,6 +41,7 @@ const INTERNAL_ERROR_MSG: &'static str = "Fatal internal error. Please consider

#[macro_use]
mod macros;
mod manual;
mod shells;

use shells::{ComplGen, Shell};
Expand All @@ -49,6 +51,8 @@ use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

pub use manual::gen_manuals;

/// Generate a completions file for a specified shell at compile time.
///
/// **NOTE:** to generate the file at compile time you must use a `build.rs` "Build Script"
Expand Down
65 changes: 65 additions & 0 deletions src/manual.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use clap;
use man;

/// Generate a man page from a `clap::App` instance.
// NOTE(yw): in future versions we should allow this to recurse and generate
// man pages for subcommands. We're returning a vector now to support this in
// future versions.
pub fn gen_manuals(app: &clap::App) -> Vec<man::Manual> {
let mut manual = man::Manual::new(&app.name);

for about in &app.about {
manual = manual.about(about.to_string());
}

// Assume multiple authors are passed separated by newline. Worst case the
// formatting comes out slightly different.
for authors in &app.author {
for author in authors.split("\n") {
manual = manual.author(man::Author::new(author));
}
}

for arg in &app.args {
if let Some(_index) = arg.index {
let mut positional_arg = man::Arg::new(arg.name);
manual = manual.arg(positional_arg);
} else if arg.is_set(clap::ArgSettings::TakesValue) {
let mut opt = man::Opt::new(arg.name);
if let Some(help) = get_help(arg) {
opt = opt.help(&help);
}
if let Some(short) = arg.short {
opt = opt.short(&format!("-{}", short.to_string()));
}
if let Some(long) = arg.long {
opt = opt.long(&format!("--{}", long));
}
manual = manual.option(opt);
} else {
let mut flag = man::Flag::new();
if let Some(help) = get_help(arg) {
flag = flag.help(&help);
}
if let Some(short) = arg.short {
flag = flag.short(&format!("-{}", short.to_string()));
}
if let Some(long) = arg.long {
flag = flag.long(&format!("--{}", long));
}
manual = manual.flag(flag);
}
}

vec![manual]
}

fn get_help(arg: &clap::Arg) -> Option<String> {
if let Some(help) = arg.long_help {
Some(help.into())
} else if let Some(help) = arg.help {
Some(help.into())
} else {
None
}
}