vault_tasks_core/
vault_data.rs1use std::{fmt::Display, path::PathBuf};
2
3use format_utils::{write_indent, write_underline_with_indent};
4
5use super::task::Task;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum VaultNode {
10 Vault {
11 name: String,
12 path: PathBuf,
13 content: Vec<VaultNode>,
14 },
15 Directory {
16 name: String,
17 path: PathBuf,
18 content: Vec<VaultNode>,
19 },
20 File {
21 name: String,
22 path: PathBuf,
23 content: Vec<FileEntryNode>,
24 },
25}
26impl Display for VaultNode {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 fn fmt_node_rec(
29 node: &VaultNode,
30 f: &mut std::fmt::Formatter,
31 depth: usize,
32 ) -> std::fmt::Result {
33 match node {
34 VaultNode::Vault { name, content, .. }
35 | VaultNode::Directory { name, content, .. } => {
36 write_underline_with_indent(&name.to_string(), depth, f)?;
37 for entry in content {
38 fmt_node_rec(entry, f, depth + 1)?;
39 }
40 }
41 VaultNode::File { name, content, .. } => {
42 write_underline_with_indent(&name.to_string(), depth, f)?;
43 for entry in content {
44 entry.fmt_with_depth(f, depth + 1)?;
46 }
47 }
48 }
49 Ok(())
50 }
51 fmt_node_rec(self, f, 0)
52 }
53}
54
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub enum FileEntryNode {
58 Header {
59 name: String,
60 heading_level: usize,
61 content: Vec<FileEntryNode>,
62 },
63 Task(Task),
64}
65
66impl FileEntryNode {
67 pub(crate) fn fmt_with_depth(
68 &self,
69 f: &mut std::fmt::Formatter,
70 depth: usize,
71 ) -> std::fmt::Result {
72 match self {
73 FileEntryNode::Header {
74 name,
75 heading_level: _,
76 content,
77 } => {
78 write_underline_with_indent(name, depth, f)?;
79 for entry in content {
80 entry.fmt_with_depth(f, depth + 1)?;
81 }
82 }
83 FileEntryNode::Task(task) => {
84 for line in task.to_string().replace('\r', "").split('\n') {
85 write_indent(depth, f)?;
86 writeln!(f, "{line}")?;
87 }
88 for subtask in &task.subtasks {
89 for line in (FileEntryNode::Task(subtask.clone()))
90 .to_string()
91 .split('\n')
92 {
93 write_indent(depth + 1, f)?;
94 writeln!(f, "{line}")?;
95 }
96 }
97 }
98 }
99 Ok(())
100 }
101}
102
103impl Display for FileEntryNode {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 self.fmt_with_depth(f, 0)
106 }
107}
108#[derive(Debug, Clone, PartialEq, Eq)]
109pub struct Vaults {
110 pub root: Vec<VaultNode>,
111}
112
113impl Vaults {
114 #[must_use]
115 pub fn new(root: Vec<VaultNode>) -> Self {
116 Self { root }
117 }
118 #[must_use]
119 pub fn empty() -> Self {
120 Self { root: vec![] }
121 }
122}
123
124impl Display for Vaults {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 for vault in &self.root {
127 writeln!(f, "{vault}")?;
128 }
129 Ok(())
130 }
131}
132mod format_utils {
133 pub fn write_indent(indent_length: usize, f: &mut std::fmt::Formatter) -> std::fmt::Result {
134 (1..=indent_length).try_for_each(|_| write!(f, "\t"))?;
135 Ok(())
136 }
137 pub fn write_underline_with_indent(
138 text: &str,
139 indent_length: usize,
140 f: &mut std::fmt::Formatter,
141 ) -> std::fmt::Result {
142 write_indent(indent_length, f)?;
143 writeln!(f, "{text}")?;
144 write_indent(indent_length, f)?;
145 for _i in 0..(text.len()) {
146 write!(f, "‾")?;
147 }
148 writeln!(f)?;
149 Ok(())
150 }
151}