Match key events using macros

This commit is contained in:
Joscha 2022-08-04 01:05:04 +02:00
parent df0403a782
commit 20ea96f83e
7 changed files with 152 additions and 155 deletions

View file

@ -6,13 +6,14 @@ mod widgets;
use std::sync::Arc;
use async_trait::async_trait;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use crossterm::event::KeyCode;
use parking_lot::FairMutex;
use tokio::sync::Mutex;
use toss::frame::{Frame, Pos, Size};
use toss::terminal::Terminal;
use crate::store::{Msg, MsgStore};
use crate::ui::input::{key, KeyEvent};
use crate::ui::widgets::editor::EditorState;
use crate::ui::widgets::Widget;
@ -66,101 +67,61 @@ impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> {
coming_from: Option<M::Id>,
parent: Option<M::Id>,
) -> Reaction<M> {
let harmless_char = (event.modifiers - KeyModifiers::SHIFT).is_empty();
// TODO Tab-completion
match event.code {
KeyCode::Esc => {
match event {
key!(Esc) => {
self.cursor = coming_from.map(Cursor::Msg).unwrap_or(Cursor::Bottom);
Reaction::Handled
return Reaction::Handled;
}
KeyCode::Enter if event.modifiers.is_empty() => {
key!(Enter) => {
let content = self.editor.text();
if content.trim().is_empty() {
Reaction::Handled
} else {
if !content.trim().is_empty() {
self.cursor = Cursor::Pseudo {
coming_from,
parent: parent.clone(),
};
Reaction::Composed { parent, content }
return Reaction::Composed { parent, content };
}
}
KeyCode::Enter => {
// Enter with *any* modifier pressed - if ctrl and shift don't
// work, maybe alt does
self.editor.insert_char('\n');
self.correction = Some(Correction::MakeCursorVisible);
Reaction::Handled
}
KeyCode::Backspace => {
self.editor.backspace();
self.correction = Some(Correction::MakeCursorVisible);
Reaction::Handled
}
KeyCode::Left => {
self.editor.move_cursor_left();
self.correction = Some(Correction::MakeCursorVisible);
Reaction::Handled
}
KeyCode::Right => {
self.editor.move_cursor_right();
self.correction = Some(Correction::MakeCursorVisible);
Reaction::Handled
}
KeyCode::Delete => {
self.editor.delete();
self.correction = Some(Correction::MakeCursorVisible);
Reaction::Handled
}
KeyCode::Char(ch) if harmless_char => {
self.editor.insert_char(ch);
self.correction = Some(Correction::MakeCursorVisible);
Reaction::Handled
}
KeyCode::Char('e') if event.modifiers == KeyModifiers::CONTROL => {
self.editor.edit_externally(terminal, crossterm_lock);
self.correction = Some(Correction::MakeCursorVisible);
Reaction::Handled
}
KeyCode::Char('l') if event.modifiers == KeyModifiers::CONTROL => {
self.editor.clear();
self.correction = Some(Correction::MakeCursorVisible);
Reaction::Handled
}
_ => Reaction::NotHandled,
// Enter with *any* modifier pressed - if ctrl and shift don't
// work, maybe alt does
KeyEvent {
code: KeyCode::Enter,
..
} => self.editor.insert_char('\n'),
key!(Char ch) => self.editor.insert_char(ch),
key!(Backspace) => self.editor.backspace(),
key!(Left) => self.editor.move_cursor_left(),
key!(Right) => self.editor.move_cursor_right(),
key!(Delete) => self.editor.delete(),
key!(Ctrl + 'e') => self.editor.edit_externally(terminal, crossterm_lock),
key!(Ctrl + 'l') => self.editor.clear(),
_ => return Reaction::NotHandled,
}
self.correction = Some(Correction::MakeCursorVisible);
Reaction::Handled
}
async fn handle_movement_key_event(&mut self, frame: &mut Frame, event: KeyEvent) -> bool {
let chat_height = frame.size().height - 3;
let shift_only = event.modifiers.difference(KeyModifiers::SHIFT).is_empty();
match event.code {
KeyCode::Char('k') | KeyCode::Up if shift_only => self.move_cursor_up().await,
KeyCode::Char('j') | KeyCode::Down if shift_only => self.move_cursor_down().await,
KeyCode::Char('h') | KeyCode::Left if shift_only => self.move_cursor_older().await,
KeyCode::Char('l') | KeyCode::Right if shift_only => self.move_cursor_newer().await,
KeyCode::Char('g') | KeyCode::Home if shift_only => self.move_cursor_to_top().await,
KeyCode::Char('G') | KeyCode::End if shift_only => self.move_cursor_to_bottom().await,
KeyCode::Char('y') if event.modifiers == KeyModifiers::CONTROL => self.scroll_up(1),
KeyCode::Char('e') if event.modifiers == KeyModifiers::CONTROL => self.scroll_down(1),
KeyCode::Char('u') if event.modifiers == KeyModifiers::CONTROL => {
let delta = chat_height / 2;
self.scroll_up(delta.into());
}
KeyCode::Char('d') if event.modifiers == KeyModifiers::CONTROL => {
let delta = chat_height / 2;
self.scroll_down(delta.into());
}
KeyCode::Char('b') if event.modifiers == KeyModifiers::CONTROL => {
let delta = chat_height.saturating_sub(1);
self.scroll_up(delta.into());
}
KeyCode::Char('f') if event.modifiers == KeyModifiers::CONTROL => {
let delta = chat_height.saturating_sub(1);
self.scroll_down(delta.into());
}
match event {
key!('k') | key!(Up) => self.move_cursor_up().await,
key!('j') | key!(Down) => self.move_cursor_down().await,
key!('h') | key!(Left) => self.move_cursor_older().await,
key!('l') | key!(Right) => self.move_cursor_newer().await,
key!('g') | key!(Home) => self.move_cursor_to_top().await,
key!('G') | key!(End) => self.move_cursor_to_bottom().await,
key!(Ctrl + 'y') => self.scroll_up(1),
key!(Ctrl + 'e') => self.scroll_down(1),
key!(Ctrl + 'u') => self.scroll_up((chat_height / 2).into()),
key!(Ctrl + 'd') => self.scroll_down((chat_height / 2).into()),
key!(Ctrl + 'b') => self.scroll_up(chat_height.saturating_sub(1).into()),
key!(Ctrl + 'f') => self.scroll_down(chat_height.saturating_sub(1).into()),
_ => return false,
}
@ -172,35 +133,21 @@ impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> {
event: KeyEvent,
id: Option<M::Id>,
) -> bool {
let shift_only = event.modifiers.difference(KeyModifiers::SHIFT).is_empty();
if !shift_only {
return false;
}
match event.code {
KeyCode::Char('r') => {
match event {
key!('r') => {
if let Some(parent) = self.parent_for_normal_reply().await {
self.cursor = Cursor::Editor {
coming_from: id,
parent,
};
self.cursor = Cursor::editor(id, parent);
self.correction = Some(Correction::MakeCursorVisible);
}
}
KeyCode::Char('R') => {
key!('R') => {
if let Some(parent) = self.parent_for_alternate_reply().await {
self.cursor = Cursor::Editor {
coming_from: id,
parent,
};
self.cursor = Cursor::editor(id, parent);
self.correction = Some(Correction::MakeCursorVisible);
}
}
KeyCode::Char('t' | 'T') => {
self.cursor = Cursor::Editor {
coming_from: id,
parent: None,
};
key!('t') | key!('T') => {
self.cursor = Cursor::editor(id, None);
self.correction = Some(Correction::MakeCursorVisible);
}
_ => return false,