diff --git a/yazi-binding/src/fd.rs b/yazi-binding/src/fd.rs index 62185505..0c1650ef 100644 --- a/yazi-binding/src/fd.rs +++ b/yazi-binding/src/fd.rs @@ -1,5 +1,5 @@ -use mlua::{IntoLuaMulti, UserData, UserDataMethods}; -use tokio::io::AsyncWriteExt; +use mlua::{IntoLuaMulti, UserData, UserDataMethods, Value}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; use crate::Error; @@ -7,17 +7,27 @@ pub struct Fd(pub yazi_vfs::provider::RwFile); impl UserData for Fd { fn add_methods>(methods: &mut M) { - methods.add_async_method_mut("write_all", |lua, mut me, src: mlua::String| async move { - match me.0.write_all(&*src.as_bytes()).await { - Ok(()) => true.into_lua_multi(&lua), - Err(e) => (false, Error::Io(e)).into_lua_multi(&lua), - } - }); methods.add_async_method_mut("flush", |lua, mut me, ()| async move { match me.0.flush().await { Ok(()) => true.into_lua_multi(&lua), Err(e) => (false, Error::Io(e)).into_lua_multi(&lua), } }); + methods.add_async_method_mut("read", |lua, mut me, len: usize| async move { + let mut buf = vec![0; len]; + match me.0.read(&mut buf).await { + Ok(n) => { + buf.truncate(n); + lua.create_external_string(buf)?.into_lua_multi(&lua) + } + Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua), + } + }); + methods.add_async_method_mut("write_all", |lua, mut me, src: mlua::String| async move { + match me.0.write_all(&*src.as_bytes()).await { + Ok(()) => true.into_lua_multi(&lua), + Err(e) => (false, Error::Io(e)).into_lua_multi(&lua), + } + }); } } diff --git a/yazi-plugin/preset/plugins/archive.lua b/yazi-plugin/preset/plugins/archive.lua index 4a291815..0ba738ad 100644 --- a/yazi-plugin/preset/plugins/archive.lua +++ b/yazi-plugin/preset/plugins/archive.lua @@ -26,7 +26,7 @@ function M:peek(job) }):icon() if f.size > 0 then - right[#right + 1] = string.format(" %s ", ya.readable_size(f.size)) + right[#right + 1] = " " .. ya.readable_size(f.size) .. " " else right[#right + 1] = " " end @@ -42,7 +42,7 @@ function M:peek(job) left[#left], ui.truncate(f.path.name, { rtl = true, - max = math.max(0, job.area.w - ui.width(left[#left]) - ui.width(right[#right])), + max = math.max(0, job.area.w - (f.depth * 2) - ui.width(left[#left]) - ui.width(right[#right])), }), } end diff --git a/yazi-plugin/preset/plugins/empty.lua b/yazi-plugin/preset/plugins/empty.lua index d85034a5..105b4b62 100644 --- a/yazi-plugin/preset/plugins/empty.lua +++ b/yazi-plugin/preset/plugins/empty.lua @@ -3,41 +3,24 @@ local M = {} function M.msg(job, s) ya.preview_widget(job, ui.Text(ui.Line(s):reverse()):area(job.area):wrap(ui.Wrap.YES)) end function M:peek(job) - local path = tostring(job.file.path) - if path:sub(1, 6) ~= "/proc/" then + if not job.file.url:starts_with("/proc/") then return self.msg(job, "Empty file") end - local i, j, lines = 0, 0, {} - local file = io.open(path, "r") - if not file then - return self.msg(job, "Failed to open file") + local fd, err = fs.access():read(true):open(job.file.url) + if not fd then + return self.msg(job, "Failed to open file: " .. err) end - local limit = job.area.h - while true do - local chunk = file:read(4096) - if not chunk then - break - end + local lines, err = M.read_up_to(fd, job.skip, job.area.h) + ya.drop(fd) - j = j + #chunk - if j > 5242880 then - return self.msg(job, "File too large") - end - - for line in chunk:gmatch("[^\n]*\n?") do - i = i + 1 - if i > job.skip + limit then - break - elseif i > job.skip then - lines[#lines + 1] = line - end - end - end - - if job.skip > 0 and i < job.skip + limit then - ya.emit("peek", { math.max(0, i - limit), only_if = job.file.url, upper_bound = true }) + if not lines then + self.msg(job, tostring(err)) + elseif lines.n == 0 then + self.msg(job, "Empty file") + elseif job.skip > 0 and lines.n < job.skip + job.area.h then + ya.emit("peek", { math.max(0, lines.n - job.area.h), only_if = job.file.url, upper_bound = true }) else ya.preview_widget(job, ui.Text(lines):area(job.area)) end @@ -45,4 +28,36 @@ end function M:seek(job) require("code"):seek(job) end +--- @param fd Fd +--- @param skip integer +--- @param limit integer +--- @return { [integer]: string, n: integer }? +--- @return Error? +function M.read_up_to(fd, skip, limit) + local seen, lines = 0, { n = 0 } + while true do + local chunk, err = fd:read(4096) + if not chunk then + return nil, Err("Failed to read file: %s", err) + elseif chunk == "" then + break + end + + seen = seen + #chunk + if seen > 5242880 then + return nil, Err("File too large") + end + + for line in chunk:gmatch("[^\n]*\n?") do + lines.n = lines.n + 1 + if lines.n > skip + limit then + break + elseif lines.n > skip then + lines[#lines + 1] = line + end + end + end + return lines +end + return M diff --git a/yazi-plugin/preset/plugins/mime-remote.lua b/yazi-plugin/preset/plugins/mime-remote.lua index b6f0223c..4654940f 100644 --- a/yazi-plugin/preset/plugins/mime-remote.lua +++ b/yazi-plugin/preset/plugins/mime-remote.lua @@ -4,13 +4,13 @@ local function stale_cache(file) local url = file.url local lock = url.scheme.cache:join(string.format("%%lock/%s", url:hash(true))) - local f = io.open(tostring(lock), "r") - if not f then + local fd = fs.access():read(true):open(Url(lock)) + if not fd then return true end - local hash = f:read(32) - f:close() + local hash = fd:read(32) + ya.drop(fd) return hash ~= file.cha:hash(true) end diff --git a/yazi-proxy/src/mgr.rs b/yazi-proxy/src/mgr.rs index 2cdd1a12..9b4fdb58 100644 --- a/yazi-proxy/src/mgr.rs +++ b/yazi-proxy/src/mgr.rs @@ -35,6 +35,10 @@ impl MgrProxy { emit!(Call(relay!(mgr:open_do).with_any("opt", opt))); } + pub fn refresh() { + emit!(Call(relay!(mgr:refresh))); + } + pub fn remove_do(targets: Vec, permanently: bool) { emit!(Call( relay!(mgr:remove_do).with("permanently", permanently).with_any("targets", targets) diff --git a/yazi-watcher/src/backend.rs b/yazi-watcher/src/backend.rs index 10f6ca4e..646e12be 100644 --- a/yazi-watcher/src/backend.rs +++ b/yazi-watcher/src/backend.rs @@ -14,6 +14,7 @@ impl Backend { pub(crate) fn serve() -> Self { #[cfg(any(target_os = "linux", target_os = "macos"))] yazi_fs::mounts::Partitions::monitor(&yazi_fs::mounts::PARTITIONS, || { + yazi_proxy::MgrProxy::refresh(); yazi_macro::err!(yazi_dds::Pubsub::pub_after_mount()) });