codetether_agent/tui/app/state/
input_cursor.rs1impl super::AppState {
7 pub(crate) fn input_char_count(&self) -> usize {
8 self.input.chars().count()
9 }
10
11 pub(crate) fn char_to_byte_index(&self, char_index: usize) -> usize {
12 if char_index == 0 {
13 return 0;
14 }
15 self.input
16 .char_indices()
17 .nth(char_index)
18 .map(|(idx, _)| idx)
19 .unwrap_or_else(|| self.input.len())
20 }
21
22 fn char_at(&self, char_index: usize) -> Option<char> {
23 self.input.chars().nth(char_index)
24 }
25
26 pub fn clamp_input_cursor(&mut self) {
27 self.input_cursor = self.input_cursor.min(self.input_char_count());
28 }
29
30 #[allow(dead_code)]
31 pub fn ensure_input_cursor_visible(&mut self, visible_width: usize) {
32 if visible_width == 0 {
33 self.input_scroll = self.input_cursor;
34 return;
35 }
36 if self.input_cursor < self.input_scroll {
37 self.input_scroll = self.input_cursor;
38 } else if self.input_cursor >= self.input_scroll.saturating_add(visible_width) {
39 self.input_scroll = self
40 .input_cursor
41 .saturating_sub(visible_width.saturating_sub(1));
42 }
43 }
44
45 pub fn move_cursor_left(&mut self) {
46 if self.input_cursor > 0 {
47 self.input_cursor -= 1;
48 }
49 }
50
51 pub fn move_cursor_right(&mut self) {
52 if self.input_cursor < self.input_char_count() {
53 self.input_cursor += 1;
54 }
55 }
56
57 pub fn move_cursor_word_left(&mut self) {
58 self.clamp_input_cursor();
59 while self.input_cursor > 0
60 && self
61 .char_at(self.input_cursor - 1)
62 .is_some_and(char::is_whitespace)
63 {
64 self.input_cursor -= 1;
65 }
66 while self.input_cursor > 0
67 && self
68 .char_at(self.input_cursor - 1)
69 .is_some_and(|c| !c.is_whitespace())
70 {
71 self.input_cursor -= 1;
72 }
73 }
74
75 pub fn move_cursor_word_right(&mut self) {
76 self.clamp_input_cursor();
77 while self.input_cursor < self.input_char_count()
78 && self
79 .char_at(self.input_cursor)
80 .is_some_and(char::is_whitespace)
81 {
82 self.input_cursor += 1;
83 }
84 while self.input_cursor < self.input_char_count()
85 && self
86 .char_at(self.input_cursor)
87 .is_some_and(|c| !c.is_whitespace())
88 {
89 self.input_cursor += 1;
90 }
91 }
92
93 pub fn move_cursor_home(&mut self) {
94 self.input_cursor = 0;
95 }
96
97 pub fn move_cursor_end(&mut self) {
98 self.input_cursor = self.input_char_count();
99 }
100}