marks 0.1.0

A simple and /hopefully/ fast semantic search tool for org/markdown files. WIP.
Documentation
use regex::Regex;
use std::iter::Peekable;

use super::parser;

#[derive(Debug)]
pub enum QueryToken {
    Regex(Regex),
    Must(String),
    None(String),
    Plain(String),
}

#[derive(Debug)]
pub struct Query {
    /// Query string that user provided.
    pub full: String,
    /// "keyword"
    pub musts: Vec<String>,
    /// -keyword
    pub nones: Vec<String>,
    /// `(some|regex)`
    pub regexes: Vec<Regex>,
    /// full - (musts + nones + regexes). Used for fuzzy searching.
    pub rest: Vec<String>,
}

impl Query {
    pub fn new(input: &str) -> Query {
        let full = input.to_string();
        let mut musts = vec![];
        let mut nones = vec![];
        let mut regexes = vec![];
        let mut rest = vec![];

        let iter = &mut full.chars().peekable();
        while let Some(x) = Query::tokenize_single(iter) {
            match x {
                QueryToken::Regex(r) => regexes.push(r),
                QueryToken::Plain(r) => rest.push(r),
                QueryToken::Must(r) => musts.push(r),
                QueryToken::None(r) => nones.push(r),
            }
        }

        Query { full, musts, nones, regexes, rest }
    }

    pub fn tokenize_single<I>(iter: &mut Peekable<I>) -> Option<QueryToken>
    where I: Iterator<Item = char> {
        while parser::parse_whitespace(iter) {
            continue
        }

        parser::parse_around(iter, '"', '"').map(QueryToken::Must)
            .or_else(|| parser::parse_around(iter, '`', '`').map(|x| QueryToken::Regex(Regex::new(&x).unwrap())))
            .or_else(|| parser::parse_prefixed(iter, '-').map(QueryToken::None))
            .or_else(|| parser::parse_plain(iter).map(QueryToken::Plain))
    }
}