mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
refactor: replace FilesOp::IOErr with FilesOp::Deleting
This commit is contained in:
parent
cf769bf533
commit
63f81f6431
20 changed files with 82 additions and 108 deletions
|
|
@ -35,15 +35,15 @@ impl<'de> Deserialize<'de> for Keymap {
|
|||
|
||||
let shadow = Shadow::deserialize(deserializer)?;
|
||||
|
||||
// TODO: remove this when v0.1.6 is released --
|
||||
// TODO: remove this when v0.2.0 is released --
|
||||
if !shadow.input.keymap.iter().any(|c| c.on() == "<Backspace>") {
|
||||
println!(
|
||||
"WARNING: Default keybinding for `<Backspace>` is missing, please add a `{}` to the `[input]` section of `keymap.toml`.
|
||||
In Yazi v0.1.6, `<Backspace>` previously hardcoded within the Input component has been moved to `keymap.toml` to allow users to customize it.",
|
||||
In Yazi v0.2.0, `<Backspace>` previously hardcoded within the input component has been moved to `keymap.toml` to allow users to customize it.",
|
||||
r#"{ on = [ "<Backspace>" ], exec = "backspace" }"#
|
||||
);
|
||||
}
|
||||
// TODO: -- remove this when v0.1.6 is released
|
||||
// TODO: -- remove this when v0.2.0 is released
|
||||
|
||||
Ok(Self {
|
||||
manager: shadow.manager.keymap,
|
||||
|
|
|
|||
|
|
@ -40,29 +40,13 @@ impl<'de> Deserialize<'de> for Opener {
|
|||
desc: Option<String>,
|
||||
#[serde(rename = "for")]
|
||||
for_: Option<String>,
|
||||
|
||||
// TODO: remove this when v0.1.6 is released --
|
||||
display_name: Option<String>,
|
||||
// TODO: -- remove this when v0.1.6 is released
|
||||
}
|
||||
|
||||
let mut shadow = Shadow::deserialize(deserializer)?;
|
||||
let shadow = Shadow::deserialize(deserializer)?;
|
||||
if shadow.exec.is_empty() {
|
||||
return Err(serde::de::Error::custom("`exec` cannot be empty"));
|
||||
}
|
||||
|
||||
// TODO: remove this when v0.1.6 is released --
|
||||
if shadow.display_name.is_some() {
|
||||
println!(
|
||||
"WARNING: `display_name` is deprecated and will be removed in Yazi v0.1.7. Use `desc` instead.\ne.g. {}\n\n",
|
||||
r#"{ exec = 'nvim "$@"', display_name = "Edit" } ==> { exec = 'nvim "$@"', desc = "Edit" }"#
|
||||
);
|
||||
}
|
||||
if shadow.display_name.is_some() && shadow.desc.is_none() {
|
||||
shadow.desc = shadow.display_name.clone();
|
||||
}
|
||||
// TODO: -- remove this when v0.1.6 is released
|
||||
|
||||
let desc =
|
||||
shadow.desc.unwrap_or_else(|| shadow.exec.split_whitespace().next().unwrap().to_string());
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ impl Folder {
|
|||
FilesOp::Deleting(_, urls) => self.files.update_deleting(urls),
|
||||
FilesOp::Updating(_, files) => _ = self.files.update_updating(files),
|
||||
FilesOp::Upserting(_, files) => self.files.update_upserting(files),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
if !self.files.catchup_revision() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use anyhow::anyhow;
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_config::popup::InputCfg;
|
||||
use yazi_shared::{emit, event::Exec, render, InputError, Layer};
|
||||
|
|
@ -11,11 +10,9 @@ pub struct Opt {
|
|||
}
|
||||
|
||||
impl TryFrom<&Exec> for Opt {
|
||||
type Error = anyhow::Error;
|
||||
type Error = ();
|
||||
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> {
|
||||
e.take_data().ok_or_else(|| anyhow!("invalid data"))
|
||||
}
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> { e.take_data().ok_or(()) }
|
||||
}
|
||||
|
||||
impl Input {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl Manager {
|
|||
env::set_current_dir(self.cwd()).ok();
|
||||
env::set_var("PWD", self.cwd());
|
||||
|
||||
self.active_mut().apply_files_attrs(false);
|
||||
self.active_mut().apply_files_attrs();
|
||||
|
||||
if let Some(p) = self.parent() {
|
||||
self.watcher.trigger_dirs(&[self.cwd(), &p.cwd]);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ impl Tabs {
|
|||
|
||||
let mut tab = Tab::from(url);
|
||||
tab.conf = self.active().conf.clone();
|
||||
tab.apply_files_attrs(false);
|
||||
tab.apply_files_attrs();
|
||||
|
||||
self.items.insert(self.idx + 1, tab);
|
||||
self.set_idx(self.idx + 1);
|
||||
|
|
|
|||
|
|
@ -13,43 +13,52 @@ impl TryFrom<&Exec> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
// TODO: refactor this
|
||||
fn handle_read(&mut self, op: FilesOp) {
|
||||
let url = op.url().clone();
|
||||
let cwd = self.cwd().to_owned();
|
||||
let hovered = self.hovered().map(|h| h.url());
|
||||
fn update_parent(&mut self, op: FilesOp) {
|
||||
let cwd = self.cwd().clone();
|
||||
let leave = matches!(op, FilesOp::Deleting(_, ref urls) if urls.contains(&cwd));
|
||||
|
||||
if cwd == url {
|
||||
render!(self.current_mut().update(op));
|
||||
} else if matches!(self.parent(), Some(p) if p.cwd == url) {
|
||||
render!(self.active_mut().parent.as_mut().unwrap().update(op));
|
||||
} else if matches!(self.hovered(), Some(h) if h.url == url) {
|
||||
self.active_mut().history.entry(url.clone()).or_insert_with(|| Folder::from(&url));
|
||||
self.active_mut().apply_files_attrs(true);
|
||||
render!(self.active_mut().history.get_mut(&url).unwrap().update(op));
|
||||
self.peek(true);
|
||||
} else {
|
||||
self.active_mut().history.entry(url.clone()).or_insert_with(|| Folder::from(&url)).update(op);
|
||||
if let Some(p) = self.active_mut().parent.as_mut() {
|
||||
render!(p.update(op));
|
||||
render!(p.hover(&cwd));
|
||||
}
|
||||
|
||||
render!(self.active_mut().parent.as_mut().is_some_and(|p| p.hover(&cwd)));
|
||||
if leave {
|
||||
self.active_mut().leave(());
|
||||
}
|
||||
}
|
||||
|
||||
fn update_current(&mut self, op: FilesOp, tasks: &Tasks) {
|
||||
let hovered = self.hovered().map(|h| h.url());
|
||||
let calc = !matches!(op, FilesOp::Size(..) | FilesOp::Deleting(..));
|
||||
|
||||
render!(self.current_mut().update(op));
|
||||
render!(hovered.as_ref().is_some_and(|h| self.current_mut().hover(h)));
|
||||
|
||||
if hovered.as_ref() != self.hovered().map(|h| &h.url) {
|
||||
self.hover(None);
|
||||
}
|
||||
if calc {
|
||||
tasks.preload_sorted(&self.current().files);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_ioerr(&mut self, op: FilesOp) {
|
||||
fn update_hovered(&mut self, op: FilesOp) {
|
||||
let url = op.url();
|
||||
let op = FilesOp::Full(url.clone(), vec![]);
|
||||
self.active_mut().history.entry(url.clone()).or_insert_with(|| Folder::from(url)).update(op);
|
||||
|
||||
if url == self.cwd() {
|
||||
self.current_mut().update(op);
|
||||
self.peek(true);
|
||||
}
|
||||
|
||||
fn update_history(&mut self, op: FilesOp) {
|
||||
let leave = self.parent().and_then(|f| f.cwd.parent_url().map(|p| (&f.cwd, p))).is_some_and(
|
||||
|(p, pp)| matches!(op, FilesOp::Deleting(ref parent, ref urls) if *parent == pp && urls.contains(p)),
|
||||
);
|
||||
|
||||
let url = op.url();
|
||||
self.active_mut().history.entry(url.clone()).or_insert_with(|| Folder::from(url)).update(op);
|
||||
|
||||
if leave {
|
||||
self.active_mut().leave(());
|
||||
render!();
|
||||
} else if matches!(self.parent(), Some(p) if &p.cwd == url) {
|
||||
render!(self.active_mut().parent.as_mut().unwrap().update(op));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +66,6 @@ impl Manager {
|
|||
let Ok(opt) = opt.try_into() else {
|
||||
return;
|
||||
};
|
||||
let calc = !matches!(opt.op, FilesOp::Size(..) | FilesOp::IOErr(_) | FilesOp::Deleting(..));
|
||||
|
||||
let mut ops = vec![opt.op];
|
||||
for u in self.watcher.linked.read().from_dir(ops[0].url()) {
|
||||
|
|
@ -65,14 +73,18 @@ impl Manager {
|
|||
}
|
||||
|
||||
for op in ops {
|
||||
match op {
|
||||
FilesOp::IOErr(..) => self.handle_ioerr(op),
|
||||
_ => self.handle_read(op),
|
||||
};
|
||||
let url = op.url();
|
||||
if self.cwd() == url {
|
||||
self.update_current(op, tasks);
|
||||
} else if matches!(self.parent(), Some(p) if p.cwd == *url) {
|
||||
self.update_parent(op);
|
||||
} else if matches!(self.hovered(), Some(h) if h.url == *url) {
|
||||
self.update_hovered(op);
|
||||
} else {
|
||||
self.update_history(op);
|
||||
}
|
||||
}
|
||||
|
||||
if calc {
|
||||
tasks.preload_sorted(&self.current().files);
|
||||
}
|
||||
self.active_mut().apply_files_attrs();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,13 +91,12 @@ impl Watcher {
|
|||
|
||||
tokio::spawn(async move {
|
||||
for u in urls {
|
||||
let Ok(rx) = Files::from_dir(&u).await else {
|
||||
FilesOp::IOErr(u).emit();
|
||||
return;
|
||||
};
|
||||
|
||||
let files: Vec<_> = UnboundedReceiverStream::new(rx).collect().await;
|
||||
FilesOp::Full(u, files).emit();
|
||||
if let Ok(rx) = Files::from_dir(&u).await {
|
||||
let files: Vec<_> = UnboundedReceiverStream::new(rx).collect().await;
|
||||
FilesOp::Full(u, files).emit();
|
||||
} else if let Some(p) = u.parent_url() {
|
||||
FilesOp::Deleting(p, vec![u]).emit();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use anyhow::Result;
|
||||
use tokio::sync::oneshot;
|
||||
use yazi_config::popup::SelectCfg;
|
||||
use yazi_shared::{emit, event::Exec, render, term::Term, Layer};
|
||||
|
|
@ -11,11 +11,9 @@ pub struct Opt {
|
|||
}
|
||||
|
||||
impl TryFrom<&Exec> for Opt {
|
||||
type Error = anyhow::Error;
|
||||
type Error = ();
|
||||
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> {
|
||||
e.take_data().ok_or_else(|| anyhow!("invalid data"))
|
||||
}
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> { e.take_data().ok_or(()) }
|
||||
}
|
||||
|
||||
impl Select {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ impl Tab {
|
|||
_ => !self.conf.show_hidden,
|
||||
};
|
||||
|
||||
self.apply_files_attrs(false);
|
||||
self.apply_files_attrs();
|
||||
Manager::_hover(None);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use anyhow::anyhow;
|
||||
use yazi_plugin::utils::PreviewLock;
|
||||
use yazi_shared::{event::Exec, render};
|
||||
|
||||
|
|
@ -9,11 +8,9 @@ pub struct Opt {
|
|||
}
|
||||
|
||||
impl TryFrom<&Exec> for Opt {
|
||||
type Error = anyhow::Error;
|
||||
type Error = ();
|
||||
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> {
|
||||
Ok(Self { lock: e.take_data().ok_or_else(|| anyhow!("invalid data"))? })
|
||||
}
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> { Ok(Self { lock: e.take_data().ok_or(())? }) }
|
||||
}
|
||||
|
||||
impl Tab {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ impl Tab {
|
|||
self.conf.sort_reverse = e.named.contains_key("reverse");
|
||||
self.conf.sort_dir_first = e.named.contains_key("dir-first");
|
||||
|
||||
self.apply_files_attrs(false);
|
||||
self.apply_files_attrs();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ impl Preview {
|
|||
self.folder_handle.take().map(|h| h.abort());
|
||||
self.folder_handle = Some(tokio::spawn(async move {
|
||||
let Ok(rx) = Files::from_dir(&file.url).await else {
|
||||
FilesOp::IOErr(file.url).emit();
|
||||
file.url.parent_url().map(|p| FilesOp::Deleting(p, vec![file.url]).emit());
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ impl Tab {
|
|||
self.history.remove(url).unwrap_or_else(|| Folder::from(url))
|
||||
}
|
||||
|
||||
pub fn apply_files_attrs(&mut self, just_preview: bool) {
|
||||
pub fn apply_files_attrs(&mut self) {
|
||||
let apply = |f: &mut Folder| {
|
||||
let hovered = f.hovered().map(|h| h.url());
|
||||
|
||||
|
|
@ -87,9 +87,6 @@ impl Tab {
|
|||
{
|
||||
apply(f);
|
||||
}
|
||||
if just_preview {
|
||||
return;
|
||||
}
|
||||
|
||||
apply(&mut self.current);
|
||||
if let Some(parent) = self.parent.as_mut() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use anyhow::anyhow;
|
||||
use yazi_config::open::Opener;
|
||||
use yazi_shared::{emit, event::Exec, fs::Url, Layer};
|
||||
|
||||
|
|
@ -10,11 +9,9 @@ pub struct Opt {
|
|||
}
|
||||
|
||||
impl TryFrom<&Exec> for Opt {
|
||||
type Error = anyhow::Error;
|
||||
type Error = ();
|
||||
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> {
|
||||
e.take_data().ok_or_else(|| anyhow!("invalid data"))
|
||||
}
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> { e.take_data().ok_or(()) }
|
||||
}
|
||||
|
||||
impl Tasks {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use anyhow::anyhow;
|
||||
use yazi_shared::{emit, event::Exec, render, Layer};
|
||||
|
||||
use crate::tasks::{Tasks, TasksProgress};
|
||||
|
|
@ -8,11 +7,9 @@ pub struct Opt {
|
|||
}
|
||||
|
||||
impl TryFrom<&Exec> for Opt {
|
||||
type Error = anyhow::Error;
|
||||
type Error = ();
|
||||
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> {
|
||||
e.take_data().ok_or_else(|| anyhow!("invalid data"))
|
||||
}
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> { e.take_data().ok_or(()) }
|
||||
}
|
||||
|
||||
impl Tasks {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::mem;
|
||||
|
||||
use yazi_config::{keymap::{Control, Key}, KEYMAP};
|
||||
use yazi_shared::{emit, Layer};
|
||||
use yazi_shared::{emit, render, Layer};
|
||||
|
||||
pub struct Which {
|
||||
layer: Layer,
|
||||
|
|
@ -18,15 +18,15 @@ impl Default for Which {
|
|||
}
|
||||
|
||||
impl Which {
|
||||
pub fn show(&mut self, key: &Key, layer: Layer) -> bool {
|
||||
pub fn show(&mut self, key: &Key, layer: Layer) {
|
||||
self.layer = layer;
|
||||
self.times = 1;
|
||||
self.cands = KEYMAP.get(layer).iter().filter(|s| s.on.len() > 1 && &s.on[0] == key).collect();
|
||||
self.visible = true;
|
||||
true
|
||||
render!();
|
||||
}
|
||||
|
||||
pub fn press(&mut self, key: Key) -> bool {
|
||||
pub fn type_(&mut self, key: Key) -> bool {
|
||||
self.cands = mem::take(&mut self.cands)
|
||||
.into_iter()
|
||||
.filter(|s| s.on.len() > self.times && s.on[self.times] == key)
|
||||
|
|
@ -43,6 +43,8 @@ impl Which {
|
|||
}
|
||||
|
||||
self.times += 1;
|
||||
render!();
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use anyhow::Result;
|
||||
use tokio::sync::oneshot;
|
||||
use yazi_shared::{event::Exec, term::Term};
|
||||
|
||||
|
|
@ -9,11 +8,9 @@ pub struct Opt {
|
|||
tx: Option<oneshot::Sender<()>>,
|
||||
}
|
||||
|
||||
impl TryFrom<&Exec> for Opt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> {
|
||||
Ok(Self { state: e.args.first().map_or(false, |s| s == "true"), tx: e.take_data() })
|
||||
impl From<&Exec> for Opt {
|
||||
fn from(e: &Exec) -> Self {
|
||||
Self { state: e.args.first().map_or(false, |s| s == "true"), tx: e.take_data() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ impl<'a> Executor<'a> {
|
|||
let cx = &mut self.app.cx;
|
||||
|
||||
if cx.which.visible {
|
||||
return cx.which.press(key);
|
||||
return cx.which.type_(key);
|
||||
}
|
||||
if cx.help.visible && cx.help.type_(&key) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ pub enum FilesOp {
|
|||
Full(Url, Vec<File>),
|
||||
Part(Url, Vec<File>, u64),
|
||||
Size(Url, BTreeMap<Url, u64>),
|
||||
IOErr(Url),
|
||||
|
||||
Creating(Url, Vec<File>),
|
||||
Deleting(Url, Vec<Url>),
|
||||
|
|
@ -25,7 +24,6 @@ impl FilesOp {
|
|||
Self::Full(url, _) => url,
|
||||
Self::Part(url, ..) => url,
|
||||
Self::Size(url, _) => url,
|
||||
Self::IOErr(url) => url,
|
||||
|
||||
Self::Creating(url, _) => url,
|
||||
Self::Deleting(url, _) => url,
|
||||
|
|
@ -80,7 +78,7 @@ impl FilesOp {
|
|||
Self::Full(_, files) => Self::Full(u, files!(files)),
|
||||
Self::Part(_, files, ticket) => Self::Part(u, files!(files), *ticket),
|
||||
Self::Size(_, map) => Self::Size(u, map.iter().map(|(k, v)| (new!(k), *v)).collect()),
|
||||
Self::IOErr(_) => Self::IOErr(u),
|
||||
|
||||
Self::Creating(_, files) => Self::Creating(u, files!(files)),
|
||||
Self::Deleting(_, urls) => Self::Deleting(u, urls.iter().map(|u| new!(u)).collect()),
|
||||
Self::Updating(_, map) => Self::Updating(u, map!(map)),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue