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

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

@@ -6,6 +6,8 @@ pub enum CursorMove {
Down, Down,
Head, Head,
End, End,
Top,
Bottom,
} }
impl CursorMove { impl CursorMove {
@@ -14,6 +16,15 @@ impl CursorMove {
(row, col): (usize, usize), (row, col): (usize, usize),
lines: &[String], lines: &[String],
) -> Option<(usize, usize)> { ) -> 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 { match self {
CursorMove::Forward if col + 1 >= lines[row].chars().count() => { CursorMove::Forward if col + 1 >= lines[row].chars().count() => {
if row + 1 < lines.len() { if row + 1 < lines.len() {
@@ -32,25 +43,16 @@ impl CursorMove {
} }
CursorMove::Back => Some((row, col - 1)), CursorMove::Back => Some((row, col - 1)),
CursorMove::Up if row == 0 => None, CursorMove::Up if row == 0 => None,
CursorMove::Up => { CursorMove::Up => Some((row - 1, fit_col(col, &lines[row - 1]))),
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 if row + 1 >= lines.len() => None,
CursorMove::Down => { CursorMove::Down => (Some((row + 1, fit_col(col, &lines[row + 1])))),
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::Head => Some((row, 0)),
CursorMove::End => Some((row, lines[row].chars().count() - 1)), 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 struct Input {
pub key: Key, pub key: Key,
pub ctrl: bool, pub ctrl: bool,
pub alt: bool,
} }
impl Default for Input { impl Default for Input {
@@ -27,6 +28,7 @@ impl Default for Input {
Input { Input {
key: Key::Null, key: Key::Null,
ctrl: false, ctrl: false,
alt: false,
} }
} }
} }
@@ -44,6 +46,7 @@ impl From<Event> for Input {
impl From<KeyEvent> for Input { impl From<KeyEvent> for Input {
fn from(key: KeyEvent) -> Self { fn from(key: KeyEvent) -> Self {
let ctrl = key.modifiers.contains(KeyModifiers::CONTROL); let ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
let alt = key.modifiers.contains(KeyModifiers::ALT);
let key = match key.code { let key = match key.code {
KeyCode::Char(c) => Key::Char(c), KeyCode::Char(c) => Key::Char(c),
KeyCode::Backspace => Key::Backspace, KeyCode::Backspace => Key::Backspace,
@@ -58,6 +61,6 @@ impl From<KeyEvent> for Input {
KeyCode::End => Key::End, KeyCode::End => Key::End,
_ => Key::Null, _ => Key::Null,
}; };
Self { key, ctrl } Self { key, ctrl, alt }
} }
} }

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

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