srctrait_note/
note.rs

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(&note_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(&note_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(&note_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(&note_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(&note_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(&note_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(&note_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(&note_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}