diff --git a/Cargo.lock b/Cargo.lock index 752d275..9415901 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -412,7 +412,6 @@ dependencies = [ "owo-colors", "petgraph", "ratatui", - "temp-file", "termsize", ] @@ -800,12 +799,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "temp-file" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f210bda61d003f311d95611d1b68361df8fe8e732c3609f945441bde881321d" - [[package]] name = "termion" version = "1.5.6" diff --git a/programs/jrnl/Cargo.toml b/programs/jrnl/Cargo.toml index 12f231a..0b97fee 100644 --- a/programs/jrnl/Cargo.toml +++ b/programs/jrnl/Cargo.toml @@ -13,5 +13,4 @@ markdown = "0.3.0" owo-colors = "4.0.0" petgraph = "0.6.4" ratatui = "0.26.2" -temp-file = "0.1.8" termsize = "0.1.6" diff --git a/programs/jrnl/src/commands/list_entries.rs b/programs/jrnl/src/commands/list_entries.rs index 9471095..6d46388 100644 --- a/programs/jrnl/src/commands/list_entries.rs +++ b/programs/jrnl/src/commands/list_entries.rs @@ -5,20 +5,16 @@ use crate::md::Doc; pub fn list_entries(path: PathBuf) { let file = fs::read_to_string(path).unwrap(); + let doc = Doc::new(&file); - if let Some(doc) = Doc::new(&file) { - for (i, entry) in doc.entries.into_iter().enumerate() { - let n = format!("{:>2}", i + 1); - let r = format!(". {}", entry.title,); - let l = format!(" {} ", crate::utils::format_datetime(entry.timestamp)); - let termsize::Size { cols, .. } = termsize::get().unwrap(); + for (i, entry) in doc.entries.into_iter().enumerate() { + let n = format!("{:>2}", i + 1); + let r = format!(". {}", entry.title,); + let l = format!(" {} ", crate::utils::format_datetime(entry.timestamp)); + let termsize::Size { cols, .. } = termsize::get().unwrap(); - let padding = " ".repeat(cols as usize - (n.len() + r.len() + l.len())); + let padding = " ".repeat(cols as usize - (n.len() + r.len() + l.len())); - println!("{}{r}{padding}{}", n.cyan(), l.white()) - } - } else { - eprintln!("Parsing error..."); - std::process::exit(1); + println!("{}{r}{padding}{}", n.cyan(), l.white()) } } diff --git a/programs/jrnl/src/main.rs b/programs/jrnl/src/main.rs index 22faae3..294ade8 100644 --- a/programs/jrnl/src/main.rs +++ b/programs/jrnl/src/main.rs @@ -1,11 +1,7 @@ -#![feature(iter_collect_into)] use clap::{Parser, Subcommand}; use std::{fs, path::PathBuf}; -use crate::{ - commands::list_entries::list_entries, - md::{Doc, ToMd}, -}; +use crate::{commands::list_entries::list_entries, md::Doc}; mod commands; mod md; @@ -38,8 +34,8 @@ fn main() { // TODO: handle btter let file = fs::read_to_string(cli.s10e_jrnl_file_loc).unwrap(); - let doc = Doc::new(&file).unwrap(); - println!("{}", doc.to_md()) + let doc = Doc::new(&file); + dbg!(doc); } } } diff --git a/programs/jrnl/src/md.rs b/programs/jrnl/src/md.rs index cd3ab43..b04ef2e 100644 --- a/programs/jrnl/src/md.rs +++ b/programs/jrnl/src/md.rs @@ -1,64 +1,59 @@ use chrono::{DateTime, FixedOffset}; use markdown::{Block, Span}; -use std::convert::identity; -pub trait ToMd { - fn to_md(&self) -> String; +#[derive(Debug)] +pub struct Doc { + pub title: Vec, + pub entries: Vec, +} + +impl Doc { + pub fn new(f: &str) -> Self { + let mut entries = Vec::new(); + let mut doc_title = vec![Span::Text("Journal".to_owned())]; + let toks = markdown::tokenize(f); + let mut current = None; + + for tok in toks { + match tok { + Block::Header(title, 1) => doc_title = title, + Block::Header(entry_title, 2) => { + if let Some(cur) = current.take() { + entries.push(cur); + } + + let Some(Span::Text(title)) = entry_title.first() else { + eprintln!("Error: Titles should be text."); + std::process::exit(1); + }; + + let (ts, entry_title) = title.split_once(": ").unwrap(); + let ts = DateTime::parse_from_rfc3339(ts).unwrap(); + // let ts = PrimitiveDateTime::parse(ts, &DT_FORMAT).unwrap(); + + current = Some(Entry { + timestamp: ts, + title: entry_title.to_owned(), + content: Vec::new(), + }); + } + other => current.as_mut().unwrap().content.push(other), + } + } + if let Some(cur) = current { + entries.push(cur); + } + + Self { + title: doc_title, + entries, + } + } } #[derive(Debug)] -pub struct Doc<'src> { - pub entries: Vec>, -} - -impl<'src> Doc<'src> { - // TODO: better parsing errors? - pub fn new(f: &'src str) -> Option { - let entries = f - .split("\n## ") - .map(|s| s.split_once("\n")) - .skip(1) - .filter_map(identity) - .map(|(title, content)| (title.split_once(": "), content)) - .map(|(title, content)| { - if let Some((ts, title)) = title { - Some(Entry { - timestamp: DateTime::parse_from_rfc3339(ts).unwrap(), - title, - content: content.trim_matches('\n'), - }) - } else { - None - } - }) - .collect::>(); - - entries.iter().all(|it| it.is_some()).then_some(Self { - entries: entries.into_iter().filter_map(identity).collect(), - }) - } -} - -impl ToMd for Doc<'_> { - fn to_md(&self) -> String { - let mut r = "# Journal\n\n".to_owned(); - - self.entries.iter().fold(r, |mut r, it| r + &it.to_md()) - } -} - -#[derive(Debug, Clone)] -pub struct Entry<'src> { +pub struct Entry { pub timestamp: DateTime, - pub title: &'src str, - pub content: &'src str, -} - -impl ToMd for Entry<'_> { - fn to_md(&self) -> String { - format!( - "## {}: {}\n\n{}\n\n", - self.timestamp, self.title, self.content - ) - } + pub title: String, + pub content: Vec, }