mdvault_core/scripting/
selector.rs1use std::sync::Arc;
7
8#[derive(Debug, Clone)]
10pub struct SelectorItem {
11 pub label: String,
13 pub value: String,
15 pub description: Option<String>,
17}
18
19impl SelectorItem {
20 pub fn new(label: impl Into<String>, value: impl Into<String>) -> Self {
22 Self { label: label.into(), value: value.into(), description: None }
23 }
24
25 pub fn with_description(
27 label: impl Into<String>,
28 value: impl Into<String>,
29 description: impl Into<String>,
30 ) -> Self {
31 Self {
32 label: label.into(),
33 value: value.into(),
34 description: Some(description.into()),
35 }
36 }
37}
38
39#[derive(Debug, Clone, Default)]
41pub struct SelectorOptions {
42 pub prompt: String,
44 pub fuzzy: bool,
46 pub default: Option<usize>,
48 pub allow_cancel: bool,
50}
51
52impl SelectorOptions {
53 pub fn new(prompt: impl Into<String>) -> Self {
55 Self {
56 prompt: prompt.into(),
57 fuzzy: true, default: Some(0),
59 allow_cancel: true,
60 }
61 }
62
63 pub fn with_fuzzy(mut self, fuzzy: bool) -> Self {
65 self.fuzzy = fuzzy;
66 self
67 }
68
69 pub fn with_default(mut self, index: usize) -> Self {
71 self.default = Some(index);
72 self
73 }
74}
75
76pub type SelectorCallback =
81 Arc<dyn Fn(&[SelectorItem], &SelectorOptions) -> Option<String> + Send + Sync>;
82
83pub fn noop_selector(
86 _items: &[SelectorItem],
87 _options: &SelectorOptions,
88) -> Option<String> {
89 None
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_selector_item_new() {
98 let item = SelectorItem::new("Label", "value");
99 assert_eq!(item.label, "Label");
100 assert_eq!(item.value, "value");
101 assert!(item.description.is_none());
102 }
103
104 #[test]
105 fn test_selector_item_with_description() {
106 let item = SelectorItem::with_description("Label", "value", "A description");
107 assert_eq!(item.label, "Label");
108 assert_eq!(item.value, "value");
109 assert_eq!(item.description, Some("A description".to_string()));
110 }
111
112 #[test]
113 fn test_selector_options_defaults() {
114 let opts = SelectorOptions::new("Select an item");
115 assert_eq!(opts.prompt, "Select an item");
116 assert!(opts.fuzzy);
117 assert_eq!(opts.default, Some(0));
118 assert!(opts.allow_cancel);
119 }
120
121 #[test]
122 fn test_selector_options_with_fuzzy() {
123 let opts = SelectorOptions::new("Select").with_fuzzy(false);
124 assert!(!opts.fuzzy);
125 }
126
127 #[test]
128 fn test_selector_options_with_default() {
129 let opts = SelectorOptions::new("Select").with_default(5);
130 assert_eq!(opts.default, Some(5));
131 }
132
133 #[test]
134 fn test_noop_selector() {
135 let items = vec![
136 SelectorItem::new("Item 1", "val1"),
137 SelectorItem::new("Item 2", "val2"),
138 ];
139 let opts = SelectorOptions::new("Select");
140 assert_eq!(noop_selector(&items, &opts), None);
141 }
142
143 #[test]
144 fn test_selector_callback_type() {
145 let callback: SelectorCallback = Arc::new(|items, _opts| {
147 items.first().map(|i| i.value.clone())
149 });
150
151 let items = vec![SelectorItem::new("First", "first_value")];
152 let opts = SelectorOptions::new("Test");
153 let result = callback(&items, &opts);
154 assert_eq!(result, Some("first_value".to_string()));
155 }
156}