diff options
author | Joscha <joscha@plugh.de> | 2022-09-26 17:27:47 +0200 |
---|---|---|
committer | Joscha <joscha@plugh.de> | 2022-09-26 17:36:49 +0200 |
commit | 61a9cc10f1058f3fcabd18993d42afe9a25671a7 (patch) | |
tree | 2dd4ea9e078fcb56b8cde5c25aa03590084456cb | |
parent | 5ed0cd5f3f754cc1cb5c852f1dfc46868623011d (diff) |
Update toss to version with separate widthdb
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/ui.rs | 2 | ||||
-rw-r--r-- | src/ui/chat/tree/layout.rs | 3 | ||||
-rw-r--r-- | src/ui/chat/tree/widgets.rs | 6 | ||||
-rw-r--r-- | src/ui/util.rs | 24 | ||||
-rw-r--r-- | src/ui/widgets/editor.rs | 144 | ||||
-rw-r--r-- | src/ui/widgets/text.rs | 12 |
8 files changed, 101 insertions, 94 deletions
@@ -1214,7 +1214,7 @@ dependencies = [ [[package]] name = "toss" version = "0.1.0" -source = "git+https://github.com/Garmelon/toss.git?rev=24fd0050fbfdd72ac2f03029148370b362291777#24fd0050fbfdd72ac2f03029148370b362291777" +source = "git+https://github.com/Garmelon/toss.git?rev=06aefd562bd66f5564f7c1ea73a4959f51be74e7#06aefd562bd66f5564f7c1ea73a4959f51be74e7" dependencies = [ "crossterm", "unicode-linebreak", @@ -41,7 +41,7 @@ rev = "bdb17db5bf4796696d6375168abb76920ab11b87" [dependencies.toss] git = "https://github.com/Garmelon/toss.git" -rev = "24fd0050fbfdd72ac2f03029148370b362291777" +rev = "06aefd562bd66f5564f7c1ea73a4959f51be74e7" # [patch."https://github.com/Garmelon/toss.git"] # toss = { path = "../toss/" } @@ -1,5 +1,3 @@ -// TODO Reduce need to pass Terminal when only width db is needed - mod chat; mod euph; mod input; diff --git a/src/ui/chat/tree/layout.rs b/src/ui/chat/tree/layout.rs index 35ff3b4..3a22bc0 100644 --- a/src/ui/chat/tree/layout.rs +++ b/src/ui/chat/tree/layout.rs @@ -75,7 +75,8 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> { frame: &mut Frame, indent: usize, ) -> Block<BlockId<M::Id>> { - let (widget, cursor_row) = widgets::editor::<M>(frame, indent, &context.nick, &self.editor); + let (widget, cursor_row) = + widgets::editor::<M>(frame.widthdb(), indent, &context.nick, &self.editor); let cursor_row = cursor_row as i32; Block::new(frame, BlockId::Cursor, widget).focus(cursor_row..cursor_row + 1) } diff --git a/src/ui/chat/tree/widgets.rs b/src/ui/chat/tree/widgets.rs index 8733926..8854dcd 100644 --- a/src/ui/chat/tree/widgets.rs +++ b/src/ui/chat/tree/widgets.rs @@ -3,8 +3,8 @@ mod seen; mod time; use crossterm::style::{ContentStyle, Stylize}; -use toss::frame::Frame; use toss::styled::Styled; +use toss::widthdb::WidthDb; use super::super::ChatMsg; use crate::store::Msg; @@ -111,14 +111,14 @@ pub fn msg_placeholder( } pub fn editor<M: ChatMsg>( - frame: &mut Frame, + widthdb: &mut WidthDb, indent: usize, nick: &str, editor: &EditorState, ) -> (BoxedWidget, usize) { let (nick, content) = M::edit(nick, &editor.text()); let editor = editor.widget().highlight(|_| content); - let cursor_row = editor.cursor_row(frame); + let cursor_row = editor.cursor_row(widthdb); let widget = HJoin::new(vec![ Segment::new(seen::widget(true)), diff --git a/src/ui/util.rs b/src/ui/util.rs index 0ee4d3b..583dcd5 100644 --- a/src/ui/util.rs +++ b/src/ui/util.rs @@ -98,10 +98,10 @@ pub fn handle_editor_input_event( InputEvent::Key(crate::ui::input::KeyEvent { code: crossterm::event::KeyCode::Enter, .. - }) if char_filter('\n') => editor.insert_char(terminal.frame(), '\n'), + }) if char_filter('\n') => editor.insert_char(terminal.widthdb(), '\n'), // Editing - key!(Char ch) if char_filter(*ch) => editor.insert_char(terminal.frame(), *ch), + key!(Char ch) if char_filter(*ch) => editor.insert_char(terminal.widthdb(), *ch), key!(Paste str) => { // It seems that when pasting, '\n' are converted into '\r' for some // reason. I don't really know why, or at what point this happens. @@ -109,25 +109,25 @@ pub fn handle_editor_input_event( // decided to mirror that behaviour. let str = str.replace('\r', "\n"); if str.chars().all(char_filter) { - editor.insert_str(terminal.frame(), &str); + editor.insert_str(terminal.widthdb(), &str); } else { return false; } } - key!(Ctrl + 'h') | key!(Backspace) => editor.backspace(terminal.frame()), + key!(Ctrl + 'h') | key!(Backspace) => editor.backspace(terminal.widthdb()), key!(Ctrl + 'd') | key!(Delete) => editor.delete(), key!(Ctrl + 'l') => editor.clear(), // TODO Key bindings to delete words // Cursor movement - key!(Ctrl + 'b') | key!(Left) => editor.move_cursor_left(terminal.frame()), - key!(Ctrl + 'f') | key!(Right) => editor.move_cursor_right(terminal.frame()), - key!(Alt + 'b') | key!(Ctrl + Left) => editor.move_cursor_left_a_word(terminal.frame()), - key!(Alt + 'f') | key!(Ctrl + Right) => editor.move_cursor_right_a_word(terminal.frame()), - key!(Ctrl + 'a') | key!(Home) => editor.move_cursor_to_start_of_line(terminal.frame()), - key!(Ctrl + 'e') | key!(End) => editor.move_cursor_to_end_of_line(terminal.frame()), - key!(Up) => editor.move_cursor_up(terminal.frame()), - key!(Down) => editor.move_cursor_down(terminal.frame()), + key!(Ctrl + 'b') | key!(Left) => editor.move_cursor_left(terminal.widthdb()), + key!(Ctrl + 'f') | key!(Right) => editor.move_cursor_right(terminal.widthdb()), + key!(Alt + 'b') | key!(Ctrl + Left) => editor.move_cursor_left_a_word(terminal.widthdb()), + key!(Alt + 'f') | key!(Ctrl + Right) => editor.move_cursor_right_a_word(terminal.widthdb()), + key!(Ctrl + 'a') | key!(Home) => editor.move_cursor_to_start_of_line(terminal.widthdb()), + key!(Ctrl + 'e') | key!(End) => editor.move_cursor_to_end_of_line(terminal.widthdb()), + key!(Up) => editor.move_cursor_up(terminal.widthdb()), + key!(Down) => editor.move_cursor_down(terminal.widthdb()), _ => return false, } diff --git a/src/ui/widgets/editor.rs b/src/ui/widgets/editor.rs index 8de6cf0..54c8fd4 100644 --- a/src/ui/widgets/editor.rs +++ b/src/ui/widgets/editor.rs @@ -7,6 +7,7 @@ use parking_lot::{FairMutex, Mutex}; use toss::frame::{Frame, Pos, Size}; use toss::styled::Styled; use toss::terminal::Terminal; +use toss::widthdb::WidthDb; use unicode_segmentation::UnicodeSegmentation; use crate::ui::util; @@ -14,10 +15,10 @@ use crate::ui::util; use super::text::Text; use super::Widget; -/// Like [`Frame::wrap`] but includes a final break index if the text ends with -/// a newline. -fn wrap(frame: &mut Frame, text: &str, width: usize) -> Vec<usize> { - let mut breaks = frame.wrap(text, width); +/// Like [`WidthDb::wrap`] but includes a final break index if the text ends +/// with a newline. +fn wrap(widthdb: &mut WidthDb, text: &str, width: usize) -> Vec<usize> { + let mut breaks = widthdb.wrap(text, width); if text.ends_with('\n') { breaks.push(text.len()) } @@ -125,8 +126,8 @@ impl InnerEditorState { result } - fn cursor_col(&self, frame: &mut Frame, line_start: usize) -> usize { - frame.width(&self.text[line_start..self.idx]) + fn cursor_col(&self, widthdb: &mut WidthDb, line_start: usize) -> usize { + widthdb.width(&self.text[line_start..self.idx]) } fn line(&self, line: usize) -> (usize, usize) { @@ -139,7 +140,7 @@ impl InnerEditorState { .expect("line exists") } - fn move_cursor_to_line_col(&mut self, frame: &mut Frame, line: usize, col: usize) { + fn move_cursor_to_line_col(&mut self, widthdb: &mut WidthDb, line: usize, col: usize) { let (start, end) = self.line(line); let line = &self.text[start..end]; @@ -147,7 +148,7 @@ impl InnerEditorState { for (gi, g) in line.grapheme_indices(true) { self.idx = start + gi; if col > width { - width += frame.grapheme_width(g, width) as usize; + width += widthdb.grapheme_width(g, width) as usize; } else { return; } @@ -158,10 +159,10 @@ impl InnerEditorState { } } - fn record_cursor_col(&mut self, frame: &mut Frame) { + fn record_cursor_col(&mut self, widthdb: &mut WidthDb) { let boundaries = self.line_boundaries(); let (_, start, _) = self.cursor_line(&boundaries); - self.col = self.cursor_col(frame, start); + self.col = self.cursor_col(widthdb, start); } ///////////// @@ -174,36 +175,36 @@ impl InnerEditorState { self.col = 0; } - fn set_text(&mut self, frame: &mut Frame, text: String) { + fn set_text(&mut self, widthdb: &mut WidthDb, text: String) { self.text = text; self.move_cursor_to_grapheme_boundary(); - self.record_cursor_col(frame); + self.record_cursor_col(widthdb); } /// Insert a character at the current cursor position and move the cursor /// accordingly. - fn insert_char(&mut self, frame: &mut Frame, ch: char) { + fn insert_char(&mut self, widthdb: &mut WidthDb, ch: char) { self.text.insert(self.idx, ch); self.idx += ch.len_utf8(); - self.record_cursor_col(frame); + self.record_cursor_col(widthdb); } /// Insert a string at the current cursor position and move the cursor /// accordingly. - fn insert_str(&mut self, frame: &mut Frame, str: &str) { + fn insert_str(&mut self, widthdb: &mut WidthDb, str: &str) { self.text.insert_str(self.idx, str); self.idx += str.len(); - self.record_cursor_col(frame); + self.record_cursor_col(widthdb); } /// Delete the grapheme before the cursor position. - fn backspace(&mut self, frame: &mut Frame) { + fn backspace(&mut self, widthdb: &mut WidthDb) { let boundaries = self.grapheme_boundaries(); for (start, end) in boundaries.iter().zip(boundaries.iter().skip(1)) { if *end == self.idx { self.text.replace_range(start..end, ""); self.idx = *start; - self.record_cursor_col(frame); + self.record_cursor_col(widthdb); break; } } @@ -224,29 +225,29 @@ impl InnerEditorState { // Cursor movement // ///////////////////// - fn move_cursor_left(&mut self, frame: &mut Frame) { + fn move_cursor_left(&mut self, widthdb: &mut WidthDb) { let boundaries = self.grapheme_boundaries(); for (start, end) in boundaries.iter().zip(boundaries.iter().skip(1)) { if *end == self.idx { self.idx = *start; - self.record_cursor_col(frame); + self.record_cursor_col(widthdb); break; } } } - fn move_cursor_right(&mut self, frame: &mut Frame) { + fn move_cursor_right(&mut self, widthdb: &mut WidthDb) { let boundaries = self.grapheme_boundaries(); for (start, end) in boundaries.iter().zip(boundaries.iter().skip(1)) { if *start == self.idx { self.idx = *end; - self.record_cursor_col(frame); + self.record_cursor_col(widthdb); break; } } } - fn move_cursor_left_a_word(&mut self, frame: &mut Frame) { + fn move_cursor_left_a_word(&mut self, widthdb: &mut WidthDb) { let boundaries = self.grapheme_boundaries(); let mut encountered_word = false; for (start, end) in boundaries.iter().zip(boundaries.iter().skip(1)).rev() { @@ -261,10 +262,10 @@ impl InnerEditorState { self.idx = *start; } } - self.record_cursor_col(frame); + self.record_cursor_col(widthdb); } - fn move_cursor_right_a_word(&mut self, frame: &mut Frame) { + fn move_cursor_right_a_word(&mut self, widthdb: &mut WidthDb) { let boundaries = self.grapheme_boundaries(); let mut encountered_word = false; for (start, end) in boundaries.iter().zip(boundaries.iter().skip(1)) { @@ -279,32 +280,32 @@ impl InnerEditorState { self.idx = *end; } } - self.record_cursor_col(frame); + self.record_cursor_col(widthdb); } - fn move_cursor_to_start_of_line(&mut self, frame: &mut Frame) { + fn move_cursor_to_start_of_line(&mut self, widthdb: &mut WidthDb) { let boundaries = self.line_boundaries(); let (line, _, _) = self.cursor_line(&boundaries); - self.move_cursor_to_line_col(frame, line, 0); - self.record_cursor_col(frame); + self.move_cursor_to_line_col(widthdb, line, 0); + self.record_cursor_col(widthdb); } - fn move_cursor_to_end_of_line(&mut self, frame: &mut Frame) { + fn move_cursor_to_end_of_line(&mut self, widthdb: &mut WidthDb) { let boundaries = self.line_boundaries(); let (line, _, _) = self.cursor_line(&boundaries); - self.move_cursor_to_line_col(frame, line, usize::MAX); - self.record_cursor_col(frame); + self.move_cursor_to_line_col(widthdb, line, usize::MAX); + self.record_cursor_col(widthdb); } - fn move_cursor_up(&mut self, frame: &mut Frame) { + fn move_cursor_up(&mut self, widthdb: &mut WidthDb) { let boundaries = self.line_boundaries(); let (line, _, _) = self.cursor_line(&boundaries); if line > 0 { - self.move_cursor_to_line_col(frame, line - 1, self.col); + self.move_cursor_to_line_col(widthdb, line - 1, self.col); } } - fn move_cursor_down(&mut self, frame: &mut Frame) { + fn move_cursor_down(&mut self, widthdb: &mut WidthDb) { let boundaries = self.line_boundaries(); // There's always at least one line, and always at least two line @@ -313,7 +314,7 @@ impl InnerEditorState { let (line, _, _) = self.cursor_line(&boundaries); if line + 1 < amount_of_lines { - self.move_cursor_to_line_col(frame, line + 1, self.col); + self.move_cursor_to_line_col(widthdb, line + 1, self.col); } } } @@ -350,21 +351,21 @@ impl EditorState { self.0.lock().clear(); } - pub fn set_text(&self, frame: &mut Frame, text: String) { - self.0.lock().set_text(frame, text); + pub fn set_text(&self, widthdb: &mut WidthDb, text: String) { + self.0.lock().set_text(widthdb, text); } - pub fn insert_char(&self, frame: &mut Frame, ch: char) { - self.0.lock().insert_char(frame, ch); + pub fn insert_char(&self, widthdb: &mut WidthDb, ch: char) { + self.0.lock().insert_char(widthdb, ch); } - pub fn insert_str(&self, frame: &mut Frame, str: &str) { - self.0.lock().insert_str(frame, str); + pub fn insert_str(&self, widthdb: &mut WidthDb, str: &str) { + self.0.lock().insert_str(widthdb, str); } /// Delete the grapheme before the cursor position. - pub fn backspace(&self, frame: &mut Frame) { - self.0.lock().backspace(frame); + pub fn backspace(&self, widthdb: &mut WidthDb) { + self.0.lock().backspace(widthdb); } /// Delete the grapheme after the cursor position. @@ -372,36 +373,36 @@ impl EditorState { self.0.lock().delete(); } - pub fn move_cursor_left(&self, frame: &mut Frame) { - self.0.lock().move_cursor_left(frame); + pub fn move_cursor_left(&self, widthdb: &mut WidthDb) { + self.0.lock().move_cursor_left(widthdb); } - pub fn move_cursor_right(&self, frame: &mut Frame) { - self.0.lock().move_cursor_right(frame); + pub fn move_cursor_right(&self, widthdb: &mut WidthDb) { + self.0.lock().move_cursor_right(widthdb); } - pub fn move_cursor_left_a_word(&self, frame: &mut Frame) { - self.0.lock().move_cursor_left_a_word(frame); + pub fn move_cursor_left_a_word(&self, widthdb: &mut WidthDb) { + self.0.lock().move_cursor_left_a_word(widthdb); } - pub fn move_cursor_right_a_word(&self, frame: &mut Frame) { - self.0.lock().move_cursor_right_a_word(frame); + pub fn move_cursor_right_a_word(&self, widthdb: &mut WidthDb) { + self.0.lock().move_cursor_right_a_word(widthdb); } - pub fn move_cursor_to_start_of_line(&self, frame: &mut Frame) { - self.0.lock().move_cursor_to_start_of_line(frame); + pub fn move_cursor_to_start_of_line(&self, widthdb: &mut WidthDb) { + self.0.lock().move_cursor_to_start_of_line(widthdb); } - pub fn move_cursor_to_end_of_line(&self, frame: &mut Frame) { - self.0.lock().move_cursor_to_end_of_line(frame); + pub fn move_cursor_to_end_of_line(&self, widthdb: &mut WidthDb) { + self.0.lock().move_cursor_to_end_of_line(widthdb); } - pub fn move_cursor_up(&self, frame: &mut Frame) { - self.0.lock().move_cursor_up(frame); + pub fn move_cursor_up(&self, widthdb: &mut WidthDb) { + self.0.lock().move_cursor_up(widthdb); } - pub fn move_cursor_down(&self, frame: &mut Frame) { - self.0.lock().move_cursor_down(frame); + pub fn move_cursor_down(&self, widthdb: &mut WidthDb) { + self.0.lock().move_cursor_down(widthdb); } pub fn edit_externally( @@ -422,9 +423,9 @@ impl EditorState { // Some editors like vim add a trailing newline that would look out // of place in cove's editor. To intentionally add a trailing // newline, simply add two in-editor. - guard.set_text(terminal.frame(), text.to_string()); + guard.set_text(terminal.widthdb(), text.to_string()); } else { - guard.set_text(terminal.frame(), text); + guard.set_text(terminal.widthdb(), text); } Ok(()) @@ -484,10 +485,10 @@ impl Editor { (row, line_idx) } - pub fn cursor_row(&self, frame: &mut Frame) -> usize { + pub fn cursor_row(&self, widthdb: &mut WidthDb) -> usize { let width = self.state.lock().last_width; let text_width = (width - 1) as usize; - let indices = wrap(frame, self.text.text(), text_width); + let indices = wrap(widthdb, self.text.text(), text_width); let (row, _) = Self::wrapped_cursor(self.idx, &indices); row } @@ -506,14 +507,16 @@ impl Widget for Editor { return size; } + let widthdb = frame.widthdb(); + let max_width = max_width.map(|w| w as usize).unwrap_or(usize::MAX).max(1); let max_text_width = max_width - 1; - let indices = wrap(frame, self.text.text(), max_text_width); + let indices = wrap(widthdb, self.text.text(), max_text_width); let lines = self.text.clone().split_at_indices(&indices); let min_width = lines .iter() - .map(|l| frame.width(l.text().trim_end())) + .map(|l| widthdb.width(l.text().trim_end())) .max() .unwrap_or(0) + 1; @@ -532,15 +535,18 @@ impl Widget for Editor { return; } - let width = frame.size().width.max(1); + let size = frame.size(); + let widthdb = frame.widthdb(); + + let width = size.width.max(1); let text_width = (width - 1) as usize; - let indices = wrap(frame, self.text.text(), text_width); + let indices = wrap(widthdb, self.text.text(), text_width); let lines = self.text.split_at_indices(&indices); // Determine cursor position now while we still have the lines. let cursor_pos = if self.focus { let (cursor_row, cursor_line_idx) = Self::wrapped_cursor(self.idx, &indices); - let cursor_col = frame.width(lines[cursor_row].text().split_at(cursor_line_idx).0); + let cursor_col = widthdb.width(lines[cursor_row].text().split_at(cursor_line_idx).0); let cursor_col = cursor_col.min(text_width); Some(Pos::new(cursor_col as i32, cursor_row as i32)) } else { diff --git a/src/ui/widgets/text.rs b/src/ui/widgets/text.rs index 3ac47cb..5ab65d8 100644 --- a/src/ui/widgets/text.rs +++ b/src/ui/widgets/text.rs @@ -1,6 +1,7 @@ use async_trait::async_trait; use toss::frame::{Frame, Pos, Size}; use toss::styled::Styled; +use toss::widthdb::WidthDb; use super::Widget; @@ -23,14 +24,14 @@ impl Text { self } - fn wrapped(&self, frame: &mut Frame, max_width: Option<u16>) -> Vec<Styled> { + fn wrapped(&self, widthdb: &mut WidthDb, max_width: Option<u16>) -> Vec<Styled> { let max_width = if self.wrap { max_width.map(|w| w as usize).unwrap_or(usize::MAX) } else { usize::MAX }; - let indices = frame.wrap(self.styled.text(), max_width); + let indices = widthdb.wrap(self.styled.text(), max_width); self.styled.clone().split_at_indices(&indices) } } @@ -38,10 +39,11 @@ impl Text { #[async_trait] impl Widget for Text { fn size(&self, frame: &mut Frame, max_width: Option<u16>, _max_height: Option<u16>) -> Size { - let lines = self.wrapped(frame, max_width); + let lines = self.wrapped(frame.widthdb(), max_width); + let widthdb = frame.widthdb(); let min_width = lines .iter() - .map(|l| frame.width(l.text().trim_end())) + .map(|l| widthdb.width(l.text().trim_end())) .max() .unwrap_or(0); let min_height = lines.len(); @@ -51,7 +53,7 @@ impl Widget for Text { async fn render(self: Box<Self>, frame: &mut Frame) { let size = frame.size(); for (i, line) in self - .wrapped(frame, Some(size.width)) + .wrapped(frame.widthdb(), Some(size.width)) .into_iter() .enumerate() { |