зеркало из
https://github.com/glebtv/tui-textarea.git
synced 2026-09-03 14:26:17 +03:00
separate logic to move cursor
Этот коммит содержится в:
56
src/cursor.rs
Обычный файл
56
src/cursor.rs
Обычный файл
@@ -0,0 +1,56 @@
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum CursorMove {
|
||||
Forward,
|
||||
Back,
|
||||
Up,
|
||||
Down,
|
||||
Head,
|
||||
End,
|
||||
}
|
||||
|
||||
impl CursorMove {
|
||||
pub fn next_cursor(
|
||||
&self,
|
||||
(row, col): (usize, usize),
|
||||
lines: &[String],
|
||||
) -> Option<(usize, usize)> {
|
||||
match self {
|
||||
CursorMove::Forward if col + 1 >= lines[row].chars().count() => {
|
||||
if row + 1 < lines.len() {
|
||||
Some((row + 1, 0))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
CursorMove::Forward => Some((row, col + 1)),
|
||||
CursorMove::Back if col == 0 => {
|
||||
if row > 0 {
|
||||
Some((row - 1, lines[row - 1].chars().count() - 1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
CursorMove::Back => Some((row, col - 1)),
|
||||
CursorMove::Up if row == 0 => None,
|
||||
CursorMove::Up => {
|
||||
let mut col = col;
|
||||
let end = lines[row - 1].chars().count();
|
||||
if end <= col {
|
||||
col = end - 1;
|
||||
}
|
||||
Some((row - 1, col))
|
||||
}
|
||||
CursorMove::Down if row + 1 >= lines.len() => None,
|
||||
CursorMove::Down => {
|
||||
let mut col = col;
|
||||
let end = lines[row + 1].chars().count();
|
||||
if end <= col {
|
||||
col = end - 1;
|
||||
}
|
||||
Some((row + 1, col))
|
||||
}
|
||||
CursorMove::Head => Some((row, 0)),
|
||||
CursorMove::End => Some((row, lines[row].chars().count() - 1)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
mod cursor;
|
||||
mod edit;
|
||||
mod history;
|
||||
mod input;
|
||||
mod textarea;
|
||||
|
||||
pub use cursor::CursorMove;
|
||||
pub use input::{Input, Key};
|
||||
pub use textarea::TextArea;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::cursor::CursorMove;
|
||||
use crate::edit::{Edit, EditKind};
|
||||
use crate::history::EditHistory;
|
||||
use crate::input::{Input, Key};
|
||||
@@ -34,12 +35,12 @@ impl<'a> TextArea<'a> {
|
||||
match input.key {
|
||||
Key::Char('h') => self.delete_char(),
|
||||
Key::Char('m') => self.insert_newline(),
|
||||
Key::Char('p') => self.cursor_up(),
|
||||
Key::Char('f') => self.cursor_forward(),
|
||||
Key::Char('n') => self.cursor_down(),
|
||||
Key::Char('b') => self.cursor_back(),
|
||||
Key::Char('a') => self.cursor_start(),
|
||||
Key::Char('e') => self.cursor_end(),
|
||||
Key::Char('p') => self.move_cursor(CursorMove::Up),
|
||||
Key::Char('f') => self.move_cursor(CursorMove::Forward),
|
||||
Key::Char('n') => self.move_cursor(CursorMove::Down),
|
||||
Key::Char('b') => self.move_cursor(CursorMove::Back),
|
||||
Key::Char('a') => self.move_cursor(CursorMove::Head),
|
||||
Key::Char('e') => self.move_cursor(CursorMove::End),
|
||||
Key::Char('u') => self.undo(),
|
||||
Key::Char('r') => self.redo(),
|
||||
_ => {}
|
||||
@@ -50,12 +51,12 @@ impl<'a> TextArea<'a> {
|
||||
Key::Backspace => self.delete_char(),
|
||||
Key::Tab => self.insert_tab(),
|
||||
Key::Enter => self.insert_newline(),
|
||||
Key::Up => self.cursor_up(),
|
||||
Key::Right => self.cursor_forward(),
|
||||
Key::Down => self.cursor_down(),
|
||||
Key::Left => self.cursor_back(),
|
||||
Key::Home => self.cursor_start(),
|
||||
Key::End => self.cursor_end(),
|
||||
Key::Up => self.move_cursor(CursorMove::Up),
|
||||
Key::Right => self.move_cursor(CursorMove::Forward),
|
||||
Key::Down => self.move_cursor(CursorMove::Down),
|
||||
Key::Left => self.move_cursor(CursorMove::Back),
|
||||
Key::Home => self.move_cursor(CursorMove::Head),
|
||||
Key::End => self.move_cursor(CursorMove::End),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -165,60 +166,12 @@ impl<'a> TextArea<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor_forward(&mut self) {
|
||||
let (r, c) = self.cursor;
|
||||
if c + 1 >= self.lines[r].chars().count() {
|
||||
if r + 1 < self.lines.len() {
|
||||
self.cursor = (r + 1, 0);
|
||||
}
|
||||
} else {
|
||||
self.cursor.1 += 1;
|
||||
pub fn move_cursor(&mut self, m: CursorMove) {
|
||||
if let Some(cursor) = m.next_cursor(self.cursor, &self.lines) {
|
||||
self.cursor = cursor;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor_back(&mut self) {
|
||||
let (r, c) = self.cursor;
|
||||
if c == 0 {
|
||||
if r > 0 {
|
||||
self.cursor = (r - 1, self.lines[r - 1].chars().count() - 1);
|
||||
}
|
||||
} else {
|
||||
self.cursor.1 -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor_down(&mut self) {
|
||||
let (r, c) = self.cursor;
|
||||
if r + 1 >= self.lines.len() {
|
||||
return;
|
||||
}
|
||||
self.cursor.0 += 1;
|
||||
let len = self.lines[r + 1].chars().count();
|
||||
if len <= c {
|
||||
self.cursor.1 = len - 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor_up(&mut self) {
|
||||
let (r, c) = self.cursor;
|
||||
if r == 0 {
|
||||
return;
|
||||
}
|
||||
self.cursor.0 -= 1;
|
||||
let len = self.lines[r - 1].chars().count();
|
||||
if len <= c {
|
||||
self.cursor.1 = len - 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor_start(&mut self) {
|
||||
self.cursor.1 = 0;
|
||||
}
|
||||
|
||||
pub fn cursor_end(&mut self) {
|
||||
self.cursor.1 = self.lines[self.cursor.0].chars().count() - 1;
|
||||
}
|
||||
|
||||
pub fn undo(&mut self) {
|
||||
if let Some(cursor) = self.history.undo(&mut self.lines) {
|
||||
self.cursor = cursor;
|
||||
|
||||
Ссылка в новой задаче
Block a user