Skip to content

Commit

Permalink
fixup! feat(derive): Support markdown
Browse files Browse the repository at this point in the history
  • Loading branch information
ModProg committed Jan 29, 2025
1 parent fbc7d0e commit 35eac60
Show file tree
Hide file tree
Showing 14 changed files with 659 additions and 71 deletions.
33 changes: 33 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ rustversion = "1.0.15"
# Cutting out `filesystem` feature
trycmd = { version = "0.15.3", default-features = false, features = ["color-auto", "diff", "examples"] }
humantime = "2.1.0"
snapbox = "0.6.16"
snapbox = { version = "0.6.16", features = ["term-svg"] }
shlex = "1.3.0"
automod = "1.0.14"
clap-cargo = { version = "0.14.1", default-features = false }
Expand All @@ -205,10 +205,6 @@ name = "cargo-example-derive"
required-features = ["derive", "color"]
doc-scrape-examples = true

[[example]]
name = "markdown-derive"
required-features = ["derive"]

[[example]]
name = "escaped-positional"
required-features = ["cargo"]
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ _FEATURES_minimal = --no-default-features --features "std"
_FEATURES_default =
_FEATURES_wasm = --no-default-features --features "std help usage error-context suggestions" --features "deprecated derive cargo env unicode string"
_FEATURES_full = --features "deprecated derive cargo env unicode string wrap_help unstable-ext"
_FEATURES_next = ${_FEATURES_full} --features unstable-v5
_FEATURES_next = ${_FEATURES_full} --features "unstable-v5 unstable-markdown"
_FEATURES_debug = ${_FEATURES_full} --features debug --features clap_complete/debug
_FEATURES_release = ${_FEATURES_full} --release

