codetether_agent/tui/app/state/
slash_suggest.rs1use crate::tui::models::InputMode;
6
7impl super::AppState {
8 pub fn refresh_slash_suggestions(&mut self) {
9 if !self.input.starts_with('/') {
10 self.slash_suggestions.clear();
11 self.selected_slash_suggestion = 0;
12 return;
13 }
14 let raw_query = self.input.split_whitespace().next().unwrap_or("");
15 let query = crate::tui::app::text::normalize_slash_command(raw_query).to_lowercase();
16 let mut matches: Vec<&str> = super::slash_commands::SLASH_COMMANDS
17 .iter()
18 .filter(|cmd| cmd.starts_with(&query))
19 .copied()
20 .collect();
21 if matches.is_empty() && query.len() > 1 {
22 let needle = &query[1..];
23 matches = super::slash_commands::SLASH_COMMANDS
24 .iter()
25 .filter(|cmd| cmd.contains(needle))
26 .copied()
27 .collect();
28 }
29 if matches.is_empty() && query == "/" {
30 matches = super::slash_commands::SLASH_COMMANDS
31 .iter()
32 .copied()
33 .collect();
34 }
35 self.slash_suggestions = matches.into_iter().map(String::from).collect();
36 if self.selected_slash_suggestion >= self.slash_suggestions.len() {
37 self.selected_slash_suggestion = self.slash_suggestions.len().saturating_sub(1);
38 }
39 }
40
41 pub fn slash_suggestions_visible(&self) -> bool {
42 self.view_mode == crate::tui::models::ViewMode::Chat
46 && !self.processing
47 && self.input.starts_with('/')
48 }
49
50 pub fn slash_suggestions_navigable(&self) -> bool {
55 self.slash_suggestions_visible() && !self.slash_suggestions.is_empty()
56 }
57
58 pub fn current_slash_hint(&self) -> Option<&'static str> {
64 let cmd = self.input.split_whitespace().next()?;
65 super::slash_hints::usage_hint(cmd)
66 }
67
68 pub fn select_prev_slash_suggestion(&mut self) {
69 if !self.slash_suggestions.is_empty() {
70 self.selected_slash_suggestion = self.selected_slash_suggestion.saturating_sub(1);
71 }
72 }
73
74 pub fn select_next_slash_suggestion(&mut self) {
75 if !self.slash_suggestions.is_empty() {
76 self.selected_slash_suggestion =
77 (self.selected_slash_suggestion + 1).min(self.slash_suggestions.len() - 1);
78 }
79 }
80
81 pub fn selected_slash_suggestion(&self) -> Option<&str> {
82 self.slash_suggestions
83 .get(self.selected_slash_suggestion)
84 .map(String::as_str)
85 }
86
87 pub fn apply_selected_slash_suggestion(&mut self) -> bool {
88 if let Some(selected) = self.selected_slash_suggestion() {
89 self.input = selected.to_string();
90 self.input_cursor = self.input_char_count();
91 self.input_mode = InputMode::Command;
92 self.refresh_slash_suggestions();
93 return true;
94 }
95 false
96 }
97}