Note: This site is currently "Under construction". I'm migrating to a new version of my site building software. Lots of things are in a state of disrepair as a result (for example, footnote links aren't working). It's all part of the process of building in public. Most things should still be readable though.

Use The rest nom Parser With many0 and many1 In Rust

  • Pares this down and write up how to use verify to grab to the end of a file with nom

Code

#![allow(unused_imports)]
use nom::branch::alt;
use nom::bytes::complete::tag_no_case;
use nom::bytes::streaming::is_not;
use nom::character::complete::line_ending;
use nom::character::complete::not_line_ending;
use nom::character::complete::space0;
use nom::character::complete::space1;
use nom::combinator::eof;
use nom::combinator::not;
use nom::combinator::opt;
use nom::combinator::peek;
use nom::combinator::rest;
use nom::combinator::verify;
use nom::sequence::delimited;
use nom::sequence::pair;
use nom::sequence::preceded;
use nom::sequence::terminated;
use nom::IResult;
use nom::Parser;
use serde::Serialize;

#[derive(Debug, PartialEq, Serialize)]
#[serde(tag = "type", content = "content", rename_all = "lowercase")]
pub enum Section {
    Blurb(String),
    Date(String),
    Id(String),
    Status(String),
    Title(String),
    Type(String),
    Updated(String),
    DEV(String),
    None,
}

pub fn metadata<'a>(source: &'a str) -> IResult<&'a str, Option<&str>> {
    let (source, value) = terminated(
        opt(preceded(space1, not_line_ending)),
        alt((line_ending, eof)),
    )(source)?;
    if let Some(x) = value {
        dbg!(&x);
        match x {
            "" => {
                dbg!("e");
                Ok((source, None))
            }

            _ => {
                dbg!("r");
                Ok((source, Some(x)))
            }
        }
    } else {
        dbg!("a");
        Ok((source, None))
    }
}

pub fn section(source: &str) -> IResult<&str, Section> {
    // make sure there's something left to process
    let (source, section) = alt((
        preceded(tag_no_case("#+BLURB:"), metadata).map(|x| match x {
            Some(d) => Section::Blurb(d.to_string()),
            None => Section::None,
        }),
        preceded(tag_no_case("#+DATE:"), metadata).map(|x| match x {
            Some(d) => Section::Date(d.to_string()),
            None => Section::None,
        }),
        preceded(tag_no_case("#+ID:"), metadata).map(|x| match x {
            Some(d) => Section::Id(d.to_s