mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
2c2e1668fc
commit
e6a4c0e7ab
9 changed files with 97 additions and 93 deletions
|
|
@ -76,7 +76,9 @@ impl App {
|
||||||
fn dispatch_render(&mut self) {
|
fn dispatch_render(&mut self) {
|
||||||
if let Some(term) = &mut self.term {
|
if let Some(term) = &mut self.term {
|
||||||
let _ = term.draw(|f| {
|
let _ = term.draw(|f| {
|
||||||
f.render_widget(Root::new(&self.cx), f.size());
|
plugin::scope(&self.cx, || {
|
||||||
|
f.render_widget(Root::new(&self.cx), f.size());
|
||||||
|
});
|
||||||
|
|
||||||
if let Some((x, y)) = self.cx.cursor() {
|
if let Some((x, y)) = self.cx.cursor() {
|
||||||
f.set_cursor(x, y);
|
f.set_cursor(x, y);
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ impl<'a> Folder<'a> {
|
||||||
|
|
||||||
impl<'a> Widget for Folder<'a> {
|
impl<'a> Widget for Folder<'a> {
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
let x = plugin::Folder { kind: self.kind as u8 }.render(self.cx, area);
|
let x = plugin::Folder { kind: self.kind as u8 }.render(area);
|
||||||
if x.is_err() {
|
if x.is_err() {
|
||||||
info!("{:?}", x);
|
info!("{:?}", x);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ impl<'a> Layout<'a> {
|
||||||
|
|
||||||
impl<'a> Widget for Layout<'a> {
|
impl<'a> Widget for Layout<'a> {
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
let x = plugin::Status::render(self.cx, area);
|
let x = plugin::Status::render(area);
|
||||||
if x.is_err() {
|
if x.is_err() {
|
||||||
info!("{:?}", x);
|
info!("{:?}", x);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"language":"en","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable"],"version":"0.2"}
|
{"language":"en","version":"0.2","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort"]}
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,9 @@ function Folder:by_kind(kind)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Folder:window(kind)
|
function Folder:window(kind) return (self:by_kind(kind) or {}).window end
|
||||||
local folder = self:by_kind(kind)
|
|
||||||
if folder ~= nil then
|
|
||||||
return folder.files:slice(folder.offset, MANAGER.layout.folder_height())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Folder:hovered(kind)
|
function Folder:hovered(kind) return (self:by_kind(kind) or {}).hovered end
|
||||||
local folder = self:by_kind(kind)
|
|
||||||
return folder and folder.hovered
|
|
||||||
end
|
|
||||||
|
|
||||||
function Folder:parent(area)
|
function Folder:parent(area)
|
||||||
local window = self:window(self.Kind.Parent)
|
local window = self:window(self.Kind.Parent)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,31 @@
|
||||||
use config::THEME;
|
use config::{MANAGER, THEME};
|
||||||
use mlua::{AnyUserData, Function, IntoLua, MetaMethod, UserDataFields, UserDataMethods, Value};
|
use mlua::{AnyUserData, Function, IntoLua, MetaMethod, UserData, UserDataFields, UserDataMethods, Value};
|
||||||
|
|
||||||
use super::Url;
|
use super::Url;
|
||||||
use crate::{layout::Style, LUA};
|
use crate::{layout::Style, LUA};
|
||||||
|
|
||||||
pub struct Manager;
|
struct File(core::files::File);
|
||||||
|
|
||||||
impl Manager {
|
impl From<&core::files::File> for File {
|
||||||
|
fn from(value: &core::files::File) -> Self { Self(value.clone()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserData for File {
|
||||||
|
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_get("url", |_, me| Ok(Url::from(me.0.url())));
|
||||||
|
fields.add_field_method_get("length", |_, me| Ok(me.0.length()));
|
||||||
|
fields.add_field_method_get("link_to", |_, me| Ok(me.0.link_to().map(Url::from)));
|
||||||
|
fields.add_field_method_get("is_link", |_, me| Ok(me.0.is_link()));
|
||||||
|
fields.add_field_method_get("is_hidden", |_, me| Ok(me.0.is_hidden()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Manager<'a, 'b> {
|
||||||
|
scope: &'b mlua::Scope<'a, 'a>,
|
||||||
|
inner: &'a core::manager::Manager,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> Manager<'a, 'b> {
|
||||||
pub(crate) fn init() -> mlua::Result<()> {
|
pub(crate) fn init() -> mlua::Result<()> {
|
||||||
LUA.register_userdata_type::<core::manager::Manager>(|reg| {
|
LUA.register_userdata_type::<core::manager::Manager>(|reg| {
|
||||||
reg.add_field_function_get("mode", |_, me| me.named_user_value::<AnyUserData>("mode"));
|
reg.add_field_function_get("mode", |_, me| me.named_user_value::<AnyUserData>("mode"));
|
||||||
|
|
@ -29,6 +48,7 @@ impl Manager {
|
||||||
reg.add_field_method_get("offset", |_, me| Ok(me.offset()));
|
reg.add_field_method_get("offset", |_, me| Ok(me.offset()));
|
||||||
reg.add_field_method_get("cursor", |_, me| Ok(me.cursor()));
|
reg.add_field_method_get("cursor", |_, me| Ok(me.cursor()));
|
||||||
|
|
||||||
|
reg.add_field_function_get("window", |_, me| me.named_user_value::<Value>("window"));
|
||||||
reg.add_field_function_get("files", |_, me| me.named_user_value::<AnyUserData>("files"));
|
reg.add_field_function_get("files", |_, me| me.named_user_value::<AnyUserData>("files"));
|
||||||
reg.add_field_function_get("hovered", |_, me| me.named_user_value::<Value>("hovered"));
|
reg.add_field_function_get("hovered", |_, me| me.named_user_value::<Value>("hovered"));
|
||||||
})?;
|
})?;
|
||||||
|
|
@ -38,22 +58,20 @@ impl Manager {
|
||||||
|
|
||||||
reg.add_meta_function(MetaMethod::Pairs, |lua, me: AnyUserData| {
|
reg.add_meta_function(MetaMethod::Pairs, |lua, me: AnyUserData| {
|
||||||
let iter = lua.create_function(|lua, (me, i): (AnyUserData, usize)| {
|
let iter = lua.create_function(|lua, (me, i): (AnyUserData, usize)| {
|
||||||
let items: Vec<AnyUserData> = me.named_user_value("items")?;
|
let files = me.borrow::<core::files::Files>()?;
|
||||||
|
|
||||||
let i = i + 1;
|
let i = i + 1;
|
||||||
Ok(if i > items.len() {
|
Ok(if i > files.len() {
|
||||||
mlua::Variadic::new()
|
mlua::Variadic::new()
|
||||||
} else {
|
} else {
|
||||||
let item = items[i - 1].clone().into_lua(lua)?;
|
mlua::Variadic::from_iter([i.into_lua(lua)?, File::from(&files[i - 1]).into_lua(lua)?])
|
||||||
mlua::Variadic::from_iter([i.into_lua(lua)?, item])
|
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
Ok((iter, me, 0))
|
Ok((iter, me, 0))
|
||||||
});
|
});
|
||||||
|
|
||||||
reg.add_function("slice", |_, (me, skip, take): (AnyUserData, usize, usize)| {
|
reg.add_function("slice", |_, (me, skip, take): (AnyUserData, usize, usize)| {
|
||||||
let items = me.named_user_value::<Vec<AnyUserData>>("items")?;
|
let files = me.borrow::<core::files::Files>()?;
|
||||||
Ok(items.iter().skip(skip).take(take).cloned().collect::<Vec<_>>())
|
Ok(files.iter().skip(skip).take(take).map(File::from).collect::<Vec<_>>())
|
||||||
});
|
});
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
@ -87,61 +105,56 @@ impl Manager {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn make<'a>(
|
pub(crate) fn new(scope: &'b mlua::Scope<'a, 'a>, inner: &'a core::manager::Manager) -> Self {
|
||||||
scope: &mlua::Scope<'a, 'a>,
|
Self { scope, inner }
|
||||||
inner: &'a core::manager::Manager,
|
}
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
|
||||||
let ud = scope.create_any_userdata_ref(inner)?;
|
pub(crate) fn make(&self) -> mlua::Result<AnyUserData<'a>> {
|
||||||
ud.set_named_user_value("mode", scope.create_any_userdata_ref(inner.active().mode())?)?;
|
let ud = self.scope.create_any_userdata_ref(self.inner)?;
|
||||||
ud.set_named_user_value(
|
ud.set_named_user_value(
|
||||||
"parent",
|
"mode",
|
||||||
inner.parent().and_then(|p| Self::folder(scope, inner, p).ok()),
|
self.scope.create_any_userdata_ref(self.inner.active().mode())?,
|
||||||
)?;
|
)?;
|
||||||
ud.set_named_user_value("current", Self::folder(scope, inner, inner.current())?)?;
|
ud.set_named_user_value("parent", self.inner.parent().and_then(|p| self.folder(p, None).ok()))?;
|
||||||
ud.set_named_user_value("preview", Self::preview(scope, inner, inner.active())?)?;
|
ud.set_named_user_value("current", self.folder(self.inner.current(), None)?)?;
|
||||||
|
ud.set_named_user_value("preview", self.preview(self.inner.active())?)?;
|
||||||
|
|
||||||
Ok(ud)
|
Ok(ud)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn folder<'a>(
|
pub(crate) fn folder(
|
||||||
scope: &mlua::Scope<'a, 'a>,
|
&self,
|
||||||
manager: &'a core::manager::Manager,
|
|
||||||
inner: &'a core::manager::Folder,
|
inner: &'a core::manager::Folder,
|
||||||
|
window: Option<(usize, usize)>,
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
) -> mlua::Result<AnyUserData<'a>> {
|
||||||
let ud = scope.create_any_userdata_ref(inner)?;
|
let window = window.unwrap_or_else(|| (inner.offset(), MANAGER.layout.folder_height()));
|
||||||
ud.set_named_user_value("files", Self::files(scope, manager, &inner.files)?)?;
|
|
||||||
|
let ud = self.scope.create_any_userdata_ref(inner)?;
|
||||||
ud.set_named_user_value(
|
ud.set_named_user_value(
|
||||||
"hovered",
|
"window",
|
||||||
inner.hovered.as_ref().and_then(|h| Self::file(scope, manager, h).ok()),
|
inner
|
||||||
|
.files
|
||||||
|
.iter()
|
||||||
|
.skip(window.0)
|
||||||
|
.take(window.1)
|
||||||
|
.filter_map(|f| self.file(f).ok())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
)?;
|
)?;
|
||||||
|
ud.set_named_user_value("files", self.files(&inner.files)?)?;
|
||||||
|
ud.set_named_user_value("hovered", inner.hovered.as_ref().and_then(|h| self.file(h).ok()))?;
|
||||||
|
|
||||||
Ok(ud)
|
Ok(ud)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn files<'a>(
|
fn files(&self, inner: &'a core::files::Files) -> mlua::Result<AnyUserData<'a>> {
|
||||||
scope: &mlua::Scope<'a, 'a>,
|
self.scope.create_any_userdata_ref(inner)
|
||||||
manager: &'a core::manager::Manager,
|
|
||||||
inner: &'a core::files::Files,
|
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
|
||||||
let ud = scope.create_any_userdata_ref(inner)?;
|
|
||||||
ud.set_named_user_value(
|
|
||||||
"items",
|
|
||||||
inner.iter().filter_map(|f| Self::file(scope, manager, f).ok()).collect::<Vec<_>>(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(ud)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn file<'a>(
|
fn file(&self, inner: &'a core::files::File) -> mlua::Result<AnyUserData<'a>> {
|
||||||
scope: &mlua::Scope<'a, 'a>,
|
let ud = self.scope.create_any_userdata_ref(inner)?;
|
||||||
manager: &'a core::manager::Manager,
|
|
||||||
inner: &'a core::files::File,
|
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
|
||||||
let ud = scope.create_any_userdata_ref(inner)?;
|
|
||||||
|
|
||||||
ud.set_named_user_value(
|
ud.set_named_user_value(
|
||||||
"icon",
|
"icon",
|
||||||
scope.create_function(|_, ()| {
|
self.scope.create_function(|_, ()| {
|
||||||
Ok(
|
Ok(
|
||||||
THEME
|
THEME
|
||||||
.icons
|
.icons
|
||||||
|
|
@ -154,8 +167,8 @@ impl Manager {
|
||||||
|
|
||||||
ud.set_named_user_value(
|
ud.set_named_user_value(
|
||||||
"style",
|
"style",
|
||||||
scope.create_function(|_, ()| {
|
self.scope.create_function(|_, ()| {
|
||||||
let mime = manager.mimetype.get(inner.url());
|
let mime = self.inner.mimetype.get(inner.url());
|
||||||
Ok(
|
Ok(
|
||||||
THEME
|
THEME
|
||||||
.filetypes
|
.filetypes
|
||||||
|
|
@ -169,14 +182,10 @@ impl Manager {
|
||||||
Ok(ud)
|
Ok(ud)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preview<'a>(
|
fn preview(&self, tab: &'a core::manager::Tab) -> mlua::Result<AnyUserData<'a>> {
|
||||||
scope: &mlua::Scope<'a, 'a>,
|
|
||||||
manager: &'a core::manager::Manager,
|
|
||||||
tab: &'a core::manager::Tab,
|
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
|
||||||
let inner = tab.preview();
|
let inner = tab.preview();
|
||||||
|
|
||||||
let ud = scope.create_any_userdata_ref(inner)?;
|
let ud = self.scope.create_any_userdata_ref(inner)?;
|
||||||
ud.set_named_user_value(
|
ud.set_named_user_value(
|
||||||
"folder",
|
"folder",
|
||||||
inner
|
inner
|
||||||
|
|
@ -184,7 +193,7 @@ impl Manager {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.filter(|l| l.is_folder())
|
.filter(|l| l.is_folder())
|
||||||
.and_then(|l| tab.history(&l.url))
|
.and_then(|l| tab.history(&l.url))
|
||||||
.and_then(|f| Self::folder(scope, manager, f).ok()),
|
.and_then(|f| self.folder(f, Some((f.offset(), MANAGER.layout.preview_height()))).ok()),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(ud)
|
Ok(ud)
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,14 @@
|
||||||
use core::Ctx;
|
|
||||||
|
|
||||||
use mlua::{Result, Table, TableExt};
|
use mlua::{Result, Table, TableExt};
|
||||||
use ratatui::layout;
|
use ratatui::layout;
|
||||||
|
|
||||||
use crate::{bindings, layout::{Paragraph, Rect}, GLOBALS, LUA};
|
use crate::{layout::{Paragraph, Rect}, GLOBALS, LUA};
|
||||||
|
|
||||||
pub struct Status;
|
pub struct Status;
|
||||||
|
|
||||||
impl Status {
|
impl Status {
|
||||||
pub fn render(cx: &Ctx, area: layout::Rect) -> Result<Vec<Paragraph>> {
|
pub fn render(area: layout::Rect) -> Result<Vec<Paragraph>> {
|
||||||
LUA.scope(|scope| {
|
let comp: Table = GLOBALS.get("Status")?;
|
||||||
let tbl = LUA.create_table()?;
|
comp.call_method::<_, _>("render", Rect(area))
|
||||||
tbl.set("manager", bindings::Manager::make(scope, &cx.manager)?)?;
|
|
||||||
tbl.set("tasks", bindings::Tasks::make(scope, &cx.tasks)?)?;
|
|
||||||
GLOBALS.set("cx", tbl)?;
|
|
||||||
|
|
||||||
let comp: Table = GLOBALS.get("Status")?;
|
|
||||||
comp.call_method::<_, _>("render", Rect(area))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,14 +23,8 @@ impl Folder {
|
||||||
Ok(tbl)
|
Ok(tbl)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self, cx: &Ctx, area: layout::Rect) -> Result<Vec<Paragraph>> {
|
pub fn render(self, area: layout::Rect) -> Result<Vec<Paragraph>> {
|
||||||
LUA.scope(|scope| {
|
let comp: Table = GLOBALS.get("Folder")?;
|
||||||
let tbl = LUA.create_table()?;
|
comp.call_method::<_, _>("render", (Rect(area), self.args()?))
|
||||||
tbl.set("manager", bindings::Manager::make(scope, &cx.manager)?)?;
|
|
||||||
GLOBALS.set("cx", tbl)?;
|
|
||||||
|
|
||||||
let comp: Table = GLOBALS.get("Folder")?;
|
|
||||||
comp.call_method::<_, _>("render", (Rect(area), self.args()?))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@ mod components;
|
||||||
mod config;
|
mod config;
|
||||||
mod layout;
|
mod layout;
|
||||||
mod plugin;
|
mod plugin;
|
||||||
|
mod scope;
|
||||||
|
|
||||||
pub use components::*;
|
pub use components::*;
|
||||||
use config::*;
|
use config::*;
|
||||||
pub use plugin::*;
|
pub use plugin::*;
|
||||||
|
pub use scope::*;
|
||||||
|
|
|
||||||
14
plugin/src/scope.rs
Normal file
14
plugin/src/scope.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
use core::Ctx;
|
||||||
|
|
||||||
|
use crate::{bindings, GLOBALS, LUA};
|
||||||
|
|
||||||
|
pub fn scope<F: FnOnce()>(cx: &Ctx, f: F) {
|
||||||
|
let _ = LUA.scope(|scope| {
|
||||||
|
let tbl = LUA.create_table()?;
|
||||||
|
tbl.set("manager", bindings::Manager::new(scope, &cx.manager).make()?)?;
|
||||||
|
tbl.set("tasks", bindings::Tasks::make(scope, &cx.tasks)?)?;
|
||||||
|
GLOBALS.set("cx", tbl)?;
|
||||||
|
|
||||||
|
Ok(f())
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue