#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![doc = include_str!("../README.md")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![forbid(unsafe_code)]
#![deny(missing_docs)]
mod render;
pub use roff;
use render::subcommand_heading;
use roff::{roman, Roff};
use std::io::Write;
pub struct Man {
cmd: clap::Command,
title: String,
section: String,
date: String,
source: String,
manual: String,
}
impl Man {
pub fn new(mut cmd: clap::Command) -> Self {
cmd.build();
let title = cmd.get_name().to_owned();
let section = "1".to_owned();
let date = "".to_owned();
let source = format!(
"{} {}",
cmd.get_name(),
cmd.get_version().unwrap_or_default()
);
let manual = "".to_owned();
Self {
cmd,
title,
section,
date,
source,
manual,
}
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = title.into();
self
}
pub fn section(mut self, section: impl Into<String>) -> Self {
self.section = section.into();
self
}
pub fn date(mut self, date: impl Into<String>) -> Self {
self.date = date.into();
self
}
pub fn source(mut self, source: impl Into<String>) -> Self {
self.source = source.into();
self
}
pub fn manual(mut self, manual: impl Into<String>) -> Self {
self.manual = manual.into();
self
}
}
impl Man {
pub fn render(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_title(&mut roff);
self._render_name_section(&mut roff);
self._render_synopsis_section(&mut roff);
self._render_description_section(&mut roff);
if app_has_arguments(&self.cmd) {
self._render_options_section(&mut roff);
}
if app_has_subcommands(&self.cmd) {
self._render_subcommands_section(&mut roff);
}
if self.cmd.get_after_long_help().is_some() || self.cmd.get_after_help().is_some() {
self._render_extra_section(&mut roff);
}
if app_has_version(&self.cmd) {
self._render_version_section(&mut roff);
}
if self.cmd.get_author().is_some() {
self._render_authors_section(&mut roff);
}
roff.to_writer(w)
}
pub fn render_title(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_title(&mut roff);
roff.to_writer(w)
}
fn _render_title(&self, roff: &mut Roff) {
roff.control("TH", self.title_args());
}
fn title_args(&self) -> Vec<&str> {
vec![
&self.title,
&self.section,
&self.date,
&self.source,
&self.manual,
]
}
pub fn render_name_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_name_section(&mut roff);
roff.to_writer(w)
}
fn _render_name_section(&self, roff: &mut Roff) {
roff.control("SH", ["NAME"]);
render::about(roff, &self.cmd);
}
pub fn render_synopsis_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_synopsis_section(&mut roff);
roff.to_writer(w)
}
fn _render_synopsis_section(&self, roff: &mut Roff) {
roff.control("SH", ["SYNOPSIS"]);
render::synopsis(roff, &self.cmd);
}
pub fn render_description_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_description_section(&mut roff);
roff.to_writer(w)
}
fn _render_description_section(&self, roff: &mut Roff) {
roff.control("SH", ["DESCRIPTION"]);
render::description(roff, &self.cmd);
}
pub fn render_options_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_options_section(&mut roff);
roff.to_writer(w)
}
fn _render_options_section(&self, roff: &mut Roff) {
roff.control("SH", ["OPTIONS"]);
render::options(roff, &self.cmd);
}
pub fn render_subcommands_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_subcommands_section(&mut roff);
roff.to_writer(w)
}
fn _render_subcommands_section(&self, roff: &mut Roff) {
let heading = subcommand_heading(&self.cmd);
roff.control("SH", [heading]);
render::subcommands(roff, &self.cmd, &self.section);
}
pub fn render_extra_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_extra_section(&mut roff);
roff.to_writer(w)
}
fn _render_extra_section(&self, roff: &mut Roff) {
roff.control("SH", ["EXTRA"]);
render::after_help(roff, &self.cmd);
}
pub fn render_version_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_version_section(&mut roff);
roff.to_writer(w)
}
fn _render_version_section(&self, roff: &mut Roff) {
let version = roman(render::version(&self.cmd));
roff.control("SH", ["VERSION"]);
roff.text([version]);
}
pub fn render_authors_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
let mut roff = Roff::default();
self._render_authors_section(&mut roff);
roff.to_writer(w)
}
fn _render_authors_section(&self, roff: &mut Roff) {
let author = roman(self.cmd.get_author().unwrap_or_default());
roff.control("SH", ["AUTHORS"]);
roff.text([author]);
}
}
fn app_has_version(cmd: &clap::Command) -> bool {
cmd.get_version()
.or_else(|| cmd.get_long_version())
.is_some()
}
fn app_has_arguments(cmd: &clap::Command) -> bool {
cmd.get_arguments().any(|i| !i.is_hide_set())
}
fn app_has_subcommands(cmd: &clap::Command) -> bool {
cmd.get_subcommands().any(|i| !i.is_hide_set())
}