Skip to content

Commit

Permalink
Use markdown module to render descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
jirutka committed Apr 17, 2023
1 parent f215ec1 commit 900d45d
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The public API of this library consists primarily of the `FromArgs` derive and t
* Derive-based API – you define structs and enums for the parsed values, use attributes to specify how they should be parsed and a procedural derive macro will generate the parser at compile-time.
* Context-sensitive parsing.
* Support for subcommands.
* Help message generator with dynamic wrapping based on terminal width.
* Help message generator with Markdown support and dynamic wrapping based on terminal width.


== Origins
Expand Down
31 changes: 31 additions & 0 deletions argp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,37 @@
//! real_first_arg: String,
//! }
//! ```
//!
//! ### Markdown
//!
//! Any descriptions provided as a doc comment (or `doc` attribute) are
//! interpreted as Markdown and converted to plain text (at build time) as shown
//! in the table below. The output format may change slightly in the future.
//!
//! | Markdown | Output |
//! |:------------------------------------------------|:----------------------------------------------------|
//! | `# Heading`, `## Heading`, ... | `Heading` |
//! | `*italic*`, `_italic_` | `italic` |
//! | `**bold**`, `__bold__` | `*bold*` |
//! | `` `monospace` `` | `` `monospace` `` |
//! | `[link title](https://example.org)` | `https://example.org` |
//! | <pre>* unordered list<br> - nested list </pre> | <pre>* unordered list<br> * nested list </pre> |
//! | <pre>1. ordered list<br> 1. nested list </pre> | <pre>1. ordered list<br> 1. nested list </pre> |
//! | <pre>\```<br>code<br>block<br>\``` </pre> | <pre>code<br>block </pre> |
//! | <pre>> block<br>> quote<br>><br>>> nested</pre> | <pre> block<br> quote<br><br> nested </pre> |
//! | `<p>html</p>` | `<p>html</p>` |
//! | `Line<br>break` | <pre>Line<br>break </pre> |
//!
//! If you want to remove an implicit blank line between two blocks, for example
//! a paragraph and a list, you can do this with `<br>`:
//!
//! ```plain
//! List of items:<br>
//! * one
//! * two
//! ```
//!
//! This can also be used to write several empty lines in a row, which would otherwise be stripped.

#![deny(missing_docs)]

Expand Down
24 changes: 11 additions & 13 deletions argp_derive/src/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,19 +154,17 @@ pub fn require_description(
desc: &Option<Description>,
kind: &str, // the thing being described ("type" or "field"),
) -> String {
desc.as_ref()
.map(|d| d.lines.join("").trim().to_owned())
.unwrap_or_else(|| {
errors.err_span(
err_span,
&format!(
"#[derive(FromArgs)] {} with no description.
desc.as_ref().map(|d| d.to_string()).unwrap_or_else(|| {
errors.err_span(
err_span,
&format!(
"#[derive(FromArgs)] {} with no description.
Add a doc comment or an `#[argp(description = \"...\")]` attribute.",
kind
),
);
"".to_string()
})
kind
),
);
"".to_string()
})
}

fn positional_info(field: &StructField<'_>) -> TokenStream {
Expand All @@ -180,7 +178,7 @@ fn positional_info(field: &StructField<'_>) -> TokenStream {
field_name = field.positional_arg_name();

if let Some(desc) = &field.attrs.description {
description = desc.lines.join("").trim().to_owned()
description = desc.to_string()
}
}

Expand Down
16 changes: 16 additions & 0 deletions argp_derive/src/parse_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use proc_macro2::Span;

use crate::errors::Errors;
use crate::markdown;

/// Attributes applied to a field of a `#![derive(FromArgs)]` struct.
#[derive(Default)]
Expand Down Expand Up @@ -209,6 +210,21 @@ impl FieldAttrs {
}
}

impl ToString for Description {
fn to_string(&self) -> String {
if self.explicit {
self.lines.join("\n")
} else {
let mut buf = String::new();
for line in &self.lines {
buf.push_str(&line.replace('\n', "\\n"));
buf.push('\n');
}
markdown::to_plain_text(&buf)
}
}
}

pub(crate) fn check_long_name(errors: &Errors, spanned: &impl syn::spanned::Spanned, value: &str) {
if !value.is_ascii() {
errors.err(spanned, "Long names must be ASCII");
Expand Down

0 comments on commit 900d45d

Please sign in to comment.