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}