use crossterm::event::{ self, Event, KeyCode, KeyModifiers, KeyEvent };
use std::time::Duration;
use crate::buffer::TextBuffer;
#[derive( Debug, PartialEq, Eq )]
pub enum KeyAction
{
Submit,
Cancel,
Continue,
}
pub fn read_key( timeout: Option< Duration > ) -> std::io::Result< KeyEvent >
{
loop
{
let has_event = if let Some( timeout ) = timeout
{
event::poll( timeout )?
}
else
{
event::poll( Duration::from_secs( 86400 ) )?
};
if has_event
{
if let Event::Key( key_event ) = event::read()?
{
if key_event.kind == event::KeyEventKind::Press
{
return Ok( key_event );
}
}
}
else if timeout.is_some()
{
return Err( std::io::Error::new(
std::io::ErrorKind::TimedOut,
"Key read timeout"
) );
}
}
}
pub fn handle_key( key: KeyEvent, buffer: &mut TextBuffer ) -> KeyAction
{
match ( key.code, key.modifiers )
{
( KeyCode::Enter, KeyModifiers::NONE ) => KeyAction::Submit,
( KeyCode::Enter, mods ) if mods.contains( KeyModifiers::CONTROL ) || mods.contains( KeyModifiers::SHIFT ) =>
{
buffer.insert_newline();
KeyAction::Continue
}
( KeyCode::Char( 'd' ), mods ) if mods.contains( KeyModifiers::CONTROL ) =>
{
KeyAction::Submit
}
( KeyCode::Esc, _ ) => KeyAction::Cancel,
( KeyCode::Char( 'c' ), mods ) if mods.contains( KeyModifiers::CONTROL ) =>
{
KeyAction::Cancel
}
( KeyCode::Backspace, _ ) =>
{
buffer.delete_char_before();
KeyAction::Continue
}
( KeyCode::Delete, _ ) =>
{
buffer.delete_char_at();
KeyAction::Continue
}
( KeyCode::Left, _ ) =>
{
buffer.move_left();
KeyAction::Continue
}
( KeyCode::Right, _ ) =>
{
buffer.move_right();
KeyAction::Continue
}
( KeyCode::Up, _ ) =>
{
buffer.move_up();
KeyAction::Continue
}
( KeyCode::Down, _ ) =>
{
buffer.move_down();
KeyAction::Continue
}
( KeyCode::Home, KeyModifiers::NONE ) =>
{
buffer.move_to_line_start();
KeyAction::Continue
}
( KeyCode::End, KeyModifiers::NONE ) =>
{
buffer.move_to_line_end();
KeyAction::Continue
}
( KeyCode::Home, mods ) if mods.contains( KeyModifiers::CONTROL ) =>
{
buffer.move_to_text_start();
KeyAction::Continue
}
( KeyCode::End, mods ) if mods.contains( KeyModifiers::CONTROL ) =>
{
buffer.move_to_text_end();
KeyAction::Continue
}
( KeyCode::Char( ch ), mods )
if !mods.contains( KeyModifiers::CONTROL ) || mods == KeyModifiers::SHIFT =>
{
buffer.insert_char( ch );
KeyAction::Continue
}
( KeyCode::Tab, _ ) =>
{
buffer.insert_char( ' ' );
buffer.insert_char( ' ' );
KeyAction::Continue
}
_ => KeyAction::Continue,
}
}