mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 14:51:03 +00:00
refactor: async fs.access() instead of sync io.open() (#3670)
This commit is contained in:
parent
1a121bbfb0
commit
30ec603441
6 changed files with 73 additions and 43 deletions
|
|
@ -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),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue