зеркало из
https://github.com/glebtv/tui-textarea.git
synced 2026-09-08 00:15:50 +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 edit;
|
||||||
mod history;
|
mod history;
|
||||||
mod input;
|
mod input;
|
||||||
mod textarea;
|
mod textarea;
|
||||||
|
|
||||||
|
pub use cursor::CursorMove;
|
||||||
pub use input::{Input, Key};
|
pub use input::{Input, Key};
|
||||||
pub use textarea::TextArea;
|
pub use textarea::TextArea;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::cursor::CursorMove;
|
||||||
use crate::edit::{Edit, EditKind};
|
use crate::edit::{Edit, EditKind};
|
||||||
use crate::history::EditHistory;
|
use crate::history::EditHistory;
|
||||||
use crate::input::{Input, Key};
|
use crate::input::{Input, Key};
|
||||||
@@ -34,12 +35,12 @@ impl<'a> TextArea<'a> {
|
|||||||
match input.key {
|
match input.key {
|
||||||
Key::Char('h') => self.delete_char(),
|
Key::Char('h') => self.delete_char(),
|
||||||
Key::Char('m') => self.insert_newline(),
|
Key::Char('m') => self.insert_newline(),
|
||||||
Key::Char('p') => self.cursor_up(),
|
Key::Char('p') => self.move_cursor(CursorMove::Up),
|
||||||
Key::Char('f') => self.cursor_forward(),
|
Key::Char('f') => self.move_cursor(CursorMove::Forward),
|
||||||
Key::Char('n') => self.cursor_down(),
|
Key::Char('n') => self.move_cursor(CursorMove::Down),
|
||||||
Key::Char('b') => self.cursor_back(),
|
Key::Char('b') => self.move_cursor(CursorMove::Back),
|
||||||
Key::Char('a') => self.cursor_start(),
|
Key::Char('a') => self.move_cursor(CursorMove::Head),
|
||||||
Key::Char('e') => self.cursor_end(),
|
Key::Char('e') => self.move_cursor(CursorMove::End),
|
||||||
Key::Char('u') => self.undo(),
|
Key::Char('u') => self.undo(),
|
||||||
Key::Char('r') => self.redo(),
|
Key::Char('r') => self.redo(),
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -50,12 +51,12 @@ impl<'a> TextArea<'a> {
|
|||||||
Key::Backspace => self.delete_char(),
|
Key::Backspace => self.delete_char(),
|
||||||
Key::Tab => self.insert_tab(),
|
Key::Tab => self.insert_tab(),
|
||||||
Key::Enter => self.insert_newline(),
|
Key::Enter => self.insert_newline(),
|
||||||
Key::Up => self.cursor_up(),
|
Key::Up => self.move_cursor(CursorMove::Up),
|
||||||
Key::Right => self.cursor_forward(),
|
Key::Right => self.move_cursor(CursorMove::Forward),
|
||||||
Key::Down => self.cursor_down(),
|
Key::Down => self.move_cursor(CursorMove::Down),
|
||||||
Key::Left => self.cursor_back(),
|
Key::Left => self.move_cursor(CursorMove::Back),
|
||||||
Key::Home => self.cursor_start(),
|
Key::Home => self.move_cursor(CursorMove::Head),
|
||||||
Key::End => self.cursor_end(),
|
Key::End => self.move_cursor(CursorMove::End),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,58 +166,10 @@ impl<'a> TextArea<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cursor_forward(&mut self) {
|
pub fn move_cursor(&mut self, m: CursorMove) {
|
||||||
let (r, c) = self.cursor;
|
if let Some(cursor) = m.next_cursor(self.cursor, &self.lines) {
|
||||||
if c + 1 >= self.lines[r].chars().count() {
|
self.cursor = cursor;
|
||||||
if r + 1 < self.lines.len() {
|
|
||||||
self.cursor = (r + 1, 0);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
self.cursor.1 += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
pub fn undo(&mut self) {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user