mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +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 mlua::{IntoLuaMulti, UserData, UserDataMethods, Value};
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
|
@ -7,17 +7,27 @@ pub struct Fd(pub yazi_vfs::provider::RwFile);
|
||||||
|
|
||||||
impl UserData for Fd {
|
impl UserData for Fd {
|
||||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
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 {
|
methods.add_async_method_mut("flush", |lua, mut me, ()| async move {
|
||||||
match me.0.flush().await {
|
match me.0.flush().await {
|
||||||
Ok(()) => true.into_lua_multi(&lua),
|
Ok(()) => true.into_lua_multi(&lua),
|
||||||
Err(e) => (false, Error::Io(e)).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()
|
}):icon()
|
||||||
|
|
||||||
if f.size > 0 then
|
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
|
else
|
||||||
right[#right + 1] = " "
|
right[#right + 1] = " "
|
||||||
end
|
end
|
||||||
|
|
@ -42,7 +42,7 @@ function M:peek(job)
|
||||||
left[#left],
|
left[#left],
|
||||||
ui.truncate(f.path.name, {
|
ui.truncate(f.path.name, {
|
||||||
rtl = true,
|
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
|
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.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)
|
function M:peek(job)
|
||||||
local path = tostring(job.file.path)
|
if not job.file.url:starts_with("/proc/") then
|
||||||
if path:sub(1, 6) ~= "/proc/" then
|
|
||||||
return self.msg(job, "Empty file")
|
return self.msg(job, "Empty file")
|
||||||
end
|
end
|
||||||
|
|
||||||
local i, j, lines = 0, 0, {}
|
local fd, err = fs.access():read(true):open(job.file.url)
|
||||||
local file = io.open(path, "r")
|
if not fd then
|
||||||
if not file then
|
return self.msg(job, "Failed to open file: " .. err)
|
||||||
return self.msg(job, "Failed to open file")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local limit = job.area.h
|
local lines, err = M.read_up_to(fd, job.skip, job.area.h)
|
||||||
while true do
|
ya.drop(fd)
|
||||||
local chunk = file:read(4096)
|
|
||||||
if not chunk then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
j = j + #chunk
|
if not lines then
|
||||||
if j > 5242880 then
|
self.msg(job, tostring(err))
|
||||||
return self.msg(job, "File too large")
|
elseif lines.n == 0 then
|
||||||
end
|
self.msg(job, "Empty file")
|
||||||
|
elseif job.skip > 0 and lines.n < job.skip + job.area.h then
|
||||||
for line in chunk:gmatch("[^\n]*\n?") do
|
ya.emit("peek", { math.max(0, lines.n - job.area.h), only_if = job.file.url, upper_bound = true })
|
||||||
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 })
|
|
||||||
else
|
else
|
||||||
ya.preview_widget(job, ui.Text(lines):area(job.area))
|
ya.preview_widget(job, ui.Text(lines):area(job.area))
|
||||||
end
|
end
|
||||||
|
|
@ -45,4 +28,36 @@ end
|
||||||
|
|
||||||
function M:seek(job) require("code"):seek(job) 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
|
return M
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ local function stale_cache(file)
|
||||||
local url = file.url
|
local url = file.url
|
||||||
local lock = url.scheme.cache:join(string.format("%%lock/%s", url:hash(true)))
|
local lock = url.scheme.cache:join(string.format("%%lock/%s", url:hash(true)))
|
||||||
|
|
||||||
local f = io.open(tostring(lock), "r")
|
local fd = fs.access():read(true):open(Url(lock))
|
||||||
if not f then
|
if not fd then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local hash = f:read(32)
|
local hash = fd:read(32)
|
||||||
f:close()
|
ya.drop(fd)
|
||||||
return hash ~= file.cha:hash(true)
|
return hash ~= file.cha:hash(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@ impl MgrProxy {
|
||||||
emit!(Call(relay!(mgr:open_do).with_any("opt", opt)));
|
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) {
|
pub fn remove_do(targets: Vec<UrlBuf>, permanently: bool) {
|
||||||
emit!(Call(
|
emit!(Call(
|
||||||
relay!(mgr:remove_do).with("permanently", permanently).with_any("targets", targets)
|
relay!(mgr:remove_do).with("permanently", permanently).with_any("targets", targets)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ impl Backend {
|
||||||
pub(crate) fn serve() -> Self {
|
pub(crate) fn serve() -> Self {
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
yazi_fs::mounts::Partitions::monitor(&yazi_fs::mounts::PARTITIONS, || {
|
yazi_fs::mounts::Partitions::monitor(&yazi_fs::mounts::PARTITIONS, || {
|
||||||
|
yazi_proxy::MgrProxy::refresh();
|
||||||
yazi_macro::err!(yazi_dds::Pubsub::pub_after_mount())
|
yazi_macro::err!(yazi_dds::Pubsub::pub_after_mount())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue