mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
refactor: tab locking
This commit is contained in:
parent
36381e676f
commit
b066652b65
21 changed files with 81 additions and 48 deletions
|
|
@ -7,13 +7,19 @@ use crate::manager::Manager;
|
|||
|
||||
pub struct Opt {
|
||||
url: Option<Url>,
|
||||
tab: Option<usize>,
|
||||
}
|
||||
|
||||
impl From<Cmd> for Opt {
|
||||
fn from(mut c: Cmd) -> Self { Self { url: c.take_first().and_then(Data::into_url) } }
|
||||
fn from(mut c: Cmd) -> Self {
|
||||
Self {
|
||||
url: c.take_first().and_then(Data::into_url),
|
||||
tab: c.get("tab").and_then(Data::as_usize),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<Option<Url>> for Opt {
|
||||
fn from(url: Option<Url>) -> Self { Self { url } }
|
||||
fn from(url: Option<Url>) -> Self { Self { url, tab: None } }
|
||||
}
|
||||
|
||||
impl Manager {
|
||||
|
|
@ -21,11 +27,11 @@ impl Manager {
|
|||
let opt = opt.into() as Opt;
|
||||
|
||||
// Hover on the file
|
||||
render!(self.current_mut().repos(opt.url.as_ref()));
|
||||
render!(self.current_or_mut(opt.tab).repos(opt.url.as_ref()));
|
||||
if opt.url.zip(self.current().hovered()).is_some_and(|(u, f)| u == f.url) {
|
||||
// `hover(Some)` occurs after user actions, such as create, rename, reveal, etc.
|
||||
// At this point, it's intuitive to track the location of this file regardless.
|
||||
self.current_mut().tracing = true;
|
||||
self.current_or_mut(opt.tab).tracing = true;
|
||||
}
|
||||
|
||||
// Repeek
|
||||
|
|
|
|||
|
|
@ -7,17 +7,6 @@ use yazi_shared::event::Cmd;
|
|||
use crate::{manager::Manager, tasks::Tasks};
|
||||
|
||||
impl Manager {
|
||||
fn title(&self) -> String {
|
||||
let home = dirs::home_dir().unwrap_or_default();
|
||||
let cwd = if let Some(p) = self.cwd().strip_prefix(home) {
|
||||
format!("~{}{}", MAIN_SEPARATOR, p.display())
|
||||
} else {
|
||||
format!("{}", self.cwd().display())
|
||||
};
|
||||
|
||||
MANAGER.title_format.replace("{cwd}", &cwd)
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self, _: Cmd, tasks: &Tasks) {
|
||||
env::set_current_dir(self.cwd()).ok();
|
||||
env::set_var("PWD", self.cwd());
|
||||
|
|
@ -39,4 +28,15 @@ impl Manager {
|
|||
|
||||
tasks.prework_sorted(&self.current().files);
|
||||
}
|
||||
|
||||
fn title(&self) -> String {
|
||||
let home = dirs::home_dir().unwrap_or_default();
|
||||
let cwd = if let Some(p) = self.cwd().strip_prefix(home) {
|
||||
format!("~{}{}", MAIN_SEPARATOR, p.display())
|
||||
} else {
|
||||
format!("{}", self.cwd().display())
|
||||
};
|
||||
|
||||
MANAGER.title_format.replace("{cwd}", &cwd)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ impl Manager {
|
|||
return;
|
||||
}
|
||||
|
||||
ManagerProxy::hover(None); // Re-hover in next loop
|
||||
ManagerProxy::hover(None, tab.idx); // Re-hover in next loop
|
||||
ManagerProxy::update_paged(); // Update for paged files in next loop
|
||||
if calc {
|
||||
tasks.prework_sorted(&tab.current.files);
|
||||
|
|
|
|||
|
|
@ -39,19 +39,33 @@ impl Manager {
|
|||
pub fn active_mut(&mut self) -> &mut Tab { self.tabs.active_mut() }
|
||||
|
||||
#[inline]
|
||||
pub fn current(&self) -> &Folder { &self.tabs.active().current }
|
||||
pub fn active_or(&self, idx: Option<usize>) -> &Tab { self.tabs.active_or(idx) }
|
||||
|
||||
#[inline]
|
||||
pub fn current_mut(&mut self) -> &mut Folder { &mut self.tabs.active_mut().current }
|
||||
pub fn active_or_mut(&mut self, idx: Option<usize>) -> &mut Tab { self.tabs.active_or_mut(idx) }
|
||||
|
||||
#[inline]
|
||||
pub fn parent(&self) -> Option<&Folder> { self.tabs.active().parent.as_ref() }
|
||||
pub fn current(&self) -> &Folder { &self.active().current }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered(&self) -> Option<&File> { self.tabs.active().current.hovered() }
|
||||
pub fn current_mut(&mut self) -> &mut Folder { &mut self.active_mut().current }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_folder(&self) -> Option<&Folder> { self.tabs.active().hovered_folder() }
|
||||
pub fn current_or(&self, idx: Option<usize>) -> &Folder { &self.active_or(idx).current }
|
||||
|
||||
#[inline]
|
||||
pub fn current_or_mut(&mut self, idx: Option<usize>) -> &mut Folder {
|
||||
&mut self.active_or_mut(idx).current
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn parent(&self) -> Option<&Folder> { self.active().parent.as_ref() }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered(&self) -> Option<&File> { self.active().current.hovered() }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_folder(&self) -> Option<&Folder> { self.active().hovered_folder() }
|
||||
|
||||
#[inline]
|
||||
pub fn selected_or_hovered(&self, reorder: bool) -> Box<dyn Iterator<Item = &Url> + '_> {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,20 @@ impl Tabs {
|
|||
|
||||
#[inline]
|
||||
pub(super) fn active_mut(&mut self) -> &mut Tab { &mut self.items[self.cursor] }
|
||||
|
||||
#[inline]
|
||||
pub fn active_or(&self, idx: Option<usize>) -> &Tab {
|
||||
idx.and_then(|i| self.items.get(i)).unwrap_or(&self.items[self.cursor])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn active_or_mut(&mut self, idx: Option<usize>) -> &mut Tab {
|
||||
if let Some(i) = idx.filter(|&i| i < self.items.len()) {
|
||||
&mut self.items[i]
|
||||
} else {
|
||||
&mut self.items[self.cursor]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Tabs {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ impl Notify {
|
|||
msg.timeout += instant - self.messages.first().map_or(instant, |m| m.instant);
|
||||
self.messages.push(msg);
|
||||
|
||||
emit!(Call(Cmd::args("update_notify", vec![0.to_string()]), Layer::App));
|
||||
emit!(Call(Cmd::args("update_notify", &[0]), Layer::App));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ impl Notify {
|
|||
|
||||
self.tick_handle = Some(tokio::spawn(async move {
|
||||
tokio::time::sleep(interval).await;
|
||||
emit!(Call(Cmd::args("update_notify", vec![interval.as_secs_f64().to_string()]), Layer::App));
|
||||
emit!(Call(Cmd::args("update_notify", &[interval.as_secs_f64()]), Layer::App));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
|
||||
ManagerProxy::hover(None);
|
||||
ManagerProxy::hover(None, self.idx);
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ impl Tab {
|
|||
let (Ok(s) | Err(InputError::Typed(s))) = result else { continue };
|
||||
|
||||
emit!(Call(
|
||||
Cmd::args("filter_do", vec![s])
|
||||
Cmd::args("filter_do", &[s])
|
||||
.with_bool("smart", opt.case == FilterCase::Smart)
|
||||
.with_bool("insensitive", opt.case == FilterCase::Insensitive)
|
||||
.with_bool("done", done),
|
||||
|
|
@ -72,7 +72,7 @@ impl Tab {
|
|||
|
||||
self.current.repos(hovered.as_ref());
|
||||
if self.current.hovered().map(|f| &f.url) != hovered.as_ref() {
|
||||
ManagerProxy::hover(None);
|
||||
ManagerProxy::hover(None, self.idx);
|
||||
}
|
||||
|
||||
render!();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ impl Tab {
|
|||
|
||||
while let Some(Ok(s)) | Some(Err(InputError::Typed(s))) = rx.next().await {
|
||||
emit!(Call(
|
||||
Cmd::args("find_do", vec![s])
|
||||
Cmd::args("find_do", &[s])
|
||||
.with_bool("previous", opt.prev)
|
||||
.with_bool("smart", opt.case == FilterCase::Smart)
|
||||
.with_bool("insensitive", opt.case == FilterCase::Insensitive),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl Tab {
|
|||
self.apply_files_attrs();
|
||||
|
||||
if hovered.as_ref() != self.current.hovered().map(|f| &f.url) {
|
||||
ManagerProxy::hover(hovered);
|
||||
ManagerProxy::hover(hovered, self.idx);
|
||||
} else if self.current.hovered().is_some_and(|f| f.is_dir()) {
|
||||
ManagerProxy::peek(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,6 @@ impl Tab {
|
|||
|
||||
self.cd(parent.clone());
|
||||
FilesOp::Creating(parent, vec![File::from_dummy(opt.target.clone(), None)]).emit();
|
||||
ManagerProxy::hover(Some(opt.target));
|
||||
ManagerProxy::hover(Some(opt.target), self.idx);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ impl TryFrom<Cmd> for Opt {
|
|||
impl From<Opt> for Cmd {
|
||||
fn from(value: Opt) -> Self {
|
||||
let mut cmd =
|
||||
Cmd::args("", vec![value.id]).with_bool("sync", value.sync).with_any("args", value.args);
|
||||
Cmd::args("", &[value.id]).with_bool("sync", value.sync).with_any("args", value.args);
|
||||
|
||||
if let Some(cb) = value.cb {
|
||||
cmd = cmd.with_any("callback", cb);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ impl Utils {
|
|||
let cand = cand?;
|
||||
cands.push(Control {
|
||||
on: Self::parse_keys(cand.raw_get("on")?)?,
|
||||
run: vec![Cmd::args("callback", vec![i.to_string()]).with_any("tx", tx.clone())],
|
||||
run: vec![Cmd::args("callback", &[i]).with_any("tx", tx.clone())],
|
||||
desc: cand.raw_get("desc").ok(),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,9 +71,7 @@ impl Utils {
|
|||
};
|
||||
|
||||
emit!(Call(
|
||||
Cmd::args("plugin", vec![name.to_owned()])
|
||||
.with_bool("sync", true)
|
||||
.with_any("callback", callback),
|
||||
Cmd::args("plugin", &[name]).with_bool("sync", true).with_any("callback", callback),
|
||||
Layer::App
|
||||
));
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,6 @@ impl CompletionProxy {
|
|||
|
||||
#[inline]
|
||||
pub fn trigger(word: &str, ticket: usize) {
|
||||
emit!(Call(
|
||||
Cmd::args("trigger", vec![word.to_owned()]).with("ticket", ticket),
|
||||
Layer::Completion
|
||||
));
|
||||
emit!(Call(Cmd::args("trigger", &[word]).with("ticket", ticket), Layer::Completion));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ impl InputProxy {
|
|||
|
||||
#[inline]
|
||||
pub fn complete(word: &str, ticket: usize) {
|
||||
emit!(Call(Cmd::args("complete", vec![word.to_owned()]).with("ticket", ticket), Layer::Input));
|
||||
emit!(Call(Cmd::args("complete", &[word]).with("ticket", ticket), Layer::Input));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ impl ManagerProxy {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hover(url: Option<Url>) {
|
||||
pub fn hover(url: Option<Url>, tab: usize) {
|
||||
emit!(Call(
|
||||
Cmd::args("hover", url.map_or_else(Vec::new, |u| vec![u.to_string()])),
|
||||
Cmd::args("hover", &url.map_or_else(Vec::new, |u| vec![u])).with("tab", tab),
|
||||
Layer::Manager
|
||||
));
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ impl ManagerProxy {
|
|||
#[inline]
|
||||
pub fn update_paged_by(page: usize, only_if: &Url) {
|
||||
emit!(Call(
|
||||
Cmd::args("update_paged", vec![page.to_string()]).with_any("only-if", only_if.clone()),
|
||||
Cmd::args("update_paged", &[page]).with_any("only-if", only_if.clone()),
|
||||
Layer::Manager
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,18 +7,18 @@ pub struct TabProxy;
|
|||
impl TabProxy {
|
||||
#[inline]
|
||||
pub fn cd(target: &Url) {
|
||||
emit!(Call(Cmd::args("cd", vec![target.to_string()]), Layer::Manager));
|
||||
emit!(Call(Cmd::args("cd", &[target]), Layer::Manager));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn reveal(target: &Url) {
|
||||
emit!(Call(Cmd::args("reveal", vec![target.to_string()]), Layer::Manager));
|
||||
emit!(Call(Cmd::args("reveal", &[target]), Layer::Manager));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn search_do(opt: SearchOpt) {
|
||||
emit!(Call(
|
||||
Cmd::args("search_do", vec![opt.subject]).with("via", opt.via).with("args", opt.args_raw),
|
||||
Cmd::args("search_do", &[opt.subject]).with("via", opt.via).with("args", opt.args_raw),
|
||||
Layer::Manager
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ impl Process {
|
|||
let (id, cmd) = (task.id, task.cmd.clone());
|
||||
let result = super::shell(task.into());
|
||||
if let Err(e) = result {
|
||||
AppProxy::notify_warn(&cmd.to_string_lossy(), &format!("Failed to spawn process: {e}"));
|
||||
AppProxy::notify_warn(&cmd.to_string_lossy(), format!("Failed to spawn process: {e}"));
|
||||
return self.succ(id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,10 +16,14 @@ impl Cmd {
|
|||
pub fn new(name: &str) -> Self { Self { name: name.to_owned(), ..Default::default() } }
|
||||
|
||||
#[inline]
|
||||
pub fn args(name: &str, args: Vec<String>) -> Self {
|
||||
pub fn args(name: &str, args: &[impl ToString]) -> Self {
|
||||
Self {
|
||||
name: name.to_owned(),
|
||||
args: args.into_iter().enumerate().map(|(i, s)| (i.to_string(), Data::String(s))).collect(),
|
||||
args: args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, s)| (i.to_string(), Data::String(s.to_string())))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue