diff --git a/src/core/event.rs b/src/core/event.rs index 2dc4a092..78193f2c 100644 --- a/src/core/event.rs +++ b/src/core/event.rs @@ -12,6 +12,7 @@ static mut TX: Option> = None; pub enum Event { Quit, Key(KeyEvent), + Paste(String), Render(String), Resize(u16, u16), Stop(bool, Option>), diff --git a/src/core/input/input.rs b/src/core/input/input.rs index aaba385a..33499685 100644 --- a/src/core/input/input.rs +++ b/src/core/input/input.rs @@ -34,7 +34,7 @@ pub enum InputMode { impl InputMode { #[inline] - fn delta(&self) -> usize { (*self != InputMode::Insert) as usize } + pub(super) fn delta(&self) -> usize { (*self != InputMode::Insert) as usize } } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] @@ -199,24 +199,26 @@ impl Input { self.move_(snap.len() as isize) } + #[inline] pub fn type_(&mut self, c: char) -> bool { + let mut bits = [0; 4]; + self.type_str(c.encode_utf8(&mut bits)) + } + + pub fn type_str(&mut self, s: &str) -> bool { let snap = self.snap_mut(); if snap.cursor < 1 { - snap.value.insert(0, c); - } else if snap.cursor == snap.count() { - snap.value.push(c); + snap.value.insert_str(0, s); } else { - snap.value.insert(snap.idx(snap.cursor).unwrap(), c); + snap.value.insert_str(snap.idx(snap.cursor).unwrap(), s); } - self.move_(1) + self.move_(s.chars().count() as isize) } pub fn backspace(&mut self) -> bool { let snap = self.snap_mut(); if snap.cursor < 1 { return false; - } else if snap.cursor == snap.count() { - snap.value.pop(); } else { snap.value.remove(snap.idx(snap.cursor - 1).unwrap()); } diff --git a/src/core/input/snap.rs b/src/core/input/snap.rs index ed83b6dc..c100a8d2 100644 --- a/src/core/input/snap.rs +++ b/src/core/input/snap.rs @@ -18,20 +18,25 @@ pub(super) struct InputSnap { impl InputSnap { pub(super) fn new(value: String) -> Self { - let cursor = value.chars().count(); - let offset = - cursor.saturating_sub(Self::find_window(&value.chars().rev().collect::(), 0).end); - - Self { + let mut snap = Self { value, op: Default::default(), start: Default::default(), mode: Default::default(), - offset, - cursor, - } + offset: usize::MAX, + cursor: usize::MAX, + }; + snap.reset(); + snap + } + + #[inline] + pub(super) fn reset(&mut self) { + self.cursor = self.cursor.min(self.value.chars().count().saturating_sub(self.mode.delta())); + self.offset = + self.offset.min(self.cursor.saturating_sub(Self::find_window(&self.rev(), 0).end)); } pub(super) fn insert(&mut self) -> bool { @@ -80,6 +85,9 @@ impl InputSnap { &self.value[s.unwrap()..e.unwrap()] } + #[inline] + pub(super) fn rev(&self) -> String { self.value.chars().rev().collect::() } + #[inline] pub(super) fn range(&mut self, cursor: usize, include: bool) -> Option> { self diff --git a/src/core/input/snaps.rs b/src/core/input/snaps.rs index 2076a724..3b882a29 100644 --- a/src/core/input/snaps.rs +++ b/src/core/input/snaps.rs @@ -55,6 +55,7 @@ impl InputSnaps { let value = mem::replace(&mut self.versions[self.idx].value, String::new()); self.versions[self.idx] = self.current.clone(); self.versions[self.idx].value = value; + self.versions[self.idx].reset(); } } diff --git a/src/ui/app.rs b/src/ui/app.rs index 30f564ef..6c615b8f 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -3,7 +3,7 @@ use crossterm::event::KeyEvent; use tokio::sync::oneshot::{self}; use super::{root::Root, Ctx, Executor, Logs, Signals, Term}; -use crate::{config::keymap::{Control, Key, KeymapLayer}, core::{files::FilesOp, Event}, emit, misc::absolute_path}; +use crate::{config::keymap::{Control, Key, KeymapLayer}, core::{files::FilesOp, input::InputMode, Event}, emit, misc::absolute_path}; pub struct App { cx: Ctx, @@ -23,6 +23,7 @@ impl App { match event { Event::Quit => break, Event::Key(key) => app.dispatch_key(key), + Event::Paste(str) => app.dispatch_paste(str), Event::Render(_) => app.dispatch_render(), Event::Resize(..) => app.dispatch_resize(), Event::Stop(state, tx) => app.dispatch_stop(state, tx), @@ -40,6 +41,15 @@ impl App { } } + fn dispatch_paste(&mut self, str: String) { + if self.cx.layer() == KeymapLayer::Input { + let input = &mut self.cx.input; + if input.mode() == InputMode::Insert && input.type_str(&str) { + emit!(Render); + } + } + } + fn dispatch_render(&mut self) { if let Some(term) = &mut self.term { let _ = term.draw(|f| { diff --git a/src/ui/signals.rs b/src/ui/signals.rs index 99b10974..3636c703 100644 --- a/src/ui/signals.rs +++ b/src/ui/signals.rs @@ -60,6 +60,7 @@ impl Signals { Some(Ok(event)) = reader.next() => { let event = match event { CrosstermEvent::Key(key) => Event::Key(key), + CrosstermEvent::Paste(str) => Event::Paste(str), CrosstermEvent::Resize(cols, rows) => Event::Resize(cols, rows), _ => continue, };