Match key events using macros
This commit is contained in:
parent
df0403a782
commit
20ea96f83e
7 changed files with 152 additions and 155 deletions
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue