use std::time::Instant;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use super::app::App;
use super::paste_burst::CharDecision;
pub fn handle_paste_burst_key(app: &mut App, key: &KeyEvent, now: Instant) -> bool {
let has_ctrl_alt_or_super = key.modifiers.contains(KeyModifiers::CONTROL)
|| key.modifiers.contains(KeyModifiers::ALT)
|| key.modifiers.contains(KeyModifiers::SUPER);
match key.code {
KeyCode::Enter => {
if !in_command_context(app) && app.paste_burst.append_newline_if_active(now) {
return true;
}
if !in_command_context(app)
&& app.paste_burst.newline_should_insert_instead_of_submit(now)
{
app.insert_char('\n');
app.paste_burst.extend_window(now);
return true;
}
}
KeyCode::Char(c) if !has_ctrl_alt_or_super => {
if !c.is_ascii() {
if let Some(pending) = app.paste_burst.flush_before_modified_input() {
app.insert_str(&pending);
}
if app.paste_burst.try_append_char_if_active(c, now) {
return true;
}
if let Some(decision) = app.paste_burst.on_plain_char_no_hold(now) {
return handle_paste_burst_decision(app, decision, c, now);
}
app.insert_char(c);
return true;
}
let decision = app.paste_burst.on_plain_char(c, now);
return handle_paste_burst_decision(app, decision, c, now);
}
_ => {}
}
false
}
pub fn handle_paste_burst_decision(
app: &mut App,
decision: CharDecision,
c: char,
now: Instant,
) -> bool {
match decision {
CharDecision::RetainFirstChar => true,
CharDecision::BeginBufferFromPending | CharDecision::BufferAppend => {
app.paste_burst.append_char_to_buffer(c, now);
true
}
CharDecision::BeginBuffer { retro_chars } => {
if apply_paste_burst_retro_capture(app, retro_chars as usize, c, now) {
return true;
}
app.insert_char(c);
true
}
}
}
fn apply_paste_burst_retro_capture(
app: &mut App,
retro_chars: usize,
c: char,
now: Instant,
) -> bool {
let cursor_byte = app.cursor_byte_index();
let before = &app.input[..cursor_byte];
let Some(grab) = app
.paste_burst
.decide_begin_buffer(now, before, retro_chars)
else {
return false;
};
if !grab.grabbed.is_empty() {
app.input.replace_range(grab.start_byte..cursor_byte, "");
let removed = grab.grabbed.chars().count();
app.cursor_position = app.cursor_position.saturating_sub(removed);
}
app.paste_burst.append_char_to_buffer(c, now);
true
}
fn in_command_context(app: &App) -> bool {
app.input.starts_with('/')
}