2022-01-28 20:55:55 +00:00
|
|
|
use roff::{bold, italic, roman, Inline, Roff};
|
|
|
|
|
2022-08-15 19:29:46 +00:00
|
|
|
pub(crate) fn subcommand_heading(cmd: &clap::Command) -> &str {
|
2022-02-14 21:47:20 +00:00
|
|
|
match cmd.get_subcommand_help_heading() {
|
2022-08-15 19:29:46 +00:00
|
|
|
Some(title) => title.as_str(),
|
|
|
|
None => "SUBCOMMANDS",
|
2022-01-28 20:55:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
pub(crate) fn about(roff: &mut Roff, cmd: &clap::Command) {
|
|
|
|
let s = match cmd.get_about().or_else(|| cmd.get_long_about()) {
|
|
|
|
Some(about) => format!("{} - {}", cmd.get_name(), about),
|
|
|
|
None => cmd.get_name().to_string(),
|
2022-01-28 20:55:55 +00:00
|
|
|
};
|
|
|
|
roff.text([roman(&s)]);
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
pub(crate) fn description(roff: &mut Roff, cmd: &clap::Command) {
|
|
|
|
if let Some(about) = cmd.get_long_about().or_else(|| cmd.get_about()) {
|
2022-01-28 20:55:55 +00:00
|
|
|
for line in about.lines() {
|
|
|
|
if line.trim().is_empty() {
|
|
|
|
roff.control("PP", []);
|
|
|
|
} else {
|
|
|
|
roff.text([roman(line)]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
pub(crate) fn synopsis(roff: &mut Roff, cmd: &clap::Command) {
|
2022-08-15 19:29:46 +00:00
|
|
|
let mut line = vec![bold(cmd.get_name().as_str()), roman(" ")];
|
2022-01-28 20:55:55 +00:00
|
|
|
|
2022-04-02 23:11:29 +00:00
|
|
|
for opt in cmd.get_arguments().filter(|i| !i.is_hide_set()) {
|
2022-01-28 20:55:55 +00:00
|
|
|
let (lhs, rhs) = option_markers(opt);
|
|
|
|
match (opt.get_short(), opt.get_long()) {
|
|
|
|
(Some(short), Some(long)) => {
|
|
|
|
line.push(roman(lhs));
|
|
|
|
line.push(bold(&format!("-{}", short)));
|
|
|
|
line.push(roman("|"));
|
|
|
|
line.push(bold(&format!("--{}", long)));
|
|
|
|
line.push(roman(rhs));
|
|
|
|
line.push(roman(" "));
|
|
|
|
}
|
|
|
|
(Some(short), None) => {
|
|
|
|
line.push(roman(lhs));
|
|
|
|
line.push(bold(&format!("-{} ", short)));
|
|
|
|
line.push(roman(rhs));
|
|
|
|
line.push(roman(" "));
|
|
|
|
}
|
|
|
|
(None, Some(long)) => {
|
|
|
|
line.push(roman(lhs));
|
|
|
|
line.push(bold(&format!("--{}", long)));
|
|
|
|
line.push(roman(rhs));
|
|
|
|
line.push(roman(" "));
|
|
|
|
}
|
|
|
|
(None, None) => (),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
for arg in cmd.get_positionals() {
|
2022-01-28 20:55:55 +00:00
|
|
|
let (lhs, rhs) = option_markers(arg);
|
|
|
|
line.push(roman(lhs));
|
2022-03-28 19:42:56 +00:00
|
|
|
if let Some(value) = arg.get_value_names() {
|
2022-04-03 12:05:22 +00:00
|
|
|
line.push(italic(value.join(" ")));
|
2022-03-28 19:42:56 +00:00
|
|
|
} else {
|
2022-08-11 20:33:23 +00:00
|
|
|
line.push(italic(arg.get_id().as_str()));
|
2022-03-28 19:42:56 +00:00
|
|
|
}
|
2022-01-28 20:55:55 +00:00
|
|
|
line.push(roman(rhs));
|
|
|
|
line.push(roman(" "));
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
if cmd.has_subcommands() {
|
|
|
|
let (lhs, rhs) = subcommand_markers(cmd);
|
2022-01-28 20:55:55 +00:00
|
|
|
line.push(roman(lhs));
|
|
|
|
line.push(italic(
|
2022-08-15 19:29:46 +00:00
|
|
|
cmd.get_subcommand_value_name()
|
|
|
|
.map(|s| s.as_str())
|
|
|
|
.unwrap_or_else(|| subcommand_heading(cmd))
|
2022-01-28 20:55:55 +00:00
|
|
|
.to_lowercase(),
|
|
|
|
));
|
|
|
|
line.push(roman(rhs));
|
|
|
|
}
|
|
|
|
|
|
|
|
roff.text(line);
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) {
|
|
|
|
let items: Vec<_> = cmd.get_arguments().filter(|i| !i.is_hide_set()).collect();
|
2022-01-28 20:55:55 +00:00
|
|
|
|
|
|
|
for opt in items.iter().filter(|a| !a.is_positional()) {
|
|
|
|
let mut header = match (opt.get_short(), opt.get_long()) {
|
|
|
|
(Some(short), Some(long)) => {
|
|
|
|
vec![short_option(short), roman(", "), long_option(long)]
|
|
|
|
}
|
|
|
|
(Some(short), None) => vec![short_option(short)],
|
|
|
|
(None, Some(long)) => vec![long_option(long)],
|
|
|
|
(None, None) => vec![],
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(value) = &opt.get_value_names() {
|
|
|
|
header.push(roman("="));
|
|
|
|
header.push(italic(&value.join(" ")));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(defs) = option_default_values(opt) {
|
|
|
|
header.push(roman(" "));
|
|
|
|
header.push(roman(&defs));
|
|
|
|
}
|
|
|
|
|
2022-03-28 19:42:56 +00:00
|
|
|
let mut body = vec![];
|
2022-01-28 20:55:55 +00:00
|
|
|
if let Some(help) = opt.get_long_help().or_else(|| opt.get_help()) {
|
2022-08-15 19:29:46 +00:00
|
|
|
body.push(roman(help.as_str()));
|
2022-01-28 20:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
roff.control("TP", []);
|
|
|
|
roff.text(header);
|
|
|
|
roff.text(body);
|
2022-04-20 13:50:11 +00:00
|
|
|
|
|
|
|
if let Some(env) = option_environment(opt) {
|
|
|
|
roff.control("RS", []);
|
|
|
|
roff.text(env);
|
|
|
|
roff.control("RE", []);
|
|
|
|
}
|
2022-01-28 20:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for pos in items.iter().filter(|a| a.is_positional()) {
|
2022-03-28 19:42:56 +00:00
|
|
|
let mut header = vec![];
|
2022-01-28 20:55:55 +00:00
|
|
|
let (lhs, rhs) = option_markers(pos);
|
2022-03-28 19:42:56 +00:00
|
|
|
header.push(roman(lhs));
|
|
|
|
if let Some(value) = pos.get_value_names() {
|
2022-04-03 12:05:22 +00:00
|
|
|
header.push(italic(value.join(" ")));
|
2022-03-28 19:42:56 +00:00
|
|
|
} else {
|
2022-08-11 20:33:23 +00:00
|
|
|
header.push(italic(pos.get_id().as_str()));
|
2022-03-28 19:42:56 +00:00
|
|
|
};
|
|
|
|
header.push(roman(rhs));
|
2022-01-28 20:55:55 +00:00
|
|
|
|
|
|
|
if let Some(defs) = option_default_values(pos) {
|
|
|
|
header.push(roman(&format!(" {}", defs)));
|
|
|
|
}
|
|
|
|
|
2022-03-28 19:42:56 +00:00
|
|
|
let mut body = vec![];
|
2022-01-28 20:55:55 +00:00
|
|
|
if let Some(help) = pos.get_long_help().or_else(|| pos.get_help()) {
|
|
|
|
body.push(roman(&help.to_string()));
|
|
|
|
}
|
|
|
|
|
|
|
|
roff.control("TP", []);
|
2022-03-28 19:42:56 +00:00
|
|
|
roff.text(header);
|
2022-01-28 20:55:55 +00:00
|
|
|
roff.text(body);
|
2022-04-20 13:50:11 +00:00
|
|
|
|
|
|
|
if let Some(env) = option_environment(pos) {
|
|
|
|
roff.control("RS", []);
|
|
|
|
roff.text(env);
|
|
|
|
roff.control("RE", []);
|
|
|
|
}
|
2022-01-28 20:55:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
pub(crate) fn subcommands(roff: &mut Roff, cmd: &clap::Command, section: &str) {
|
|
|
|
for sub in cmd.get_subcommands().filter(|s| !s.is_hide_set()) {
|
2022-01-28 20:55:55 +00:00
|
|
|
roff.control("TP", []);
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
let name = format!("{}-{}({})", cmd.get_name(), sub.get_name(), section);
|
2022-01-28 20:55:55 +00:00
|
|
|
roff.text([roman(&name)]);
|
|
|
|
|
|
|
|
if let Some(about) = sub.get_about().or_else(|| sub.get_long_about()) {
|
|
|
|
for line in about.lines() {
|
|
|
|
roff.text([roman(line)]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
pub(crate) fn version(cmd: &clap::Command) -> String {
|
2022-01-28 20:55:55 +00:00
|
|
|
format!(
|
|
|
|
"v{}",
|
2022-02-14 21:47:20 +00:00
|
|
|
cmd.get_long_version()
|
|
|
|
.or_else(|| cmd.get_version())
|
2022-01-28 20:55:55 +00:00
|
|
|
.unwrap()
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:47:20 +00:00
|
|
|
pub(crate) fn after_help(roff: &mut Roff, cmd: &clap::Command) {
|
|
|
|
if let Some(about) = cmd.get_after_long_help().or_else(|| cmd.get_after_help()) {
|
2022-01-28 20:55:55 +00:00
|
|
|
for line in about.lines() {
|
|
|
|
roff.text([roman(line)]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-12 03:48:29 +00:00
|
|
|
fn subcommand_markers(cmd: &clap::Command) -> (&'static str, &'static str) {
|
2022-07-22 17:22:22 +00:00
|
|
|
markers(cmd.is_subcommand_required_set())
|
2022-01-28 20:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn option_markers(opt: &clap::Arg) -> (&'static str, &'static str) {
|
2022-02-09 17:16:34 +00:00
|
|
|
markers(opt.is_required_set())
|
2022-01-28 20:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn markers(required: bool) -> (&'static str, &'static str) {
|
|
|
|
if required {
|
|
|
|
("<", ">")
|
|
|
|
} else {
|
|
|
|
("[", "]")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn short_option(opt: char) -> Inline {
|
|
|
|
bold(&format!("-{}", opt))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn long_option(opt: &str) -> Inline {
|
|
|
|
bold(&format!("--{}", opt))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn option_environment(opt: &clap::Arg) -> Option<Vec<Inline>> {
|
2022-02-09 17:16:34 +00:00
|
|
|
if opt.is_hide_env_set() {
|
2022-01-28 20:55:55 +00:00
|
|
|
return None;
|
|
|
|
} else if let Some(env) = opt.get_env() {
|
|
|
|
return Some(vec![
|
|
|
|
roman("May also be specified with the "),
|
|
|
|
bold(env.to_string_lossy().to_owned()),
|
|
|
|
roman(" environment variable. "),
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
fn option_default_values(opt: &clap::Arg) -> Option<String> {
|
|
|
|
if !opt.get_default_values().is_empty() {
|
|
|
|
let values = opt
|
|
|
|
.get_default_values()
|
|
|
|
.iter()
|
|
|
|
.map(|s| s.to_string_lossy())
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join(",");
|
|
|
|
|
|
|
|
return Some(format!("[default: {}]", values));
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|