Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf!: reimplement and significantly speed up archive previewing #1220

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion yazi-adapter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ futures = "0.3.30"
image = "=0.24.9"
imagesize = "0.13.0"
kamadak-exif = "0.5.5"
ratatui = "0.26.3"
ratatui = "0.27.0"
scopeguard = "1.2.0"
tokio = { version = "1.38.0", features = [ "full" ] }

Expand Down
2 changes: 1 addition & 1 deletion yazi-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ bitflags = "2.5.0"
crossterm = "0.27.0"
globset = "0.4.14"
indexmap = "2.2.6"
ratatui = "0.26.3"
ratatui = "0.27.0"
serde = { version = "1.0.203", features = [ "derive" ] }
toml = { version = "0.8.14", features = [ "preserve_order" ] }
validator = { version = "0.18.1", features = [ "derive" ] }
20 changes: 10 additions & 10 deletions yazi-config/preset/theme.toml
Original file line number Diff line number Diff line change
Expand Up @@ -764,18 +764,18 @@ exts = [
]
conds = [
# Special files
{ cond = "orphan", text = "" },
{ cond = "link" , text = "" },
{ cond = "block" , text = "" },
{ cond = "char" , text = "" },
{ cond = "fifo" , text = "" },
{ cond = "sock" , text = "" },
{ cond = "sticky", text = "" },
{ if = "orphan", text = "" },
{ if = "link" , text = "" },
{ if = "block" , text = "" },
{ if = "char" , text = "" },
{ if = "fifo" , text = "" },
{ if = "sock" , text = "" },
{ if = "sticky", text = "" },

# Fallback
{ cond = "dir", text = "" },
{ cond = "exec", text = "" },
{ cond = "!dir", text = "" },
{ if = "dir", text = "" },
{ if = "exec", text = "" },
{ if = "!dir", text = "" },
]

# : }}}
2 changes: 1 addition & 1 deletion yazi-config/preset/yazi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ suppress_preload = false

