1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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(())
}
}
|