flag_rs/
completion_optimized.rs1use crate::active_help::ActiveHelp;
7use crate::completion_item::CompletionItem;
8use crate::context::Context;
9use crate::error::Result;
10use std::borrow::Cow;
11
12#[derive(Clone, Debug)]
17pub struct CompletionResultOptimized {
18 pub items: Vec<CompletionItem>,
20 pub active_help: Vec<ActiveHelp>,
22}
23
24impl CompletionResultOptimized {
25 #[must_use]
27 pub fn new() -> Self {
28 Self {
29 items: Vec::new(),
30 active_help: Vec::new(),
31 }
32 }
33
34 #[allow(clippy::should_implement_trait)]
36 #[must_use]
37 pub fn add(mut self, value: impl Into<Cow<'static, str>>) -> Self {
38 self.items.push(CompletionItem::new(value));
39 self
40 }
41
42 #[must_use]
44 pub fn add_with_description(
45 mut self,
46 value: impl Into<Cow<'static, str>>,
47 desc: impl Into<Cow<'static, str>>,
48 ) -> Self {
49 self.items
50 .push(CompletionItem::with_description(value, desc));
51 self
52 }
53
54 #[must_use]
56 pub fn extend<I, S>(mut self, values: I) -> Self
57 where
58 I: IntoIterator<Item = S>,
59 S: Into<Cow<'static, str>>,
60 {
61 self.items
62 .extend(values.into_iter().map(|v| CompletionItem::new(v)));
63 self
64 }
65
66 #[must_use]
68 pub fn extend_items<I>(mut self, items: I) -> Self
69 where
70 I: IntoIterator<Item = CompletionItem>,
71 {
72 self.items.extend(items);
73 self
74 }
75
76 #[must_use]
78 pub fn add_help(mut self, help: ActiveHelp) -> Self {
79 self.active_help.push(help);
80 self
81 }
82
83 #[must_use]
85 pub fn add_help_text<S: Into<String>>(mut self, message: S) -> Self {
86 self.active_help.push(ActiveHelp::new(message));
87 self
88 }
89
90 #[must_use]
92 pub fn add_conditional_help<S, F>(mut self, message: S, condition: F) -> Self
93 where
94 S: Into<String>,
95 F: Fn(&Context) -> bool + Send + Sync + 'static,
96 {
97 self.active_help
98 .push(ActiveHelp::with_condition(message, condition));
99 self
100 }
101
102 #[must_use]
104 pub fn merge(mut self, other: Self) -> Self {
105 self.items.extend(other.items);
106 self.active_help.extend(other.active_help);
107 self
108 }
109
110 #[must_use]
112 pub fn into_legacy(self) -> crate::completion::CompletionResult {
113 let mut result = crate::completion::CompletionResult::new();
114 for item in self.items {
115 result.values.push(item.value.into_owned());
116 result
117 .descriptions
118 .push(item.description.map_or(String::new(), Cow::into_owned));
119 }
120 result.active_help = self.active_help;
121 result
122 }
123
124 #[must_use]
126 pub fn from_legacy(legacy: crate::completion::CompletionResult) -> Self {
127 let items = legacy
128 .values
129 .into_iter()
130 .zip(legacy.descriptions)
131 .map(|(value, desc)| {
132 if desc.is_empty() {
133 CompletionItem::new(value)
134 } else {
135 CompletionItem::with_description(value, desc)
136 }
137 })
138 .collect();
139
140 Self {
141 items,
142 active_help: legacy.active_help,
143 }
144 }
145}
146
147impl Default for CompletionResultOptimized {
148 fn default() -> Self {
149 Self::new()
150 }
151}
152
153pub type CompletionFuncOptimized =
155 Box<dyn Fn(&Context, &str) -> Result<CompletionResultOptimized> + Send + Sync>;
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160
161 #[test]
162 fn test_optimized_completion_result() {
163 let result = CompletionResultOptimized::new()
164 .add("option1")
165 .add_with_description("option2", "Description for option2")
166 .extend(["option3", "option4"]);
167
168 assert_eq!(result.items.len(), 4);
169 assert_eq!(result.items[0].value, "option1");
170 assert_eq!(result.items[0].description, None);
171 assert_eq!(result.items[1].value, "option2");
172 assert_eq!(
173 result.items[1].description.as_deref(),
174 Some("Description for option2")
175 );
176 }
177
178 #[test]
179 fn test_memory_efficiency() {
180 let result = CompletionResultOptimized::new()
182 .add("static1")
183 .add_with_description("static2", "static description");
184
185 assert!(matches!(result.items[0].value, Cow::Borrowed(_)));
187 assert!(matches!(
188 result.items[1].description.as_ref().unwrap(),
189 Cow::Borrowed(_)
190 ));
191 }
192
193 #[test]
194 fn test_legacy_conversion() {
195 let optimized = CompletionResultOptimized::new()
196 .add("val1")
197 .add_with_description("val2", "desc2");
198
199 let legacy = optimized.clone().into_legacy();
200 assert_eq!(legacy.values, vec!["val1", "val2"]);
201 assert_eq!(legacy.descriptions, vec!["", "desc2"]);
202
203 let back = CompletionResultOptimized::from_legacy(legacy);
204 assert_eq!(back.items.len(), optimized.items.len());
205 assert_eq!(back.items[0].value, optimized.items[0].value);
206 }
207}