pocket_cli/models/
mod.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4use anyhow::Result;
5use std::collections::HashMap;
6
7/// Represents an entry in the pocket storage
8#[derive(Debug, Serialize, Deserialize, Clone)]
9pub struct Entry {
10    /// Unique identifier for the entry
11    pub id: String,
12    
13    /// Title or first line of the entry
14    pub title: String,
15    
16    /// When the entry was created
17    pub created_at: DateTime<Utc>,
18    
19    /// When the entry was last updated
20    pub updated_at: DateTime<Utc>,
21    
22    /// Source of the entry (file path, etc.)
23    pub source: Option<String>,
24    
25    /// Tags associated with the entry
26    pub tags: Vec<String>,
27    
28    /// Type of content (code, text, etc.)
29    pub content_type: ContentType,
30    
31    /// Metadata associated with the entry
32    #[serde(default)]
33    pub metadata: HashMap<String, String>,
34}
35
36/// Represents the type of content in an entry
37#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
38pub enum ContentType {
39    Code,
40    Text,
41    Script,
42    Other(String),
43}
44
45/// Represents a backpack for organizing entries
46#[derive(Debug, Serialize, Deserialize, Clone)]
47pub struct Backpack {
48    /// Name of the backpack
49    pub name: String,
50    
51    /// Description of the backpack
52    pub description: Option<String>,
53    
54    /// When the backpack was created
55    pub created_at: DateTime<Utc>,
56}
57
58/// Represents a saved workflow
59#[derive(Debug, Serialize, Deserialize, Clone)]
60pub struct Workflow {
61    /// Name of the workflow
62    pub name: String,
63    
64    /// Commands in the workflow
65    pub commands: Vec<WorkflowCommand>,
66    
67    /// When the workflow was created
68    pub created_at: DateTime<Utc>,
69}
70
71/// Represents a command in a workflow
72#[derive(Debug, Serialize, Deserialize, Clone)]
73pub struct WorkflowCommand {
74    /// The command to execute
75    pub command: String,
76    
77    /// Arguments for the command
78    pub args: Vec<String>,
79}
80
81impl Entry {
82    /// Create a new entry
83    pub fn new(title: String, content_type: ContentType, source: Option<String>, tags: Vec<String>) -> Self {
84        let now = Utc::now();
85        Self {
86            id: Uuid::new_v4().to_string(),
87            title,
88            created_at: now,
89            updated_at: now,
90            source,
91            tags,
92            content_type,
93            metadata: HashMap::new(),
94        }
95    }
96    
97    /// Add metadata to the entry
98    pub fn add_metadata(&mut self, key: &str, value: &str) {
99        self.metadata.insert(key.to_string(), value.to_string());
100    }
101    
102    /// Get metadata from the entry
103    pub fn get_metadata(&self, key: &str) -> Option<&str> {
104        self.metadata.get(key).map(|s| s.as_str())
105    }
106}
107
108impl Backpack {
109    /// Create a new backpack
110    pub fn new(name: String, description: Option<String>) -> Self {
111        Self {
112            name,
113            description,
114            created_at: Utc::now(),
115        }
116    }
117}
118
119impl Workflow {
120    /// Create a new workflow
121    pub fn new(name: String, commands: Vec<WorkflowCommand>) -> Self {
122        Self {
123            name,
124            commands,
125            created_at: Utc::now(),
126        }
127    }
128}
129
130impl WorkflowCommand {
131    /// Parse a command string into a WorkflowCommand
132    pub fn parse(command_str: &str) -> Result<Self> {
133        let command_str = command_str.trim();
134        if command_str.is_empty() {
135            return Err(anyhow::anyhow!("Empty command"));
136        }
137        
138        let parts: Vec<&str> = command_str.split_whitespace().collect();
139        
140        Ok(Self {
141            command: parts[0].to_string(),
142            args: parts[1..].iter().map(|s| s.to_string()).collect(),
143        })
144    }
145}
146
147/// Configuration for the pocket application
148#[derive(Debug, Serialize, Deserialize)]
149pub struct Config {
150    /// User preferences
151    pub user: UserConfig,
152    
153    /// Display settings
154    pub display: DisplayConfig,
155    
156    /// Search settings
157    pub search: SearchConfig,
158    
159    /// Extension settings
160    pub extensions: ExtensionConfig,
161}
162
163/// User configuration
164#[derive(Debug, Serialize, Deserialize)]
165pub struct UserConfig {
166    /// Default editor for -e flag
167    pub editor: String,
168    
169    /// Default backpack for new entries
170    pub default_backpack: String,
171}
172
173/// Display configuration
174#[derive(Debug, Serialize, Deserialize)]
175pub struct DisplayConfig {
176    /// Enable colorful output
177    pub color: bool,
178    
179    /// Tree style (unicode, ascii, or minimal)
180    pub tree_style: TreeStyle,
181}
182
183/// Search configuration
184#[derive(Debug, Serialize, Deserialize)]
185pub struct SearchConfig {
186    /// Search algorithm (semantic or literal)
187    pub algorithm: SearchAlgorithm,
188    
189    /// Maximum number of search results
190    pub max_results: usize,
191}
192
193/// Extension configuration
194#[derive(Debug, Serialize, Deserialize)]
195pub struct ExtensionConfig {
196    /// Auto-reload extensions when they change
197    pub auto_reload: bool,
198}
199
200/// Tree style for display
201#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
202pub enum TreeStyle {
203    Unicode,
204    Ascii,
205    Minimal,
206}
207
208/// Search algorithm
209#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
210pub enum SearchAlgorithm {
211    Semantic,
212    Literal,
213}
214
215impl Default for Config {
216    fn default() -> Self {
217        Self {
218            user: UserConfig {
219                editor: "vim".to_string(),
220                default_backpack: "general".to_string(),
221            },
222            display: DisplayConfig {
223                color: true,
224                tree_style: TreeStyle::Unicode,
225            },
226            search: SearchConfig {
227                algorithm: SearchAlgorithm::Semantic,
228                max_results: 10,
229            },
230            extensions: ExtensionConfig {
231                auto_reload: true,
232            },
233        }
234    }
235}