1use rand::Rng;
6
7pub const LOADING_MESSAGES: &[&str] = &[
9 "Summoning plugin spirits...",
10 "Warming up the Fusabi engine...",
11 "Compiling joy into bytecode...",
12 "Sprinkling some plugin magic...",
13 "Waking up the terminal wizards...",
14 "Brewing fresh plugin goodness...",
15 "Initializing awesomeness modules...",
16 "Loading super powers...",
17 "Charging plugin batteries...",
18 "Consulting the plugin oracle...",
19 "Calibrating terminal enhancers...",
20 "Activating plugin neurons...",
21];
22
23pub const SUCCESS_MESSAGES: &[&str] = &[
25 "Plugin loaded successfully!",
26 "And we're live!",
27 "That's what I'm talking about!",
28 "Nailed it!",
29 "Plugin is ready to roll!",
30 "Successfully deployed!",
31 "Good to go!",
32 "All systems green!",
33 "Plugin successfully summoned!",
34 "Welcome aboard!",
35];
36
37pub const ERROR_PREFIXES: &[&str] = &[
39 "Oops, something went sideways:",
40 "Well, this is awkward:",
41 "Houston, we have a problem:",
42 "Not quite what we expected:",
43 "Hmm, that didn't work:",
44 "Plot twist:",
45 "Yikes:",
46 "Oh no:",
47];
48
49pub const CONFETTI: &str = r#"
51 * . * . * . *
52 . * . * . * . * .
53* . * . * . * . * .
54 . * . * . * . * .
55"#;
56
57pub const PARTY_POPPER: &str = r#"
58 \ | /
59 \ | /
60 \|/
61 --- * ---
62 /|\
63 / | \
64 / | \
65"#;
66
67pub const TROPHY: &str = r#"
68 ___
69 | |
70 |___|
71 /| |\
72 /_|___|_\
73 | |
74 |___|
75"#;
76
77pub const ROCKET: &str = r#"
78 /\
79 / \
80 | |
81 | ** |
82 | |
83 /| |\
84 / | | \
85 / | | \
86 | |
87 /| |\
88 / '--' |
89 /________\
90"#;
91
92pub fn random_loading_message() -> &'static str {
94 let mut rng = rand::thread_rng();
95 LOADING_MESSAGES[rng.gen_range(0..LOADING_MESSAGES.len())]
96}
97
98pub fn random_success_message() -> &'static str {
100 let mut rng = rand::thread_rng();
101 SUCCESS_MESSAGES[rng.gen_range(0..SUCCESS_MESSAGES.len())]
102}
103
104pub fn random_error_prefix() -> &'static str {
106 let mut rng = rand::thread_rng();
107 ERROR_PREFIXES[rng.gen_range(0..ERROR_PREFIXES.len())]
108}
109
110#[derive(Debug, Clone, PartialEq, Eq)]
112pub enum Achievement {
113 FirstPlugin,
114 TenPlugins,
115 FiftyPlugins,
116 HundredPlugins,
117 FirstCustomPlugin,
118 PluginDeveloper,
119 PluginMaster,
120 ZeroFailures,
121}
122
123impl Achievement {
124 pub fn title(&self) -> &'static str {
126 match self {
127 Achievement::FirstPlugin => "Plugin Pioneer",
128 Achievement::TenPlugins => "Plugin Enthusiast",
129 Achievement::FiftyPlugins => "Plugin Collector",
130 Achievement::HundredPlugins => "Plugin Legend",
131 Achievement::FirstCustomPlugin => "Plugin Creator",
132 Achievement::PluginDeveloper => "Plugin Developer",
133 Achievement::PluginMaster => "Plugin Master",
134 Achievement::ZeroFailures => "Flawless Execution",
135 }
136 }
137
138 pub fn description(&self) -> &'static str {
140 match self {
141 Achievement::FirstPlugin => "Loaded your very first plugin!",
142 Achievement::TenPlugins => "Running 10 plugins like a boss!",
143 Achievement::FiftyPlugins => "Wow, 50 plugins! Your terminal is a powerhouse!",
144 Achievement::HundredPlugins => "100 plugins!? You're absolutely legendary!",
145 Achievement::FirstCustomPlugin => "Created and loaded your own custom plugin!",
146 Achievement::PluginDeveloper => "Successfully built 5 custom plugins!",
147 Achievement::PluginMaster => "Built 25 custom plugins. You're a plugin wizard!",
148 Achievement::ZeroFailures => "Plugin running smoothly with zero failures!",
149 }
150 }
151
152 pub fn emoji(&self) -> &'static str {
154 match self {
155 Achievement::FirstPlugin => "š",
156 Achievement::TenPlugins => "ā",
157 Achievement::FiftyPlugins => "š",
158 Achievement::HundredPlugins => "š",
159 Achievement::FirstCustomPlugin => "š ļø",
160 Achievement::PluginDeveloper => "š",
161 Achievement::PluginMaster => "š§",
162 Achievement::ZeroFailures => "āØ",
163 }
164 }
165
166 pub fn format(&self) -> String {
168 format!("{} {} - {}", self.emoji(), self.title(), self.description())
169 }
170
171 pub fn ascii_art(&self) -> Option<&'static str> {
173 match self {
174 Achievement::FirstPlugin => Some(PARTY_POPPER),
175 Achievement::HundredPlugins => Some(TROPHY),
176 Achievement::PluginMaster => Some(ROCKET),
177 _ => None,
178 }
179 }
180}
181
182#[derive(Debug, Clone, Copy, PartialEq, Eq)]
184pub enum PluginMood {
185 Happy,
186 Content,
187 Worried,
188 Struggling,
189 Disabled,
190}
191
192impl PluginMood {
193 pub fn from_failure_count(failures: u32, max_failures: u32, enabled: bool) -> Self {
195 if !enabled {
196 return PluginMood::Disabled;
197 }
198
199 match failures {
200 0 => PluginMood::Happy,
201 1 => PluginMood::Content,
202 f if f < max_failures - 1 => PluginMood::Worried,
203 _ => PluginMood::Struggling,
204 }
205 }
206
207 pub fn emoji(&self) -> &'static str {
209 match self {
210 PluginMood::Happy => "š",
211 PluginMood::Content => "š",
212 PluginMood::Worried => "š",
213 PluginMood::Struggling => "š°",
214 PluginMood::Disabled => "š¤",
215 }
216 }
217
218 pub fn description(&self) -> &'static str {
220 match self {
221 PluginMood::Happy => "Running perfectly!",
222 PluginMood::Content => "Doing well",
223 PluginMood::Worried => "Having some trouble",
224 PluginMood::Struggling => "Needs attention",
225 PluginMood::Disabled => "Taking a break",
226 }
227 }
228}
229
230pub const DEVELOPER_TIPS: &[&str] = &[
232 "Pro tip: Use ctx.log() to debug your plugin hooks!",
233 "Did you know? Plugins can communicate via shared state in PluginContext.",
234 "Hot reload tip: .fsx scripts reload automatically, no rebuild needed!",
235 "Performance tip: Keep your hooks lightweight for snappy terminal response.",
236 "Debug trick: Check plugin.failure_count to see if your hooks are erroring.",
237 "Cool feature: Plugins can define custom emojis and colors for personality!",
238 "Remember: on_output runs for every line, so optimize for speed!",
239 "Quick win: Add a catchphrase to your plugin metadata for extra charm.",
240 "Testing tip: Use on_attach to show debug overlays when clients connect.",
241 "Style guide: Choose a unique emoji that represents your plugin's purpose.",
242];
243
244pub fn random_developer_tip() -> &'static str {
246 let mut rng = rand::thread_rng();
247 DEVELOPER_TIPS[rng.gen_range(0..DEVELOPER_TIPS.len())]
248}
249
250pub fn friendly_error(error: &str, suggestions: Vec<&str>) -> String {
252 let mut msg = format!("{} {}\n", random_error_prefix(), error);
253
254 if !suggestions.is_empty() {
255 msg.push_str("\nš” Suggestions:\n");
256 for (i, suggestion) in suggestions.iter().enumerate() {
257 msg.push_str(&format!(" {}. {}\n", i + 1, suggestion));
258 }
259 }
260
261 msg
262}
263
264pub fn celebration_message(occasion: &str, ascii_art: Option<&str>) -> String {
266 let mut msg = format!("\nš {} š\n", occasion);
267
268 if let Some(art) = ascii_art {
269 msg.push_str(art);
270 msg.push('\n');
271 }
272
273 msg
274}
275
276pub fn special_date_message() -> Option<String> {
278 use chrono::{Datelike, Local};
279
280 let today = Local::now();
281 let month = today.month();
282 let day = today.day();
283
284 match (month, day) {
285 (1, 1) => Some("š Happy New Year! May your plugins be bug-free! š".to_string()),
286 (3, 14) => Some("š„§ Happy Pi Day! 3.14159... plugins loaded! š„§".to_string()),
287 (4, 1) => Some("𤔠April Fools! Just kidding, your plugins are real. š¤”".to_string()),
288 (5, 4) => Some("ā May the 4th be with you! Plugin Force activated! ā".to_string()),
289 (10, 31) => Some("š Happy Halloween! Your plugins are spooktacular! š".to_string()),
290 (12, 25) => Some("š Merry Christmas! Unwrapping plugin presents! š".to_string()),
291 _ => None,
292 }
293}
294
295#[cfg(test)]
296mod tests {
297 use super::*;
298
299 #[test]
300 fn test_plugin_mood() {
301 assert_eq!(
302 PluginMood::from_failure_count(0, 3, true),
303 PluginMood::Happy
304 );
305 assert_eq!(
306 PluginMood::from_failure_count(1, 3, true),
307 PluginMood::Content
308 );
309 assert_eq!(
310 PluginMood::from_failure_count(2, 3, true),
311 PluginMood::Struggling
312 );
313 assert_eq!(
314 PluginMood::from_failure_count(0, 3, false),
315 PluginMood::Disabled
316 );
317 }
318
319 #[test]
320 fn test_achievement_formatting() {
321 let achievement = Achievement::FirstPlugin;
322 let formatted = achievement.format();
323 assert!(formatted.contains("Plugin Pioneer"));
324 assert!(formatted.contains("š"));
325 }
326
327 #[test]
328 fn test_friendly_error() {
329 let error = friendly_error(
330 "Plugin failed to load",
331 vec!["Check the file path", "Verify plugin format"],
332 );
333 assert!(error.contains("Plugin failed to load"));
334 assert!(error.contains("Check the file path"));
335 }
336}