Expand Down
79 changes: 56 additions & 23 deletions clap_derive/src/utils/doc_comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ fn parse_markdown(lines: &[String]) -> (String, Option<String>) {
(short, Some(long))
} else {
let short = merge_lines(lines);
let short = remove_period(short);
(short, None)
}
}
Expand All @@ -144,30 +143,40 @@ mod markdown {
#[derive(Default)]
struct MarkdownWriter {
output: String,
indentation: usize,
prefix: &'static str,
/// Prefix inserted for each line.
prefix: String,
/// Should an empty line be inserted before the next anything.
hanging_paragraph: bool,
/// Are we in an empty line
dirty_line: bool,
styles: Vec<Style>,
}

impl MarkdownWriter {
fn newline(&mut self) {
self.reset();
self.output.push('\n');
self.dirty_line = false;
}
fn endline(&mut self) {
if !self.output.ends_with('\n') {
if self.dirty_line {
self.newline();
}
}
fn new_paragraph(&mut self) {
self.endline();
self.newline();
self.hanging_paragraph = true;
}

fn write_fmt(&mut self, arguments: fmt::Arguments<'_>) {
if self.output.ends_with('\n') {
write!(self.output, "{}{: <2$}", self.prefix, "", self.indentation).unwrap();
if self.hanging_paragraph {
self.hanging_paragraph = false;
self.newline();
}
if !self.dirty_line {
self.output.push_str(&self.prefix);
self.apply_styles();
self.dirty_line = true;
}
self.output.write_fmt(arguments).unwrap();
}
Expand Down Expand Up @@ -204,6 +213,20 @@ mod markdown {
write!(self.output, "{style}").unwrap();
}
}

fn remove_prefix(&mut self, quote_prefix: &str) {
debug_assert!(self.prefix.ends_with(quote_prefix));
let new_len = self.prefix.len() - quote_prefix.len();
self.prefix.truncate(new_len);
}

fn add_prefix(&mut self, quote_prefix: &str) {
if self.hanging_paragraph {
self.hanging_paragraph = false;
self.newline();
}
self.prefix += quote_prefix;
}
}

pub(super) fn parse_markdown(input: &[String]) -> (String, Option<String>) {
Expand All @@ -216,19 +239,24 @@ mod markdown {
let style_strike_through = Style::new().strikethrough();
let style_link = Style::new().underline();
let style_code = Style::new().bold();
let tab_width = 2;
let list_symbol = '-';
let quote_prefix = "| ";
let indentation = " ";

let input = input.join("\n");
let input = Parser::new_ext(&input, parsing_options);

let mut short = None;
let mut has_details = false;

let mut writer = MarkdownWriter::default();

let mut list_indices = Vec::new();

for event in input {
if short.is_some() {
has_details = true;
}
match event {
Event::Start(Tag::Paragraph) => { /* nothing to do */ }
Event::End(TagEnd::Paragraph) => {
Expand All @@ -245,22 +273,24 @@ mod markdown {
}

Event::Start(Tag::Image { .. } | Tag::HtmlBlock) => { /* IGNORED */ }
Event::End(TagEnd::Image | TagEnd::HtmlBlock) => { /* IGNORED */ }
Event::End(TagEnd::Image) => { /* IGNORED */ }
Event::End(TagEnd::HtmlBlock) => writer.new_paragraph(),

Event::Start(Tag::BlockQuote(_)) => writer.prefix = " | ",
Event::Start(Tag::BlockQuote(_)) => writer.add_prefix(quote_prefix),
Event::End(TagEnd::BlockQuote(_)) => {
writer.prefix = "";
writer.remove_prefix(quote_prefix);
writer.new_paragraph();
}

Event::Start(Tag::CodeBlock(_)) => {
writer.indentation += 2;
writer.add_prefix(indentation);
writer.start_style(style_code);
}
Event::End(TagEnd::CodeBlock) => {
writer.indentation -= 2;
writer.remove_prefix(indentation);
writer.end_style(style_code);
writer.new_paragraph();
writer.dirty_line = false;
writer.hanging_paragraph = true;
}

Event::Start(Tag::List(list_start)) => {
Expand All @@ -271,7 +301,7 @@ mod markdown {
let list = list_indices.pop();
debug_assert!(list.is_some());
if list_indices.is_empty() {
writer.newline();
writer.new_paragraph();
}
}
Event::Start(Tag::Item) => {
Expand All @@ -281,10 +311,10 @@ mod markdown {
} else {
write!(writer, "{list_symbol} ");
}
writer.indentation += tab_width;
writer.add_prefix(indentation);
}
Event::End(TagEnd::Item) => {
writer.indentation -= tab_width;
writer.remove_prefix(indentation);
writer.endline();
}

Expand Down Expand Up @@ -313,6 +343,9 @@ mod markdown {
writer.endline();
write!(writer, "{line}");
}
if segment.ends_with('\n') {
writer.endline();
}
}

Event::Code(code) => {
Expand All @@ -329,9 +362,9 @@ mod markdown {
Event::HardBreak => writer.endline(),

Event::Rule => {
writer.endline();
writer.newline();
write!(writer, "---\n\n");
writer.new_paragraph();
write!(writer, "---");
writer.new_paragraph();
}

// Markdown features currently not supported
Expand Down Expand Up @@ -365,9 +398,9 @@ mod markdown {
}
}
}
let short = short.unwrap_or_else(|| writer.output.trim().to_owned());
let long = writer.output.trim();
let long = (short != long).then(|| long.to_owned());
let short = short.unwrap_or_else(|| writer.output.trim_end().to_owned());
let long = writer.output.trim_end();
let long = has_details.then(|| long.to_owned());
(short, long)
}
}
40 changes: 0 additions & 40 deletions examples/markdown-derive.rs

This file was deleted.

4 changes: 2 additions & 2 deletions examples/typed-derive.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ $ typed-derive --help
Usage: typed-derive[EXE] [OPTIONS]

Options:
-O <OPTIMIZATION> Implicitly using std::str::FromStr
-O <OPTIMIZATION> Implicitly using `std::str::FromStr`
-I <DIR> Allow invalid UTF-8 paths
--bind <BIND> Handle IP addresses
--sleep <SLEEP> Allow human-readable durations
-D <DEFINES> Hand-written parser for tuples
--port <PORT> Support for discrete numbers [default: 22] [possible values: 22, 80]
--log-level <LOG_LEVEL> Support enums from a foreign crate that don't implement ValueEnum [default: info] [possible values: trace, debug, info, warn, error]
--log-level <LOG_LEVEL> Support enums from a foreign crate that don't implement `ValueEnum` [default: info] [possible values: trace, debug, info, warn, error]
-h, --help Print help

```
Expand Down
Loading

0 comments on commit 35eac60

Please sign in to comment.