mirror of
https://github.com/sxyazi/yazi.git
synced 2024-12-25 17:54:57 +03:00
feat: new builtin session.lua
plugin (#940)
This commit is contained in:
parent
68da8998aa
commit
cb92bb7980
@ -20,4 +20,5 @@ mod unyank;
|
||||
mod update_files;
|
||||
mod update_mimetype;
|
||||
mod update_paged;
|
||||
mod update_yanked;
|
||||
mod yank;
|
||||
|
@ -61,6 +61,7 @@ impl Manager {
|
||||
self.yanked.remove(u);
|
||||
}
|
||||
|
||||
self.yanked.catchup_revision(false);
|
||||
tasks.file_remove(opt.targets, opt.permanently);
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,7 @@ impl From<()> for Opt {
|
||||
|
||||
impl Manager {
|
||||
pub fn unyank(&mut self, _: impl Into<Opt>) {
|
||||
render!(!self.yanked.is_empty());
|
||||
|
||||
self.yanked = Default::default();
|
||||
self.yanked.clear();
|
||||
render!(self.yanked.catchup_revision(false));
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ impl Manager {
|
||||
Self::update_tab(self.active_mut(), Cow::Owned(op), tasks);
|
||||
}
|
||||
|
||||
render!(self.yanked.catchup_revision(false));
|
||||
self.active_mut().apply_files_attrs();
|
||||
}
|
||||
|
||||
|
36
yazi-core/src/manager/commands/update_yanked.rs
Normal file
36
yazi-core/src/manager/commands/update_yanked.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use yazi_shared::{event::Cmd, fs::Url, render};
|
||||
|
||||
use crate::manager::{Manager, Yanked};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Opt {
|
||||
cut: bool,
|
||||
urls: HashSet<Url>,
|
||||
}
|
||||
|
||||
impl TryFrom<Cmd> for Opt {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
|
||||
if let Some(iter) = c.take_any::<yazi_dds::body::BodyYankIter>("urls") {
|
||||
Ok(Self { urls: iter.urls.into_iter().collect(), cut: iter.cut })
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Manager {
|
||||
pub fn update_yanked(&mut self, opt: impl TryInto<Opt>) {
|
||||
let Ok(opt) = opt.try_into() else { return };
|
||||
|
||||
if opt.urls.is_empty() && self.yanked.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.yanked = Yanked::new(opt.cut, opt.urls);
|
||||
render!();
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_shared::{event::Cmd, render};
|
||||
|
||||
use crate::manager::{Manager, Yanked};
|
||||
@ -17,12 +16,9 @@ impl Manager {
|
||||
return;
|
||||
}
|
||||
|
||||
self.yanked =
|
||||
Yanked { cut: opt.into().cut, urls: self.selected_or_hovered(false).cloned().collect() };
|
||||
self.yanked = Yanked::new(opt.into().cut, self.selected_or_hovered(false).cloned().collect());
|
||||
render!(self.yanked.catchup_revision(true));
|
||||
|
||||
self.active_mut().escape_select();
|
||||
Pubsub::pub_from_yank(self.yanked.cut, &self.yanked.urls);
|
||||
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,15 @@
|
||||
use std::{collections::HashSet, ops::{Deref, DerefMut}};
|
||||
use std::{collections::HashSet, ops::Deref};
|
||||
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_shared::fs::{FilesOp, Url};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Yanked {
|
||||
pub cut: bool,
|
||||
pub(super) urls: HashSet<Url>,
|
||||
urls: HashSet<Url>,
|
||||
|
||||
version: u64,
|
||||
revision: u64,
|
||||
}
|
||||
|
||||
impl Deref for Yanked {
|
||||
@ -14,11 +18,26 @@ impl Deref for Yanked {
|
||||
fn deref(&self) -> &Self::Target { &self.urls }
|
||||
}
|
||||
|
||||
impl DerefMut for Yanked {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.urls }
|
||||
}
|
||||
|
||||
impl Yanked {
|
||||
pub fn new(cut: bool, urls: HashSet<Url>) -> Self {
|
||||
Self { cut, urls, version: 0, ..Default::default() }
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, url: &Url) {
|
||||
if self.urls.remove(url) {
|
||||
self.revision += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
if self.urls.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.urls.clear();
|
||||
self.revision += 1;
|
||||
}
|
||||
|
||||
pub fn apply_op(&mut self, op: &FilesOp) {
|
||||
let (removal, addition) = match op {
|
||||
FilesOp::Deleting(_, urls) => (urls.iter().collect(), vec![]),
|
||||
@ -28,7 +47,26 @@ impl Yanked {
|
||||
_ => (vec![], vec![]),
|
||||
};
|
||||
|
||||
if !removal.is_empty() {
|
||||
let old = self.urls.len();
|
||||
self.urls.retain(|u| !removal.contains(&u));
|
||||
self.revision += (old != self.urls.len()) as u64;
|
||||
}
|
||||
|
||||
if !addition.is_empty() {
|
||||
let old = self.urls.len();
|
||||
self.urls.extend(addition);
|
||||
self.revision += (old != self.urls.len()) as u64;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn catchup_revision(&mut self, force: bool) -> bool {
|
||||
if self.version == self.revision && !force {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.version = self.revision;
|
||||
Pubsub::pub_from_yank(self.cut, &self.urls);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -69,9 +69,11 @@ impl Tab {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.current.repos(hovered) {
|
||||
self.current.repos(hovered.as_ref());
|
||||
if self.current.hovered().map(|f| &f.url) != hovered.as_ref() {
|
||||
ManagerProxy::hover(None);
|
||||
}
|
||||
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
@ -81,8 +81,7 @@ impl Pubsub {
|
||||
}
|
||||
|
||||
pub fn pub_static(severity: u16, body: Body) {
|
||||
let kind = body.kind();
|
||||
if REMOTE.read().contains_key(kind) || PEERS.read().values().any(|c| c.able(kind)) {
|
||||
if Self::own_static_ability(body.kind()) {
|
||||
Client::push(body.with_severity(severity));
|
||||
}
|
||||
}
|
||||
@ -99,7 +98,7 @@ impl Pubsub {
|
||||
if LOCAL.read().contains_key("cd") {
|
||||
Self::pub_(BodyCd::dummy(tab));
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("cd")) {
|
||||
if Self::own_static_ability("cd") {
|
||||
Client::push(BodyCd::borrowed(tab, url).with_severity(100));
|
||||
}
|
||||
if BOOT.local_events.contains("cd") {
|
||||
@ -111,7 +110,7 @@ impl Pubsub {
|
||||
if LOCAL.read().contains_key("hover") {
|
||||
Self::pub_(BodyHover::dummy(tab));
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("hover")) {
|
||||
if Self::own_static_ability("hover") {
|
||||
Client::push(BodyHover::borrowed(tab, url).with_severity(200));
|
||||
}
|
||||
if BOOT.local_events.contains("hover") {
|
||||
@ -135,7 +134,7 @@ impl Pubsub {
|
||||
if LOCAL.read().contains_key("yank") {
|
||||
Self::pub_(BodyYank::dummy());
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("yank")) {
|
||||
if Self::own_static_ability("yank") {
|
||||
Client::push(BodyYank::borrowed(cut, urls).with_severity(300));
|
||||
}
|
||||
if BOOT.local_events.contains("yank") {
|
||||
@ -178,4 +177,11 @@ impl Pubsub {
|
||||
Self::pub_(BodyDelete::owned(urls));
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn own_static_ability(kind: &str) -> bool {
|
||||
REMOTE.read().contains_key(kind) // Owned abilities
|
||||
|| PEERS.read().values().any(|p| p.able(kind)) // Remote peers' abilities
|
||||
|| BOOT.remote_events.contains(kind) // Owned abilities from the command-line argument
|
||||
}
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ impl<'a> Executor<'a> {
|
||||
on!(MANAGER, update_files, &self.app.cx.tasks);
|
||||
on!(MANAGER, update_mimetype, &self.app.cx.tasks);
|
||||
on!(MANAGER, update_paged, &self.app.cx.tasks);
|
||||
on!(MANAGER, update_yanked);
|
||||
on!(MANAGER, hover);
|
||||
on!(MANAGER, peek);
|
||||
on!(MANAGER, seek);
|
||||
|
@ -3,7 +3,7 @@ local M = {}
|
||||
function M:peek()
|
||||
local _, bound = ya.preview_archive(self)
|
||||
if bound then
|
||||
ya.manager_emit("peek", { bound, only_if = tostring(self.file.url), upper_bound = true })
|
||||
ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
|
||||
end
|
||||
end
|
||||
|
||||
@ -13,7 +13,7 @@ function M:seek(units)
|
||||
local step = math.floor(units * self.area.h / 10)
|
||||
ya.manager_emit("peek", {
|
||||
math.max(0, cx.active.preview.skip + step),
|
||||
only_if = tostring(self.file.url),
|
||||
only_if = self.file.url,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
@ -3,7 +3,7 @@ local M = {}
|
||||
function M:peek()
|
||||
local _, bound = ya.preview_code(self)
|
||||
if bound then
|
||||
ya.manager_emit("peek", { bound, only_if = tostring(self.file.url), upper_bound = true })
|
||||
ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
|
||||
end
|
||||
end
|
||||
|
||||
@ -13,7 +13,7 @@ function M:seek(units)
|
||||
local step = math.floor(units * self.area.h / 10)
|
||||
ya.manager_emit("peek", {
|
||||
math.max(0, cx.active.preview.skip + step),
|
||||
only_if = tostring(self.file.url),
|
||||
only_if = self.file.url,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
@ -8,7 +8,7 @@ function M:peek()
|
||||
|
||||
local bound = math.max(0, #folder.files - self.area.h)
|
||||
if self.skip > bound then
|
||||
return ya.manager_emit("peek", { bound, only_if = tostring(self.file.url), upper_bound = true })
|
||||
return ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
|
||||
end
|
||||
|
||||
if #folder.files == 0 then
|
||||
@ -45,7 +45,7 @@ function M:seek(units)
|
||||
local bound = math.max(0, #folder.files - self.area.h)
|
||||
ya.manager_emit("peek", {
|
||||
ya.clamp(0, cx.active.preview.skip + step, bound),
|
||||
only_if = tostring(self.file.url),
|
||||
only_if = self.file.url,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
@ -1,10 +1,10 @@
|
||||
local state = ya.sync(function() return tostring(cx.active.current.cwd) end)
|
||||
local state = ya.sync(function() return cx.active.current.cwd end)
|
||||
|
||||
local function fail(s, ...) ya.notify { title = "Fzf", content = string.format(s, ...), timeout = 5, level = "error" } end
|
||||
|
||||
local function entry()
|
||||
local _permit = ya.hide()
|
||||
local cwd = state()
|
||||
local cwd = tostring(state())
|
||||
|
||||
local child, err =
|
||||
Command("fzf"):cwd(cwd):stdin(Command.INHERIT):stdout(Command.PIPED):stderr(Command.INHERIT):spawn()
|
||||
|
@ -34,7 +34,7 @@ function M:peek()
|
||||
|
||||
child:start_kill()
|
||||
if self.skip > 0 and i < self.skip + limit then
|
||||
ya.manager_emit("peek", { math.max(0, i - limit), only_if = tostring(self.file.url), upper_bound = true })
|
||||
ya.manager_emit("peek", { math.max(0, i - limit), only_if = self.file.url, upper_bound = true })
|
||||
else
|
||||
lines = lines:gsub("\t", string.rep(" ", PREVIEW.tab_size))
|
||||
ya.preview_widgets(self, { ui.Paragraph.parse(self.area, lines) })
|
||||
@ -47,7 +47,7 @@ function M:seek(units)
|
||||
local step = math.floor(units * self.area.h / 10)
|
||||
ya.manager_emit("peek", {
|
||||
math.max(0, cx.active.preview.skip + step),
|
||||
only_if = tostring(self.file.url),
|
||||
only_if = self.file.url,
|
||||
})
|
||||
end
|
||||
end
|
||||
@ -55,7 +55,7 @@ end
|
||||
function M:fallback_to_builtin()
|
||||
local _, bound = ya.preview_code(self)
|
||||
if bound then
|
||||
ya.manager_emit("peek", { bound, only_if = tostring(self.file.url), upper_bound = true })
|
||||
ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -16,7 +16,7 @@ function M:seek(units)
|
||||
local h = cx.active.current.hovered
|
||||
if h and h.url == self.file.url then
|
||||
local step = ya.clamp(-1, units, 1)
|
||||
ya.manager_emit("peek", { math.max(0, cx.active.preview.skip + step), only_if = tostring(self.file.url) })
|
||||
ya.manager_emit("peek", { math.max(0, cx.active.preview.skip + step), only_if = self.file.url })
|
||||
end
|
||||
end
|
||||
|
||||
@ -37,7 +37,7 @@ function M:preload()
|
||||
elseif not output.status:success() then
|
||||
local pages = tonumber(output.stderr:match("the last page %((%d+)%)")) or 0
|
||||
if self.skip > 0 and pages > 0 then
|
||||
ya.manager_emit("peek", { math.max(0, pages - 1), only_if = tostring(self.file.url), upper_bound = true })
|
||||
ya.manager_emit("peek", { math.max(0, pages - 1), only_if = self.file.url, upper_bound = true })
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
7
yazi-plugin/preset/plugins/session.lua
Normal file
7
yazi-plugin/preset/plugins/session.lua
Normal file
@ -0,0 +1,7 @@
|
||||
local function setup(_, opts)
|
||||
if opts.sync_yanked then
|
||||
ps.sub_remote("yank", function(body) ya.manager_emit("update_yanked", { cut = body.cut, urls = body }) end)
|
||||
end
|
||||
end
|
||||
|
||||
return { setup = setup }
|
@ -17,7 +17,7 @@ function M:seek(units)
|
||||
if h and h.url == self.file.url then
|
||||
ya.manager_emit("peek", {
|
||||
math.max(0, cx.active.preview.skip + units),
|
||||
only_if = tostring(self.file.url),
|
||||
only_if = self.file.url,
|
||||
})
|
||||
end
|
||||
end
|
||||
@ -25,7 +25,7 @@ end
|
||||
function M:preload()
|
||||
local percentage = 5 + self.skip
|
||||
if percentage > 95 then
|
||||
ya.manager_emit("peek", { 90, only_if = tostring(self.file.url), upper_bound = true })
|
||||
ya.manager_emit("peek", { 90, only_if = self.file.url, upper_bound = true })
|
||||
return 2
|
||||
end
|
||||
|
||||
|
@ -25,6 +25,7 @@ impl Loader {
|
||||
let b = match name {
|
||||
"dds" => Some(&include_bytes!("../../preset/plugins/dds.lua")[..]),
|
||||
"noop" => Some(&include_bytes!("../../preset/plugins/noop.lua")[..]),
|
||||
"session" => Some(&include_bytes!("../../preset/plugins/session.lua")[..]),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(b) = b {
|
||||
|
Loading…
Reference in New Issue
Block a user