bubbletea_widgets/textinput/
movement.rs

1//! Cursor movement and text deletion methods.
2
3use super::model::Model;
4use super::types::EchoMode;
5
6impl Model {
7    /// Delete all text before the cursor
8    pub(super) fn delete_before_cursor(&mut self) {
9        if self.pos < self.value.len() {
10            self.value.drain(..self.pos);
11        } else {
12            self.value.clear();
13        }
14        self.err = self.validate_runes(&self.value);
15        self.offset = 0;
16        self.set_cursor(0);
17    }
18
19    /// Delete all text after the cursor
20    pub(super) fn delete_after_cursor(&mut self) {
21        self.value.truncate(self.pos);
22        self.err = self.validate_runes(&self.value);
23        self.set_cursor(self.value.len());
24    }
25
26    /// Delete the word before the cursor
27    pub(super) fn delete_word_backward(&mut self) {
28        if self.pos == 0 || self.value.is_empty() {
29            return;
30        }
31
32        if self.echo_mode != EchoMode::EchoNormal {
33            self.delete_before_cursor();
34            return;
35        }
36
37        let old_pos = self.pos;
38
39        // Move to start of current word
40        if self.pos > 0 {
41            self.pos -= 1;
42
43            // Skip whitespace
44            while self.pos > 0 && self.value[self.pos].is_whitespace() {
45                self.pos -= 1;
46            }
47
48            // Skip non-whitespace
49            while self.pos > 0 && !self.value[self.pos].is_whitespace() {
50                self.pos -= 1;
51            }
52
53            if self.pos > 0 {
54                self.pos += 1; // Keep one space
55            }
56        }
57
58        self.value.drain(self.pos..old_pos);
59        self.err = self.validate_runes(&self.value);
60    }
61
62    /// Delete the word after the cursor
63    pub(super) fn delete_word_forward(&mut self) {
64        if self.pos >= self.value.len() || self.value.is_empty() {
65            return;
66        }
67
68        if self.echo_mode != EchoMode::EchoNormal {
69            self.delete_after_cursor();
70            return;
71        }
72
73        let old_pos = self.pos;
74        let mut end_pos = self.pos;
75
76        // Skip whitespace
77        while end_pos < self.value.len() && self.value[end_pos].is_whitespace() {
78            end_pos += 1;
79        }
80
81        // Skip non-whitespace
82        while end_pos < self.value.len() && !self.value[end_pos].is_whitespace() {
83            end_pos += 1;
84        }
85
86        self.value.drain(old_pos..end_pos);
87        self.err = self.validate_runes(&self.value);
88        self.set_cursor(old_pos);
89    }
90
91    /// Move cursor backward by one word
92    pub(super) fn word_backward(&mut self) {
93        if self.pos == 0 || self.value.is_empty() {
94            return;
95        }
96
97        if self.echo_mode != EchoMode::EchoNormal {
98            self.cursor_start();
99            return;
100        }
101
102        let mut i = self.pos;
103        if i > 0 {
104            i -= 1;
105
106            // Skip whitespace
107            while i > 0 && self.value[i].is_whitespace() {
108                self.set_cursor(self.pos - 1);
109                i -= 1;
110            }
111
112            // Skip non-whitespace
113            while i > 0 && !self.value[i].is_whitespace() {
114                self.set_cursor(self.pos - 1);
115                i -= 1;
116            }
117        }
118    }
119
120    /// Move cursor forward by one word
121    pub(super) fn word_forward(&mut self) {
122        if self.pos >= self.value.len() || self.value.is_empty() {
123            return;
124        }
125
126        if self.echo_mode != EchoMode::EchoNormal {
127            self.cursor_end();
128            return;
129        }
130
131        let mut i = self.pos;
132
133        // Skip whitespace
134        while i < self.value.len() && self.value[i].is_whitespace() {
135            self.set_cursor(self.pos + 1);
136            i += 1;
137        }
138
139        // Skip non-whitespace
140        while i < self.value.len() && !self.value[i].is_whitespace() {
141            self.set_cursor(self.pos + 1);
142            i += 1;
143        }
144    }
145}