basalt_core/obsidian/
vault.rs1use std::{
2 cmp::Ordering,
3 fs::{self, read_dir},
4 path::{Path, PathBuf},
5 result,
6};
7
8use serde::{Deserialize, Deserializer};
9
10use crate::obsidian::Note;
11
12#[derive(Debug, Clone, Default, PartialEq)]
16pub struct Vault {
17 pub name: String,
19
20 pub path: PathBuf,
22
23 pub open: bool,
25
26 pub ts: u64,
28}
29
30impl Vault {
31 pub fn notes(&self) -> Vec<Note> {
47 read_dir(&self.path)
48 .into_iter()
49 .flatten()
50 .filter_map(|entry| Option::<Note>::from(DirEntry::from(entry.ok()?)))
51 .collect()
52 }
53
54 pub fn notes_sorted_by(&self, compare: impl Fn(&Note, &Note) -> Ordering) -> Vec<Note> {
74 let mut notes: Vec<Note> = self.notes();
75 notes.sort_by(compare);
76 notes
77 }
78}
79
80impl<'de> Deserialize<'de> for Vault {
81 fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
82 where
83 D: Deserializer<'de>,
84 {
85 #[derive(Deserialize)]
86 struct Json {
87 path: PathBuf,
88 open: Option<bool>,
89 ts: u64,
90 }
91
92 impl TryFrom<Json> for Vault {
93 type Error = String;
94 fn try_from(value: Json) -> Result<Self, Self::Error> {
95 let path = Path::new(&value.path);
96 let name = path
97 .file_name()
98 .ok_or_else(|| String::from("unable to retrieve vault name"))?
99 .to_string_lossy()
100 .to_string();
101 Ok(Vault {
102 name,
103 path: value.path,
104 open: value.open.unwrap_or_default(),
105 ts: value.ts,
106 })
107 }
108 }
109
110 let deserialized: Json = Deserialize::deserialize(deserializer)?;
111 deserialized.try_into().map_err(serde::de::Error::custom)
112 }
113}
114
115#[derive(Debug)]
118struct DirEntry(fs::DirEntry);
119
120impl AsRef<fs::DirEntry> for DirEntry {
121 fn as_ref(&self) -> &fs::DirEntry {
122 &self.0
123 }
124}
125
126impl From<fs::DirEntry> for DirEntry {
127 fn from(value: fs::DirEntry) -> Self {
128 DirEntry(value)
129 }
130}
131
132impl From<DirEntry> for Option<Note> {
133 fn from(value: DirEntry) -> Option<Note> {
135 let path = value.as_ref().path();
136
137 if path.extension()? != "md" {
138 return None;
139 }
140
141 let name = path
142 .with_extension("")
143 .file_name()
144 .map(|file_name| file_name.to_string_lossy().into_owned())?;
145
146 Some(Note { name, path })
147 }
148}