alfred_workflow_rust_project/
workflow_item.rs1use std::collections::HashMap;
2
3use serde::ser::SerializeSeq;
4use serde::{Deserialize, Serialize, Serializer};
5
6use crate::common::EnumIdent;
7use crate::icon::Icon;
8
9pub enum ModKey {
11 CMD,
12 CTRL,
13 ALT,
14 FN,
15 SHIFT,
16}
17
18#[derive(Serialize, Deserialize)]
19pub struct Modifier {
20 #[serde(skip_serializing_if = "Option::is_none")]
21 arg: Option<Vec<String>>,
22 subtitle: String,
23 valid: bool,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 icon: Option<Icon>,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 variables: Option<HashMap<String, String>>,
28}
29
30impl Modifier {
31 pub fn new() -> Modifier {
32 return Modifier {
33 arg: None,
34 subtitle: "".to_string(),
35 valid: true,
36 icon: None,
37 variables: None,
38 };
39 }
40
41 pub fn valid(mut self, v: bool) -> Modifier {
42 self.valid = v;
43 self
44 }
45
46 pub fn subtitle(mut self, title: &str) -> Modifier {
47 self.subtitle = title.to_string();
48 self
49 }
50
51 pub fn icon(mut self, icon: Icon) -> Modifier {
52 self.icon = Some(icon);
53 self
54 }
55
56 pub fn args(mut self, arg: &str) -> Modifier {
57 let mut args = self.arg.unwrap_or_default();
58 args.push(arg.to_string());
59 self.arg = Some(args);
60 self
61 }
62
63 pub fn vars(mut self, name: &str, value: &str) -> Modifier {
64 let mut map = self.variables.unwrap_or_default();
65 map.insert(name.to_string(), value.to_string());
66 self.variables = Some(map);
67 self
68 }
69}
70
71pub enum ItemType {
72 DEFAULT,
73 FILE,
74 FILE2,
75}
76
77impl EnumIdent for ModKey {
78 fn name(&self) -> &'static str {
79 match self {
80 ModKey::CMD => "cmd",
81 ModKey::FN => "fn",
82 ModKey::CTRL => "ctrl",
83 ModKey::ALT => "alt",
84 ModKey::SHIFT => "shift",
85 }
86 }
87}
88
89impl EnumIdent for ItemType {
90 fn name(&self) -> &'static str {
91 match self {
92 ItemType::DEFAULT => "default",
93 ItemType::FILE => "file",
94 ItemType::FILE2 => "file:skipcheck",
95 }
96 }
97}
98
99#[derive(Serialize, Deserialize)]
100pub struct WorkflowItem {
101 #[serde(skip_serializing_if = "Option::is_none")]
102 uid: Option<String>,
103 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
104 item_type: Option<String>,
105 title: String,
106 #[serde(skip_serializing_if = "Option::is_none")]
107 subtitle: Option<String>,
108 #[serde(skip_serializing_if = "Option::is_none")]
109 icon: Option<Icon>,
110 valid: bool,
111 #[serde(rename = "match", skip_serializing_if = "Option::is_none")]
112 matches: Option<String>,
113 #[serde(skip_serializing_if = "Option::is_none")]
114 mods: Option<HashMap<String, Modifier>>,
115 #[serde(skip_serializing_if = "Option::is_none")]
116 arg: Option<Vec<String>>,
117 #[serde(rename = "action", skip_serializing_if = "Option::is_none")]
118 actions: Option<Action>,
119 #[serde(skip_serializing_if = "Option::is_none")]
120 text: Option<ItemText>,
121 #[serde(rename = "quicklookurl", skip_serializing_if = "Option::is_none")]
122 quick_look: Option<String>,
123 #[serde(skip_serializing_if = "Option::is_none")]
124 autocomplete: Option<String>,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 variables: Option<HashMap<String, String>>,
127}
128
129impl WorkflowItem {
130 pub fn new(title: &str) -> WorkflowItem {
131 WorkflowItem {
132 title: title.to_string(),
133 uid: None,
134 item_type: None,
135 subtitle: None,
136 icon: None,
137 valid: true,
138 matches: None,
139 mods: None,
140 arg: None,
141 actions: None,
142 text: None,
143 quick_look: None,
144 autocomplete: None,
145 variables: None,
146 }
147 }
148
149 pub fn uid(mut self, uid: &str) -> WorkflowItem {
150 self.uid = Some(uid.to_string());
151 self
152 }
153
154 pub fn item_type(mut self, item_type: ItemType) -> WorkflowItem {
155 self.item_type = Some(item_type.name().to_string());
156 self
157 }
158
159 pub fn subtitle(mut self, subtitle: &str) -> WorkflowItem {
160 self.subtitle = Some(subtitle.to_string());
161 self
162 }
163
164 pub fn icon(mut self, icon: Icon) -> WorkflowItem {
165 self.icon = Some(icon);
166 self
167 }
168
169 pub fn valid(mut self, v: bool) -> WorkflowItem {
170 self.valid = v;
171 self
172 }
173
174 pub fn matches(mut self, matches: &str) -> WorkflowItem {
175 self.matches = Some(matches.to_string());
176 self
177 }
178
179 pub fn mods(mut self, keys: Vec<ModKey>, modifier: Modifier) -> WorkflowItem {
180 if keys.len() <= 0 {
182 return self;
183 }
184
185 let x1: Vec<&str> = keys.iter().map(|x| x.name()).collect();
186 let key_str = x1.join("+");
187
188 let mut map = self.mods.unwrap_or_default();
189 map.insert(key_str, modifier);
190 self.mods = Some(map);
191 self
192 }
193
194 pub fn actions(mut self, action: Action) -> WorkflowItem {
195 self.actions = Some(action);
196 self
197 }
198 pub fn text(mut self, text: ItemText) -> WorkflowItem {
199 self.text = Some(text);
200 self
201 }
202 pub fn quick_look(mut self, look_uri: &str) -> WorkflowItem {
203 self.quick_look = Some(look_uri.to_string());
204 self
205 }
206 pub fn auto_complete(mut self, auto_complete: &str) -> WorkflowItem {
207 self.autocomplete = Some(auto_complete.to_string());
208 self
209 }
210 pub fn vars(mut self, name: &str, value: &str) -> WorkflowItem {
211 let mut vars = self.variables.unwrap_or_default();
212 vars.insert(name.to_string(), value.to_string());
213 self.variables = Some(vars);
214 self
215 }
216 pub fn args(mut self, arg: &str) -> WorkflowItem {
217 let mut vec = self.arg.unwrap_or_default();
218 vec.push(arg.to_string());
219 self.arg = Some(vec);
220 self
221 }
222}
223
224#[derive(Deserialize)]
226pub enum Action {
227 SingleItem(String),
228 MultiItem(Vec<String>),
229 ObjectItem(ActionItem),
230}
231
232impl Serialize for Action {
233 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
234 where
235 S: Serializer,
236 {
237 match self {
238 Action::SingleItem(var) => serializer.serialize_str(var),
239 Action::MultiItem(var) => {
240 let mut seq = serializer.serialize_seq(Some(var.len()))?;
241 for e in var {
242 seq.serialize_element(e)?;
243 }
244 seq.end()
245 }
246 Action::ObjectItem(var) => ActionItem::serialize(var, serializer),
247 }
248 }
249}
250
251#[derive(Serialize, Deserialize)]
252pub struct ActionItem {
253 #[serde(skip_serializing_if = "Option::is_none")]
254 text: Option<Vec<String>>,
255 #[serde(skip_serializing_if = "Option::is_none")]
256 url: Option<String>,
257 #[serde(skip_serializing_if = "Option::is_none")]
258 file: Option<String>,
259 #[serde(skip_serializing_if = "Option::is_none")]
260 auto: Option<String>,
261}
262
263impl ActionItem {
264 pub fn new() -> ActionItem {
265 ActionItem {
266 text: None,
267 url: None,
268 file: None,
269 auto: None,
270 }
271 }
272
273 pub fn text(mut self, text: &str) -> ActionItem {
274 let mut texts = self.text.unwrap_or_default();
275 texts.push(text.to_string());
276 self.text = Some(texts);
277 self
278 }
279
280 pub fn texts(mut self, texts: Vec<&str>) -> ActionItem {
281 let mut a_texts = self.text.unwrap_or_default();
282 texts.iter().for_each(|it| a_texts.push(it.to_string()));
283 self.text = Some(a_texts);
284 self
285 }
286
287 pub fn url(mut self, url: &str) -> ActionItem {
288 self.url = Some(url.to_string());
289 self
290 }
291
292 pub fn file(mut self, file: &str) -> ActionItem {
293 self.file = Some(file.to_string());
294 self
295 }
296
297 pub fn auto(mut self, auto: &str) -> ActionItem {
298 self.auto = Some(auto.to_string());
299 self
300 }
301}
302
303#[derive(Serialize, Deserialize)]
304pub struct ItemText {
305 #[serde(skip_serializing_if = "Option::is_none")]
306 copy: Option<String>,
307 #[serde(skip_serializing_if = "Option::is_none")]
308 #[serde(rename = "largetype")]
309 large_type: Option<String>,
310}
311
312impl ItemText {
313 pub fn new(copy_text: &str) -> ItemText {
314 ItemText {
315 copy: Some(copy_text.to_string()),
316 large_type: None,
317 }
318 }
319
320 pub fn large_text(mut self, text: &str) -> ItemText {
321 self.large_type = Some(text.to_string());
322 self
323 }
324}