diff options
Diffstat (limited to 'src/journal.rs')
-rw-r--r-- | src/journal.rs | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/journal.rs b/src/journal.rs new file mode 100644 index 0000000..911f9a3 --- /dev/null +++ b/src/journal.rs @@ -0,0 +1,108 @@ +use crate::error::JournalError; +use chrono::Local; +use log::debug; +use std::path::{Path, PathBuf}; +use std::process::Command; + +const MAX_DRAFT_COUNT: usize = 1000; + +pub struct Journal { + dirname: PathBuf, +} + +impl Journal { + pub fn is_journal(path: &Path) -> bool { + if let Ok(meta) = std::fs::symlink_metadata(path) { + meta.is_dir() + } else { + false + } + } + + pub fn init(path: &Path) -> Result<Self, JournalError> { + std::fs::create_dir(path) + .map_err(|err| JournalError::CreateDirectory(path.to_path_buf(), err))?; + Ok(Self { + dirname: path.to_path_buf(), + }) + } + + pub fn new(path: &Path) -> Result<Self, JournalError> { + let dirname = path.to_path_buf(); + if dirname.exists() { + Ok(Self { dirname }) + } else { + Err(JournalError::NotAJournal(dirname.display().to_string())) + } + } + + fn dirname(&self) -> &Path { + &self.dirname + } + + fn drafts(&self) -> PathBuf { + self.dirname().join("drafts") + } + + fn entries(&self) -> PathBuf { + self.dirname().join("entries") + } + + pub fn new_draft(&self, title: &str, _editor: &str) -> anyhow::Result<()> { + let drafts = self.drafts(); + if !drafts.exists() { + std::fs::create_dir(&drafts)?; + } + + let pathname = self.pick_file_id(&drafts)?; + let text = format!(r#"[[!meta title="{}"]]"#, title); + std::fs::write(pathname, format!("{}\n\n", text))?; + Ok(()) + } + + fn pick_file_id(&self, dirname: &Path) -> Result<PathBuf, JournalError> { + for i in 0..MAX_DRAFT_COUNT { + let basename = format!("{}.md", i); + let pathname = dirname.join(basename); + if !pathname.exists() { + return Ok(pathname); + } + } + return Err(JournalError::TooManyDrafts( + MAX_DRAFT_COUNT, + dirname.to_path_buf(), + )); + } + + pub fn pick_draft(&self, id: &str) -> Result<PathBuf, JournalError> { + let drafts = self.drafts(); + let filename = drafts.join(format!("{}.md", id)); + if filename.exists() { + return Ok(filename); + } else { + return Err(JournalError::NoSuchDraft(id.to_string(), self.drafts())); + } + } + + pub fn edit_draft(&self, editor: &str, filename: &Path) -> anyhow::Result<()> { + debug!("edit_draft: editor={:?}", editor); + debug!("edit_draft: filename={:?}", filename); + Command::new(editor).arg(filename).status()?; + debug!("edit_draft: editor finished"); + Ok(()) + } + + pub fn finish_draft(&self, filename: &Path, basename: &str) -> anyhow::Result<()> { + let entries = self.entries(); + if !entries.exists() { + std::fs::create_dir(&entries)?; + } + + let subdir = entries.join(Local::today().format("%Y/%m/%d").to_string()); + std::fs::create_dir_all(&subdir)?; + + let entry = subdir.join(basename); + std::fs::rename(filename, entry)?; + Ok(()) + } +} |