lattice_mode/modes/
completion.rs1use std::sync::Arc;
36
37use lattice_completion::{
38 BufferWordsSource, CompletionSourceContribution, CompletionSourceKind, PathCompletionSource,
39 SourceId,
40};
41use lattice_config::OptionOverrideSet;
42
43use crate::{BufferLocal, CapabilitySet, LifecycleFuture, Mode, ModeContext, ModeId, ModeKind};
44
45pub struct CompletionMode;
49
50impl CompletionMode {
51 pub fn mode_id() -> ModeId {
55 ModeId::new("completion-mode")
56 }
57}
58
59impl Mode for CompletionMode {
60 type Guard = ();
61 fn id(&self) -> ModeId {
62 Self::mode_id()
63 }
64 fn kind(&self) -> ModeKind {
65 ModeKind::Minor
66 }
67 fn options(&self) -> OptionOverrideSet {
68 OptionOverrideSet::default()
69 }
70 fn required_capabilities(&self) -> CapabilitySet {
71 CapabilitySet::empty()
72 }
73 fn on_activate(&self, _ctx: ModeContext) -> LifecycleFuture<'_, ()> {
74 Box::pin(async { Ok(()) })
75 }
76}
77
78pub struct BufferWordsMode;
96
97impl BufferWordsMode {
98 pub fn mode_id() -> ModeId {
102 ModeId::new("buffer-words-mode")
103 }
104}
105
106impl Mode for BufferWordsMode {
107 type Guard = ();
108 fn id(&self) -> ModeId {
109 Self::mode_id()
110 }
111 fn kind(&self) -> ModeKind {
112 ModeKind::Minor
113 }
114 fn options(&self) -> OptionOverrideSet {
115 OptionOverrideSet::default()
116 }
117 fn required_capabilities(&self) -> CapabilitySet {
118 CapabilitySet::empty()
119 }
120 fn completion_sources(&self) -> Vec<CompletionSourceContribution> {
121 vec![CompletionSourceContribution {
122 accepts_non_word_query: false,
123 id: SourceId::new(BufferWordsSource::ID),
124 default_priority: 100,
125 auto_trigger: true,
126 trigger_chars: Vec::new(),
127 popup_filter_chord: Some('b'),
128 kind: CompletionSourceKind::Sync(Arc::new(BufferWordsSource::new())),
129 }]
130 }
131 fn on_activate(&self, _ctx: ModeContext) -> LifecycleFuture<'_, ()> {
132 Box::pin(async { Ok(()) })
133 }
134}
135
136pub struct PathCompletionMode;
153
154impl PathCompletionMode {
155 pub fn mode_id() -> ModeId {
159 ModeId::new("path-completion-mode")
160 }
161}
162
163impl Mode for PathCompletionMode {
164 type Guard = ();
165 fn id(&self) -> ModeId {
166 Self::mode_id()
167 }
168 fn kind(&self) -> ModeKind {
169 ModeKind::Minor
170 }
171 fn options(&self) -> OptionOverrideSet {
172 OptionOverrideSet::default()
173 }
174 fn required_capabilities(&self) -> CapabilitySet {
175 CapabilitySet::empty()
176 }
177 fn completion_sources(&self) -> Vec<CompletionSourceContribution> {
178 vec![CompletionSourceContribution {
179 accepts_non_word_query: false,
180 id: SourceId::new(lattice_completion::PATH_SOURCE_ID),
181 default_priority: 90,
186 auto_trigger: true,
187 trigger_chars: vec!['/'],
188 popup_filter_chord: Some('f'),
189 kind: CompletionSourceKind::Sync(Arc::new(PathCompletionSource)),
190 }]
191 }
192 fn on_activate(&self, _ctx: ModeContext) -> LifecycleFuture<'_, ()> {
193 Box::pin(async { Ok(()) })
194 }
195}
196
197pub struct CompletionPopupMode;
199
200impl CompletionPopupMode {
201 pub fn mode_id() -> ModeId {
205 ModeId::new("completion-popup-mode")
206 }
207}
208
209impl Mode for CompletionPopupMode {
210 type Guard = ();
211 fn id(&self) -> ModeId {
212 Self::mode_id()
213 }
214 fn kind(&self) -> ModeKind {
215 ModeKind::Minor
216 }
217 fn options(&self) -> OptionOverrideSet {
218 OptionOverrideSet::default()
219 }
220 fn required_capabilities(&self) -> CapabilitySet {
221 CapabilitySet::empty()
222 }
223 fn on_activate(&self, _ctx: ModeContext) -> LifecycleFuture<'_, ()> {
224 Box::pin(async { Ok(()) })
225 }
226}
227
228#[derive(Debug, Clone, Default)]
243pub struct ActiveCompletionSources(pub Vec<CompletionSourceContribution>);
244
245impl BufferLocal for ActiveCompletionSources {
246 const NAME: &'static str = "completion-mode.active-sources";
247 const DOC: &'static str = "Cached active insert-completion source set for this \
248 buffer. Recomputed on every mode-activation / \
249 -deactivation transition; read by the aggregator on \
250 the popup-open / refilter path.";
251 const OWNER_MODE: &'static str = "completion-mode";
252 fn describe(&self) -> String {
253 format!("{} source(s)", self.0.len())
254 }
255}
256
257#[cfg(test)]
258mod tests {
259 use super::*;
260 use crate::{ActiveModes, BufferLocals, GuardStoreHandle, ModeRegistry};
261 use lattice_protocol::ids::BufferId;
262
263 #[test]
264 fn completion_mode_is_a_minor() {
265 assert_eq!(CompletionMode.kind(), ModeKind::Minor);
266 assert_eq!(CompletionMode.id(), CompletionMode::mode_id());
267 assert_eq!(CompletionMode::mode_id().as_str(), "completion-mode");
268 }
269
270 #[test]
271 fn completion_popup_mode_is_a_minor() {
272 assert_eq!(CompletionPopupMode.kind(), ModeKind::Minor);
273 assert_eq!(CompletionPopupMode.id(), CompletionPopupMode::mode_id());
274 assert_eq!(
275 CompletionPopupMode::mode_id().as_str(),
276 "completion-popup-mode",
277 );
278 }
279
280 #[test]
281 fn both_modes_register_and_activate() {
282 let mut registry = ModeRegistry::new();
283 registry
284 .register(CompletionMode)
285 .expect("register completion-mode");
286 registry
287 .register(CompletionPopupMode)
288 .expect("register completion-popup-mode");
289 let mut active = ActiveModes::new();
290 let guards = GuardStoreHandle::new();
291 let cfg = Arc::new(lattice_config::ConfigRegistry::new());
292 let evt = Arc::new(lattice_runtime::EventBus::new());
293 let svc = Arc::new(crate::services::ServiceRegistry::new());
294 registry
295 .activate_minor(
296 &mut active,
297 &guards,
298 &cfg,
299 &evt,
300 &svc,
301 BufferId::new(0),
302 CompletionMode::mode_id(),
303 CapabilitySet::empty(),
304 )
305 .expect("activate completion-mode");
306 registry
307 .activate_minor(
308 &mut active,
309 &guards,
310 &cfg,
311 &evt,
312 &svc,
313 BufferId::new(0),
314 CompletionPopupMode::mode_id(),
315 CapabilitySet::empty(),
316 )
317 .expect("activate completion-popup-mode");
318 assert!(active.has_minor(CompletionMode::mode_id()));
319 assert!(active.has_minor(CompletionPopupMode::mode_id()));
320 }
321
322 #[test]
323 fn both_modes_default_completion_sources_is_empty() {
324 assert!(<CompletionMode as Mode>::completion_sources(&CompletionMode).is_empty());
326 assert!(<CompletionPopupMode as Mode>::completion_sources(&CompletionPopupMode).is_empty());
327 }
328
329 #[test]
330 fn active_completion_sources_describes_count() {
331 let empty = ActiveCompletionSources::default();
332 assert_eq!(empty.describe(), "0 source(s)");
333 }
334
335 #[test]
336 fn active_completion_sources_is_a_buffer_local() {
337 let mut locals = BufferLocals::new();
338 locals.insert(ActiveCompletionSources(Vec::new()));
339 assert!(locals.get::<ActiveCompletionSources>().is_some());
340 let d = locals.iter_descriptors().next().expect("descriptor");
341 assert_eq!(d.name, "completion-mode.active-sources");
342 assert_eq!(d.owner_mode, "completion-mode");
343 }
344}