From 2a1560cfb9c41f244d90086da14ab2f73d20c5e2 Mon Sep 17 00:00:00 2001 From: Joscha Date: Wed, 17 Nov 2021 22:40:11 +0100 Subject: [PATCH] Start parsing lines --- src/main.rs | 4 ++ src/parse.rs | 16 ++++++++ src/parse/line.rs | 97 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 src/parse.rs create mode 100644 src/parse/line.rs diff --git a/src/main.rs b/src/main.rs index 887b3bc..68a0165 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use structopt::StructOpt; mod commands; +mod parse; #[derive(Debug, StructOpt)] pub struct Opt { @@ -13,4 +14,7 @@ pub struct Opt { fn main() { let opt = Opt::from_args(); println!("{:#?}", opt); + + let commands = parse::parse(&opt.file); + println!("{:#?}", commands); } diff --git a/src/parse.rs b/src/parse.rs new file mode 100644 index 0000000..9f938be --- /dev/null +++ b/src/parse.rs @@ -0,0 +1,16 @@ +use std::fs; +use std::path::Path; + +use crate::commands::Command; + +use self::line::parse_lines; + +mod line; + +pub fn parse(file: &Path) -> anyhow::Result> { + let content = fs::read_to_string(file)?; + let lines = parse_lines(&content)?; + + println!("{:#?}", lines); + todo!() +} diff --git a/src/parse/line.rs b/src/parse/line.rs new file mode 100644 index 0000000..12f3bea --- /dev/null +++ b/src/parse/line.rs @@ -0,0 +1,97 @@ +use std::result; + +use chrono::NaiveDate; + +use crate::commands::{BirthdaySpec, Done, Spec}; + +#[derive(Debug)] +pub enum Line { + Empty, + Indented(String), + + Task(String), + Note(String), + Birthday(String), + Date(Spec), + BDate(BirthdaySpec), + From(NaiveDate), + Until(NaiveDate), + Except(NaiveDate), + Done(Done), +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("line {line}: unknown command {name:?}")] + UnknownCommand { line: usize, name: String }, + #[error("line {line}: unknown format")] + UnknownFormat { line: usize }, +} + +type Result = result::Result; + +pub fn parse_lines(content: &str) -> Result> { + content + .lines() + .enumerate() + .map(|(line, content)| parse_line(line, content)) + .collect() +} + +fn parse_line(line: usize, content: &str) -> Result { + println!("Parsing line {:?}", content); + + if content.is_empty() { + Ok(Line::Empty) + } else if content.starts_with('\t') || content.starts_with(' ') { + Ok(Line::Indented(content.to_string())) + } else if let Some((name, rest)) = parse_command(content) { + match name { + "TASK" => Ok(Line::Task(rest.to_string())), + "NOTE" => Ok(Line::Note(rest.to_string())), + "BIRTHDAY" => Ok(Line::Birthday(rest.to_string())), + "DATE" => parse_date(rest), + "BDATE" => parse_bdate(rest), + "FROM" => parse_datum(rest).map(Line::From), + "UNTIL" => parse_datum(rest).map(Line::Until), + "EXCEPT" => parse_datum(rest).map(Line::Except), + "DONE" => parse_done(rest), + _ => Err(Error::UnknownCommand { + line, + name: name.to_string(), + }), + } + } else { + Err(Error::UnknownFormat { line }) + } +} + +fn parse_command(line: &str) -> Option<(&str, &str)> { + if let Some(space) = line.find(' ') { + let name = &line[..space]; + let content = &line[space + 1..]; + Some((name, content)) + } else { + None + } +} + +fn parse_date(s: &str) -> Result { + println!(" parsing date from {:?}", s); + Ok(Line::Empty) // TODO +} + +fn parse_bdate(s: &str) -> Result { + println!(" parsing bdate from {:?}", s); + Ok(Line::Empty) // TODO +} + +fn parse_datum(s: &str) -> Result { + println!(" parsing datum from {:?}", s); + Ok(NaiveDate::from_ymd(2015, 3, 14)) // TODO +} + +fn parse_done(s: &str) -> Result { + println!(" parsing done from {:?}", s); + Ok(Line::Empty) // TODO +}