Skip to content

Commit

Permalink
feat: expose selected/yanked files as API
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi committed Feb 14, 2024
1 parent b027487 commit b44dc75
Show file tree
Hide file tree
Showing 27 changed files with 258 additions and 130 deletions.
137 changes: 66 additions & 71 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions yazi-config/preset/keymap.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ keymap = [
{ on = [ "<PageUp>" ], exec = "arrow -100%", desc = "Move cursor up one page" },
{ on = [ "<PageDown>" ], exec = "arrow 100%", desc = "Move cursor down one page" },

{ on = [ "h" ], exec = [ "leave", "escape --visual --select" ], desc = "Go back to the parent directory" },
{ on = [ "l" ], exec = [ "enter", "escape --visual --select" ], desc = "Enter the child directory" },
{ on = [ "h" ], exec = [ "escape --visual", "leave" ], desc = "Go back to the parent directory" },
{ on = [ "l" ], exec = [ "escape --visual", "enter" ], desc = "Enter the child directory" },

{ on = [ "H" ], exec = "back", desc = "Go back to the previous directory" },
{ on = [ "L" ], exec = "forward", desc = "Go forward to the next directory" },
Expand Down
4 changes: 2 additions & 2 deletions yazi-config/preset/yazi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ ueberzug_offset = [ 0, 0, 0, 0 ]

[opener]
edit = [
{ exec = '[ -n "$EDITOR" ] && $EDITOR "$@"', desc = "$EDITOR", block = true, for = "unix" },
{ exec = 'code "%*"', orphan = true, for = "windows" },
{ exec = '${EDITOR:=vi} "$@"', desc = "$EDITOR", block = true, for = "unix" },
{ exec = 'code "%*"', orphan = true, for = "windows" },
]
open = [
{ exec = 'xdg-open "$@"', desc = "Open", for = "linux" },
Expand Down
5 changes: 2 additions & 3 deletions yazi-core/src/manager/commands/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ impl From<Cmd> for Opt {

impl Manager {
pub fn link(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
let (cut, ref src) = self.yanked;
if cut {
if self.yanked.cut {
return;
}

let opt = opt.into() as Opt;
tasks.file_link(src, self.cwd(), opt.relative, opt.force);
tasks.file_link(&self.yanked, self.cwd(), opt.relative, opt.force);
}
}
11 changes: 5 additions & 6 deletions yazi-core/src/manager/commands/paste.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@ impl From<Cmd> for Opt {

impl Manager {
pub fn paste(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
let dest = self.cwd();
let (cut, ref src) = self.yanked;

let opt = opt.into() as Opt;
if cut {
tasks.file_cut(src, dest, opt.force);

let dest = self.cwd();
if self.yanked.cut {
tasks.file_cut(&self.yanked, dest, opt.force);
} else {
tasks.file_copy(src, dest, opt.force, opt.follow);
tasks.file_copy(&self.yanked, dest, opt.force, opt.follow);
}
}
}
2 changes: 1 addition & 1 deletion yazi-core/src/manager/commands/unyank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::manager::Manager;

impl Manager {
pub fn unyank(&mut self, _: Cmd) {
render!(!self.yanked.1.is_empty());
render!(!self.yanked.is_empty());

self.yanked = Default::default();
}
Expand Down
6 changes: 3 additions & 3 deletions yazi-core/src/manager/commands/yank.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use yazi_shared::{event::Cmd, render};

use crate::manager::Manager;
use crate::manager::{Manager, Yanked};

pub struct Opt {
cut: bool,
Expand All @@ -14,8 +14,8 @@ impl Manager {
pub fn yank(&mut self, opt: impl Into<Opt>) {
let opt = opt.into() as Opt;

self.yanked.0 = opt.cut;
self.yanked.1 = self.selected().into_iter().map(|f| f.url()).collect();
self.yanked =
Yanked { cut: opt.cut, urls: self.selected().into_iter().map(|f| f.url()).collect() };
render!();
}
}
6 changes: 3 additions & 3 deletions yazi-core/src/manager/manager.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;

use yazi_shared::fs::{File, Url};

use super::{Tabs, Watcher};
use super::{Tabs, Watcher, Yanked};
use crate::{folder::Folder, tab::Tab};

pub struct Manager {
pub tabs: Tabs,
pub yanked: (bool, HashSet<Url>),
pub yanked: Yanked,

pub(super) watcher: Watcher,
pub mimetype: HashMap<Url, String>,
Expand Down
2 changes: 2 additions & 0 deletions yazi-core/src/manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ mod linked;
mod manager;
mod tabs;
mod watcher;
mod yanked;

pub use linked::*;
pub use manager::*;
pub use tabs::*;
pub use watcher::*;
pub use yanked::*;
15 changes: 15 additions & 0 deletions yazi-core/src/manager/yanked.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use std::{collections::HashSet, ops::Deref};

use yazi_shared::fs::Url;

#[derive(Default)]
pub struct Yanked {
pub cut: bool,
pub(super) urls: HashSet<Url>,
}

impl Deref for Yanked {
type Target = HashSet<Url>;

fn deref(&self) -> &Self::Target { &self.urls }
}
14 changes: 10 additions & 4 deletions yazi-core/src/tab/commands/escape.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bitflags::bitflags;
use yazi_shared::{event::Cmd, render};

use crate::tab::{Mode, Tab};
use crate::{manager::Manager, tab::{Mode, Tab}};

bitflags! {
pub struct Opt: u8 {
Expand Down Expand Up @@ -53,9 +53,15 @@ impl Tab {

#[inline]
fn escape_select(&mut self) -> bool {
let old = self.selected.len();
self.select_all(Some(false));
old != self.selected.len()
if self.selected.is_empty() {
return false;
}

self.selected.clear();
if self.current.hovered().is_some_and(|h| h.is_dir()) {
Manager::_peek(true);
}
true
}

#[inline]
Expand Down
2 changes: 1 addition & 1 deletion yazi-fm/src/help/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl<'a> Widget for Layout<'a> {
let help = &self.cx.help;
widgets::Clear.render(area, buf);

let chunks = layout::Layout::vertical([Constraint::Min(0), Constraint::Length(1)]).split(area);
let chunks = layout::Layout::vertical([Constraint::Fill(1), Constraint::Length(1)]).split(area);
Line::styled(
help.keyword().unwrap_or_else(|| format!("{}.help", help.layer.to_string())),
THEME.help.footer,
Expand Down
7 changes: 5 additions & 2 deletions yazi-fm/src/lives/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ impl File {
});
reg.add_method("is_yanked", |lua, me, ()| {
let cx = lua.named_registry_value::<CtxRef>("cx")?;
Ok(if !cx.manager.yanked.1.contains(&me.url) {
Ok(if !cx.manager.yanked.contains(&me.url) {
0u8
} else if cx.manager.yanked.0 {
} else if cx.manager.yanked.cut {
2u8
} else {
1u8
Expand All @@ -88,8 +88,11 @@ impl File {
let cx = lua.named_registry_value::<CtxRef>("cx")?;
let selected = me.tab().selected.contains(&me.url);

#[allow(clippy::if_same_then_else)]
Ok(if !cx.manager.active().mode.is_visual() {
selected
} else if me.folder().cwd != me.tab().current.cwd {
selected
} else {
cx.manager.active().mode.pending(me.idx, selected)
})
Expand Down
3 changes: 3 additions & 0 deletions yazi-fm/src/lives/lives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ impl Lives {
super::Folder::register(&LUA)?;
super::Mode::register(&LUA)?;
super::Preview::register(&LUA)?;
super::Selected::register(&LUA)?;
super::Tab::register(&LUA)?;
super::Tabs::register(&LUA)?;
super::Tasks::register(&LUA)?;
super::Yanked::register(&LUA)?;

Ok(())
}
Expand All @@ -42,6 +44,7 @@ impl Lives {
("active", super::Tab::make(cx.manager.active())?),
("tabs", super::Tabs::make(&cx.manager.tabs)?),
("tasks", super::Tasks::make(&cx.tasks)?),
("yanked", scope.create_any_userdata_ref(&cx.manager.yanked)?),
])?,
)?;

Expand Down
4 changes: 4 additions & 0 deletions yazi-fm/src/lives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ mod folder;
mod lives;
mod mode;
mod preview;
mod selected;
mod tab;
mod tabs;
mod tasks;
mod yanked;

use config::*;
use file::*;
Expand All @@ -18,8 +20,10 @@ use folder::*;
pub(super) use lives::*;
use mode::*;
use preview::*;
use selected::*;
use tab::*;
use tabs::*;
use tasks::*;
use yanked::*;

type CtxRef<'lua> = mlua::UserDataRef<'lua, crate::Ctx>;
52 changes: 52 additions & 0 deletions yazi-fm/src/lives/selected.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::{collections::{btree_set, BTreeSet}, ops::Deref};

use mlua::{AnyUserData, Lua, MetaMethod, UserDataMethods, UserDataRefMut};
use yazi_plugin::{bindings::Cast, url::Url};

use super::SCOPE;

#[derive(Clone, Copy)]
pub(super) struct Selected {
inner: *const BTreeSet<yazi_shared::fs::Url>,
}

impl Deref for Selected {
type Target = BTreeSet<yazi_shared::fs::Url>;

fn deref(&self) -> &Self::Target { self.inner() }
}

impl Selected {
#[inline]
pub(crate) fn make(inner: &BTreeSet<yazi_shared::fs::Url>) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
}

pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));

reg.add_meta_method(MetaMethod::Pairs, |lua, me, ()| {
let iter = lua.create_function(|lua, mut iter: UserDataRefMut<SelectedIter>| {
Ok(if let Some(url) = iter.0.next() { Some(Url::cast(lua, url.clone())?) } else { None })
})?;

Ok((iter, SelectedIter::make(me.inner())))
});
})?;

Ok(())
}

#[inline]
fn inner(&self) -> &'static BTreeSet<yazi_shared::fs::Url> { unsafe { &*self.inner } }
}

struct SelectedIter(btree_set::Iter<'static, yazi_shared::fs::Url>);

impl SelectedIter {
#[inline]
fn make(selected: &'static BTreeSet<yazi_shared::fs::Url>) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self(selected.iter()))
}
}
7 changes: 5 additions & 2 deletions yazi-fm/src/lives/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::ops::Deref;

use mlua::{AnyUserData, Lua, UserDataFields, UserDataMethods};

use super::{Config, Folder, Mode, Preview, SCOPE};
use super::{Config, Folder, Mode, Preview, Selected, SCOPE};

pub(super) struct Tab {
inner: *const yazi_core::tab::Tab,
Expand Down Expand Up @@ -36,10 +36,13 @@ impl Tab {

reg.add_field_method_get("mode", |_, me| Mode::make(&me.mode));
reg.add_field_method_get("conf", |_, me| Config::make(&me.conf));
reg.add_field_method_get("current", |_, me| Folder::make(None, &me.current, me));
reg.add_field_method_get("parent", |_, me| {
me.parent.as_ref().map(|f| Folder::make(None, f, me)).transpose()
});
reg.add_field_method_get("current", |_, me| Folder::make(None, &me.current, me));

reg.add_field_method_get("selected", |_, me| Selected::make(&me.selected));

reg.add_field_method_get("preview", |_, me| Preview::make(me));
})?;

Expand Down
13 changes: 13 additions & 0 deletions yazi-fm/src/lives/yanked.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use mlua::{Lua, MetaMethod, UserDataFields, UserDataMethods};

pub(super) struct Yanked;

impl Yanked {
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<yazi_core::manager::Yanked>(|reg| {
reg.add_field_method_get("is_cut", |_, me| Ok(me.cut));

reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
})
}
}
6 changes: 5 additions & 1 deletion yazi-fm/src/notify/notify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ impl<'a> Notify<'a> {
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }

fn chunks(area: Rect, messages: &[Message]) -> Rc<[Rect]> {
let chunks = Layout::horizontal([Constraint::Percentage(100), Constraint::Min(40)]).split(area);
let chunks =
Layout::horizontal([Constraint::Fill(1), Constraint::Length(40), Constraint::Max(1)])
.split(area);

let chunks = Layout::vertical([Constraint::Max(1), Constraint::Min(1)]).split(chunks[1]);

Layout::vertical(messages.iter().map(|m| Constraint::Length(m.height() as u16)))
.spacing(1)
Expand Down
2 changes: 1 addition & 1 deletion yazi-fm/src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl<'a> Root<'a> {
impl<'a> Widget for Root<'a> {
fn render(self, area: Rect, buf: &mut Buffer) {
let chunks =
Layout::vertical([Constraint::Length(1), Constraint::Min(0), Constraint::Length(1)])
Layout::vertical([Constraint::Length(1), Constraint::Fill(1), Constraint::Length(1)])
.split(area);

components::Header.render(chunks[0], buf);
Expand Down
17 changes: 13 additions & 4 deletions yazi-plugin/preset/components/current.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ Current = {
function Current:render(area)
self.area = area

local markers = {}
local items = {}
for i, f in ipairs(Folder:by_kind(Folder.CURRENT).window) do
local files = Folder:by_kind(Folder.CURRENT).window
if #files == 0 then
return {}
end

local items, markers = {}, {}
for i, f in ipairs(files) do
local name = Folder:highlighted_name(f)

-- Highlight hovered file
Expand All @@ -27,5 +31,10 @@ function Current:render(area)
markers[#markers + 1] = { i, 3 }
end
end
return ya.flat { ui.List(area, items), Folder:linemode(area), Folder:markers(area, markers) }

return ya.flat {
ui.List(area, items),
Folder:linemode(area, files),
Folder:markers(area, markers),
}
end
Loading

0 comments on commit b44dc75

Please sign in to comment.