1
0
зеркало из https://github.com/glebtv/tui-textarea.git synced 2026-09-03 22:35:50 +03:00
Этот коммит содержится в:
rhysd
2022-06-10 14:44:29 +09:00
родитель f4ee02d858
Коммит 389aea85ff
3 изменённых файлов: 141 добавлений и 43 удалений

Просмотреть файл

@@ -6,6 +6,8 @@ pub enum CursorMove {
Down,
Head,
End,
Top,
Bottom,
}
impl CursorMove {
@@ -14,6 +16,15 @@ impl CursorMove {
(row, col): (usize, usize),
lines: &[String],
) -> Option<(usize, usize)> {
fn fit_col(col: usize, line: &str) -> usize {
let end = line.chars().count();
if end <= col {
end - 1
} else {
col
}
}
match self {
CursorMove::Forward if col + 1 >= lines[row].chars().count() => {
if row + 1 < lines.len() {
@@ -32,25 +43,16 @@ impl CursorMove {
}
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::Up => Some((row - 1, fit_col(col, &lines[row - 1]))),
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::Down => (Some((row + 1, fit_col(col, &lines[row + 1])))),
CursorMove::Head => Some((row, 0)),
CursorMove::End => Some((row, lines[row].chars().count() - 1)),
CursorMove::Top => Some((0, fit_col(col, &lines[0]))),
CursorMove::Bottom => {
let row = lines.len() - 1;
Some((row, fit_col(col, &lines[row])))
}
}
}
}

Просмотреть файл

@@ -20,6 +20,7 @@ pub enum Key {
pub struct Input {
pub key: Key,
pub ctrl: bool,
pub alt: bool,
}
impl Default for Input {
@@ -27,6 +28,7 @@ impl Default for Input {
Input {
key: Key::Null,
ctrl: false,
alt: false,
}
}
}
@@ -44,6 +46,7 @@ impl From<Event> for Input {
impl From<KeyEvent> for Input {
fn from(key: KeyEvent) -> Self {
let ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
let alt = key.modifiers.contains(KeyModifiers::ALT);
let key = match key.code {
KeyCode::Char(c) => Key::Char(c),
KeyCode::Backspace => Key::Backspace,
@@ -58,6 +61,6 @@ impl From<KeyEvent> for Input {
KeyCode::End => Key::End,
_ => Key::Null,
};
Self { key, ctrl }
Self { key, ctrl, alt }
}
}

Просмотреть файл

@@ -38,34 +38,127 @@ impl<'a> Default for TextArea<'a> {
impl<'a> TextArea<'a> {
pub fn input(&mut self, input: impl Into<Input>) {
let input = input.into();
if input.ctrl {
match input.key {
Key::Char('h') => self.delete_char(),
Key::Char('m') => self.insert_newline(),
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(),
_ => {}
match input {
Input {
key: Key::Char(c),
ctrl: false,
alt: false,
} => self.insert_char(c),
Input {
key: Key::Tab,
ctrl: false,
alt: false,
} => self.insert_tab(),
Input {
key: Key::Char('h'),
ctrl: true,
alt: false,
}
} else {
match input.key {
Key::Char(c) => self.insert_char(c),
Key::Backspace => self.delete_char(),
Key::Tab => self.insert_tab(),
Key::Enter => self.insert_newline(),
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),
_ => {}
| Input {
key: Key::Backspace,
..
} => self.delete_char(),
Input {
key: Key::Char('m'),
ctrl: true,
alt: false,
}
| Input {
key: Key::Enter, ..
} => self.insert_newline(),
Input {
key: Key::Char('n'),
ctrl: true,
alt: false,
}
| Input {
key: Key::Down,
ctrl: false,
alt: false,
} => self.move_cursor(CursorMove::Down),
Input {
key: Key::Char('p'),
ctrl: true,
alt: false,
}
| Input {
key: Key::Up,
ctrl: false,
alt: false,
} => self.move_cursor(CursorMove::Up),
Input {
key: Key::Char('f'),
ctrl: true,
alt: false,
}
| Input {
key: Key::Right,
ctrl: false,
alt: false,
} => self.move_cursor(CursorMove::Forward),
Input {
key: Key::Char('b'),
ctrl: true,
alt: false,
}
| Input {
key: Key::Left,
ctrl: false,
alt: false,
} => self.move_cursor(CursorMove::Back),
Input {
key: Key::Char('a'),
ctrl: true,
alt: false,
}
| Input { key: Key::Home, .. }
| Input {
key: Key::Left | Key::Char('b'),
ctrl: true,
alt: true,
} => self.move_cursor(CursorMove::Head),
Input {
key: Key::Char('e'),
ctrl: true,
alt: false,
}
| Input { key: Key::End, .. }
| Input {
key: Key::Right | Key::Char('f'),
ctrl: true,
alt: true,
} => self.move_cursor(CursorMove::End),
Input {
key: Key::Char('<'),
ctrl: false,
alt: true,
}
| Input {
key: Key::Up | Key::Char('p'),
ctrl: true,
alt: true,
} => self.move_cursor(CursorMove::Top),
Input {
key: Key::Char('>'),
ctrl: false,
alt: true,
}
| Input {
key: Key::Down | Key::Char('n'),
ctrl: true,
alt: true,
} => self.move_cursor(CursorMove::Bottom),
Input {
key: Key::Char('u'),
ctrl: true,
alt: false,
} => self.undo(),
Input {
key: Key::Char('r'),
ctrl: true,
alt: false,
} => self.redo(),
_ => {}
}
// Check invariants