Skip to content

Commit

Permalink
..
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi committed Oct 3, 2023
1 parent 5a8735b commit 77e1005
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 93 deletions.
4 changes: 3 additions & 1 deletion app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ impl App {
fn dispatch_render(&mut self) {
if let Some(term) = &mut self.term {
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() {
f.set_cursor(x, y);
Expand Down
2 changes: 1 addition & 1 deletion app/src/manager/folder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl<'a> Folder<'a> {

impl<'a> Widget for Folder<'a> {
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() {
info!("{:?}", x);
return;
Expand Down
2 changes: 1 addition & 1 deletion app/src/status/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ impl<'a> Layout<'a> {

impl<'a> Widget for Layout<'a> {
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() {
info!("{:?}", x);
return;
Expand Down
2 changes: 1 addition & 1 deletion cspell.json
Original file line number Diff line number Diff line change
@@ -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"]}
12 changes: 2 additions & 10 deletions plugin/preset/components/folder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,9 @@ function Folder:by_kind(kind)
end
end

function Folder:window(kind)
local folder = self:by_kind(kind)
if folder ~= nil then
return folder.files:slice(folder.offset, MANAGER.layout.folder_height())
end
end
function Folder:window(kind) return (self:by_kind(kind) or {}).window end

function Folder:hovered(kind)
local folder = self:by_kind(kind)
return folder and folder.hovered
end
function Folder:hovered(kind) return (self:by_kind(kind) or {}).hovered end

function Folder:parent(area)
local window = self:window(self.Kind.Parent)
Expand Down
123 changes: 66 additions & 57 deletions plugin/src/bindings/manager.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
use config::THEME;
use mlua::{AnyUserData, Function, IntoLua, MetaMethod, UserDataFields, UserDataMethods, Value};
use config::{MANAGER, THEME};
use mlua::{AnyUserData, Function, IntoLua, MetaMethod, UserData, UserDataFields, UserDataMethods, Value};

use super::Url;
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<()> {
LUA.register_userdata_type::<core::manager::Manager>(|reg| {
reg.add_field_function_get("mode", |_, me| me.named_user_value::<AnyUserData>("mode"));
Expand All @@ -29,6 +48,7 @@ impl Manager {
reg.add_field_method_get("offset", |_, me| Ok(me.offset()));
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("hovered", |_, me| me.named_user_value::<Value>("hovered"));
})?;
Expand All @@ -38,22 +58,20 @@ impl Manager {

reg.add_meta_function(MetaMethod::Pairs, |lua, me: AnyUserData| {
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;
Ok(if i > items.len() {
Ok(if i > files.len() {
mlua::Variadic::new()
} else {
let item = items[i - 1].clone().into_lua(lua)?;
mlua::Variadic::from_iter([i.into_lua(lua)?, item])
mlua::Variadic::from_iter([i.into_lua(lua)?, File::from(&files[i - 1]).into_lua(lua)?])
})
})?;
Ok((iter, me, 0))
});

reg.add_function("slice", |_, (me, skip, take): (AnyUserData, usize, usize)| {
let items = me.named_user_value::<Vec<AnyUserData>>("items")?;
Ok(items.iter().skip(skip).take(take).cloned().collect::<Vec<_>>())
let files = me.borrow::<core::files::Files>()?;
Ok(files.iter().skip(skip).take(take).map(File::from).collect::<Vec<_>>())
});
})?;

Expand Down Expand Up @@ -87,61 +105,56 @@ impl Manager {
Ok(())
}

pub(crate) fn make<'a>(
scope: &mlua::Scope<'a, 'a>,
inner: &'a core::manager::Manager,
) -> mlua::Result<AnyUserData<'a>> {
let ud = scope.create_any_userdata_ref(inner)?;
ud.set_named_user_value("mode", scope.create_any_userdata_ref(inner.active().mode())?)?;
ud.set_named_user_value(
"parent",
inner.parent().and_then(|p| Self::folder(scope, inner, p).ok()),
)?;
ud.set_named_user_value("current", Self::folder(scope, inner, inner.current())?)?;
ud.set_named_user_value("preview", Self::preview(scope, inner, inner.active())?)?;

Ok(ud)
pub(crate) fn new(scope: &'b mlua::Scope<'a, 'a>, inner: &'a core::manager::Manager) -> Self {
Self { scope, inner }
}

pub(crate) fn folder<'a>(
scope: &mlua::Scope<'a, 'a>,
manager: &'a core::manager::Manager,
inner: &'a core::manager::Folder,
) -> mlua::Result<AnyUserData<'a>> {
let ud = scope.create_any_userdata_ref(inner)?;
ud.set_named_user_value("files", Self::files(scope, manager, &inner.files)?)?;
pub(crate) fn make(&self) -> mlua::Result<AnyUserData<'a>> {
let ud = self.scope.create_any_userdata_ref(self.inner)?;
ud.set_named_user_value(
"hovered",
inner.hovered.as_ref().and_then(|h| Self::file(scope, manager, h).ok()),
"mode",
self.scope.create_any_userdata_ref(self.inner.active().mode())?,
)?;
ud.set_named_user_value("parent", self.inner.parent().and_then(|p| self.folder(p, None).ok()))?;
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)
}

fn files<'a>(
scope: &mlua::Scope<'a, 'a>,
manager: &'a core::manager::Manager,
inner: &'a core::files::Files,
pub(crate) fn folder(
&self,
inner: &'a core::manager::Folder,
window: Option<(usize, usize)>,
) -> mlua::Result<AnyUserData<'a>> {
let ud = scope.create_any_userdata_ref(inner)?;
let window = window.unwrap_or_else(|| (inner.offset(), MANAGER.layout.folder_height()));

let ud = self.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<_>>(),
"window",
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)
}

fn file<'a>(
scope: &mlua::Scope<'a, 'a>,
manager: &'a core::manager::Manager,
inner: &'a core::files::File,
) -> mlua::Result<AnyUserData<'a>> {
let ud = scope.create_any_userdata_ref(inner)?;
fn files(&self, inner: &'a core::files::Files) -> mlua::Result<AnyUserData<'a>> {
self.scope.create_any_userdata_ref(inner)
}

fn file(&self, inner: &'a core::files::File) -> mlua::Result<AnyUserData<'a>> {
let ud = self.scope.create_any_userdata_ref(inner)?;
ud.set_named_user_value(
"icon",
scope.create_function(|_, ()| {
self.scope.create_function(|_, ()| {
Ok(
THEME
.icons
Expand All @@ -154,8 +167,8 @@ impl Manager {

ud.set_named_user_value(
"style",
scope.create_function(|_, ()| {
let mime = manager.mimetype.get(inner.url());
self.scope.create_function(|_, ()| {
let mime = self.inner.mimetype.get(inner.url());
Ok(
THEME
.filetypes
Expand All @@ -169,22 +182,18 @@ impl Manager {
Ok(ud)
}

fn preview<'a>(
scope: &mlua::Scope<'a, 'a>,
manager: &'a core::manager::Manager,
tab: &'a core::manager::Tab,
) -> mlua::Result<AnyUserData<'a>> {
fn preview(&self, tab: &'a core::manager::Tab) -> mlua::Result<AnyUserData<'a>> {
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(
"folder",
inner
.lock
.as_ref()
.filter(|l| l.is_folder())
.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)
Expand Down
29 changes: 7 additions & 22 deletions plugin/src/components.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
use core::Ctx;

use mlua::{Result, Table, TableExt};
use ratatui::layout;

use crate::{bindings, layout::{Paragraph, Rect}, GLOBALS, LUA};
use crate::{layout::{Paragraph, Rect}, GLOBALS, LUA};

pub struct Status;

impl Status {
pub fn render(cx: &Ctx, area: layout::Rect) -> Result<Vec<Paragraph>> {
LUA.scope(|scope| {
let tbl = LUA.create_table()?;
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))
})
pub fn render(area: layout::Rect) -> Result<Vec<Paragraph>> {
let comp: Table = GLOBALS.get("Status")?;
comp.call_method::<_, _>("render", Rect(area))
}
}

Expand All @@ -32,14 +23,8 @@ impl Folder {
Ok(tbl)
}

pub fn render(self, cx: &Ctx, area: layout::Rect) -> Result<Vec<Paragraph>> {
LUA.scope(|scope| {
let tbl = LUA.create_table()?;
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()?))
})
pub fn render(self, area: layout::Rect) -> Result<Vec<Paragraph>> {
let comp: Table = GLOBALS.get("Folder")?;
comp.call_method::<_, _>("render", (Rect(area), self.args()?))
}
}
2 changes: 2 additions & 0 deletions plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ mod components;
mod config;
mod layout;
mod plugin;
mod scope;

pub use components::*;
use config::*;
pub use plugin::*;
pub use scope::*;
14 changes: 14 additions & 0 deletions plugin/src/scope.rs
Original file line number Diff line number Diff line change
@@ -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())
});
}

0 comments on commit 77e1005

Please sign in to comment.