refactor: async fs.access() instead of sync io.open() (#3670)

This commit is contained in:
三咲雅 misaki masa 2026-02-10 11:29:46 +08:00 committed by GitHub
parent 1a121bbfb0
commit 30ec603441
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 73 additions and 43 deletions

View file

@ -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<M: UserDataMethods<Self>>(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),
}
});
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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<UrlBuf>, permanently: bool) {
emit!(Call(
relay!(mgr:remove_do).with("permanently", permanently).with_any("targets", targets)

View file

@ -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())
});