feat: new builtin session.lua plugin (#940)

This commit is contained in:
三咲雅 · Misaki Masa 2024-04-22 14:18:00 +08:00 committed by GitHub
parent 68da8998aa
commit cb92bb7980
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 128 additions and 39 deletions

View File

@ -20,4 +20,5 @@ mod unyank;
mod update_files;
mod update_mimetype;
mod update_paged;
mod update_yanked;
mod yank;

View File

@ -61,6 +61,7 @@ impl Manager {
self.yanked.remove(u);
}
self.yanked.catchup_revision(false);
tasks.file_remove(opt.targets, opt.permanently);
}
}

View File

@ -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));
}
}

View File

@ -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();
}

View 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!();
}
}

View File

@ -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!();
}
}

View File

@ -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>,
pub cut: bool,
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![]),
};
self.urls.retain(|u| !removal.contains(&u));
self.urls.extend(addition);
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
}
}

View File

@ -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!();
}
}

View File

@ -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
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View 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 }

View File

@ -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

View File

@ -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 {