summaryrefslogtreecommitdiff
path: root/src/journal.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/journal.rs')
-rw-r--r--src/journal.rs108
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(())
+ }
+}