uucore_procs: drop need for "Usage" header in help

This commit is contained in:
Daniel Hofstetter 2023-02-17 14:51:40 +01:00
parent 94eddc4701
commit 1ba0c6853c

View file

@ -7,6 +7,8 @@ use std::{fs::File, io::Read, path::PathBuf};
use proc_macro::{Literal, TokenStream, TokenTree}; use proc_macro::{Literal, TokenStream, TokenTree};
use quote::quote; use quote::quote;
const MARKDOWN_CODE_FENCES: &str = "```";
//## rust proc-macro background info //## rust proc-macro background info
//* ref: <https://dev.to/naufraghi/procedural-macro-in-rust-101-k3f> @@ <http://archive.is/Vbr5e> //* ref: <https://dev.to/naufraghi/procedural-macro-in-rust-101-k3f> @@ <http://archive.is/Vbr5e>
//* ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ <http://archive.is/8YDua> //* ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ <http://archive.is/8YDua>
@ -51,7 +53,7 @@ fn render_markdown(s: &str) -> String {
s.replace('`', "") s.replace('`', "")
} }
/// Get the usage from the "Usage" section in the help file. /// Get the usage from the help file.
/// ///
/// The usage is assumed to be surrounded by markdown code fences. It may span /// The usage is assumed to be surrounded by markdown code fences. It may span
/// multiple lines. The first word of each line is assumed to be the name of /// multiple lines. The first word of each line is assumed to be the name of
@ -61,7 +63,7 @@ fn render_markdown(s: &str) -> String {
pub fn help_usage(input: TokenStream) -> TokenStream { pub fn help_usage(input: TokenStream) -> TokenStream {
let input: Vec<TokenTree> = input.into_iter().collect(); let input: Vec<TokenTree> = input.into_iter().collect();
let filename = get_argument(&input, 0, "filename"); let filename = get_argument(&input, 0, "filename");
let text: String = parse_usage(&parse_help_section("usage", &read_help(&filename))); let text: String = parse_usage(&read_help(&filename));
TokenTree::Literal(Literal::string(&text)).into() TokenTree::Literal(Literal::string(&text)).into()
} }
@ -167,17 +169,17 @@ fn parse_help_section(section: &str, content: &str) -> String {
.to_string() .to_string()
} }
/// Parses a markdown code block into a usage string /// Parses the first markdown code block into a usage string
/// ///
/// The code fences are removed and the name of the util is replaced /// The code fences are removed and the name of the util is replaced
/// with `{}` so that it can be replaced with the appropriate name /// with `{}` so that it can be replaced with the appropriate name
/// at runtime. /// at runtime.
fn parse_usage(content: &str) -> String { fn parse_usage(content: &str) -> String {
content content
.strip_suffix("```")
.unwrap()
.lines() .lines()
.skip(1) // Skip the "```" of markdown syntax .skip_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES))
.skip(1)
.take_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES))
.map(|l| { .map(|l| {
// Replace the util name (assumed to be the first word) with "{}" // Replace the util name (assumed to be the first word) with "{}"
// to be replaced with the runtime value later. // to be replaced with the runtime value later.
@ -187,7 +189,10 @@ fn parse_usage(content: &str) -> String {
"{}\n".to_string() "{}\n".to_string()
} }
}) })
.collect() .collect::<Vec<_>>()
.join("")
.trim()
.to_string()
} }
#[cfg(test)] #[cfg(test)]
@ -237,7 +242,6 @@ mod tests {
fn usage_parsing() { fn usage_parsing() {
let input = "\ let input = "\
# ls\n\ # ls\n\
## Usage\n\
```\n\ ```\n\
ls -l\n\ ls -l\n\
```\n\ ```\n\
@ -248,17 +252,21 @@ mod tests {
This is the other section\n\ This is the other section\n\
with multiple lines\n"; with multiple lines\n";
assert_eq!(parse_usage(&parse_help_section("usage", input)), "{} -l",); assert_eq!(parse_usage(input), "{} -l");
}
assert_eq!( #[test]
parse_usage( fn multi_line_usage_parsing() {
"\ let input = "\
```\n\ # ls\n\
util [some] [options]\n\ ```\n\
```\ ls -a\n\
" ls -b\n\
), ls -c\n\
"{} [some] [options]" ```\n\
); ## some section\n\
This is some section\n";
assert_eq!(parse_usage(input), "{} -a\n{} -b\n{} -c");
} }
} }