1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4use anyhow::Result;
5
6#[derive(Debug, Serialize, Deserialize, Clone)]
8pub struct Entry {
9 pub id: String,
11
12 pub title: String,
14
15 pub created_at: DateTime<Utc>,
17
18 pub updated_at: DateTime<Utc>,
20
21 pub source: Option<String>,
23
24 pub tags: Vec<String>,
26
27 pub content_type: ContentType,
29}
30
31#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
33pub enum ContentType {
34 Code,
35 Text,
36 Script,
37 Other(String),
38}
39
40#[derive(Debug, Serialize, Deserialize, Clone)]
42pub struct Backpack {
43 pub name: String,
45
46 pub description: Option<String>,
48
49 pub created_at: DateTime<Utc>,
51}
52
53#[derive(Debug, Serialize, Deserialize, Clone)]
55pub struct Workflow {
56 pub name: String,
58
59 pub commands: Vec<WorkflowCommand>,
61
62 pub created_at: DateTime<Utc>,
64}
65
66#[derive(Debug, Serialize, Deserialize, Clone)]
68pub struct WorkflowCommand {
69 pub command: String,
71
72 pub args: Vec<String>,
74}
75
76impl Entry {
77 pub fn new(title: String, content_type: ContentType, source: Option<String>, tags: Vec<String>) -> Self {
79 let now = Utc::now();
80 Self {
81 id: Uuid::new_v4().to_string(),
82 title,
83 created_at: now,
84 updated_at: now,
85 source,
86 tags,
87 content_type,
88 }
89 }
90}
91
92impl Backpack {
93 pub fn new(name: String, description: Option<String>) -> Self {
95 Self {
96 name,
97 description,
98 created_at: Utc::now(),
99 }
100 }
101}
102
103impl Workflow {
104 pub fn new(name: String, commands: Vec<WorkflowCommand>) -> Self {
106 Self {
107 name,
108 commands,
109 created_at: Utc::now(),
110 }
111 }
112}
113
114impl WorkflowCommand {
115 pub fn parse(command_str: &str) -> Result<Self> {
117 let command_str = command_str.trim();
118 if command_str.is_empty() {
119 return Err(anyhow::anyhow!("Empty command"));
120 }
121
122 let parts: Vec<&str> = command_str.split_whitespace().collect();
123
124 Ok(Self {
125 command: parts[0].to_string(),
126 args: parts[1..].iter().map(|s| s.to_string()).collect(),
127 })
128 }
129}
130
131#[derive(Debug, Serialize, Deserialize)]
133pub struct Config {
134 pub user: UserConfig,
136
137 pub display: DisplayConfig,
139
140 pub search: SearchConfig,
142
143 pub extensions: ExtensionConfig,
145}
146
147#[derive(Debug, Serialize, Deserialize)]
149pub struct UserConfig {
150 pub editor: String,
152
153 pub default_backpack: String,
155}
156
157#[derive(Debug, Serialize, Deserialize)]
159pub struct DisplayConfig {
160 pub color: bool,
162
163 pub tree_style: TreeStyle,
165}
166
167#[derive(Debug, Serialize, Deserialize)]
169pub struct SearchConfig {
170 pub algorithm: SearchAlgorithm,
172
173 pub max_results: usize,
175}
176
177#[derive(Debug, Serialize, Deserialize)]
179pub struct ExtensionConfig {
180 pub auto_reload: bool,
182}
183
184#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
186pub enum TreeStyle {
187 Unicode,
188 Ascii,
189 Minimal,
190}
191
192#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
194pub enum SearchAlgorithm {
195 Semantic,
196 Literal,
197}
198
199impl Default for Config {
200 fn default() -> Self {
201 Self {
202 user: UserConfig {
203 editor: "vim".to_string(),
204 default_backpack: "general".to_string(),
205 },
206 display: DisplayConfig {
207 color: true,
208 tree_style: TreeStyle::Unicode,
209 },
210 search: SearchConfig {
211 algorithm: SearchAlgorithm::Semantic,
212 max_results: 10,
213 },
214 extensions: ExtensionConfig {
215 auto_reload: true,
216 },
217 }
218 }
219}