vscode_generator/snippets/
snippets_file.rs

1use crate::prelude::*;
2use super::*;
3use std::{ fs, path::Path };
4use serde::Serialize;
5
6/// # Snippets File Manager
7/// 
8/// 📁 A file controller for managing VS Code snippets collections and their file operations.
9/// 
10/// ## Overview
11/// 
12/// `SnippetsFile` provides a convenient way to:
13/// - 📦 Create and manage collections of code snippets
14/// - 🔄 Serialize snippets to VS Code compatible format
15/// - 💾 Save snippets to the filesystem
16/// 
17/// ## Usage
18/// 
19/// #### ✨ Creating a new snippets file:
20/// ```rust
21/// let file = SnippetsFile::new(vec![
22///     Snippet::new("print", vec!["println!(\"$0\");"]),
23///     Snippet::new("debug", vec!["dbg!($0);"])
24/// ]);
25/// ```
26/// 
27/// #### ➕ Adding snippets dynamically:
28/// ```rust
29/// let mut file = SnippetsFile::new(vec![]);
30/// 
31/// // Add single snippet
32/// file.add_snippet(Snippet::new("log", vec!["log::info!(\"$0\")"]));
33/// 
34/// // Add multiple snippets
35/// file.add_snippets(vec![
36///     Snippet::new("error", vec!["log::error!(\"$0\");"]),
37///     Snippet::new("warn", vec!["log::warn!(\"$0\");"])
38/// ]);
39/// ```
40/// 
41/// #### 💾 Saving to file:
42/// ```rust
43/// let file = SnippetsFile::new(vec![
44///     Snippet::new("test", vec![
45///         "#[test]",
46///         "fn test_name() {",
47///         "    ",
48///         "}"
49///     ])
50/// ]);
51/// 
52/// // Saves to VS Code snippets directory
53/// file.write_to("./snippets/rust.code-snippets")?;
54/// ```
55/// 
56/// ## 📋 File Format
57/// 
58/// The snippets are saved in VS Code compatible JSON format:
59/// ```json
60/// {
61///     "print": {
62///         "prefix": "print",
63///         "body": [
64///             "println!(\"Hello\");"
65///         ],
66///         "description": "Basic print statement"
67///     }
68/// }
69/// ```
70/// 
71/// ## ⚠️ Error Handling
72/// 
73/// The structure uses custom `Result` type for error handling:
74/// - 🔄 JSON serialization errors
75/// - 📂 File system operation errors
76/// - 📁 Directory creation errors
77/// 
78/// ## User Snippets
79/// 📝 You can write this snippets to your VS Code custom user snippets folder
80/// Locales:
81/// * 🗂️ Windows: `%APPDATA%/Code/User/snippets`
82/// * 🍎 MacOS: `~/Library/Application Support/Code/User/snippets`
83/// * 🐧 Linux: `~/.config/Code/User/snippets`
84///
85/// 💡 Or simply access it via VS Code:
86/// 1. Press `Ctrl/Cmd + Shift + P`
87/// 2. Type "Snippets: Configure User Snippets"
88/// 3. Select the language or create a new snippet file 
89#[derive(Debug, Clone, Serialize)]
90pub struct SnippetsFile {
91    pub snippets: HashMap<String, Snippet>,
92}
93
94impl SnippetsFile {
95    /// Creates a new snippets file controller
96    pub fn new<Sn: Into<Snippet>>(snippets: impl IntoIterator<Item = Sn>) -> Self {
97        Self {
98            snippets: snippets
99                .into_iter()
100                .map(|snip| {
101                    let snip = snip.into();
102                    (snip.name.clone(), snip)
103                })
104                .collect()
105        }
106    }
107
108    /// Adds a new snippet to the collection
109    pub fn add_snippet<S: Into<Snippet>>(&mut self, snippet: S) {
110        let snippet = snippet.into();
111        self.snippets.insert(snippet.name.clone(), snippet);
112    }
113
114    /// Adds a new snippets to the collection
115    pub fn add_snippets<S: Into<Snippet>>(&mut self, snippets: impl IntoIterator<Item = S>) {
116        self.snippets.extend(
117            snippets
118                .into_iter()
119                .map(|snip| {
120                    let snip = snip.into();
121                    (snip.name.clone(), snip)
122                })
123        );
124    }
125
126    /// Converts the snippets to json string
127    pub fn to_json(&self) -> Result<String> {
128        serde_json::to_string_pretty(&self.snippets).map_err(Error::from)
129    }
130    
131    /// Writes the snippets to file path
132    pub fn write_to(&self, path: &str) -> Result<()> {
133        let path = Path::new(path);
134
135        // creating the file dir:
136        if let Some(dir) = path.parent() {
137            fs::create_dir_all(dir).map_err(Error::from)?;
138        }
139        
140        // convert snippets to json:
141        let json = self.to_json()?;
142
143        // create the file:
144        fs::write(path, json).map_err(Error::from)?;
145
146        Ok(())
147    }
148}