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
|
// --- Filter
|
||||||
|
#[inline]
|
||||||
|
pub fn filter(&self) -> Option<&Filter> { self.filter.as_ref() }
|
||||||
|
|
||||||
pub fn set_filter(&mut self, filter: Option<Filter>) -> bool {
|
pub fn set_filter(&mut self, filter: Option<Filter>) -> bool {
|
||||||
if self.filter == filter {
|
if self.filter == filter {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -54,23 +54,27 @@ impl Help {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_(&mut self, key: &Key) {
|
pub fn type_(&mut self, key: &Key) -> bool {
|
||||||
let Some(input) = &mut self.in_filter else {
|
let Some(input) = &mut self.in_filter else {
|
||||||
return;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if key.is_enter() {
|
if key.is_enter() {
|
||||||
self.in_filter = None;
|
self.in_filter = None;
|
||||||
return render!();
|
render!();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
match &key {
|
match &key {
|
||||||
Key { code: KeyCode::Backspace, shift: false, ctrl: false, alt: false } => {
|
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();
|
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};
|
use crate::input::{op::InputOp, Input};
|
||||||
|
|
||||||
|
|
@ -22,10 +22,8 @@ impl Input {
|
||||||
}
|
}
|
||||||
InputOp::Select(start) => {
|
InputOp::Select(start) => {
|
||||||
self.snap_mut().op = InputOp::Delete(opt.cut, opt.insert, start);
|
self.snap_mut().op = InputOp::Delete(opt.cut, opt.insert, start);
|
||||||
// TODO: render
|
render!(self.handle_op(self.snap().cursor, true));
|
||||||
todo!();
|
self.move_(0);
|
||||||
// return self.handle_op(self.snap().cursor, true).then(||
|
|
||||||
// self.move_(0)).is_some();
|
|
||||||
}
|
}
|
||||||
InputOp::Delete(..) => {
|
InputOp::Delete(..) => {
|
||||||
self.snap_mut().op = InputOp::Delete(opt.cut, opt.insert, 0);
|
self.snap_mut().op = InputOp::Delete(opt.cut, opt.insert, 0);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ impl Input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.snaps.tag(self.limit());
|
self.snaps.tag(self.limit());
|
||||||
render!();
|
render!();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use yazi_config::keymap::Key;
|
use yazi_config::keymap::Key;
|
||||||
use yazi_shared::{event::Exec, render};
|
use yazi_shared::event::Exec;
|
||||||
|
|
||||||
use crate::input::{Input, InputMode};
|
use crate::input::{Input, InputMode};
|
||||||
|
|
||||||
|
|
@ -10,14 +10,16 @@ impl From<&Exec> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn type_(&mut self, key: &Key) {
|
pub fn type_(&mut self, key: &Key) -> bool {
|
||||||
if self.mode() != InputMode::Insert {
|
if self.mode() != InputMode::Insert {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(c) = key.plain() {
|
if let Some(c) = key.plain() {
|
||||||
let mut bits = [0; 4];
|
self.type_str(c.encode_utf8(&mut [0; 4]));
|
||||||
render!(self.type_str(c.encode_utf8(&mut bits)));
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use yazi_shared::event::Exec;
|
use yazi_shared::{event::Exec, render};
|
||||||
|
|
||||||
use crate::input::{op::InputOp, Input};
|
use crate::input::{op::InputOp, Input};
|
||||||
|
|
||||||
|
|
@ -10,10 +10,8 @@ impl Input {
|
||||||
}
|
}
|
||||||
InputOp::Select(start) => {
|
InputOp::Select(start) => {
|
||||||
self.snap_mut().op = InputOp::Yank(start);
|
self.snap_mut().op = InputOp::Yank(start);
|
||||||
// TODO: render
|
render!(self.handle_op(self.snap().cursor, true));
|
||||||
todo!();
|
self.move_(0);
|
||||||
// return self.handle_op(self.snap().cursor, true).then(||
|
|
||||||
// self.move_(0)).is_some();
|
|
||||||
}
|
}
|
||||||
InputOp::Yank(_) => {
|
InputOp::Yank(_) => {
|
||||||
self.snap_mut().op = InputOp::Yank(0);
|
self.snap_mut().op = InputOp::Yank(0);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::ops::Range;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
use yazi_config::{popup::Position, INPUT};
|
use yazi_config::{popup::Position, INPUT};
|
||||||
use yazi_shared::InputError;
|
use yazi_shared::{render, InputError};
|
||||||
|
|
||||||
use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps};
|
use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps};
|
||||||
use crate::CLIPBOARD;
|
use crate::CLIPBOARD;
|
||||||
|
|
@ -32,7 +32,7 @@ impl Input {
|
||||||
self.position.offset.width.saturating_sub(INPUT.border()) as usize
|
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();
|
let snap = self.snaps.current_mut();
|
||||||
if snap.cursor < 1 {
|
if snap.cursor < 1 {
|
||||||
snap.value.insert_str(0, s);
|
snap.value.insert_str(0, s);
|
||||||
|
|
@ -42,7 +42,7 @@ impl Input {
|
||||||
|
|
||||||
self.move_(s.chars().count() as isize);
|
self.move_(s.chars().count() as isize);
|
||||||
self.flush_value();
|
self.flush_value();
|
||||||
true
|
render!();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn handle_op(&mut self, cursor: usize, include: bool) -> bool {
|
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());
|
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();
|
let hovered = hovered.clone();
|
||||||
if !self.active().preview.same_url(&hovered.url) {
|
if !self.active().preview.same_url(&hovered.url) {
|
||||||
self.active_mut().preview.skip = 0;
|
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 {
|
if let Some(skip) = opt.skip {
|
||||||
|
|
|
||||||
|
|
@ -42,20 +42,20 @@ impl Tab {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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]
|
#[inline]
|
||||||
fn escape_filter(&mut self) -> bool {
|
fn escape_filter(&mut self) -> bool {
|
||||||
// TODO: render
|
let b = self.current.files.filter().is_some();
|
||||||
todo!();
|
self.filter_do(super::filter::Opt { query: "", ..Default::default() });
|
||||||
// self.filter_do(super::filter::Opt { query: "", ..Default::default() })
|
b
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn escape_search(&mut self) -> bool {
|
fn escape_search(&mut self) -> bool {
|
||||||
|
let b = self.current.cwd.is_search();
|
||||||
self.search_stop();
|
self.search_stop();
|
||||||
// TODO: render
|
b
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn escape(&mut self, opt: impl Into<Opt>) {
|
pub fn escape(&mut self, opt: impl Into<Opt>) {
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ pub struct Opt {
|
||||||
impl From<&Exec> for Opt {
|
impl From<&Exec> for Opt {
|
||||||
fn from(e: &Exec) -> Self {
|
fn from(e: &Exec) -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: match e.named.get("state").map(|s| s.as_bytes()) {
|
state: match e.named.get("state").map(|s| s.as_str()) {
|
||||||
Some(b"true") => Some(true),
|
Some("true") => Some(true),
|
||||||
Some(b"false") => Some(false),
|
Some("false") => Some(false),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
use anyhow::{Ok, Result};
|
use anyhow::{Ok, Result};
|
||||||
use crossterm::event::KeyEvent;
|
use crossterm::event::KeyEvent;
|
||||||
use yazi_config::{keymap::Key, ARGS};
|
use yazi_config::keymap::Key;
|
||||||
use yazi_core::input::InputMode;
|
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};
|
use crate::{lives::Lives, Ctx, Executor, Logs, Panic, Signals};
|
||||||
|
|
||||||
|
|
@ -16,47 +18,44 @@ impl App {
|
||||||
pub(crate) async fn run() -> Result<()> {
|
pub(crate) async fn run() -> Result<()> {
|
||||||
Panic::install();
|
Panic::install();
|
||||||
let _log = Logs::init()?;
|
let _log = Logs::init()?;
|
||||||
|
|
||||||
let term = Term::start()?;
|
let term = Term::start()?;
|
||||||
let signals = Signals::start()?;
|
let signals = Signals::start()?;
|
||||||
|
|
||||||
Lives::register()?;
|
Lives::register()?;
|
||||||
let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
|
let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
|
||||||
|
|
||||||
app.render()?;
|
app.render()?;
|
||||||
while let Some(event) = app.signals.recv().await {
|
|
||||||
match event {
|
let mut events = Vec::with_capacity(10);
|
||||||
Event::Quit(no_cwd_file) => {
|
while app.signals.rx.recv_many(&mut events, 10).await > 0 {
|
||||||
app.dispatch_quit(no_cwd_file);
|
for event in events.drain(..) {
|
||||||
break;
|
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
|
if NEED_RENDER.swap(false, Ordering::Relaxed) {
|
||||||
// Event::Render(_) => app.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),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch_quit(&mut self, no_cwd_file: bool) {
|
#[inline]
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dispatch_key(&mut self, key: KeyEvent) { Executor::new(self).handle(Key::from(key)); }
|
fn dispatch_key(&mut self, key: KeyEvent) { Executor::new(self).handle(Key::from(key)); }
|
||||||
|
|
||||||
fn dispatch_paste(&mut self, str: String) {
|
fn dispatch_paste(&mut self, str: String) {
|
||||||
if self.cx.input.visible {
|
if self.cx.input.visible {
|
||||||
let input = &mut self.cx.input;
|
let input = &mut self.cx.input;
|
||||||
if input.mode() == InputMode::Insert && input.type_str(&str) {
|
if input.mode() == InputMode::Insert {
|
||||||
render!();
|
input.type_str(&str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
mod plugin;
|
mod plugin;
|
||||||
|
mod quit;
|
||||||
mod render;
|
mod render;
|
||||||
mod stop;
|
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 {
|
if cx.which.visible {
|
||||||
return cx.which.press(key);
|
return cx.which.press(key);
|
||||||
}
|
}
|
||||||
// TODO: render
|
if cx.help.visible && cx.help.type_(&key) {
|
||||||
// if cx.help.visible && cx.help.type_(&key) {
|
return true;
|
||||||
// return true;
|
}
|
||||||
// }
|
if cx.input.visible && cx.input.type_(&key) {
|
||||||
// TODO: render
|
return true;
|
||||||
// if cx.input.visible && cx.input.type_(&key) {
|
}
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if cx.completion.visible {
|
if cx.completion.visible {
|
||||||
self.matches(Layer::Completion, key) || self.matches(Layer::Input, key)
|
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;
|
use yazi_shared::event::Event;
|
||||||
|
|
||||||
pub(super) struct Signals {
|
pub(super) struct Signals {
|
||||||
tx: UnboundedSender<Event>,
|
tx: UnboundedSender<Event>,
|
||||||
rx: UnboundedReceiver<Event>,
|
pub(super) rx: UnboundedReceiver<Event>,
|
||||||
|
|
||||||
term_stop_tx: Option<oneshot::Sender<()>>,
|
term_stop_tx: Option<oneshot::Sender<()>>,
|
||||||
term_stop_rx: Option<oneshot::Receiver<()>>,
|
term_stop_rx: Option<oneshot::Receiver<()>>,
|
||||||
|
|
@ -27,9 +27,6 @@ impl Signals {
|
||||||
Ok(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) {
|
pub(super) fn stop_term(&mut self, state: bool) {
|
||||||
if state == self.term_stop_tx.is_none() {
|
if state == self.term_stop_tx.is_none() {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue