From 2318d55538f36c38613f9ef09c3dea24ba01c02a Mon Sep 17 00:00:00 2001 From: Connor Gray Date: Sat, 15 Jun 2024 13:40:17 -0700 Subject: [PATCH] [PR Integration] Use `display_name` wherever possible + table of contents option (#27) clap-markdown will now use the `Command.display_name` property if set to render the name of the command in the title, command section name, and usage messages. A new `MarkdownOptions.show_table_of_contents()` control has also been added, so users can choose to omit the generated table of contents if desired. * prefer use display name wherever possible * refactoring + use display name then fallback to bin name then to package name * extract the function to a util * move util fn downstairs * simplify the utility function * integration: Update new tests after rebase * integration: Move match out of write!(..) call * integration: Make comment into doc comment + add detail about Command.name * integation+bugfix: Fix regression, document title missing `..` * integration: Update CHANGELOG.md --------- Co-authored-by: Connor Gray Co-authored-by: Laurynas Keturakis Co-authored-by: Benno van den Berg --- docs/CHANGELOG.md | 13 ++++++ docs/examples/complex-app-custom.md | 6 --- src/lib.rs | 68 ++++++++++++++++++++--------- tests/test_examples.rs | 1 + tests/test_markdown.rs | 16 +++---- 5 files changed, 70 insertions(+), 34 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index e692b31..5e9280e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -18,6 +18,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Contents of the command title header. - Whether to show the footer explaining the documentation was generated with `clap-markdown`. + - Whether to show the command overview table of contents. + +### Changed + +* `clap-markdown` will now respect the `Command.display_name` property, if set, + and use it in the rendered Markdown when showing the name and usage of the + command. + ([#27], + co-authored-by [@keturiosakys](https://github.com/keturiosakys) + and [@hatchan](https://github.com/hatchan)) @@ -116,6 +126,9 @@ Initial release of `clap-markdown`. [#11]: https://github.com/ConnorGray/clap-markdown/pull/11 + +[#27]: https://github.com/ConnorGray/clap-markdown/pull/27 + [unreleased]: https://github.com/ConnorGray/clap-markdown/compare/v0.1.3...HEAD [0.1.3]: https://github.com/ConnorGray/clap-markdown/compare/v0.1.2...v0.1.3 diff --git a/docs/examples/complex-app-custom.md b/docs/examples/complex-app-custom.md index bdb1fa9..5611c75 100644 --- a/docs/examples/complex-app-custom.md +++ b/docs/examples/complex-app-custom.md @@ -2,12 +2,6 @@ This document contains the help content for the `complex-app` command-line program. -**Command Overview:** - -* [`complex-app`↴](#complex-app) -* [`complex-app test`↴](#complex-app-test) -* [`complex-app only-hidden-options`↴](#complex-app-only-hidden-options) - ## `complex-app` An example command-line tool diff --git a/src/lib.rs b/src/lib.rs index b90b5cf..eeeb7c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,7 @@ use clap::builder::PossibleValue; pub struct MarkdownOptions { title: Option, show_footer: bool, + show_table_of_contents: bool, } impl MarkdownOptions { @@ -35,6 +36,7 @@ impl MarkdownOptions { return Self { title: None, show_footer: true, + show_table_of_contents: true, }; } @@ -51,6 +53,13 @@ impl MarkdownOptions { return self; } + + /// Whether to show the default table of contents. + pub fn show_table_of_contents(mut self, show: bool) -> Self { + self.show_table_of_contents = show; + + return self; + } } impl Default for MarkdownOptions { @@ -122,21 +131,18 @@ fn write_help_markdown( // Write the document title //---------------------------------- - let title_name = match command.get_display_name() { - Some(display_name) => display_name.to_owned(), - None => format!("`{}`", command.get_name()), - }; + let title_name = get_canonical_name(command); let title = match options.title { Some(ref title) => title.to_owned(), - None => format!("Command-Line Help for {title_name}"), + None => format!("Command-Line Help for `{title_name}`"), }; writeln!(buffer, "# {title}\n",).unwrap(); writeln!( buffer, "This document contains the help content for the `{}` command-line program.\n", - command.get_name() + title_name ).unwrap(); //---------------------------------- @@ -147,11 +153,14 @@ fn write_help_markdown( // build_table_of_contents_html(buffer, Vec::new(), command, 0).unwrap(); // writeln!(buffer, "").unwrap(); - writeln!(buffer, "**Command Overview:**\n").unwrap(); + if options.show_table_of_contents { + writeln!(buffer, "**Command Overview:**\n").unwrap(); - build_table_of_contents_markdown(buffer, Vec::new(), command, 0).unwrap(); + build_table_of_contents_markdown(buffer, Vec::new(), command, 0) + .unwrap(); - write!(buffer, "\n").unwrap(); + write!(buffer, "\n").unwrap(); + } //---------------------------------------- // Write the commands/subcommands sections @@ -186,10 +195,12 @@ fn build_table_of_contents_markdown( return Ok(()); } + let title_name = get_canonical_name(command); + // Append the name of `command` to `command_path`. let command_path = { let mut command_path = parent_command_path; - command_path.push(command.get_name().to_owned()); + command_path.push(title_name); command_path }; @@ -274,10 +285,12 @@ fn build_command_markdown( return Ok(()); } + let title_name = get_canonical_name(command); + // Append the name of `command` to `command_path`. let command_path = { let mut command_path = parent_command_path.clone(); - command_path.push(command.get_name().to_owned()); + command_path.push(title_name); command_path }; @@ -350,15 +363,14 @@ fn build_command_markdown( continue; } - writeln!( - buffer, - "* `{}` — {}", - subcommand.get_name(), - match subcommand.get_about() { - Some(about) => about.to_string(), - None => String::new(), - } - )?; + let title_name = get_canonical_name(subcommand); + + let about = match subcommand.get_about() { + Some(about) => about.to_string(), + None => String::new(), + }; + + writeln!(buffer, "* `{title_name}` — {about}",)?; } write!(buffer, "\n")?; @@ -548,6 +560,22 @@ fn write_arg_markdown(buffer: &mut String, arg: &clap::Arg) -> fmt::Result { Ok(()) } +/// Utility function to get the canonical name of a command. +/// +/// It's logic is to get the display name if it exists, otherwise get the bin +/// name if it exists, otherwise get the package name. +/// +/// Note that the default `Command.name` field of a clap command is typically +/// meant for programmatic usage as well as for display (if no `display_name` +/// override is set). +fn get_canonical_name(command: &clap::Command) -> String { + command + .get_display_name() + .or_else(|| command.get_bin_name()) + .map(|name| name.to_owned()) + .unwrap_or_else(|| command.get_name().to_owned()) +} + /// Indents non-empty lines. The output always ends with a newline. fn indent(s: &str, first: &str, rest: &str) -> String { if s.is_empty() { diff --git a/tests/test_examples.rs b/tests/test_examples.rs index c6652d8..568c2bf 100644 --- a/tests/test_examples.rs +++ b/tests/test_examples.rs @@ -19,6 +19,7 @@ fn test_example_complex_app() { &MarkdownOptions::new() .title(format!("Some Custom Title for Complex App")) .show_footer(false) + .show_table_of_contents(false) ), include_str!("../docs/examples/complex-app-custom.md"), "Mismatch testing CUSTOM Markdown output" diff --git a/tests/test_markdown.rs b/tests/test_markdown.rs index e724775..d44aa5a 100644 --- a/tests/test_markdown.rs +++ b/tests/test_markdown.rs @@ -54,15 +54,15 @@ Options: &MarkdownOptions::new().show_footer(false) ), "\ -# Command-Line Help for my-program-display-name +# Command-Line Help for `my-program-display-name` -This document contains the help content for the `my-program-name` command-line program. +This document contains the help content for the `my-program-display-name` command-line program. **Command Overview:** -* [`my-program-name`↴](#my-program-name) +* [`my-program-display-name`↴](#my-program-display-name) -## `my-program-name` +## `my-program-display-name` This program does things. @@ -129,15 +129,15 @@ Options: &MarkdownOptions::new().show_footer(false) ), "\ -# Command-Line Help for my-program-display-name +# Command-Line Help for `my-program-display-name` -This document contains the help content for the `my-program-name` command-line program. +This document contains the help content for the `my-program-display-name` command-line program. **Command Overview:** -* [`my-program-name`↴](#my-program-name) +* [`my-program-display-name`↴](#my-program-display-name) -## `my-program-name` +## `my-program-display-name` This program does things.