use crossterm::event::{Event as CrosstermEvent, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
use super::{Event, MatchListEvent, PromptEvent};
#[inline]
pub fn keybind_default<A>(key_event: KeyEvent) -> Option<Event<A>> {
keybind_no_multi_passthrough(key_event)
.or_else(keybind_multi_passthrough)
.ok()
}
#[inline]
pub fn keybind_no_multi<A>(key_event: KeyEvent) -> Option<Event<A>> {
keybind_no_multi_passthrough(key_event).ok()
}
#[inline]
pub fn keybind_multi_passthrough<A>(key_event: KeyEvent) -> Result<Event<A>, KeyEvent> {
match key_event {
KeyEvent {
kind: KeyEventKind::Press,
modifiers: KeyModifiers::NONE,
code,
..
} => match code {
KeyCode::Tab => Ok(Event::MatchList(MatchListEvent::ToggleDown(1))),
KeyCode::BackTab => Ok(Event::MatchList(MatchListEvent::ToggleUp(1))),
_ => Err(key_event),
},
KeyEvent {
kind: KeyEventKind::Press,
modifiers: KeyModifiers::CONTROL,
code,
..
} => match code {
KeyCode::Char('-') => Ok(Event::MatchList(MatchListEvent::UnqueueAll)),
KeyCode::Char('=') => Ok(Event::MatchList(MatchListEvent::QueueMatches)),
_ => Err(key_event),
},
KeyEvent {
kind: KeyEventKind::Press,
modifiers: KeyModifiers::SHIFT,
code: KeyCode::BackTab,
..
} => Ok(Event::MatchList(MatchListEvent::ToggleUp(1))),
e => Err(e),
}
}
#[inline]
fn keybind_no_multi_passthrough<A>(key_event: KeyEvent) -> Result<Event<A>, KeyEvent> {
match key_event {
KeyEvent {
kind: KeyEventKind::Press,
modifiers: KeyModifiers::NONE,
code,
..
} => match code {
KeyCode::Esc => Ok(Event::Quit),
KeyCode::Up => Ok(Event::MatchList(MatchListEvent::Up(1))),
KeyCode::Down => Ok(Event::MatchList(MatchListEvent::Down(1))),
KeyCode::Left => Ok(Event::Prompt(PromptEvent::Left(1))),
KeyCode::Right => Ok(Event::Prompt(PromptEvent::Right(1))),
KeyCode::Home => Ok(Event::Prompt(PromptEvent::ToStart)),
KeyCode::End => Ok(Event::Prompt(PromptEvent::ToEnd)),
KeyCode::Char(ch) => Ok(Event::Prompt(PromptEvent::Insert(ch))),
KeyCode::Backspace => Ok(Event::Prompt(PromptEvent::Backspace(1))),
KeyCode::Enter => Ok(Event::Select),
KeyCode::Delete => Ok(Event::Prompt(PromptEvent::Delete(1))),
_ => Err(key_event),
},
KeyEvent {
kind: KeyEventKind::Press,
modifiers: KeyModifiers::CONTROL,
code,
..
} => match code {
KeyCode::Char('c') => Ok(Event::UserInterrupt),
KeyCode::Char('d') => Ok(Event::QuitPromptEmpty),
KeyCode::Char('0') => Ok(Event::MatchList(MatchListEvent::Reset)),
KeyCode::Char('g' | 'q') => Ok(Event::Quit),
KeyCode::Char('k' | 'p') => Ok(Event::MatchList(MatchListEvent::Up(1))),
KeyCode::Char('j' | 'n') => Ok(Event::MatchList(MatchListEvent::Down(1))),
KeyCode::Char('b') => Ok(Event::Prompt(PromptEvent::Left(1))),
KeyCode::Char('f') => Ok(Event::Prompt(PromptEvent::Right(1))),
KeyCode::Char('a') => Ok(Event::Prompt(PromptEvent::ToStart)),
KeyCode::Char('e') => Ok(Event::Prompt(PromptEvent::ToEnd)),
KeyCode::Char('h') => Ok(Event::Prompt(PromptEvent::Backspace(1))),
KeyCode::Char('w') => Ok(Event::Prompt(PromptEvent::BackspaceWord(1))),
KeyCode::Char('u') => Ok(Event::Prompt(PromptEvent::ClearBefore)),
KeyCode::Char('o') => Ok(Event::Prompt(PromptEvent::ClearAfter)),
_ => Err(key_event),
},
KeyEvent {
kind: KeyEventKind::Press,
modifiers: KeyModifiers::ALT,
code,
..
} => match code {
KeyCode::Char('f') => Ok(Event::Prompt(PromptEvent::WordLeft(1))),
KeyCode::Char('b') => Ok(Event::Prompt(PromptEvent::WordRight(1))),
_ => Err(key_event),
},
KeyEvent {
kind: KeyEventKind::Press,
modifiers: KeyModifiers::SHIFT,
code,
..
} => match code {
KeyCode::Char(ch) => Ok(Event::Prompt(PromptEvent::Insert(ch))),
KeyCode::BackTab => Ok(Event::MatchList(MatchListEvent::ToggleUp(1))),
KeyCode::Backspace => Ok(Event::Prompt(PromptEvent::Backspace(1))),
KeyCode::Enter => Ok(Event::MatchList(MatchListEvent::Down(1))),
_ => Err(key_event),
},
_ => Err(key_event),
}
}
pub fn convert_crossterm_event<A, F: FnMut(KeyEvent) -> Option<Event<A>>>(
ct_event: CrosstermEvent,
mut keybind: F,
) -> Option<Event<A>> {
match ct_event {
CrosstermEvent::Key(key_event) => keybind(key_event),
CrosstermEvent::Resize(_, _) => Some(Event::Redraw),
CrosstermEvent::Paste(contents) => Some(Event::Prompt(PromptEvent::Paste(contents))),
_ => None,
}
}