uuhelp_parser-0.0.30/.cargo_vcs_info.json0000644000000001570000000000100137750ustar { "git": { "sha1": "088599f41602e0b0505543a010ec59f5f81e74b1" }, "path_in_vcs": "src/uuhelp_parser" }uuhelp_parser-0.0.30/Cargo.toml0000644000000016460000000000100117770ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "uuhelp_parser" version = "0.0.30" build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "A collection of functions to parse the markdown code of help files" homepage = "https://github.com/uutils/coreutils" readme = false license = "MIT" repository = "https://github.com/uutils/coreutils/tree/main/src/uuhelp_parser" [lib] name = "uuhelp_parser" path = "src/lib.rs" uuhelp_parser-0.0.30/Cargo.toml.orig000064400000000000000000000005071046102023000154530ustar 00000000000000# spell-checker:ignore uuhelp [package] name = "uuhelp_parser" version = "0.0.30" edition = "2021" license = "MIT" description = "A collection of functions to parse the markdown code of help files" homepage = "https://github.com/uutils/coreutils" repository = "https://github.com/uutils/coreutils/tree/main/src/uuhelp_parser" uuhelp_parser-0.0.30/LICENSE000064400000000000000000000020401046102023000135630ustar 00000000000000Copyright (c) uutils developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. uuhelp_parser-0.0.30/src/lib.rs000064400000000000000000000140561046102023000144730ustar 00000000000000// This file is part of the uutils coreutils package. // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. #![deny(missing_docs)] //! A collection of functions to parse the markdown code of help files. //! //! The structure of the markdown code is assumed to be: //! //! # util name //! //! ```text //! usage info //! ``` //! //! About text //! //! ## Section 1 //! //! Some content //! //! ## Section 2 //! //! Some content const MARKDOWN_CODE_FENCES: &str = "```"; /// Parses the text between the first markdown code block and the next header, if any, /// into an about string. pub 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::>() .join("\n") .trim() .to_string() } /// Parses the first markdown code block into a usage string /// /// The code fences are removed and the name of the util is replaced /// with `{}` so that it can be replaced with the appropriate name /// at runtime. pub fn parse_usage(content: &str) -> String { content .lines() .skip_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES)) .skip(1) .take_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES)) .map(|l| { // Replace the util name (assumed to be the first word) with "{}" // to be replaced with the runtime value later. if let Some((_util, args)) = l.split_once(' ') { format!("{{}} {args}\n") } else { "{}\n".to_string() } }) .collect::() .trim() .to_string() } /// Get a single section from content /// /// The section must be a second level section (i.e. start with `##`). pub fn parse_section(section: &str, content: &str) -> Option { fn is_section_header(line: &str, section: &str) -> bool { line.strip_prefix("##") .is_some_and(|l| l.trim().to_lowercase() == section) } let section = §ion.to_lowercase(); // We cannot distinguish between an empty or non-existing section below, // so we do a quick test to check whether the section exists if content.lines().all(|l| !is_section_header(l, section)) { return None; } // Prefix includes space to allow processing of section with level 3-6 headers let section_header_prefix = "## "; Some( content .lines() .skip_while(|&l| !is_section_header(l, section)) .skip(1) .take_while(|l| !l.starts_with(section_header_prefix)) .collect::>() .join("\n") .trim() .to_string(), ) } #[cfg(test)] mod tests { use super::*; #[test] fn test_parse_section() { let input = "\ # ls\n\ ## some section\n\ This is some section\n\ \n\ ## ANOTHER SECTION This is the other section\n\ with multiple lines\n"; assert_eq!( parse_section("some section", input).unwrap(), "This is some section" ); assert_eq!( parse_section("SOME SECTION", input).unwrap(), "This is some section" ); assert_eq!( parse_section("another section", input).unwrap(), "This is the other section\nwith multiple lines" ); } #[test] fn test_parse_section_with_sub_headers() { let input = "\ # ls\n\ ## after section\n\ This is some section\n\ \n\ ### level 3 header\n\ \n\ Additional text under the section.\n\ \n\ #### level 4 header\n\ \n\ Yet another paragraph\n"; assert_eq!( parse_section("after section", input).unwrap(), "This is some section\n\n\ ### level 3 header\n\n\ Additional text under the section.\n\n\ #### level 4 header\n\n\ Yet another paragraph" ); } #[test] fn test_parse_non_existing_section() { let input = "\ # ls\n\ ## some section\n\ This is some section\n\ \n\ ## ANOTHER SECTION This is the other section\n\ with multiple lines\n"; assert!(parse_section("non-existing section", input).is_none()); } #[test] fn test_parse_usage() { let input = "\ # ls\n\ ```\n\ ls -l\n\ ```\n\ ## some section\n\ This is some section\n\ \n\ ## ANOTHER SECTION This is the other section\n\ with multiple lines\n"; assert_eq!(parse_usage(input), "{} -l"); } #[test] fn test_parse_multi_line_usage() { let input = "\ # ls\n\ ```\n\ ls -a\n\ ls -b\n\ ls -c\n\ ```\n\ ## some section\n\ This is some section\n"; assert_eq!(parse_usage(input), "{} -a\n{} -b\n{} -c"); } #[test] fn test_parse_about() { 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 test_parse_multi_line_about() { 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"); } }