diff --git a/cspell.json b/cspell.json index 19ff1c11..df135979 100644 --- a/cspell.json +++ b/cspell.json @@ -1 +1 @@ -{"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"],"language":"en","version":"0.2"} +{"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"} diff --git a/plugin/preset/components/status.lua b/plugin/preset/components/status.lua index 77ddee71..e567e850 100644 --- a/plugin/preset/components/status.lua +++ b/plugin/preset/components/status.lua @@ -13,39 +13,44 @@ function Status.mode() end function Status.size() - local hovered = cx.manager.current_hovered - if hovered == nil then - return ui.Span("") + -- cx.manager.current.files + + -- yazi.print(#cx.manager.current.files) + + for key, value in pairs(cx.manager.current.files) do + yazi.print(key, value) + break end - return ui.Line( - ui.Span(" " .. hovered.length .. " "):fg(THEME.status.mode_normal.bg):bg(THEME.status.fancy.bg), - ui.Span(THEME.status.separator.closing):fg(THEME.status.fancy.bg) - ) + return ui.Span("fff") + -- return ui.Line( + -- ui.Span(" " .. utils.readable_size(h.length) .. " "):fg(THEME.status.mode_normal.bg):bg(THEME.status.fancy.bg), + -- ui.Span(THEME.status.separator.closing):fg(THEME.status.fancy.bg) + -- ) end function Status.name() - local hovered = cx.manager.current_hovered - if hovered == nil then + local h = cx.manager.current.hovered + if h == nil then return ui.Span("") end - return ui.Span(" " .. utils.basename(hovered.url)) + return ui.Span(" " .. utils.basename(h.url)) end function Status.permissions() - local hovered = cx.manager.current_hovered - if hovered == nil then + local h = cx.manager.current.hovered + if h == nil then return ui.Span("") end - if hovered.permissions == nil then + if h.permissions == nil then return ui.Span("") end local spans = {} - for i = 1, #hovered.permissions do - local c = hovered.permissions:sub(i, i) + for i = 1, #h.permissions do + local c = h.permissions:sub(i, i) local style = THEME.status.permissions_t if c == "r" then style = THEME.status.permissions_r @@ -61,8 +66,8 @@ end function Status.percentage() local percent = 0 - local cursor = cx.manager.current_cursor - local length = cx.manager.current_length + local cursor = cx.manager.current.cursor + local length = cx.manager.current.len() if cursor ~= 0 and length ~= 0 then percent = math.floor((cursor + 1) * 100 / length) end @@ -74,15 +79,19 @@ function Status.percentage() end return ui.Line( - ui.Span(THEME.status.separator.opening):fg(THEME.status.fancy.bg), + ui.Span(" " .. THEME.status.separator.opening):fg(THEME.status.fancy.bg), ui.Span(percent):fg(THEME.status.mode_normal.bg):bg(THEME.status.fancy.bg) ) end function Status.position() - local cursor = cx.manager.current_cursor - local length = cx.manager.current_length - return ui.Span(string.format(" %d/%d ", cursor + 1, length)) + local cursor = cx.manager.current.cursor + local length = cx.manager.current.length + + return ui.Line( + ui.Span(string.format(" %2d/%-2d ", cursor + 1, length)):style(THEME.status.mode_normal), + ui.Span(THEME.status.separator.closing):fg(THEME.status.mode_normal.bg) + ) end function Status:render(area) @@ -91,10 +100,12 @@ function Status:render(area) :constraints({ ui.Constraint.Percentage(50), ui.Constraint.Percentage(50) }) :split(area) - local left = ui.Line(self.mode(), self.size(), self.name()) - local right = ui.Line(self.permissions(), self.percentage(), self.position()) + -- local left = ui.Line(self.mode(), self.size(), self.name()) + -- local right = ui.Line(self.permissions(), self.percentage(), self.position()) + + local left = ui.Line(self.mode(), self.size()) return ui.Paragraph.render( - ui.Paragraph(left):area(chunks[1]), - ui.Paragraph(right):align(ui.Alignment.RIGHT):area(chunks[2]) + ui.Paragraph(left):area(chunks[1]) + -- ui.Paragraph(right):align(ui.Alignment.RIGHT):area(chunks[2]) ) end diff --git a/plugin/preset/utils.lua b/plugin/preset/utils.lua index d1560a5f..f7aa3d3f 100644 --- a/plugin/preset/utils.lua +++ b/plugin/preset/utils.lua @@ -1,3 +1,13 @@ utils = utils or {} function utils.basename(str) return string.gsub(str, "(.*[/\\])(.*)", "%2") end + +function utils.readable_size(size) + local units = { "B", "KB", "MB", "GB", "TB", "PB", "EB" } + local i = 1 + while size > 1024.0 and i < #units do + size = size / 1024.0 + i = i + 1 + end + return string.format("%.1f %s", size, units[i]) +end diff --git a/plugin/src/bindings.rs b/plugin/src/bindings.rs deleted file mode 100644 index 4cb9018a..00000000 --- a/plugin/src/bindings.rs +++ /dev/null @@ -1,60 +0,0 @@ -use mlua::{LuaSerdeExt, UserData}; - -// Manager - -pub struct Manager<'a>(&'a core::manager::Manager); - -impl<'a> Manager<'a> { - pub fn new(manager: &'a core::manager::Manager) -> Self { Self(manager) } -} - -impl<'a> UserData for Manager<'a> { - fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("mode", |_, me| Ok(me.0.active().mode().to_string())); - - fields.add_field_method_get("current_cursor", |_, me| Ok(me.0.current().cursor())); - fields.add_field_method_get("current_length", |_, me| Ok(me.0.current().files.len())); - fields.add_field_method_get("current_hovered", |_, me| { - Ok(me.0.current().hovered.as_ref().map(File::from)) - }); - } -} - -// Tasks - -pub struct Tasks<'a>(&'a core::tasks::Tasks); - -impl<'a> Tasks<'a> { - pub fn new(tasks: &'a core::tasks::Tasks) -> Self { Self(tasks) } -} - -impl<'a> UserData for Tasks<'a> { - fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("progress", |lua, me| lua.to_value(&me.0.progress)) - } -} - -// File - -pub struct File(core::files::File); - -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: mlua::UserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("url", |_, me| Ok(me.0.url().to_string_lossy().to_string())); - 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(|l| l.to_string_lossy().to_string())) - }); - 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())); - - // Meta - fields.add_field_method_get("permissions", |_, me| { - Ok(shared::permissions(me.0.meta().permissions())) - }); - } -} diff --git a/plugin/src/bindings/manager.rs b/plugin/src/bindings/manager.rs new file mode 100644 index 00000000..71f51001 --- /dev/null +++ b/plugin/src/bindings/manager.rs @@ -0,0 +1,122 @@ +use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, Value}; +use tracing::info; + +use crate::{Url, LUA}; + +// Manager +pub struct Manager; + +impl Manager { + pub fn make<'a>( + scope: &mlua::Scope<'a, 'a>, + inner: &'a core::manager::Manager, + ) -> mlua::Result> { + LUA.register_userdata_type::(|reg| { + reg.add_field_method_get("mode", |_, me| Ok(me.active().mode().to_string())); + reg.add_field_function_get("current", |_, me| me.named_user_value::("current")); + reg.add_field_function_get("parent", |_, me| me.named_user_value::("parent")); + })?; + + let ud = scope.create_any_userdata_ref(inner)?; + ud.set_named_user_value("current", Folder::make(scope, inner.current())?)?; + ud.set_named_user_value("parent", inner.parent().and_then(|p| Folder::make(scope, p).ok()))?; + + Ok(ud) + } +} + +// Folder +pub struct Folder; + +impl Folder { + fn make<'a>( + scope: &mlua::Scope<'a, 'a>, + inner: &'a core::manager::Folder, + ) -> mlua::Result> { + LUA.register_userdata_type::(|reg| { + reg.add_field_method_get("cwd", |_, me| Ok(Url::from(&me.cwd))); + 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("files", |_, me| me.named_user_value::("files")); + reg.add_field_function_get("hovered", |_, me| me.named_user_value::("hovered")); + // reg.add_field_method_get("window", |_, me| { + // LUA.scope(|scope| scope.create_nonstatic_userdata(Files { files: + // &me.0.files })) + // }); + })?; + + let ud = scope.create_any_userdata_ref(inner)?; + ud.set_named_user_value("files", Files::make(scope, &inner.files)?)?; + ud.set_named_user_value( + "hovered", + inner.hovered.as_ref().and_then(|h| File::make(scope, h).ok()), + )?; + + Ok(ud) + } +} + +// Files +pub struct Files; + +impl Files { + fn make<'a>( + scope: &mlua::Scope<'a, 'a>, + inner: &'a core::files::Files, + ) -> mlua::Result> { + LUA.register_userdata_type::(|reg| { + reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len())); + + reg.add_meta_function(MetaMethod::Pairs, |lua, me: AnyUserData| { + let iter = lua.create_function(|lua, (me, i): (AnyUserData, usize)| { + let items: Vec = me.named_user_value("items")?; + + let i = i + 1; + Ok(if i > items.len() { + mlua::Variadic::new() + } else { + let item = items[i - 1].clone().into_lua(lua)?; + mlua::Variadic::from_iter([i.into_lua(lua)?, item]) + }) + })?; + Ok((iter, me, 0)) + }); + })?; + + let ud = scope.create_any_userdata_ref(inner)?; + ud.set_named_user_value( + "items", + inner.iter().filter_map(|f| File::make(scope, f).ok()).collect::>(), + )?; + Ok(ud) + } +} + +// File +pub struct File; + +impl File { + fn make<'a>( + scope: &mlua::Scope<'a, 'a>, + inner: &'a core::files::File, + ) -> mlua::Result> { + LUA.register_userdata_type::(|reg| { + reg.add_field_method_get("url", |_, me| Ok(Url::from(me.url()))); + reg.add_field_method_get("length", |_, me| Ok(me.length())); + reg.add_field_method_get("link_to", |_, me| { + Ok(me.link_to().map(|l| l.to_string_lossy().to_string())) + }); + reg.add_field_method_get("is_link", |_, me| Ok(me.is_link())); + reg.add_field_method_get("is_hidden", |_, me| Ok(me.is_hidden())); + + // Meta + reg.add_field_method_get("permissions", |_, me| { + Ok(shared::permissions(me.meta().permissions())) + }); + })?; + + let ud = scope.create_any_userdata_ref(inner)?; + Ok(ud) + } +} diff --git a/plugin/src/bindings/mod.rs b/plugin/src/bindings/mod.rs new file mode 100644 index 00000000..b68c8ca4 --- /dev/null +++ b/plugin/src/bindings/mod.rs @@ -0,0 +1,7 @@ +mod manager; +mod shared; +mod tasks; + +pub use manager::*; +pub use shared::*; +pub use tasks::*; diff --git a/plugin/src/bindings/shared.rs b/plugin/src/bindings/shared.rs new file mode 100644 index 00000000..edafa431 --- /dev/null +++ b/plugin/src/bindings/shared.rs @@ -0,0 +1,11 @@ +use mlua::UserData; + +// Url +pub struct Url(shared::Url); + +impl From<&shared::Url> for Url { + fn from(value: &shared::Url) -> Self { Self(value.clone()) } +} + +// TODO +impl UserData for Url {} diff --git a/plugin/src/bindings/tasks.rs b/plugin/src/bindings/tasks.rs new file mode 100644 index 00000000..715d454e --- /dev/null +++ b/plugin/src/bindings/tasks.rs @@ -0,0 +1,14 @@ +use mlua::{LuaSerdeExt, UserData}; + +// Tasks +pub struct Tasks<'a>(&'a core::tasks::Tasks); + +impl<'a> Tasks<'a> { + pub fn new(tasks: &'a core::tasks::Tasks) -> Self { Self(tasks) } +} + +impl<'a> UserData for Tasks<'a> { + fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) { + fields.add_field_method_get("progress", |lua, me| lua.to_value(&me.0.progress)) + } +} diff --git a/plugin/src/status.rs b/plugin/src/status.rs index fa02d1bb..8f8d65bb 100644 --- a/plugin/src/status.rs +++ b/plugin/src/status.rs @@ -9,14 +9,17 @@ pub struct Status; impl Status { fn scope Result>(cx: &Ctx, f: F) -> Result { + // crate::Manager::register()?; + LUA.scope(|scope| { - let manager = scope.create_nonstatic_userdata(bindings::Manager::new(&cx.manager))?; + let manager = crate::Manager::make(scope, &cx.manager)?; let tasks = scope.create_nonstatic_userdata(bindings::Tasks::new(&cx.tasks))?; - let cx = LUA.create_table()?; - cx.set("manager", manager)?; - cx.set("tasks", tasks)?; - GLOBALS.set("cx", cx)?; + let cx3 = LUA.create_table()?; + cx3.set("manager", manager)?; + cx3.set("tasks", tasks)?; + + GLOBALS.set("cx", cx3)?; f() }) diff --git a/shared/src/fns.rs b/shared/src/fns.rs index 061253de..eef71bcd 100644 --- a/shared/src/fns.rs +++ b/shared/src/fns.rs @@ -76,17 +76,6 @@ pub fn readable_path(p: &Path) -> String { p.display().to_string() } -pub fn readable_size(size: u64) -> String { - let units = ["B", "KB", "MB", "GB", "TB", "PB", "EB"]; - let mut size = size as f64; - let mut i = 0; - while size > 1024.0 && i < units.len() - 1 { - size /= 1024.0; - i += 1; - } - format!("{:.1} {}", size, units[i]) -} - pub async fn unique_path(mut p: Url) -> Url { let Some(name) = p.file_name().map(|n| n.to_owned()) else { return p;