Parse metadata tags

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2023-01-12 23:57:48 +01:00
parent ab40eb688b
commit 5863adc174
2 changed files with 37 additions and 5 deletions

View file

@ -15,7 +15,14 @@ https://matthewwild.co.uk/projects/scansion/usage/script-basics/
This library supports parsing the following: 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] Client
* [x] Attributes * [x] Attributes
Following lines beginning with at least a tab (`\t`) character, in the Following lines beginning with at least a tab (`\t`) character, in the

View file

@ -14,7 +14,7 @@ use nom::{
branch::alt, branch::alt,
bytes::complete::{tag, take_until, take_until1, take_while, take_while1}, bytes::complete::{tag, take_until, take_until1, take_while, take_while1},
character::complete::{digit1, multispace0, space0}, character::complete::{digit1, multispace0, space0},
combinator::{opt, recognize}, combinator::{map_res, opt, recognize},
error::{ErrorKind, ParseError}, error::{ErrorKind, ParseError},
multi::{many0, many1}, multi::{many0, many1},
sequence::{delimited, tuple}, sequence::{delimited, tuple},
@ -47,11 +47,21 @@ pub static SCANSION_NS: &'static str = "https://matthewwild.co.uk/projects/scans
pub struct Metadata { pub struct Metadata {
pub title: String, pub title: String,
pub description: Option<String>, pub description: Option<String>,
pub tags: Vec<String>,
} }
impl Metadata { impl Metadata {
pub fn new<S: Into<String>, T: Into<String>>(title: S, desc: Option<T>) -> Metadata { pub fn new<S: Into<String>, T: Into<String>>(title: S, desc: Option<T>) -> 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<String>) -> Metadata {
self.tags = tags;
self
} }
} }
@ -152,6 +162,14 @@ where
} }
} }
fn parse_meta_tags(s: Span) -> IResult<Span, Vec<String>> {
let (s, tags) = many0(map_res(
delimited(tuple((position, tag("##"))), take_until("\n"), tag("\n")),
|tag: Span| Ok::<String, ()>(tag.trim().to_string()),
))(s)?;
Ok((s, tags))
}
fn parse_meta(s: Span) -> IResult<Span, Metadata> { fn parse_meta(s: Span) -> IResult<Span, Metadata> {
let (s, (_pos, title)) = let (s, (_pos, title)) =
tuple((position, delimited(tag("#"), take_until("\n"), tag("\n"))))(s)?; tuple((position, delimited(tag("#"), take_until("\n"), tag("\n"))))(s)?;
@ -170,7 +188,9 @@ fn parse_meta(s: Span) -> IResult<Span, Metadata> {
(s, None) => s, (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)) Ok((s, meta))
} }
@ -492,6 +512,8 @@ mod tests {
fn test_parse_spec() { fn test_parse_spec() {
let buf = r#"# Test title let buf = r#"# Test title
# Description Foo # Description Foo
## tag1
## tag2
[Client] louise [Client] louise
jid: louise@localhost 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<ClientName, Client> = HashMap::new(); let mut clients: HashMap<ClientName, Client> = HashMap::new();
clients.insert(String::from("louise"), get_client("louise")); clients.insert(String::from("louise"), get_client("louise"));