Skip to content

Commit 19d68d6

Browse files
authored
polish: Add show_aliases option + change where aliases appear (#41)
1 parent 6bf1c39 commit 19d68d6

File tree

5 files changed

+51
-35
lines changed

5 files changed

+51
-35
lines changed

docs/examples/complex-app-custom.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ An example command-line tool
1010

1111
###### **Subcommands:**
1212

13-
* `test` [alias: `tester`] — does testing things
13+
* `test` — does testing things
1414
* `only-hidden-options` — Demo that `Options` is not printed if all options are hidden
1515

1616
###### **Arguments:**
@@ -38,7 +38,7 @@ An example command-line tool
3838

3939

4040

41-
## `complex-app test` [alias: `tester`]
41+
## `complex-app test`
4242

4343
does testing things
4444

docs/examples/complex-app.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ An example command-line tool
1616

1717
###### **Subcommands:**
1818

19-
* `test` [alias: `tester`] — does testing things
19+
* `test` — does testing things
2020
* `only-hidden-options` — Demo that `Options` is not printed if all options are hidden
2121

2222
###### **Arguments:**
@@ -44,12 +44,14 @@ An example command-line tool
4444

4545

4646

47-
## `complex-app test` [alias: `tester`]
47+
## `complex-app test`
4848

4949
does testing things
5050

5151
**Usage:** `complex-app test [OPTIONS]`
5252

53+
**Command Alias:** `tester`
54+
5355
###### **Options:**
5456

5557
* `-l`, `--list` — lists test values

src/lib.rs

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ mod test_readme {
1212
#![doc = include_str!("../README.md")]
1313
}
1414

15+
mod utils;
16+
1517
use std::fmt::{self, Write};
1618

1719
use clap::builder::PossibleValue;
1820

21+
use utils::pluralize;
22+
1923
//======================================
2024
// Public API types
2125
//======================================
@@ -28,6 +32,7 @@ pub struct MarkdownOptions {
2832
title: Option<String>,
2933
show_footer: bool,
3034
show_table_of_contents: bool,
35+
show_aliases: bool,
3136
}
3237

3338
impl MarkdownOptions {
@@ -37,6 +42,7 @@ impl MarkdownOptions {
3742
title: None,
3843
show_footer: true,
3944
show_table_of_contents: true,
45+
show_aliases: true,
4046
};
4147
}
4248

@@ -60,6 +66,13 @@ impl MarkdownOptions {
6066

6167
return self;
6268
}
69+
70+
/// Whether to show aliases for arguments and commands.
71+
pub fn show_aliases(mut self, show: bool) -> Self {
72+
self.show_aliases = show;
73+
74+
return self;
75+
}
6376
}
6477

