man: Support optional arguments to command line options.
This commit is contained in:
parent
a8f01ef1ae
commit
3e138d4c59
71
src/man.rs
71
src/man.rs
@ -26,6 +26,8 @@
|
|||||||
use roff::{bold, italic, roman, Inline, Roff};
|
use roff::{bold, italic, roman, Inline, Roff};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use clap::builder::ValueRange;
|
||||||
|
|
||||||
/// The "manual" the manual page is meant for. The full Unix
|
/// The "manual" the manual page is meant for. The full Unix
|
||||||
/// documentation is (or was) divided into separate manuals, some of
|
/// documentation is (or was) divided into separate manuals, some of
|
||||||
/// which don't consist of manual pages.
|
/// which don't consist of manual pages.
|
||||||
@ -507,10 +509,27 @@ struct CommandOption {
|
|||||||
index: Option<usize>,
|
index: Option<usize>,
|
||||||
short: Option<String>,
|
short: Option<String>,
|
||||||
long: Option<String>,
|
long: Option<String>,
|
||||||
value_names: Option<Vec<String>>,
|
value_names: Values,
|
||||||
help: Option<String>,
|
help: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Formal arguments for a command option.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
enum Values {
|
||||||
|
/// This option does not take any arguments.
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// This option takes the given arguments.
|
||||||
|
Some(Vec<String>),
|
||||||
|
|
||||||
|
/// This option optionally takes the given arguments.
|
||||||
|
///
|
||||||
|
/// XXX: Currently, this is all or nothing, i.e. either all
|
||||||
|
/// arguments are mandatory, or all are optional. Let's see
|
||||||
|
/// whether we need something more complicated.
|
||||||
|
Optional(Vec<String>),
|
||||||
|
}
|
||||||
|
|
||||||
impl CommandOption {
|
impl CommandOption {
|
||||||
/// Return a key for sorting a list of options.
|
/// Return a key for sorting a list of options.
|
||||||
///
|
///
|
||||||
@ -537,14 +556,23 @@ impl CommandOption {
|
|||||||
/// Create a `CommandOption` from a `clap::Arg`.
|
/// Create a `CommandOption` from a `clap::Arg`.
|
||||||
fn from_arg(arg: &clap::Arg) -> Self {
|
fn from_arg(arg: &clap::Arg) -> Self {
|
||||||
let value_names = if arg.get_num_args()
|
let value_names = if arg.get_num_args()
|
||||||
.map(|r| r == clap::builder::ValueRange::EMPTY)
|
.map(|r| r == ValueRange::EMPTY)
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
{
|
{
|
||||||
None
|
Values::None
|
||||||
} else if let Some(names) = arg.get_value_names() {
|
} else if let Some(names) = arg.get_value_names() {
|
||||||
Some(names.iter().map(|name| name.to_string()).collect())
|
let names =
|
||||||
|
names.iter().map(|name| name.to_string()).collect();
|
||||||
|
|
||||||
|
if arg.get_num_args()
|
||||||
|
.map(|r| r.min_values() == 0).unwrap_or(false)
|
||||||
|
{
|
||||||
|
Values::Optional(names)
|
||||||
|
} else {
|
||||||
|
Values::Some(names)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
Values::None
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -667,18 +695,29 @@ impl ManualPage {
|
|||||||
line.push(bold(long));
|
line.push(bold(long));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(values) = &opt.value_names {
|
match &opt.value_names {
|
||||||
if (opt.short.is_some() || opt.long.is_some())
|
Values::None => (),
|
||||||
&& values.len() == 1
|
Values::Some(values) | Values::Optional(values) => {
|
||||||
{
|
if matches!(opt.value_names, Values::Optional(_)) {
|
||||||
line.push(roman("="));
|
line.push(roman("["));
|
||||||
line.push(italic(&values[0]));
|
|
||||||
} else {
|
|
||||||
for value in values {
|
|
||||||
line.push(roman(" "));
|
|
||||||
line.push(italic(value));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (opt.short.is_some() || opt.long.is_some())
|
||||||
|
&& values.len() == 1
|
||||||
|
{
|
||||||
|
line.push(roman("="));
|
||||||
|
line.push(italic(&values[0]));
|
||||||
|
} else {
|
||||||
|
for value in values {
|
||||||
|
line.push(roman(" "));
|
||||||
|
line.push(italic(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(opt.value_names, Values::Optional(_)) {
|
||||||
|
line.push(roman("]"));
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tagged_paragraph(line, &opt.help);
|
self.tagged_paragraph(line, &opt.help);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user