fetchers = [
# Mimetype
{ id = "mime", name = "*", cond = "!mime", run = "mime", prio = "high" },
{ id = "mime", name = "*", run = "mime", if = "!mime", prio = "high" },
]
preloaders = [
# Image
Expand Down
3 changes: 2 additions & 1 deletion yazi-config/src/plugin/fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ pub struct Fetcher {
pub idx: u8,

pub id: String,
pub cond: Option<Condition>,
#[serde(rename = "if")]
pub if_: Option<Condition>,
pub name: Option<Pattern>,
pub mime: Option<Pattern>,
pub run: Cmd,
Expand Down
2 changes: 1 addition & 1 deletion yazi-config/src/plugin/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl Plugin {
.fetchers
.iter()
.filter(|&p| {
p.cond.as_ref().and_then(|c| c.eval(f)) != Some(false)
p.if_.as_ref().and_then(|c| c.eval(f)) != Some(false)
&& (p.mime.as_ref().zip(mime).map_or(false, |(p, m)| p.match_mime(m))
|| p.name.as_ref().is_some_and(|p| p.match_path(path, is_dir)))
})
Expand Down
16 changes: 11 additions & 5 deletions yazi-config/src/theme/icons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ pub struct Icons {

impl Icons {
pub fn matches(&self, file: &File) -> Option<&Icon> {
if let Some((_, i)) = self.globs.iter().find(|(p, _)| p.match_path(&file.url, file.is_dir())) {
if let Some(i) = self.match_by_glob(file) {
return Some(i);
}

if let Some(i) = self.match_name(file) {
if let Some(i) = self.match_by_name(file) {
return Some(i);
}

Expand All @@ -41,7 +41,12 @@ impl Icons {
}

#[inline]
fn match_name(&self, file: &File) -> Option<&Icon> {
fn match_by_glob(&self, file: &File) -> Option<&Icon> {
self.globs.iter().find(|(p, _)| p.match_path(&file.url, file.is_dir())).map(|(_, i)| i)
}

#[inline]
fn match_by_name(&self, file: &File) -> Option<&Icon> {
let name = file.name()?.to_str()?;
if file.is_dir() {
self.dirs.get(name).or_else(|| self.dirs.get(&name.to_ascii_lowercase()))
Expand Down Expand Up @@ -110,7 +115,8 @@ impl<'de> Deserialize<'de> for Icons {
}
#[derive(Deserialize)]
pub struct ShadowCond {
cond: Condition,
#[serde(rename = "if")]
if_: Condition,
text: String,
fg_dark: Option<Color>,
#[allow(dead_code)]
Expand All @@ -136,7 +142,7 @@ impl<'de> Deserialize<'de> for Icons {
.conds
.into_iter()
.map(|v| {
(v.cond, Icon { text: v.text, style: Style { fg: v.fg_dark, ..Default::default() } })
(v.if_, Icon { text: v.text, style: Style { fg: v.fg_dark, ..Default::default() } })
})
.collect();

Expand Down
2 changes: 1 addition & 1 deletion yazi-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dirs = "5.0.1"
futures = "0.3.30"
notify = { version = "6.1.1", default-features = false, features = [ "macos_fsevent" ] }
parking_lot = "0.12.3"
ratatui = "0.26.3"
ratatui = "0.27.0"
regex = "1.10.5"
scopeguard = "1.2.0"
serde = "1.0.203"
Expand Down
2 changes: 1 addition & 1 deletion yazi-core/src/manager/commands/open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl Manager {

done.extend(files.iter().map(|f| (f.url(), String::new())));
if let Err(e) = isolate::fetch("mime", files).await {
error!("fetch `mime` failed in opening: {e}");
error!("Fetch `mime` failed in opening: {e}");
}

ManagerProxy::open_do(OpenDoOpt { hovered, targets: done, interactive: opt.interactive });
Expand Down
2 changes: 1 addition & 1 deletion yazi-core/src/manager/watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl Watcher {
continue;
}
if let Err(e) = isolate::fetch("mime", reload).await {
error!("fetch `mime` failed in watcher: {e}");
error!("Fetch `mime` failed in watcher: {e}");
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion yazi-fm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ crossterm = { version = "0.27.0", features = [ "event-stream" ] }
fdlimit = "0.3.0"
futures = "0.3.30"
mlua = { version = "0.9.9", features = [ "lua54" ] }
ratatui = "0.26.3"
ratatui = "0.27.0"
scopeguard = "1.2.0"
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
tokio = { version = "1.38.0", features = [ "full" ] }
Expand Down
30 changes: 7 additions & 23 deletions yazi-fm/src/lives/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::ops::Deref;

use mlua::{AnyUserData, IntoLua, Lua, UserDataFields, UserDataMethods};
use yazi_config::THEME;
use yazi_plugin::{bindings::{Cast, Cha, Icon, Range}, elements::Style, url::Url};
use yazi_plugin::{bindings::Range, elements::Style};
use yazi_shared::MIME_DIR;

use super::{CtxRef, SCOPE};
Expand All @@ -19,6 +19,10 @@ impl Deref for File {
fn deref(&self) -> &Self::Target { &self.folder().files[self.idx] }
}

impl AsRef<yazi_shared::fs::File> for File {
fn as_ref(&self) -> &yazi_shared::fs::File { self }
}

impl File {
#[inline]
pub(super) fn make(
Expand All @@ -31,16 +35,9 @@ impl File {

pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
reg.add_field_method_get("url", |lua, me| Url::cast(lua, me.url.clone()));
reg.add_field_method_get("cha", |lua, me| Cha::cast(lua, me.cha));
reg.add_field_method_get("link_to", |lua, me| {
me.link_to.as_ref().cloned().map(|u| Url::cast(lua, u)).transpose()
});
yazi_plugin::file::File::register_with(reg);

reg.add_field_method_get("name", |lua, me| {
me.url.file_name().map(|n| lua.create_string(n.as_encoded_bytes())).transpose()
});
reg.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
reg.add_method("size", |_, me, ()| {
Ok(if me.is_dir() { me.folder().files.sizes.get(&me.url).copied() } else { Some(me.len) })
});
Expand All @@ -57,19 +54,6 @@ impl File {
p.next_back();
Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose()
});
reg.add_method("icon", |lua, me, ()| {
use yazi_shared::theme::IconCache;

match me.icon.get() {
IconCache::Missing => {
let matched = THEME.icons.matches(me);
me.icon.set(matched.map_or(IconCache::Undefined, IconCache::Icon));
matched.map(|i| Icon::cast(lua, i)).transpose()
}
IconCache::Undefined => Ok(None),
IconCache::Icon(cached) => Some(Icon::cast(lua, cached)).transpose(),
}
});
reg.add_method("style", |lua, me, ()| {
let cx = lua.named_registry_value::<CtxRef>("cx")?;
let mime =
Expand Down
4 changes: 1 addition & 3 deletions yazi-plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ futures = "0.3.30"
md-5 = "0.10.6"
mlua = { version = "0.9.9", features = [ "lua54", "serialize", "macros", "async" ] }
parking_lot = "0.12.3"
ratatui = "0.26.3"
serde = "1.0.203"
serde_json = "1.0.117"
ratatui = "0.27.0"
shell-escape = "0.1.5"
shell-words = "1.1.0"
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
Expand Down
69 changes: 66 additions & 3 deletions yazi-plugin/preset/plugins/archive.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,64 @@
local M = {}

function M:peek()
local _, bound = ya.preview_archive(self)
if bound then
ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
local child
if ya.target_os() == "macos" then
child = self:try_spawn("7zz") or self:try_spawn("7z")
else
child = self:try_spawn("7z") or self:try_spawn("7zz")
end

if not child then
return ya.err("spawn `7z` and `7zz` both commands failed, error code: " .. tostring(self.last_error))
end

local limit = self.area.h
local i, icon, names, sizes = 0, nil, {}, {}
repeat
local next, event = child:read_line()
if event ~= 0 then
break
end

local attr, size, name = next:match("^[-%d]+%s+[:%d]+%s+([.%a]+)%s+(%d+)%s+%d+%s+(.+)[\r\n]+")
if not name then
goto continue
end

i = i + 1
if i <= self.skip then
goto continue
end

icon = File({
url = Url(name),
cha = Cha { kind = attr:sub(1, 1) == "D" and 1 or 0 },
}):icon()

if icon then
names[#names + 1] = ui.Line { ui.Span(" " .. icon.text .. " "):style(icon.style), ui.Span(name) }
else
names[#names + 1] = ui.Line(name)
end

size = tonumber(size)
if size > 0 then
sizes[#sizes + 1] = ui.Line(string.format(" %s ", ya.readable_size(size)))
else
sizes[#sizes + 1] = ui.Line(" - ")
end

::continue::
until i >= self.skip + limit

child:start_kill()
if self.skip > 0 and i < self.skip + limit then
ya.manager_emit("peek", { math.max(0, i - limit), only_if = self.file.url, upper_bound = true })
else
ya.preview_widgets(self, {
ui.Paragraph(self.area, names),
ui.Paragraph(self.area, sizes):align(ui.Paragraph.RIGHT),
})
end
end

Expand All @@ -18,4 +73,12 @@ function M:seek(units)
end
end

function M:try_spawn(name)
local child, code = Command(name):args({ "l", "-ba", tostring(self.file.url) }):stdout(Command.PIPED):spawn()
if not child then
self.last_error = code
end
return child
end

return M
Loading