6578
impl Default for MarkdownOptions {
@@ -166,7 +179,7 @@ fn write_help_markdown(
166179
// Write the commands/subcommands sections
167180
//----------------------------------------
168181

169-
build_command_markdown(buffer, Vec::new(), command, 0).unwrap();
182+
build_command_markdown(buffer, Vec::new(), command, 0, options).unwrap();
170183

171184
//-----------------
172185
// Write the footer
@@ -278,6 +291,7 @@ fn build_command_markdown(
278291
parent_command_path: Vec<String>,
279292
command: &clap::Command,
280293
depth: usize,
294+
options: &MarkdownOptions,
281295
) -> std::fmt::Result {
282296
// Don't document commands marked with `clap(hide = true)` (which includes
283297
// `print-all-help`).
@@ -307,12 +321,7 @@ fn build_command_markdown(
307321
)
308322
}
309323
*/
310-
let aliases = command.get_visible_aliases().collect::<Vec<&str>>();
311-
let aliases = get_alias_str(&aliases)
312-
.map(|s| format!(" {s}"))
313-
.unwrap_or_default();
314-
315-
writeln!(buffer, "## `{}`{aliases}\n", command_path.join(" "),)?;
324+
writeln!(buffer, "## `{}`\n", command_path.join(" "))?;
316325

317326
if let Some(long_about) = command.get_long_about() {
318327
writeln!(buffer, "{}\n", long_about)?;
@@ -343,6 +352,17 @@ fn build_command_markdown(
343352
.replace("Usage: ", "")
344353
)?;
345354

355+
if options.show_aliases {
356+
let aliases = command.get_visible_aliases().collect::<Vec<&str>>();
357+
if let Some(aliases_str) = get_alias_string(&aliases) {
358+
writeln!(
359+
buffer,
360+
"**{}:** {aliases_str}\n",
361+
pluralize(aliases.len(), "Command Alias", "Command Aliases")
362+
)?;
363+
}
364+
}
365+
346366
if let Some(help) = command.get_after_long_help() {
347367
writeln!(buffer, "{}\n", help)?;
348368
} else if let Some(help) = command.get_after_help() {
@@ -362,17 +382,13 @@ fn build_command_markdown(
362382
}
363383

364384
let title_name = get_canonical_name(subcommand);
365-
let aliases = subcommand.get_visible_aliases().collect::<Vec<&str>>();
366-
let aliases = get_alias_str(&aliases)
367-
.map(|s| format!(" {s}"))
368-
.unwrap_or_default();
369385

370386
let about = match subcommand.get_about() {
371387
Some(about) => about.to_string(),
372388
None => String::new(),
373389
};
374390

375-
writeln!(buffer, "* `{title_name}`{aliases} — {about}",)?;
391+
writeln!(buffer, "* `{title_name}` — {about}",)?;
376392
}
377393

378394
write!(buffer, "\n")?;
@@ -425,6 +441,7 @@ fn build_command_markdown(
425441
command_path.clone(),
426442
subcommand,
427443
depth + 1,
444+
options,
428445
)?;
429446
}
430447

@@ -474,8 +491,12 @@ fn write_arg_markdown(buffer: &mut String, arg: &clap::Arg) -> fmt::Result {
474491
}
475492

476493
if let Some(aliases) = arg.get_visible_aliases().as_deref() {
477-
if let Some(aliases) = get_alias_str(aliases) {
478-
write!(buffer, " {aliases}")?;
494+
if let Some(aliases_str) = get_alias_string(aliases) {
495+
write!(
496+
buffer,
497+
" [{}: {aliases_str}]",
498+
pluralize(aliases.len(), "alias", "aliases")
499+
)?;
479500
}
480501
}
481502

@@ -605,30 +626,16 @@ fn indent(s: &str, first: &str, rest: &str) -> String {
605626
result
606627
}
607628

608-
fn wrap_with(s: &str, wrapper: &str) -> String {
609-
format!("{wrapper}{s}{wrapper}")
610-
}
611-
612-
fn wrap_with_backticks(s: &str) -> String {
613-
wrap_with(s, "`")
614-
}
615-
616-
fn get_alias_str(aliases: &[&str]) -> Option<String> {
629+
fn get_alias_string(aliases: &[&str]) -> Option<String> {
617630
if aliases.is_empty() {
618631
return None;
619632
}
620633

621-
let prefix = if aliases.len() == 1 {
622-
"alias"
623-
} else {
624-
"aliases"
625-
};
626-
627634
Some(format!(
628-
"[{prefix}: {}]",
635+
"{}",
629636
aliases
630637
.iter()
631-
.map(|s| wrap_with_backticks(s))
638+
.map(|alias| format!("`{alias}`"))
632639
.collect::<Vec<_>>()
633640
.join(", ")
634641
))

src/utils.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pub fn pluralize<T>(len: usize, singular: T, plural: T) -> T {
2+
match len {
3+
1 => singular,
4+
_ => plural,
5+
}
6+
}

tests/test_examples.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ fn test_example_complex_app() {
2020
.title("Some Custom Title for Complex App".to_string())
2121
.show_footer(false)
2222
.show_table_of_contents(false)
23+
.show_aliases(false)
2324
),
2425
include_str!("../docs/examples/complex-app-custom.md"),
2526
"Mismatch testing CUSTOM Markdown output"

0 commit comments

Comments
 (0)