From ef019dc887e0e7895852a15dfa526ae72cdbedd0 Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 21 Feb 2022 02:10:51 +0100 Subject: [PATCH] Make text input cursor moveable --- cove-tui/src/textline.rs | 51 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/cove-tui/src/textline.rs b/cove-tui/src/textline.rs index fa8b5e2..d7e960a 100644 --- a/cove-tui/src/textline.rs +++ b/cove-tui/src/textline.rs @@ -24,23 +24,64 @@ impl StatefulWidget for TextLine { #[derive(Debug, Default)] pub struct TextLineState { content: String, + cursor: usize, } impl TextLineState { pub fn set_cursor(&self, f: &mut Frame, area: Rect) { - let x = area.x + (self.content.width() as u16); - let x = cmp::min(x, area.x + area.width); + let prefix = self.content.chars().take(self.cursor).collect::(); + let position = prefix.width() as u16; + let x = area.x + cmp::min(position, area.width); f.set_cursor(x, area.y); } + fn chars(&self) -> usize { + self.content.chars().count() + } + + fn move_cursor_start(&mut self) { + self.cursor = 0; + } + + fn move_cursor_left(&mut self) { + if self.cursor > 0 { + self.cursor -= 1; + } + } + + fn move_cursor_right(&mut self) { + self.cursor = cmp::min(self.cursor + 1, self.chars()); + } + + fn move_cursor_end(&mut self) { + self.cursor = self.chars(); + } + + fn cursor_byte_offset(&self) -> usize { + self.content + .char_indices() + .nth(self.cursor) + .map(|(i, _)| i) + .unwrap_or_else(|| self.content.len()) + } + pub fn process_input(&mut self, event: Event) { if let Event::Key(k) = event { match k.code { - KeyCode::Backspace => { - self.content.pop(); + KeyCode::Backspace if self.cursor > 0 => { + self.move_cursor_left(); + self.content.remove(self.cursor_byte_offset()); + } + KeyCode::Left => self.move_cursor_left(), + KeyCode::Right => self.move_cursor_right(), + KeyCode::Home => self.move_cursor_start(), + KeyCode::End => self.move_cursor_end(), + KeyCode::Delete if self.cursor < self.chars() => { + self.content.remove(self.cursor_byte_offset()); } KeyCode::Char(c) => { - self.content.push(c); + self.content.insert(self.cursor_byte_offset(), c); + self.move_cursor_right(); } _ => {} }