mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
4ddecbb6ee
commit
86538e6555
15 changed files with 104 additions and 77 deletions
|
|
@ -391,6 +391,9 @@ impl Files {
|
|||
}
|
||||
|
||||
// --- Filter
|
||||
#[inline]
|
||||
pub fn filter(&self) -> Option<&Filter> { self.filter.as_ref() }
|
||||
|
||||
pub fn set_filter(&mut self, filter: Option<Filter>) -> bool {
|
||||
if self.filter == filter {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -54,23 +54,27 @@ impl Help {
|
|||
true
|
||||
}
|
||||
|
||||
pub fn type_(&mut self, key: &Key) {
|
||||
pub fn type_(&mut self, key: &Key) -> bool {
|
||||
let Some(input) = &mut self.in_filter else {
|
||||
return;
|
||||
return false;
|
||||
};
|
||||
|
||||
if key.is_enter() {
|
||||
self.in_filter = None;
|
||||
return render!();
|
||||
render!();
|
||||
return true;
|
||||
}
|
||||
|
||||
match &key {
|
||||
Key { code: KeyCode::Backspace, shift: false, ctrl: false, alt: false } => {
|
||||
input.backspace(false)
|
||||
input.backspace(false);
|
||||
}
|
||||
_ => {
|
||||
input.type_(key);
|
||||
}
|
||||
_ => input.type_(key),
|
||||
}
|
||||
self.filter_apply();
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use yazi_shared::event::Exec;
|
||||
use yazi_shared::{event::Exec, render};
|
||||
|
||||
use crate::input::{op::InputOp, Input};
|
||||
|
||||
|
|
@ -22,10 +22,8 @@ impl Input {
|
|||
}
|
||||
InputOp::Select(start) => {
|
||||
self.snap_mut().op = InputOp::Delete(opt.cut, opt.insert, start);
|
||||
// TODO: render
|
||||
todo!();
|
||||
// return self.handle_op(self.snap().cursor, true).then(||
|
||||
// self.move_(0)).is_some();
|
||||
render!(self.handle_op(self.snap().cursor, true));
|
||||
self.move_(0);
|
||||
}
|
||||
InputOp::Delete(..) => {
|
||||
self.snap_mut().op = InputOp::Delete(opt.cut, opt.insert, 0);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ impl Input {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.snaps.tag(self.limit());
|
||||
render!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use yazi_config::keymap::Key;
|
||||
use yazi_shared::{event::Exec, render};
|
||||
use yazi_shared::event::Exec;
|
||||
|
||||
use crate::input::{Input, InputMode};
|
||||
|
||||
|
|
@ -10,14 +10,16 @@ impl From<&Exec> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
pub fn type_(&mut self, key: &Key) {
|
||||
pub fn type_(&mut self, key: &Key) -> bool {
|
||||
if self.mode() != InputMode::Insert {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(c) = key.plain() {
|
||||
let mut bits = [0; 4];
|
||||
render!(self.type_str(c.encode_utf8(&mut bits)));
|
||||
self.type_str(c.encode_utf8(&mut [0; 4]));
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use yazi_shared::event::Exec;
|
||||
use yazi_shared::{event::Exec, render};
|
||||
|
||||
use crate::input::{op::InputOp, Input};
|
||||
|
||||
|
|
@ -10,10 +10,8 @@ impl Input {
|
|||
}
|
||||
InputOp::Select(start) => {
|
||||
self.snap_mut().op = InputOp::Yank(start);
|
||||
// TODO: render
|
||||
todo!();
|
||||
// return self.handle_op(self.snap().cursor, true).then(||
|
||||
// self.move_(0)).is_some();
|
||||
render!(self.handle_op(self.snap().cursor, true));
|
||||
self.move_(0);
|
||||
}
|
||||
InputOp::Yank(_) => {
|
||||
self.snap_mut().op = InputOp::Yank(0);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::ops::Range;
|
|||
use tokio::sync::mpsc::UnboundedSender;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
use yazi_config::{popup::Position, INPUT};
|
||||
use yazi_shared::InputError;
|
||||
use yazi_shared::{render, InputError};
|
||||
|
||||
use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps};
|
||||
use crate::CLIPBOARD;
|
||||
|
|
@ -32,7 +32,7 @@ impl Input {
|
|||
self.position.offset.width.saturating_sub(INPUT.border()) as usize
|
||||
}
|
||||
|
||||
pub fn type_str(&mut self, s: &str) -> bool {
|
||||
pub fn type_str(&mut self, s: &str) {
|
||||
let snap = self.snaps.current_mut();
|
||||
if snap.cursor < 1 {
|
||||
snap.value.insert_str(0, s);
|
||||
|
|
@ -42,7 +42,7 @@ impl Input {
|
|||
|
||||
self.move_(s.chars().count() as isize);
|
||||
self.flush_value();
|
||||
true
|
||||
render!();
|
||||
}
|
||||
|
||||
pub(super) fn handle_op(&mut self, cursor: usize, include: bool) -> bool {
|
||||
|
|
|
|||
|
|
@ -35,15 +35,15 @@ impl Manager {
|
|||
return render!(self.active_mut().preview.reset());
|
||||
};
|
||||
|
||||
let opt = opt.into() as Opt;
|
||||
if matches!(opt.only_if, Some(ref u) if *u != hovered.url) {
|
||||
return;
|
||||
}
|
||||
|
||||
let hovered = hovered.clone();
|
||||
if !self.active().preview.same_url(&hovered.url) {
|
||||
self.active_mut().preview.skip = 0;
|
||||
self.active_mut().preview.reset();
|
||||
render!(self.active_mut().preview.reset());
|
||||
}
|
||||
|
||||
let opt = opt.into() as Opt;
|
||||
if matches!(opt.only_if, Some(ref u) if *u != hovered.url) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(skip) = opt.skip {
|
||||
|
|
|
|||
|
|
@ -42,20 +42,20 @@ impl Tab {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn escape_select(&mut self) -> bool { self.current.files.select_all(None) }
|
||||
fn escape_select(&mut self) -> bool { self.current.files.select_all(Some(false)) }
|
||||
|
||||
#[inline]
|
||||
fn escape_filter(&mut self) -> bool {
|
||||
// TODO: render
|
||||
todo!();
|
||||
// self.filter_do(super::filter::Opt { query: "", ..Default::default() })
|
||||
let b = self.current.files.filter().is_some();
|
||||
self.filter_do(super::filter::Opt { query: "", ..Default::default() });
|
||||
b
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn escape_search(&mut self) -> bool {
|
||||
let b = self.current.cwd.is_search();
|
||||
self.search_stop();
|
||||
// TODO: render
|
||||
false
|
||||
b
|
||||
}
|
||||
|
||||
pub fn escape(&mut self, opt: impl Into<Opt>) {
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ pub struct Opt {
|
|||
impl From<&Exec> for Opt {
|
||||
fn from(e: &Exec) -> Self {
|
||||
Self {
|
||||
state: match e.named.get("state").map(|s| s.as_bytes()) {
|
||||
Some(b"true") => Some(true),
|
||||
Some(b"false") => Some(false),
|
||||
state: match e.named.get("state").map(|s| s.as_str()) {
|
||||
Some("true") => Some(true),
|
||||
Some("false") => Some(false),
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use std::sync::atomic::Ordering;
|
||||
|
||||
use anyhow::{Ok, Result};
|
||||
use crossterm::event::KeyEvent;
|
||||
use yazi_config::{keymap::Key, ARGS};
|
||||
use yazi_config::keymap::Key;
|
||||
use yazi_core::input::InputMode;
|
||||
use yazi_shared::{event::{Event, Exec}, render, term::Term, Layer};
|
||||
use yazi_shared::{event::{Event, Exec, NEED_RENDER}, term::Term, Layer};
|
||||
|
||||
use crate::{lives::Lives, Ctx, Executor, Logs, Panic, Signals};
|
||||
|
||||
|
|
@ -16,47 +18,44 @@ impl App {
|
|||
pub(crate) async fn run() -> Result<()> {
|
||||
Panic::install();
|
||||
let _log = Logs::init()?;
|
||||
|
||||
let term = Term::start()?;
|
||||
let signals = Signals::start()?;
|
||||
|
||||
Lives::register()?;
|
||||
let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
|
||||
|
||||
app.render()?;
|
||||
while let Some(event) = app.signals.recv().await {
|
||||
match event {
|
||||
Event::Quit(no_cwd_file) => {
|
||||
app.dispatch_quit(no_cwd_file);
|
||||
break;
|
||||
|
||||
let mut events = Vec::with_capacity(10);
|
||||
while app.signals.rx.recv_many(&mut events, 10).await > 0 {
|
||||
for event in events.drain(..) {
|
||||
match event {
|
||||
Event::Quit(no_cwd_file) => {
|
||||
app.quit(no_cwd_file)?;
|
||||
break;
|
||||
}
|
||||
Event::Key(key) => app.dispatch_key(key),
|
||||
Event::Paste(str) => app.dispatch_paste(str),
|
||||
Event::Resize(cols, rows) => app.dispatch_resize(cols, rows)?,
|
||||
Event::Call(exec, layer) => app.dispatch_call(exec, layer),
|
||||
event => app.dispatch_module(event),
|
||||
}
|
||||
Event::Key(key) => app.dispatch_key(key),
|
||||
Event::Paste(str) => app.dispatch_paste(str),
|
||||
// TODO: render
|
||||
// Event::Render(_) => app.render()?,
|
||||
Event::Resize(cols, rows) => app.dispatch_resize(cols, rows)?,
|
||||
Event::Call(exec, layer) => app.dispatch_call(exec, layer),
|
||||
event => app.dispatch_module(event),
|
||||
}
|
||||
|
||||
if NEED_RENDER.swap(false, Ordering::Relaxed) {
|
||||
app.render()?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dispatch_quit(&mut self, no_cwd_file: bool) {
|
||||
if let Some(p) = ARGS.cwd_file.as_ref().filter(|_| !no_cwd_file) {
|
||||
let cwd = self.cx.manager.cwd().as_os_str();
|
||||
std::fs::write(p, cwd.as_encoded_bytes()).ok();
|
||||
}
|
||||
Term::goodbye(|| false);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn dispatch_key(&mut self, key: KeyEvent) { Executor::new(self).handle(Key::from(key)); }
|
||||
|
||||
fn dispatch_paste(&mut self, str: String) {
|
||||
if self.cx.input.visible {
|
||||
let input = &mut self.cx.input;
|
||||
if input.mode() == InputMode::Insert && input.type_str(&str) {
|
||||
render!();
|
||||
if input.mode() == InputMode::Insert {
|
||||
input.type_str(&str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
mod plugin;
|
||||
mod quit;
|
||||
mod render;
|
||||
mod stop;
|
||||
|
|
|
|||
26
yazi-fm/src/app/commands/quit.rs
Normal file
26
yazi-fm/src/app/commands/quit.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
use anyhow::Result;
|
||||
use yazi_config::ARGS;
|
||||
use yazi_shared::term::Term;
|
||||
|
||||
use crate::app::App;
|
||||
|
||||
pub struct Opt {
|
||||
no_cwd_file: bool,
|
||||
}
|
||||
|
||||
impl From<bool> for Opt {
|
||||
fn from(no_cwd_file: bool) -> Self { Self { no_cwd_file } }
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub(crate) fn quit(&mut self, opt: impl Into<Opt>) -> Result<()> {
|
||||
let opt = opt.into() as Opt;
|
||||
|
||||
if let Some(p) = ARGS.cwd_file.as_ref().filter(|_| !opt.no_cwd_file) {
|
||||
let cwd = self.cx.manager.cwd().as_os_str();
|
||||
std::fs::write(p, cwd.as_encoded_bytes()).ok();
|
||||
}
|
||||
|
||||
Term::goodbye(|| false);
|
||||
}
|
||||
}
|
||||
|
|
@ -18,14 +18,12 @@ impl<'a> Executor<'a> {
|
|||
if cx.which.visible {
|
||||
return cx.which.press(key);
|
||||
}
|
||||
// TODO: render
|
||||
// if cx.help.visible && cx.help.type_(&key) {
|
||||
// return true;
|
||||
// }
|
||||
// TODO: render
|
||||
// if cx.input.visible && cx.input.type_(&key) {
|
||||
// return true;
|
||||
// }
|
||||
if cx.help.visible && cx.help.type_(&key) {
|
||||
return true;
|
||||
}
|
||||
if cx.input.visible && cx.input.type_(&key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if cx.completion.visible {
|
||||
self.matches(Layer::Completion, key) || self.matches(Layer::Input, key)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use tokio::{select, sync::{mpsc::{self, UnboundedReceiver, UnboundedSender}, one
|
|||
use yazi_shared::event::Event;
|
||||
|
||||
pub(super) struct Signals {
|
||||
tx: UnboundedSender<Event>,
|
||||
rx: UnboundedReceiver<Event>,
|
||||
tx: UnboundedSender<Event>,
|
||||
pub(super) rx: UnboundedReceiver<Event>,
|
||||
|
||||
term_stop_tx: Option<oneshot::Sender<()>>,
|
||||
term_stop_rx: Option<oneshot::Receiver<()>>,
|
||||
|
|
@ -27,9 +27,6 @@ impl Signals {
|
|||
Ok(signals)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) async fn recv(&mut self) -> Option<Event> { self.rx.recv().await }
|
||||
|
||||
pub(super) fn stop_term(&mut self, state: bool) {
|
||||
if state == self.term_stop_tx.is_none() {
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue