mirror of
https://github.com/uutils/coreutils
synced 2024-12-14 15:22:38 +00:00
Merge pull request #4385 from cakebaker/uucore_procs_help_about
uucore_procs: extract "about" and "usage" info from new help structure
This commit is contained in:
commit
f77a44df8b
17 changed files with 133 additions and 74 deletions
|
@ -1,12 +1,9 @@
|
||||||
# base32
|
# base32
|
||||||
|
|
||||||
## Usage
|
|
||||||
```
|
```
|
||||||
base32 [OPTION]... [FILE]
|
base32 [OPTION]... [FILE]
|
||||||
```
|
```
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
encode/decode data and print to standard output
|
encode/decode data and print to standard output
|
||||||
With no FILE, or when FILE is -, read standard input.
|
With no FILE, or when FILE is -, read standard input.
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
use std::io::{stdin, Read};
|
use std::io::{stdin, Read};
|
||||||
|
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use uucore::{encoding::Format, error::UResult, help_section, help_usage};
|
use uucore::{encoding::Format, error::UResult, help_about, help_usage};
|
||||||
|
|
||||||
pub mod base_common;
|
pub mod base_common;
|
||||||
|
|
||||||
const ABOUT: &str = help_section!("about", "base32.md");
|
const ABOUT: &str = help_about!("base32.md");
|
||||||
const USAGE: &str = help_usage!("base32.md");
|
const USAGE: &str = help_usage!("base32.md");
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
# base64
|
# base64
|
||||||
|
|
||||||
## Usage
|
|
||||||
```
|
```
|
||||||
base64 [OPTION]... [FILE]
|
base64 [OPTION]... [FILE]
|
||||||
```
|
```
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
encode/decode data and print to standard output
|
encode/decode data and print to standard output
|
||||||
With no FILE, or when FILE is -, read standard input.
|
With no FILE, or when FILE is -, read standard input.
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
use uu_base32::base_common;
|
use uu_base32::base_common;
|
||||||
pub use uu_base32::uu_app;
|
pub use uu_base32::uu_app;
|
||||||
|
|
||||||
use uucore::{encoding::Format, error::UResult, help_section, help_usage};
|
use uucore::{encoding::Format, error::UResult, help_about, help_usage};
|
||||||
|
|
||||||
use std::io::{stdin, Read};
|
use std::io::{stdin, Read};
|
||||||
|
|
||||||
const ABOUT: &str = help_section!("about", "base64.md");
|
const ABOUT: &str = help_about!("base64.md");
|
||||||
const USAGE: &str = help_usage!("base64.md");
|
const USAGE: &str = help_usage!("base64.md");
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
# cat
|
# cat
|
||||||
|
|
||||||
## Usage
|
|
||||||
```
|
```
|
||||||
cat [OPTION]... [FILE]...
|
cat [OPTION]... [FILE]...
|
||||||
```
|
```
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
Concatenate FILE(s), or standard input, to standard output
|
Concatenate FILE(s), or standard input, to standard output
|
||||||
With no FILE, or when FILE is -, read standard input.
|
With no FILE, or when FILE is -, read standard input.
|
||||||
|
|
|
@ -33,10 +33,10 @@ use std::net::Shutdown;
|
||||||
use std::os::unix::fs::FileTypeExt;
|
use std::os::unix::fs::FileTypeExt;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
use uucore::{format_usage, help_section, help_usage};
|
use uucore::{format_usage, help_about, help_usage};
|
||||||
|
|
||||||
const USAGE: &str = help_usage!("cat.md");
|
const USAGE: &str = help_usage!("cat.md");
|
||||||
const ABOUT: &str = help_section!("about", "cat.md");
|
const ABOUT: &str = help_about!("cat.md");
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
enum CatError {
|
enum CatError {
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
# cp
|
# cp
|
||||||
|
|
||||||
## Usage
|
|
||||||
```
|
```
|
||||||
cp [OPTION]... [-T] SOURCE DEST
|
cp [OPTION]... [-T] SOURCE DEST
|
||||||
cp [OPTION]... SOURCE... DIRECTORY
|
cp [OPTION]... SOURCE... DIRECTORY
|
||||||
cp [OPTION]... -t DIRECTORY SOURCE...
|
cp [OPTION]... -t DIRECTORY SOURCE...
|
||||||
```
|
```
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
|
Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
|
||||||
|
|
|
@ -40,7 +40,7 @@ use uucore::error::{set_exit_code, UClapError, UError, UResult, UUsageError};
|
||||||
use uucore::fs::{
|
use uucore::fs::{
|
||||||
canonicalize, paths_refer_to_same_file, FileInformation, MissingHandling, ResolveMode,
|
canonicalize, paths_refer_to_same_file, FileInformation, MissingHandling, ResolveMode,
|
||||||
};
|
};
|
||||||
use uucore::{crash, format_usage, help_section, help_usage, prompt_yes, show_error, show_warning};
|
use uucore::{crash, format_usage, help_about, help_usage, prompt_yes, show_error, show_warning};
|
||||||
|
|
||||||
use crate::copydir::copy_directory;
|
use crate::copydir::copy_directory;
|
||||||
|
|
||||||
|
@ -228,11 +228,11 @@ pub struct Options {
|
||||||
progress_bar: bool,
|
progress_bar: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const ABOUT: &str = help_section!("about", "cp.md");
|
const ABOUT: &str = help_about!("cp.md");
|
||||||
static EXIT_ERR: i32 = 1;
|
|
||||||
|
|
||||||
const USAGE: &str = help_usage!("cp.md");
|
const USAGE: &str = help_usage!("cp.md");
|
||||||
|
|
||||||
|
static EXIT_ERR: i32 = 1;
|
||||||
|
|
||||||
// Argument constants
|
// Argument constants
|
||||||
mod options {
|
mod options {
|
||||||
pub const ARCHIVE: &str = "archive";
|
pub const ARCHIVE: &str = "archive";
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<!-- spell-checker:ignore convs iseek oseek -->
|
<!-- spell-checker:ignore convs iseek oseek -->
|
||||||
# dd
|
# dd
|
||||||
|
|
||||||
## About
|
```
|
||||||
|
dd [OPERAND]...
|
||||||
|
dd OPTION
|
||||||
|
```
|
||||||
|
|
||||||
Copy, and optionally convert, a file system resource
|
Copy, and optionally convert, a file system resource
|
||||||
|
|
||||||
## After Help
|
## After Help
|
||||||
|
|
|
@ -39,11 +39,11 @@ use clap::{crate_version, Arg, Command};
|
||||||
use gcd::Gcd;
|
use gcd::Gcd;
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::{FromIo, UResult};
|
use uucore::error::{FromIo, UResult};
|
||||||
use uucore::help_section;
|
use uucore::{format_usage, help_about, help_section, help_usage, show_error};
|
||||||
use uucore::show_error;
|
|
||||||
|
|
||||||
const ABOUT: &str = help_section!("about", "dd.md");
|
const ABOUT: &str = help_about!("dd.md");
|
||||||
const AFTER_HELP: &str = help_section!("after help", "dd.md");
|
const AFTER_HELP: &str = help_section!("after help", "dd.md");
|
||||||
|
const USAGE: &str = help_usage!("dd.md");
|
||||||
const BUF_INIT_BYTE: u8 = 0xDD;
|
const BUF_INIT_BYTE: u8 = 0xDD;
|
||||||
|
|
||||||
/// Final settings after parsing
|
/// Final settings after parsing
|
||||||
|
@ -832,6 +832,7 @@ pub fn uu_app() -> Command {
|
||||||
Command::new(uucore::util_name())
|
Command::new(uucore::util_name())
|
||||||
.version(crate_version!())
|
.version(crate_version!())
|
||||||
.about(ABOUT)
|
.about(ABOUT)
|
||||||
|
.override_usage(format_usage(USAGE))
|
||||||
.after_help(AFTER_HELP)
|
.after_help(AFTER_HELP)
|
||||||
.infer_long_args(true)
|
.infer_long_args(true)
|
||||||
.arg(Arg::new(options::OPERANDS).num_args(1..))
|
.arg(Arg::new(options::OPERANDS).num_args(1..))
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
# expr
|
# expr
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
Print the value of `EXPRESSION` to standard output
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
```
|
```
|
||||||
expr [EXPRESSION]
|
expr [EXPRESSION]
|
||||||
expr [OPTIONS]
|
expr [OPTIONS]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Print the value of `EXPRESSION` to standard output
|
||||||
|
|
||||||
## After help
|
## After help
|
||||||
|
|
||||||
Print the value of `EXPRESSION` to standard output. A blank line below
|
Print the value of `EXPRESSION` to standard output. A blank line below
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use clap::{crate_version, Arg, ArgAction, Command};
|
use clap::{crate_version, Arg, ArgAction, Command};
|
||||||
use uucore::{
|
use uucore::{
|
||||||
error::{UResult, USimpleError},
|
error::{UResult, USimpleError},
|
||||||
format_usage, help_section, help_usage,
|
format_usage, help_about, help_section, help_usage,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod syntax_tree;
|
mod syntax_tree;
|
||||||
|
@ -23,7 +23,7 @@ mod options {
|
||||||
pub fn uu_app() -> Command {
|
pub fn uu_app() -> Command {
|
||||||
Command::new(uucore::util_name())
|
Command::new(uucore::util_name())
|
||||||
.version(crate_version!())
|
.version(crate_version!())
|
||||||
.about(help_section!("about", "expr.md"))
|
.about(help_about!("expr.md"))
|
||||||
.override_usage(format_usage(help_usage!("expr.md")))
|
.override_usage(format_usage(help_usage!("expr.md")))
|
||||||
.after_help(help_section!("after help", "expr.md"))
|
.after_help(help_section!("after help", "expr.md"))
|
||||||
.infer_long_args(true)
|
.infer_long_args(true)
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
<!-- spell-checker:ignore N'th M'th -->
|
<!-- spell-checker:ignore N'th M'th -->
|
||||||
# numfmt
|
# numfmt
|
||||||
|
|
||||||
## Usage
|
|
||||||
```
|
```
|
||||||
numfmt [OPTION]... [NUMBER]...
|
numfmt [OPTION]... [NUMBER]...
|
||||||
```
|
```
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
Convert numbers from/to human-readable strings
|
Convert numbers from/to human-readable strings
|
||||||
|
|
||||||
## After Help
|
## After Help
|
||||||
|
|
|
@ -14,16 +14,15 @@ use std::io::{BufRead, Write};
|
||||||
use units::{IEC_BASES, SI_BASES};
|
use units::{IEC_BASES, SI_BASES};
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::UResult;
|
use uucore::error::UResult;
|
||||||
use uucore::format_usage;
|
|
||||||
use uucore::ranges::Range;
|
use uucore::ranges::Range;
|
||||||
use uucore::{help_section, help_usage};
|
use uucore::{format_usage, help_about, help_section, help_usage};
|
||||||
|
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod format;
|
pub mod format;
|
||||||
pub mod options;
|
pub mod options;
|
||||||
mod units;
|
mod units;
|
||||||
|
|
||||||
const ABOUT: &str = help_section!("about", "numfmt.md");
|
const ABOUT: &str = help_about!("numfmt.md");
|
||||||
const AFTER_HELP: &str = help_section!("after help", "numfmt.md");
|
const AFTER_HELP: &str = help_section!("after help", "numfmt.md");
|
||||||
const USAGE: &str = help_usage!("numfmt.md");
|
const USAGE: &str = help_usage!("numfmt.md");
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,9 @@ use uucore::fsext::{
|
||||||
pretty_filetype, pretty_fstype, pretty_time, read_fs_list, statfs, BirthTime, FsMeta,
|
pretty_filetype, pretty_fstype, pretty_time, read_fs_list, statfs, BirthTime, FsMeta,
|
||||||
};
|
};
|
||||||
use uucore::libc::mode_t;
|
use uucore::libc::mode_t;
|
||||||
use uucore::{entries, format_usage, help_section, help_usage, show_error, show_warning};
|
use uucore::{
|
||||||
|
entries, format_usage, help_about, help_section, help_usage, show_error, show_warning,
|
||||||
|
};
|
||||||
|
|
||||||
use clap::{crate_version, Arg, ArgAction, ArgMatches, Command};
|
use clap::{crate_version, Arg, ArgAction, ArgMatches, Command};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -24,7 +26,7 @@ use std::os::unix::fs::{FileTypeExt, MetadataExt};
|
||||||
use std::os::unix::prelude::OsStrExt;
|
use std::os::unix::prelude::OsStrExt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
const ABOUT: &str = help_section!("about", "stat.md");
|
const ABOUT: &str = help_about!("stat.md");
|
||||||
const USAGE: &str = help_usage!("stat.md");
|
const USAGE: &str = help_usage!("stat.md");
|
||||||
const LONG_USAGE: &str = help_section!("long usage", "stat.md");
|
const LONG_USAGE: &str = help_section!("long usage", "stat.md");
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
# stat
|
# stat
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
Display file or file system status.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
```
|
```
|
||||||
stat [OPTION]... FILE...
|
stat [OPTION]... FILE...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Display file or file system status.
|
||||||
|
|
||||||
## Long Usage
|
## Long Usage
|
||||||
|
|
||||||
The valid format sequences for files (without `--file-system`):
|
The valid format sequences for files (without `--file-system`):
|
||||||
|
|
|
@ -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,19 @@ fn render_markdown(s: &str) -> String {
|
||||||
s.replace('`', "")
|
s.replace('`', "")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the usage from the "Usage" section in the help file.
|
/// Get the about text from the help file.
|
||||||
|
///
|
||||||
|
/// The about text is assumed to be the text between the first markdown
|
||||||
|
/// code block and the next header, if any. It may span multiple lines.
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn help_about(input: TokenStream) -> TokenStream {
|
||||||
|
let input: Vec<TokenTree> = input.into_iter().collect();
|
||||||
|
let filename = get_argument(&input, 0, "filename");
|
||||||
|
let text: String = parse_about(&read_help(&filename));
|
||||||
|
TokenTree::Literal(Literal::string(&text)).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 +75,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("usage", &filename));
|
let text: String = parse_usage(&read_help(&filename));
|
||||||
TokenTree::Literal(Literal::string(&text)).into()
|
TokenTree::Literal(Literal::string(&text)).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +108,7 @@ pub fn help_section(input: TokenStream) -> TokenStream {
|
||||||
let input: Vec<TokenTree> = input.into_iter().collect();
|
let input: Vec<TokenTree> = input.into_iter().collect();
|
||||||
let section = get_argument(&input, 0, "section");
|
let section = get_argument(&input, 0, "section");
|
||||||
let filename = get_argument(&input, 1, "filename");
|
let filename = get_argument(&input, 1, "filename");
|
||||||
let text = parse_help(§ion, &filename);
|
let text = parse_help_section(§ion, &read_help(&filename));
|
||||||
let rendered = render_markdown(&text);
|
let rendered = render_markdown(&text);
|
||||||
TokenTree::Literal(Literal::string(&rendered)).into()
|
TokenTree::Literal(Literal::string(&rendered)).into()
|
||||||
}
|
}
|
||||||
|
@ -121,13 +135,11 @@ fn get_argument(input: &[TokenTree], index: usize, name: &str) -> String {
|
||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the help file and extract a section
|
/// Read the help file
|
||||||
fn parse_help(section: &str, filename: &str) -> String {
|
fn read_help(filename: &str) -> String {
|
||||||
let section = section.to_lowercase();
|
|
||||||
let section = section.trim_matches('"');
|
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
let mut path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
|
||||||
|
|
||||||
|
let mut path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||||
path.push(filename);
|
path.push(filename);
|
||||||
|
|
||||||
File::open(path)
|
File::open(path)
|
||||||
|
@ -135,7 +147,7 @@ fn parse_help(section: &str, filename: &str) -> String {
|
||||||
.read_to_string(&mut content)
|
.read_to_string(&mut content)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
parse_help_section(section, &content)
|
content
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a single section from content
|
/// Get a single section from content
|
||||||
|
@ -147,6 +159,8 @@ fn parse_help_section(section: &str, content: &str) -> String {
|
||||||
.map_or(false, |l| l.trim().to_lowercase() == section)
|
.map_or(false, |l| l.trim().to_lowercase() == section)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let section = §ion.to_lowercase();
|
||||||
|
|
||||||
// We cannot distinguish between an empty or non-existing section below,
|
// We cannot distinguish between an empty or non-existing section below,
|
||||||
// so we do a quick test to check whether the section exists to provide
|
// so we do a quick test to check whether the section exists to provide
|
||||||
// a nice error message.
|
// a nice error message.
|
||||||
|
@ -167,17 +181,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,12 +201,31 @@ fn parse_usage(content: &str) -> String {
|
||||||
"{}\n".to_string()
|
"{}\n".to_string()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect::<Vec<_>>()
|
||||||
|
.join("")
|
||||||
|
.trim()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses the text between the first markdown code block and the next header, if any,
|
||||||
|
/// into an about string.
|
||||||
|
fn parse_about(content: &str) -> String {
|
||||||
|
content
|
||||||
|
.lines()
|
||||||
|
.skip_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES))
|
||||||
|
.skip(1)
|
||||||
|
.skip_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES))
|
||||||
|
.skip(1)
|
||||||
|
.take_while(|l| !l.starts_with('#'))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
.trim()
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{parse_help_section, parse_usage};
|
use super::{parse_about, parse_help_section, parse_usage};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn section_parsing() {
|
fn section_parsing() {
|
||||||
|
@ -209,6 +242,10 @@ mod tests {
|
||||||
parse_help_section("some section", input),
|
parse_help_section("some section", input),
|
||||||
"This is some section"
|
"This is some section"
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_help_section("SOME SECTION", input),
|
||||||
|
"This is some section"
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_help_section("another section", input),
|
parse_help_section("another section", input),
|
||||||
"This is the other section\nwith multiple lines"
|
"This is the other section\nwith multiple lines"
|
||||||
|
@ -233,7 +270,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\
|
||||||
|
@ -244,17 +280,55 @@ 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 = "\
|
||||||
|
# ls\n\
|
||||||
```\n\
|
```\n\
|
||||||
util [some] [options]\n\
|
ls -a\n\
|
||||||
```\
|
ls -b\n\
|
||||||
"
|
ls -c\n\
|
||||||
),
|
```\n\
|
||||||
"{} [some] [options]"
|
## some section\n\
|
||||||
);
|
This is some section\n";
|
||||||
|
|
||||||
|
assert_eq!(parse_usage(input), "{} -a\n{} -b\n{} -c");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn about_parsing() {
|
||||||
|
let input = "\
|
||||||
|
# ls\n\
|
||||||
|
```\n\
|
||||||
|
ls -l\n\
|
||||||
|
```\n\
|
||||||
|
\n\
|
||||||
|
This is the about section\n\
|
||||||
|
\n\
|
||||||
|
## some section\n\
|
||||||
|
This is some section\n";
|
||||||
|
|
||||||
|
assert_eq!(parse_about(input), "This is the about section");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_line_about_parsing() {
|
||||||
|
let input = "\
|
||||||
|
# ls\n\
|
||||||
|
```\n\
|
||||||
|
ls -l\n\
|
||||||
|
```\n\
|
||||||
|
\n\
|
||||||
|
about a\n\
|
||||||
|
\n\
|
||||||
|
about b\n\
|
||||||
|
\n\
|
||||||
|
## some section\n\
|
||||||
|
This is some section\n";
|
||||||
|
|
||||||
|
assert_eq!(parse_about(input), "about a\n\nabout b");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue