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