todomd 0.2.0

A simple markdown-based todo list CLI and TUI
Documentation
use crate::core::model::State;
use crate::core::store::Store;
use crate::persist::md_format;
use anyhow::{Context, Result};
use std::fs;
use std::path::PathBuf;

pub struct FileStore {
    path: PathBuf,
}

impl FileStore {
    pub fn new(path: impl Into<PathBuf>) -> Self {
        Self { path: path.into() }
    }
}

impl Store for FileStore {
    fn load(&self) -> Result<State> {
        if !self.path.exists() {
            return Ok(State::new());
        }
        let content = fs::read_to_string(&self.path)
            .with_context(|| format!("Failed to read file at {:?}", self.path))?;
        md_format::parse(&content)
    }

    fn save(&self, state: &State) -> Result<()> {
        let content = md_format::to_markdown(state);
        
        // Atomic write: write to .tmp then rename
        let tmp_path = self.path.with_extension("tmp");
        fs::write(&tmp_path, content)
            .with_context(|| format!("Failed to write tmp file at {:?}", tmp_path))?;
        
        fs::rename(&tmp_path, &self.path)
            .with_context(|| format!("Failed to rename tmp file to {:?}", self.path))?;
            
        Ok(())
    }
}