use std::ops::{Deref, DerefMut};
use crossterm::event::{KeyCode, KeyEvent};
use supercode::frontend::FrontendRuntimeDescriptor;
use supercode_frontend_model::{
ComposerAction, ComposerInputEvent, ComposerKey, ComposerKeyCode,
ComposerModel as NeutralComposerModel,
};
use crate::terminal::event_stream::TerminalEvent;
#[derive(Clone, Debug)]
pub struct ComposerModel(NeutralComposerModel);
impl ComposerModel {
pub fn new(descriptor: &FrontendRuntimeDescriptor) -> Self {
Self(NeutralComposerModel::new(descriptor))
}
pub fn handle_terminal_event(&mut self, event: TerminalEvent) -> Option<ComposerAction> {
self.0.handle_input(map_terminal_event(event))
}
pub fn handle_key(&mut self, key: KeyEvent) -> Option<ComposerAction> {
self.0.handle_key(map_key(key))
}
}
impl Deref for ComposerModel {
type Target = NeutralComposerModel;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for ComposerModel {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
fn map_terminal_event(event: TerminalEvent) -> ComposerInputEvent {
match event {
TerminalEvent::Key(key) => ComposerInputEvent::Key(map_key(key)),
TerminalEvent::Paste(text) => ComposerInputEvent::Paste(text),
TerminalEvent::Resize { width, height } => ComposerInputEvent::Resize { width, height },
TerminalEvent::FocusChanged(focused) => ComposerInputEvent::FocusChanged(focused),
}
}
fn map_key(key: KeyEvent) -> ComposerKey {
let code = match key.code {
KeyCode::Char(character) => ComposerKeyCode::Char(character),
KeyCode::Enter => ComposerKeyCode::Enter,
KeyCode::Backspace => ComposerKeyCode::Backspace,
KeyCode::Delete => ComposerKeyCode::Delete,
KeyCode::Left => ComposerKeyCode::Left,
KeyCode::Right => ComposerKeyCode::Right,
KeyCode::Home => ComposerKeyCode::Home,
KeyCode::End => ComposerKeyCode::End,
KeyCode::Up => ComposerKeyCode::Up,
KeyCode::Down => ComposerKeyCode::Down,
KeyCode::Esc => ComposerKeyCode::Escape,
_ => ComposerKeyCode::Other,
};
ComposerKey {
code,
control: key
.modifiers
.contains(crossterm::event::KeyModifiers::CONTROL),
shift: key
.modifiers
.contains(crossterm::event::KeyModifiers::SHIFT),
alt: key.modifiers.contains(crossterm::event::KeyModifiers::ALT),
release: key.kind == crossterm::event::KeyEventKind::Release,
}
}