From 5863adc174ad143f8e9d772eaffde1a2605703e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= Date: Thu, 12 Jan 2023 23:57:48 +0100 Subject: [PATCH] Parse metadata tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maxime “pep” Buquet --- README.md | 9 ++++++++- src/lib.rs | 33 +++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 073df20..18fba2d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,14 @@ https://matthewwild.co.uk/projects/scansion/usage/script-basics/ This library supports parsing the following: -- [ ] Metadata +- [x] Metadata + Lines starting with `#` at the beginning of the file. All metadata lines + are optional. If a single line is found it's set as the title, the second + lines is set as the description. Lines starting with `##` right below will + be added as tags. A description is not needed for tags to be added. + - title: optional + - description: optional + - tags: optional - [x] Client * [x] Attributes Following lines beginning with at least a tab (`\t`) character, in the diff --git a/src/lib.rs b/src/lib.rs index cec9336..1308059 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ use nom::{ branch::alt, bytes::complete::{tag, take_until, take_until1, take_while, take_while1}, character::complete::{digit1, multispace0, space0}, - combinator::{opt, recognize}, + combinator::{map_res, opt, recognize}, error::{ErrorKind, ParseError}, multi::{many0, many1}, sequence::{delimited, tuple}, @@ -47,11 +47,21 @@ pub static SCANSION_NS: &'static str = "https://matthewwild.co.uk/projects/scans pub struct Metadata { pub title: String, pub description: Option, + pub tags: Vec, } impl Metadata { pub fn new, T: Into>(title: S, desc: Option) -> Metadata { - Metadata { title: title.into(), description: desc.map(|t| t.into()) } + Metadata { + title: title.into(), + description: desc.map(|t| t.into()), + tags: vec![], + } + } + + pub fn with_tags(mut self, tags: Vec) -> Metadata { + self.tags = tags; + self } } @@ -152,6 +162,14 @@ where } } +fn parse_meta_tags(s: Span) -> IResult> { + let (s, tags) = many0(map_res( + delimited(tuple((position, tag("##"))), take_until("\n"), tag("\n")), + |tag: Span| Ok::(tag.trim().to_string()), + ))(s)?; + Ok((s, tags)) +} + fn parse_meta(s: Span) -> IResult { let (s, (_pos, title)) = tuple((position, delimited(tag("#"), take_until("\n"), tag("\n"))))(s)?; @@ -170,7 +188,9 @@ fn parse_meta(s: Span) -> IResult { (s, None) => s, }; - let meta = Metadata::new(title.trim(), desc); + let (s, tags) = parse_meta_tags(s)?; + + let meta = Metadata::new(title.trim(), desc).with_tags(tags); Ok((s, meta)) } @@ -492,6 +512,8 @@ mod tests { fn test_parse_spec() { let buf = r#"# Test title # Description Foo +## tag1 +## tag2 [Client] louise jid: louise@localhost @@ -510,7 +532,10 @@ louise receives: "#; - let metadata = Some(Metadata::new("Test title", Some("Description Foo"))); + let metadata = Some( + Metadata::new("Test title", Some("Description Foo")) + .with_tags(vec![String::from("tag1"), String::from("tag2")]), + ); let mut clients: HashMap = HashMap::new(); clients.insert(String::from("louise"), get_client("louise"));