use reovim_driver_input::{
FallbackContext, FallbackResult, InputFallbackHandler, KeyCode, KeyEvent, Modifiers,
};
use crate::modes::VimMode;
#[derive(Debug, Clone, Copy, Default)]
pub struct VimFallbackHandler;
impl<C: FallbackContext> InputFallbackHandler<C> for VimFallbackHandler {
#[cfg_attr(coverage_nightly, coverage(off))]
fn handle_unmatched(&self, key: KeyEvent, ctx: &mut C) -> FallbackResult {
let mode_id = ctx.current_mode();
if *mode_id == VimMode::INSERT_ID {
if let Some(ch) = key_to_char(&key) {
if let Some(buffer_id) = ctx.active_buffer()
&& let Some(cursor_before) = ctx.cursor_position()
&& let Some(buffer_arc) = ctx.get_buffer(buffer_id)
{
let mut buffer = buffer_arc.write();
let text = ch.to_string();
buffer.insert_at(cursor_before, &text);
drop(buffer);
let cursor_after = if ch == '\n' {
reovim_kernel::api::v1::Position::new(cursor_before.line + 1, 0)
} else {
reovim_kernel::api::v1::Position::new(
cursor_before.line,
cursor_before.column + 1,
)
};
ctx.set_cursor_position(cursor_after);
let edit = reovim_kernel::api::v1::Edit::insert(cursor_before, &text);
ctx.accumulate_edit(buffer_id, edit, cursor_before, cursor_after);
return FallbackResult::Handled;
}
return FallbackResult::Handled;
}
return FallbackResult::Ignored;
}
if *mode_id == VimMode::NORMAL_ID {
return FallbackResult::Beep;
}
FallbackResult::Ignored
}
}
fn key_to_char(key: &KeyEvent) -> Option<char> {
if !key.is_press() {
return None;
}
match key.code {
KeyCode::Char(ch) => {
if key.modifiers.is_empty() || key.modifiers == Modifiers::SHIFT {
Some(ch)
} else {
None
}
}
KeyCode::Tab => Some('\t'),
KeyCode::Enter => Some('\n'),
_ => None,
}
}
#[cfg(test)]
#[path = "fallback_tests.rs"]
mod tests;