mirror of
https://github.com/sxyazi/yazi.git
synced 2024-12-24 09:12:43 +03:00
feat: enable bracketed paste (#5)
This commit is contained in:
parent
1f8c170359
commit
a8a5ab7f8c
@ -12,6 +12,7 @@ static mut TX: Option<UnboundedSender<Event>> = None;
|
|||||||
pub enum Event {
|
pub enum Event {
|
||||||
Quit,
|
Quit,
|
||||||
Key(KeyEvent),
|
Key(KeyEvent),
|
||||||
|
Paste(String),
|
||||||
Render(String),
|
Render(String),
|
||||||
Resize(u16, u16),
|
Resize(u16, u16),
|
||||||
Stop(bool, Option<oneshot::Sender<()>>),
|
Stop(bool, Option<oneshot::Sender<()>>),
|
||||||
|
@ -34,7 +34,7 @@ pub enum InputMode {
|
|||||||
|
|
||||||
impl InputMode {
|
impl InputMode {
|
||||||
#[inline]
|
#[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)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||||
@ -199,24 +199,26 @@ impl Input {
|
|||||||
self.move_(snap.len() as isize)
|
self.move_(snap.len() as isize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn type_(&mut self, c: char) -> bool {
|
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();
|
let snap = self.snap_mut();
|
||||||
if snap.cursor < 1 {
|
if snap.cursor < 1 {
|
||||||
snap.value.insert(0, c);
|
snap.value.insert_str(0, s);
|
||||||
} else if snap.cursor == snap.count() {
|
|
||||||
snap.value.push(c);
|
|
||||||
} else {
|
} 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 {
|
pub fn backspace(&mut self) -> bool {
|
||||||
let snap = self.snap_mut();
|
let snap = self.snap_mut();
|
||||||
if snap.cursor < 1 {
|
if snap.cursor < 1 {
|
||||||
return false;
|
return false;
|
||||||
} else if snap.cursor == snap.count() {
|
|
||||||
snap.value.pop();
|
|
||||||
} else {
|
} else {
|
||||||
snap.value.remove(snap.idx(snap.cursor - 1).unwrap());
|
snap.value.remove(snap.idx(snap.cursor - 1).unwrap());
|
||||||
}
|
}
|
||||||
|
@ -18,20 +18,25 @@ pub(super) struct InputSnap {
|
|||||||
|
|
||||||
impl InputSnap {
|
impl InputSnap {
|
||||||
pub(super) fn new(value: String) -> Self {
|
pub(super) fn new(value: String) -> Self {
|
||||||
let cursor = value.chars().count();
|
let mut snap = Self {
|
||||||
let offset =
|
|
||||||
cursor.saturating_sub(Self::find_window(&value.chars().rev().collect::<String>(), 0).end);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
value,
|
value,
|
||||||
|
|
||||||
op: Default::default(),
|
op: Default::default(),
|
||||||
start: Default::default(),
|
start: Default::default(),
|
||||||
|
|
||||||
mode: Default::default(),
|
mode: Default::default(),
|
||||||
offset,
|
offset: usize::MAX,
|
||||||
cursor,
|
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 {
|
pub(super) fn insert(&mut self) -> bool {
|
||||||
@ -80,6 +85,9 @@ impl InputSnap {
|
|||||||
&self.value[s.unwrap()..e.unwrap()]
|
&self.value[s.unwrap()..e.unwrap()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super) fn rev(&self) -> String { self.value.chars().rev().collect::<String>() }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn range(&mut self, cursor: usize, include: bool) -> Option<Range<usize>> {
|
pub(super) fn range(&mut self, cursor: usize, include: bool) -> Option<Range<usize>> {
|
||||||
self
|
self
|
||||||
|
@ -55,6 +55,7 @@ impl InputSnaps {
|
|||||||
let value = mem::replace(&mut self.versions[self.idx].value, String::new());
|
let value = mem::replace(&mut self.versions[self.idx].value, String::new());
|
||||||
self.versions[self.idx] = self.current.clone();
|
self.versions[self.idx] = self.current.clone();
|
||||||
self.versions[self.idx].value = value;
|
self.versions[self.idx].value = value;
|
||||||
|
self.versions[self.idx].reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use crossterm::event::KeyEvent;
|
|||||||
use tokio::sync::oneshot::{self};
|
use tokio::sync::oneshot::{self};
|
||||||
|
|
||||||
use super::{root::Root, Ctx, Executor, Logs, Signals, Term};
|
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 {
|
pub struct App {
|
||||||
cx: Ctx,
|
cx: Ctx,
|
||||||
@ -23,6 +23,7 @@ impl App {
|
|||||||
match event {
|
match event {
|
||||||
Event::Quit => break,
|
Event::Quit => break,
|
||||||
Event::Key(key) => app.dispatch_key(key),
|
Event::Key(key) => app.dispatch_key(key),
|
||||||
|
Event::Paste(str) => app.dispatch_paste(str),
|
||||||
Event::Render(_) => app.dispatch_render(),
|
Event::Render(_) => app.dispatch_render(),
|
||||||
Event::Resize(..) => app.dispatch_resize(),
|
Event::Resize(..) => app.dispatch_resize(),
|
||||||
Event::Stop(state, tx) => app.dispatch_stop(state, tx),
|
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) {
|
fn dispatch_render(&mut self) {
|
||||||
if let Some(term) = &mut self.term {
|
if let Some(term) = &mut self.term {
|
||||||
let _ = term.draw(|f| {
|
let _ = term.draw(|f| {
|
||||||
|
@ -60,6 +60,7 @@ impl Signals {
|
|||||||
Some(Ok(event)) = reader.next() => {
|
Some(Ok(event)) = reader.next() => {
|
||||||
let event = match event {
|
let event = match event {
|
||||||
CrosstermEvent::Key(key) => Event::Key(key),
|
CrosstermEvent::Key(key) => Event::Key(key),
|
||||||
|
CrosstermEvent::Paste(str) => Event::Paste(str),
|
||||||
CrosstermEvent::Resize(cols, rows) => Event::Resize(cols, rows),
|
CrosstermEvent::Resize(cols, rows) => Event::Resize(cols, rows),
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user