diff --git a/src/main.rs b/src/main.rs index 60c59c1..d389ac6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,16 +3,37 @@ extern crate ansi_term; use std::io::{BufRead, BufReader}; use std::fs::File; use std::{env, process}; +use std::convert::From; +#[derive(Debug, Eq, PartialEq)] enum LineType { + Empty, Title(String), - Empty(String), Description(String), ExampleText(String), ExampleCode(String), + Other(String), } +impl<'a> From<&'a str> for LineType { + /// Convert a string slice to a LineType. Newlines and whitespace are trimmed. + fn from(line: &'a str) -> LineType { + let trimmed = line.trim(); + let mut chars = trimmed.chars(); + match chars.next() { + None => LineType::Empty, + Some('#') => LineType::Title(trimmed.trim_left_matches(|chr: char| chr == '#' || chr.is_whitespace()).into()), + Some('>') => LineType::Description(trimmed.trim_left_matches(|chr: char| chr == '>' || chr.is_whitespace()).into()), + Some('-') => LineType::ExampleText(trimmed.trim_left_matches(|chr: char| chr == '-' || chr.is_whitespace()).into()), + Some('`') if chars.last() == Some('`') => LineType::ExampleCode(trimmed.trim_matches(|chr: char| chr == '`' || chr.is_whitespace()).into()), + _ => LineType::Other(trimmed.into()), + } + } +} + + +#[derive(Debug)] struct Tokenizer { reader: R, current_line: String, @@ -27,12 +48,12 @@ impl Tokenizer where R: BufRead { } } - fn next(&mut self) -> Option<&str> { + fn next(&mut self) -> Option { self.current_line.clear(); let bytes_read = self.reader.read_line(&mut self.current_line).unwrap(); match bytes_read { 0 => None, - _ => Some(&self.current_line), + _ => Some(LineType::from(&self.current_line[..])), } } @@ -68,7 +89,25 @@ fn main() { // Tokenize and print output while let Some(token) = tokenizer.next() { - print!("{}", token); + println!("{:?}", token); } } + + +#[cfg(test)] +mod test { + use super::LineType; + + #[test] + fn test_linetype_from_str() { + assert_eq!(LineType::from(""), LineType::Empty); + assert_eq!(LineType::from(" \n \r"), LineType::Empty); + assert_eq!(LineType::from("# Hello there"), LineType::Title("Hello there".into())); + assert_eq!(LineType::from("> tis a description \n"), LineType::Description("tis a description".into())); + assert_eq!(LineType::from("- some command"), LineType::ExampleText("some command".into())); + assert_eq!(LineType::from("`$ cargo run`"), LineType::ExampleCode("$ cargo run".into())); + assert_eq!(LineType::from("`$ cargo run"), LineType::Other("`$ cargo run".into())); + assert_eq!(LineType::from("asdf"), LineType::Other("asdf".into())); + } +}