1pub use scarab_protocol::{ModalItem, OverlayStyle};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq)]
8pub struct OverlayConfig {
9 pub x: u16,
11 pub y: u16,
13 pub content: String,
15 pub style: OverlayStyle,
17}
18
19impl OverlayConfig {
20 pub fn new(x: u16, y: u16, content: impl Into<String>) -> Self {
22 Self {
23 x,
24 y,
25 content: content.into(),
26 style: OverlayStyle::default(),
27 }
28 }
29
30 pub fn with_style(mut self, style: OverlayStyle) -> Self {
32 self.style = style;
33 self
34 }
35}
36
37#[derive(Debug, Clone, PartialEq)]
39pub struct StatusBarItem {
40 pub label: String,
42 pub content: String,
44 pub priority: i32,
46}
47
48impl StatusBarItem {
49 pub fn new(label: impl Into<String>, content: impl Into<String>) -> Self {
51 Self {
52 label: label.into(),
53 content: content.into(),
54 priority: 0,
55 }
56 }
57
58 pub fn with_priority(mut self, priority: i32) -> Self {
60 self.priority = priority;
61 self
62 }
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum JumpDirection {
68 Up,
70 Down,
72 First,
74 Last,
76}
77
78#[derive(Debug, Clone)]
80pub enum RemoteCommand {
81 DrawOverlay {
82 id: u64,
83 x: u16,
84 y: u16,
85 text: String,
86 style: OverlayStyle,
87 },
88 ClearOverlays {
89 id: Option<u64>,
90 },
91 ShowModal {
92 title: String,
93 items: Vec<ModalItem>,
94 },
95 PluginLog {
96 plugin_name: String,
97 level: crate::context::LogLevel,
98 message: String,
99 },
100 PluginNotify {
101 title: String,
102 body: String,
103 level: crate::context::NotifyLevel,
104 },
105 ThemeUpdate {
106 theme_json: String,
107 },
108 NavEnterHintMode {
110 plugin_name: String,
111 },
112 NavExitMode {
113 plugin_name: String,
114 },
115 NavRegisterFocusable {
116 plugin_name: String,
117 x: u16,
118 y: u16,
119 width: u16,
120 height: u16,
121 label: String,
122 action: scarab_protocol::NavFocusableAction,
123 },
124 NavUnregisterFocusable {
125 plugin_name: String,
126 focusable_id: u64,
127 },
128 SpawnOverlay {
130 plugin_name: String,
131 overlay_id: u64,
132 config: OverlayConfig,
133 },
134 RemoveOverlay {
136 plugin_name: String,
137 overlay_id: u64,
138 },
139 AddStatusItem {
141 plugin_name: String,
142 item_id: u64,
143 item: StatusBarItem,
144 },
145 RemoveStatusItem {
147 plugin_name: String,
148 item_id: u64,
149 },
150 PromptJump {
152 plugin_name: String,
153 direction: JumpDirection,
154 },
155 ApplyTheme {
157 plugin_name: String,
158 theme_name: String,
159 },
160 SetPaletteColor {
162 plugin_name: String,
163 color_name: String,
164 value: String,
165 },
166 GetCurrentTheme {
168 plugin_name: String,
169 },
170}
171
172#[derive(Debug, Clone, PartialEq, Eq)]
174pub enum Action {
175 Continue,
177 Stop,
179 Modify(Vec<u8>),
181}
182
183impl Action {
184 pub fn is_modify(&self) -> bool {
186 matches!(self, Action::Modify(_))
187 }
188
189 pub fn is_stop(&self) -> bool {
191 matches!(self, Action::Stop)
192 }
193}
194
195#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
197pub enum HookType {
198 PreOutput,
200 PostInput,
202 PreCommand,
204 PostCommand,
206 OnResize,
208 OnAttach,
210 OnDetach,
212}
213
214impl HookType {
215 pub fn all() -> &'static [HookType] {
217 &[
218 HookType::PreOutput,
219 HookType::PostInput,
220 HookType::PreCommand,
221 HookType::PostCommand,
222 HookType::OnResize,
223 HookType::OnAttach,
224 HookType::OnDetach,
225 ]
226 }
227
228 pub fn name(&self) -> &'static str {
230 match self {
231 HookType::PreOutput => "pre-output",
232 HookType::PostInput => "post-input",
233 HookType::PreCommand => "pre-command",
234 HookType::PostCommand => "post-command",
235 HookType::OnResize => "on-resize",
236 HookType::OnAttach => "on-attach",
237 HookType::OnDetach => "on-detach",
238 }
239 }
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
244pub struct PluginInfo {
245 pub name: String,
247 pub version: String,
249 pub description: String,
251 pub author: String,
253 pub homepage: Option<String>,
255 pub api_version: String,
257 pub min_scarab_version: String,
259 pub enabled: bool,
261 pub failure_count: u32,
263 #[serde(default)]
265 pub emoji: Option<String>,
266 #[serde(default)]
268 pub color: Option<String>,
269 #[serde(default)]
271 pub catchphrase: Option<String>,
272}
273
274impl PluginInfo {
275 pub fn new(
277 name: impl Into<String>,
278 version: impl Into<String>,
279 description: impl Into<String>,
280 author: impl Into<String>,
281 ) -> Self {
282 Self {
283 name: name.into(),
284 version: version.into(),
285 description: description.into(),
286 author: author.into(),
287 homepage: None,
288 api_version: crate::API_VERSION.to_string(),
289 min_scarab_version: "0.1.0".to_string(),
290 enabled: true,
291 failure_count: 0,
292 emoji: None,
293 color: None,
294 catchphrase: None,
295 }
296 }
297
298 pub fn display_name(&self) -> String {
300 if let Some(emoji) = &self.emoji {
301 format!("{} {}", emoji, self.name)
302 } else {
303 self.name.clone()
304 }
305 }
306
307 pub fn mood(&self) -> crate::delight::PluginMood {
309 crate::delight::PluginMood::from_failure_count(self.failure_count, 3, self.enabled)
310 }
311}
312
313#[derive(Debug, Clone, Copy, PartialEq, Eq)]
315pub struct Cell {
316 pub c: char,
318 pub fg: (u8, u8, u8),
320 pub bg: (u8, u8, u8),
322 pub bold: bool,
324 pub italic: bool,
326 pub underline: bool,
328}
329
330impl Default for Cell {
331 fn default() -> Self {
332 Self {
333 c: ' ',
334 fg: (255, 255, 255),
335 bg: (0, 0, 0),
336 bold: false,
337 italic: false,
338 underline: false,
339 }
340 }
341}