From 069098cfcb4eee3db0e58b3f1779189d816ceb35 Mon Sep 17 00:00:00 2001 From: Tyler Calder Date: Tue, 23 Aug 2022 12:38:57 -0600 Subject: [PATCH] fix: Use roff bullet lists for possible_values --- clap_mangen/src/render.rs | 85 ++++++++++--------- clap_mangen/tests/common.rs | 23 +++++ clap_mangen/tests/roff.rs | 7 ++ .../tests/snapshots/possible_values.bash.roff | 28 ++++++ .../tests/snapshots/value_hint.bash.roff | 3 +- 5 files changed, 106 insertions(+), 40 deletions(-) create mode 100644 clap_mangen/tests/snapshots/possible_values.bash.roff diff --git a/clap_mangen/src/render.rs b/clap_mangen/src/render.rs index 6883aef4..1cd81485 100644 --- a/clap_mangen/src/render.rs +++ b/clap_mangen/src/render.rs @@ -1,3 +1,5 @@ +use std::vec; + use roff::{bold, italic, roman, Inline, Roff}; pub(crate) fn subcommand_heading(cmd: &clap::Command) -> &str { @@ -113,22 +115,49 @@ pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) { body.push(roman(help)); } + roff.control("TP", []); + roff.text(header); + roff.text(body); + let possibles = &opt.get_possible_values(); + let possibles: Vec<&clap::builder::PossibleValue> = + possibles.iter().filter(|pos| !pos.is_hide_set()).collect(); if !(possibles.is_empty() || opt.is_hide_possible_values_set()) { if help_written { // It looks nice to have a separation between the help and the values - body.push(Inline::LineBreak); + roff.text([Inline::LineBreak]); + } + // with help for each possible value + + if possibles.iter().any(|p| p.get_help().is_some()) { + roff.text([Inline::LineBreak, italic("Possible values:")]); + + // Need to indent twice to get it to look right, + // because .TP heading indents, but that indent doesn't + // Carry over to the .IP for the bullets. + // The standard shift size is 7 for terminal devices + roff.control("RS", ["14"]); + for line in format_possible_values(&possibles) { + roff.control("IP", ["\\(bu", "2"]); + roff.text([roman(line)]); + } + roff.control("RE", []); } - let possible_vals = possibles.iter().filter(|pos| !pos.is_hide_set()).collect(); - body.append(&mut format_possible_values(possible_vals)); + // without help for each possible value + else { + let possible_list = format_possible_values(&possibles); + let possible_value_text: Vec = vec![ + Inline::LineBreak, + italic("[possible values: "), + roman(possible_list.join(", ")), + roman("]"), + ]; + roff.text(possible_value_text); + } } - roff.control("TP", []); - roff.text(header); - roff.text(body); - if let Some(env) = option_environment(opt) { roff.control("RS", []); roff.text(env); @@ -253,40 +282,18 @@ fn option_default_values(opt: &clap::Arg) -> Option { None } -/// Generates a Vector of Inline Commands to push to the roff -/// to properly format possible values that an option can take. -fn format_possible_values(values: Vec<&clap::builder::PossibleValue>) -> Vec { - let mut formats: Vec = vec![]; - // With Help - if values.iter().any(|p| p.get_help().is_some()) { - formats.push(Inline::LineBreak); - formats.push(roman("Possible values:")); - formats.push(Inline::LineBreak); - for value in values { - formats.push(roman(" - ")); - formats.push(roman(value.get_name().as_str())); +fn format_possible_values(possibles: &Vec<&clap::builder::PossibleValue>) -> Vec { + let mut lines = vec![]; + if possibles.iter().any(|p| p.get_help().is_some()) { + for value in possibles { + let val_name = value.get_name(); match value.get_help() { - Some(help) => { - formats.push(roman(": ")); - formats.push(roman(help.as_str())); - } - None => {} + Some(help) => lines.push(format!("{}: {}", val_name, help)), + None => lines.push(val_name.to_string()), } - formats.push(Inline::LineBreak); } + } else { + lines.append(&mut possibles.iter().map(|p| p.get_name().to_string()).collect()); } - // Without help - else { - formats.push(Inline::LineBreak); - formats.push(roman("[possible values: ")); - formats.push(italic( - values - .iter() - .map(|p| p.get_name().as_str()) - .collect::>() - .join(", "), - )); - formats.push(roman("]")); - } - formats + lines } diff --git a/clap_mangen/tests/common.rs b/clap_mangen/tests/common.rs index 21996d84..5cafbfc2 100644 --- a/clap_mangen/tests/common.rs +++ b/clap_mangen/tests/common.rs @@ -1,3 +1,5 @@ +use clap::builder::PossibleValue; + pub fn basic_command(name: &'static str) -> clap::Command { clap::Command::new(name) .arg( @@ -278,3 +280,24 @@ pub fn assert_matches_path(expected_path: impl AsRef, cmd: clap .action_env("SNAPSHOTS") .matches_path(expected_path, buf); } + +pub fn possible_values_command(name: &'static str) -> clap::Command<'static> { + clap::Command::new(name) + .trailing_var_arg(true) + .arg( + clap::Arg::new("choice") + .long("choice") + .action(clap::ArgAction::Set) + .value_parser(["bash", "fish", "zsh"]), + ) + .arg( + clap::Arg::new("method") + .long("method") + .action(clap::ArgAction::Set) + .value_parser([ + PossibleValue::new("fast").help("use the Fast method"), + PossibleValue::new("slow").help("use the slow method"), + PossibleValue::new("normal").help("use normal mode").hide(true) + ]) + ) +} diff --git a/clap_mangen/tests/roff.rs b/clap_mangen/tests/roff.rs index 946b8e76..0c6d99db 100644 --- a/clap_mangen/tests/roff.rs +++ b/clap_mangen/tests/roff.rs @@ -62,3 +62,10 @@ fn value_env() { let cmd = common::env_value_command(name); common::assert_matches_path("tests/snapshots/value_env.bash.roff", cmd); } + +#[test] +fn possible_values() { + let name = "my-app"; + let cmd = common::possible_values_command(name); + common::assert_matches_path("tests/snapshots/possible_values.bash.roff", cmd); +} diff --git a/clap_mangen/tests/snapshots/possible_values.bash.roff b/clap_mangen/tests/snapshots/possible_values.bash.roff new file mode 100644 index 00000000..76f690a1 --- /dev/null +++ b/clap_mangen/tests/snapshots/possible_values.bash.roff @@ -0,0 +1,28 @@ +.ie /n(.g .ds Aq /(aq +.el .ds Aq ' +.TH my-app 1 "my-app " +.SH NAME +my/-app +.SH SYNOPSIS +/fBmy/-app/fR [/fB/-/-choice/fR] [/fB/-/-method/fR] [/fB/-h/fR|/fB/-/-help/fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +/fB/-/-choice/fR + +.br +/fI[possible values: /fRbash, fish, zsh] +.TP +/fB/-/-method/fR + +.br +/fIPossible values:/fR +.RS 14 +.IP /(bu 2 +fast: use the Fast method +.IP /(bu 2 +slow: use the slow method +.RE +.TP +/fB/-h/fR, /fB/-/-help/fR +Print help information diff --git a/clap_mangen/tests/snapshots/value_hint.bash.roff b/clap_mangen/tests/snapshots/value_hint.bash.roff index 4565a602..94e76c20 100644 --- a/clap_mangen/tests/snapshots/value_hint.bash.roff +++ b/clap_mangen/tests/snapshots/value_hint.bash.roff @@ -9,8 +9,9 @@ my/-app .SH OPTIONS .TP /fB/-/-choice/fR + .br -[possible values: /fIbash, fish, zsh/fR] +/fI[possible values: /fRbash, fish, zsh] .TP /fB/-/-unknown/fR