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,
61 path: PathBuf,
63 heading_level: usize,
65 content: Vec<FileEntryNode>,
67 },
68 Task(Task),
69}
70
71impl FileEntryNode {
72 pub(crate) fn fmt_with_depth(
73 &self,
74 f: &mut std::fmt::Formatter,
75 depth: usize,
76 ) -> std::fmt::Result {
77 match self {
78 FileEntryNode::Header {
79 name,
80 heading_level: _,
81 path: _,
82 content,
83 } => {
84 write_underline_with_indent(name, depth, f)?;
85 for entry in content {
86 entry.fmt_with_depth(f, depth + 1)?;
87 }
88 }
89 FileEntryNode::Task(task) => {
90 for line in task.to_string().replace('\r', "").split('\n') {
91 write_indent(depth, f)?;
92 writeln!(f, "{line}")?;
93 }
94 for subtask in &task.subtasks {
95 for line in (FileEntryNode::Task(subtask.clone()))
96 .to_string()
97 .split('\n')
98 {
99 write_indent(depth + 1, f)?;
100 writeln!(f, "{line}")?;
101 }
102 }
103 }
104 }
105 Ok(())
106 }
107}
108
109impl Display for FileEntryNode {
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 self.fmt_with_depth(f, 0)
112 }
113}
114#[derive(Debug, Clone, PartialEq, Eq)]
115pub struct Vaults {
116 pub root: Vec<VaultNode>,
117}
118
119impl Vaults {
120 #[must_use]
121 pub fn new(root: Vec<VaultNode>) -> Self {
122 Self { root }
123 }
124 #[must_use]
125 pub fn empty() -> Self {
126 Self { root: vec![] }
127 }
128}
129
130impl Display for Vaults {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 for vault in &self.root {
133 writeln!(f, "{vault}")?;
134 }
135 Ok(())
136 }
137}
138mod format_utils {
139 pub fn write_indent(indent_length: usize, f: &mut std::fmt::Formatter) -> std::fmt::Result {
140 (1..=indent_length).try_for_each(|_| write!(f, "\t"))?;
141 Ok(())
142 }
143 pub fn write_underline_with_indent(
144 text: &str,
145 indent_length: usize,
146 f: &mut std::fmt::Formatter,
147 ) -> std::fmt::Result {
148 write_indent(indent_length, f)?;
149 writeln!(f, "{text}")?;
150 write_indent(indent_length, f)?;
151 for _i in 0..(text.len()) {
152 write!(f, "‾")?;
153 }
154 writeln!(f)?;
155 Ok(())
156 }
157}