1use std::{fs, path::PathBuf};
2use convert_case::{Case, Casing};
3
4use srctrait_common_chronox::DateTimeFormat;
5
6use crate::*;
7
8pub fn note_for_date(notes_dir: &NotesDir, note: &Note, from: Option<Date>) -> Result<PathBuf> {
9 assert!(note.kind() == NoteKind::Today);
10
11 let date = note.date().expect("today note date");
12 let mut previous_contents = None;
13 if let Some(from_date) = from {
14 let from_note_dir = notes_dir
15 .kind_dir(NoteKind::Today)
16 .join(from_date.display(DateTimeFormat::YmSlash).to_string());
17
18 let from_file = from_note_dir
19 .join(format!("{}-{}.md",
20 note.kind(),
21 from_date.display(DateTimeFormat::YmdDash).to_string()));
22
23 if !from_file.is_file() {
24 return Err(Error::NoDayNotes(from_date));
25 }
26
27 let mut skip = true;
28 previous_contents = Some(fs::read_to_string(&from_file)
29 .map_err(|e| Error::Io(format!("Unable to read daily note file: {}", from_file.display()), e))?
30 .lines()
31 .filter(|l| {
32 if skip {
33 if l.starts_with("---") {
34 skip = false;
35 }
36
37 false
38 } else {
39 true
40 }
41 })
42 .collect::<Vec<_>>()
43 .join("\n"));
44 }
45
46 let note_dir = notes_dir
47 .kind_dir(NoteKind::Today)
48 .join(date.display(DateTimeFormat::YmSlash).to_string());
49
50 if !note_dir.is_dir() {
51 fs::create_dir_all(¬e_dir)
52 .map_err(|e| Error::Io(format!("Unable to create note directory: {}", note_dir.display()), e))?;
53 }
54
55 let note_file = note_dir
56 .join(format!("{}-{}.md",
57 note.kind(),
58 date.display(DateTimeFormat::YmdDash).to_string()));
59
60 if !note_file.is_file() {
61 let vars = build_template_vars(date, None);
62 let template_str = render_template_str(note.note_type().default_template_str(), vars);
63 fs::write(¬e_file, &template_str)
64 .map_err(|e| Error::Io(format!("Unable to write note file: {}", note_file.display()), e))?;
65 }
66
67 if let Some(previous_contents) = previous_contents {
68 let current = fs::read_to_string(¬e_file)
69 .map_err(|e| Error::Io(format!("Unable to read note file: {}", note_file.display()), e))?;
70 let content = format!("{current}\n{previous_contents}");
71
72 fs::write(¬e_file, &content)
73 .map_err(|e| Error::Io(format!("Unable to write note file: {}", note_file.display()), e))?;
74 }
75
76 Ok(note_file)
77}
78
79pub fn note_for_topic(notes_dir: &NotesDir, note: &Note) -> Result<PathBuf> {
80 assert!(note.kind() != NoteKind::Today);
81 let topic = note.topic().expect("topical note");
82 let date = Date::now();
83 let topic_title = topic.to_case(Case::Sentence);
84 let topic = topic.to_case(Case::Kebab);
85
86 let note_dir = notes_dir.kind_dir(note.kind());
87
88 if !note_dir.is_dir() {
89 fs::create_dir_all(¬e_dir)
90 .map_err(|e| Error::Io(format!("Unable to create note directory: {}", note_dir.display()), e))?;
91 }
92
93 let note_file = note_dir
94 .join(format!("{}-{topic}.md", note.kind()).to_string());
95
96 if !note_file.is_file() {
97 let vars = build_template_vars(&date, Some(&topic_title));
98 let template_str = render_template_str(note.note_type().default_template_str(), vars);
99 fs::write(¬e_file, &template_str)
100 .map_err(|e| Error::Io(format!("Unable to write note file: {}", note_file.display()), e))?;
101 }
102
103 Ok(note_file)
104}
105
106pub fn note_for_optional_topic(notes_dir: &NotesDir, note: &Note) -> Result<PathBuf> {
107 assert!(note.note_type().is_topical_optional());
108
109 if note.topic().is_some() {
110 return note_for_topic(notes_dir, note);
111 }
112
113 let note_dir = notes_dir.kind_dir(note.kind());
114
115 if !note_dir.is_dir() {
116 fs::create_dir_all(¬e_dir)
117 .map_err(|e| Error::Io(format!("Unable to create note directory: {}", note_dir.display()), e))?;
118 }
119
120 let note_file = note_dir.join(format!("{}.md", note.kind()));
121
122 if !note_file.is_file() {
123 let date = Date::now();
124 let vars = build_template_vars(&date, None);
125 let template_str = render_template_str(note.note_type().default_template_str(), vars);
126 fs::write(¬e_file, &template_str)
127 .map_err(|e| Error::Io(format!("Unable to write note file: {}", note_file.display()), e))?;
128 }
129
130 Ok(note_file)
131}