1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! Popup state for slash-command, @mention, and group-join autocomplete.
//!
//! Holds the current candidate list, selected index, and any pending
//! `@mention` resolutions. The behavior (filter logic, key handling) lives
//! in [`crate::app`]; this module owns only the data.
/// Which autocomplete mode is active.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AutocompleteMode {
#[default]
Command,
Mention,
Join,
}
/// Autocomplete popup state: candidates, selection index, and pending mentions.
pub struct AutocompleteState {
/// Indices into COMMANDS for current matches
pub command_candidates: Vec<usize>,
/// Selected item in autocomplete popup
pub index: usize,
/// Current autocomplete mode (Command vs Mention vs Join)
pub mode: AutocompleteMode,
/// Mention autocomplete candidates: (phone, display_name, uuid)
pub mention_candidates: Vec<(String, String, Option<String>)>,
/// Join autocomplete candidates: (display_text, completion_value)
pub join_candidates: Vec<(String, String)>,
/// Byte offset of the '@' trigger in the input buffer
pub mention_trigger_pos: usize,
/// Completed mentions for the current input: (display_name, uuid)
pub pending_mentions: Vec<(String, Option<String>)>,
}
impl Default for AutocompleteState {
fn default() -> Self {
Self::new()
}
}
impl AutocompleteState {
pub fn new() -> Self {
Self {
command_candidates: Vec::new(),
index: 0,
mode: AutocompleteMode::Command,
mention_candidates: Vec::new(),
join_candidates: Vec::new(),
mention_trigger_pos: 0,
pending_mentions: Vec::new(),
}
}
/// Whether there are no candidates in the current mode.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Number of candidates in the current mode.
pub fn len(&self) -> usize {
match self.mode {
AutocompleteMode::Command => self.command_candidates.len(),
AutocompleteMode::Mention => self.mention_candidates.len(),
AutocompleteMode::Join => self.join_candidates.len(),
}
}
/// Clear all candidates. Caller must also call `App::close_overlay`
/// if the autocomplete overlay was open.
pub fn clear(&mut self) {
self.command_candidates.clear();
self.mention_candidates.clear();
self.join_candidates.clear();
self.index = 0;
}
}