Skip to content

Commit

Permalink
..
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi committed Jul 23, 2024
1 parent 6f98a91 commit 2fbcf22
Show file tree
Hide file tree
Showing 20 changed files with 279 additions and 135 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

8 changes: 4 additions & 4 deletions yazi-dds/src/sendable.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;

use mlua::{ExternalError, Lua, Table, Value, Variadic};
use mlua::{ExternalError, Lua, MultiValue, Table, Value};
use yazi_shared::{event::{Data, DataKey}, OrderedFloat};

pub struct Sendable;
Expand Down Expand Up @@ -82,15 +82,15 @@ impl Sendable {
lua.create_sequence_from(vec)
}

pub fn list_to_variadic(lua: &Lua, data: Vec<Data>) -> mlua::Result<Variadic<Value>> {
pub fn list_to_values(lua: &Lua, data: Vec<Data>) -> mlua::Result<MultiValue> {
let mut vec = Vec::with_capacity(data.len());
for v in data {
vec.push(Self::data_to_value(lua, v)?);
}
Ok(Variadic::from_iter(vec))
Ok(MultiValue::from_iter(vec))
}

pub fn variadic_to_vec(values: Variadic<Value>) -> mlua::Result<Vec<Data>> {
pub fn values_to_vec(values: MultiValue) -> mlua::Result<Vec<Data>> {
let mut vec = Vec::with_capacity(values.len());
for value in values {
vec.push(Self::value_to_data(value)?);
Expand Down
6 changes: 3 additions & 3 deletions yazi-fm/src/app/commands/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ impl App {
};

match LUA.named_registry_value::<RtRef>("rt") {
Ok(mut r) => r.swap(&opt.id),
Ok(mut r) => r.push(&opt.id),
Err(e) => return warn!("{e}"),
}
defer! { _ = LUA.named_registry_value::<RtRef>("rt").map(|mut r| r.pop()) }

defer! { LUA.named_registry_value::<RtRef>("rt").map(|mut r| r.reset()).ok(); };
let plugin = match LOADER.load(&opt.id) {
let plugin = match LOADER.load(&LUA, &opt.id) {
Ok(plugin) => plugin,
Err(e) => return warn!("{e}"),
};
Expand Down
2 changes: 1 addition & 1 deletion yazi-fm/src/lives/lives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl Lives {
f: impl FnOnce(&Scope<'a, 'a>) -> mlua::Result<T>,
) -> mlua::Result<T> {
let result = LUA.scope(|scope| {
defer! { SCOPE.drop(); };
defer! { SCOPE.drop(); }
SCOPE.init(unsafe {
mem::transmute::<&mlua::Scope<'a, 'a>, &mlua::Scope<'static, 'static>>(scope)
});
Expand Down
1 change: 1 addition & 0 deletions yazi-plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ md-5 = "0.10.6"
mlua = { version = "0.9.9", features = [ "lua54", "serialize", "macros", "async" ] }
parking_lot = "0.12.3"
ratatui = "0.27.0"
scopeguard = "1.2.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
41 changes: 27 additions & 14 deletions yazi-plugin/preset/plugins/archive.lua
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
local M = {}
local M = {
PAT_MATCH = "^[-%d]+%s+[:%d]+%s+([.%a]+)%s+(%d+)%s+%d+%s+(.+)[\r\n]+",
}

function M:peek()
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

local child = self:spawn_7z { "l", "-ba", tostring(self.file.url) }
if not child then
return ya.err("spawn `7z` and `7zz` both commands failed, error code: " .. tostring(self.last_error))
return
end

local limit = self.area.h
Expand All @@ -20,7 +16,7 @@ function M:peek()
break
end

local attr, size, name = next:match("^[-%d]+%s+[:%d]+%s+([.%a]+)%s+(%d+)%s+%d+%s+(.+)[\r\n]+")
local attr, size, name = next:match(self.PAT_MATCH)
if not name then
goto continue
end
Expand Down Expand Up @@ -73,12 +69,29 @@ 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()
function M:spawn_7z(args)
local last_error = nil
local try = function(name)
local stdout = args[1] == "l" and Command.PIPED or Command.NULL
local stderr = args[1] == "x" and Command.PIPED or Command.NULL
local child, code = Command(name):args(args):stdout(stdout):stderr(stderr):spawn()
if not child then
last_error = code
end
return child
end

local child
if ya.target_os() == "macos" then
child = try("7zz") or try("7z")
else
child = try("7z") or try("7zz")
end

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

return M
120 changes: 120 additions & 0 deletions yazi-plugin/preset/plugins/extract.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
local WRONG_PWD = "Cannot open encrypted archive. Wrong password?"

local M = {}

function M:setup()
ps.sub_remote("extract", function(args)
for _, arg in ipairs(args) do
ya.manager_emit("plugin", { self._id, args = ya.quote(arg, true) })
end
end)
end

function M.entry(_, args)
if not args[1] then
error("No URL provided")
end

local url, pwd = Url(args[1]), ""
while true do
if not M.try_with(url, pwd) then
break
end

local value, event = ya.input {
title = string.format('Password for "%s":', url:name()),
position = { "center", w = 50 },
}
if event == 1 then
pwd = value
else
break
end
end
end

function M.try_with(url, pwd)
local actual, assumed = M.output_url(url)
if not actual then
error("Cannot determine the output directory " .. url)
end

local child, code = require("archive"):spawn_7z { "x", "-aou", "-p" .. pwd, "-o" .. tostring(actual), tostring(url) }
if not child then
error("Spawn `7z` and `7zz` both commands failed, error code: " .. code)
end

local output, err = child:wait_with_output()
if not output then
error("7zip failed to output, error code " .. tostring(err))
elseif output.status.code == 2 and output.stderr:find(WRONG_PWD, 1, true) then
return true -- Needs retry
elseif output.status.code ~= 0 then
error("7zip exited with error code " .. tostring(output.status.code))
end

if assumed then -- Needs a move
local unique = fs.unique_name(assumed)
if unique then
os.rename(tostring(actual:join(assumed:name())), tostring(unique))
os.remove(tostring(actual))
end
end
end

function M.output_url(url)
local parent = url:parent()
if not parent then
return
end

local archive = require("archive")
local child = archive:spawn_7z { "l", "-ba", "-x!*/*", tostring(url) }
if not child then
return
end

local lines = {}
repeat
local next, event = child:read_line()
if event == 0 or event == 1 then
lines[#lines + 1] = next
else
break
end
until #lines >= 2
child:start_kill()

if #lines ~= 1 then
local name = M.trim_ext(url:name())
return fs.unique_name(parent:join(name))
end

local attr, _, name = lines[1]:match(archive.PAT_MATCH)
if name and attr:sub(1, 1) == "D" then
local assumed = parent:join(name)
if fs.cha(assumed) then
local tmp = string.format(".extract_%s", ya.time())
return fs.unique_name(parent:join(tmp)), assumed
end
end

return parent
end

function M.trim_ext(name)
-- stylua: ignore
local exts = { ["7z"] = true, apk = true, bz2 = true, bzip2 = true, exe = true, gz = true, gzip = true, iso = true, jar = true, rar = true, tar = true, tgz = true, xz = true, zip = true, zst = true }

while true do
local s = name:gsub("%.([a-zA-Z0-9]+)$", function(s) return (exts[s] or exts[s:lower()]) and "" end)
if s == name or s == "" then
break
else
name = s
end
end
return name
end

return M
4 changes: 2 additions & 2 deletions yazi-plugin/preset/plugins/mime.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ local M = {}

local function match_mimetype(s)
local type, sub = s:match("([-a-z]+/)([+-.a-zA-Z0-9]+)%s*$")
if type and sub and string.find(SUPPORTED_TYPES, type, 1, true) then
if type and sub and SUPPORTED_TYPES:find(type, 1, true) then
return type .. sub
end
end
Expand Down Expand Up @@ -44,7 +44,7 @@ function M:fetch()
end

valid = match_mimetype(line)
if valid and string.find(line, valid, 1, true) ~= 1 then
if valid and line:find(valid, 1, true) ~= 1 then
goto continue
elseif valid then
j, updates[urls[i]] = j + 1, valid
Expand Down
4 changes: 1 addition & 3 deletions yazi-plugin/preset/plugins/zoxide.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ end)

local set_state = ya.sync(function(st, empty) st.empty = empty end)

local function fail(s, ...)
ya.notify { title = "Zoxide", content = string.format(s, ...), timeout = 5, level = "error" }
end
local function fail(s, ...) ya.notify { title = "Zoxide", content = s:format(...), timeout = 5, level = "error" } end

local function head(cwd)
local child = Command("zoxide"):args({ "query", "-l" }):stdout(Command.PIPED):spawn()
Expand Down
2 changes: 1 addition & 1 deletion yazi-plugin/preset/setup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ os.setlocale("")
package.path = BOOT.plugin_dir .. "/?.yazi/init.lua;" .. package.path

require("dds"):setup()
require("archive"):setup()
require("extract"):setup()
6 changes: 3 additions & 3 deletions yazi-plugin/preset/ya.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function ya.list_merge(a, b)
return a
end

function ya.basename(str) return string.gsub(str, "(.*[/\\])(.*)", "%2") end
function ya.basename(s) return s:gsub("(.*[/\\])(.*)", "%2") end

function ya.readable_size(size)
local units = { "B", "K", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q" }
Expand All @@ -37,8 +37,8 @@ function ya.readable_path(path)
local home = os.getenv("HOME") or os.getenv("USERPROFILE")
if not home then
return path
elseif string.sub(path, 1, #home) == home then
return "~" .. string.sub(path, #home + 1)
elseif path:sub(1, #home) == home then
return "~" .. path:sub(#home + 1)
else
return path
end
Expand Down
1 change: 1 addition & 0 deletions yazi-plugin/src/isolate/isolate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
crate::file::pour(&lua)?;
crate::url::pour(&lua)?;

crate::loader::install(&lua)?;
crate::fs::install(&lua)?;
crate::process::install(&lua)?;
crate::utils::install_isolate(&lua)?;
Expand Down
22 changes: 10 additions & 12 deletions yazi-plugin/src/loader/loader.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use std::{borrow::Cow, collections::HashMap, ops::Deref};

use anyhow::Result;
use mlua::{ExternalError, Table};
use mlua::{ExternalError, Lua, Table};
use parking_lot::RwLock;
use tokio::fs;
use yazi_boot::BOOT;
use yazi_shared::RoCell;

use crate::LUA;

pub static LOADER: RoCell<Loader> = RoCell::new();

#[derive(Default)]
Expand All @@ -23,11 +21,10 @@ impl Loader {
}

let preset = match name {
"dds" => &include_bytes!("../../preset/plugins/dds.lua")[..],
"noop" => include_bytes!("../../preset/plugins/noop.lua"),
"session" => include_bytes!("../../preset/plugins/session.lua"),
"archive" => include_bytes!("../../preset/plugins/archive.lua"),
"archive" => &include_bytes!("../../preset/plugins/archive.lua")[..],
"code" => include_bytes!("../../preset/plugins/code.lua"),
"dds" => include_bytes!("../../preset/plugins/dds.lua"),
"extract" => include_bytes!("../../preset/plugins/extract.lua"),
"file" => include_bytes!("../../preset/plugins/file.lua"),
"folder" => include_bytes!("../../preset/plugins/folder.lua"),
"font" => include_bytes!("../../preset/plugins/font.lua"),
Expand All @@ -36,7 +33,9 @@ impl Loader {
"json" => include_bytes!("../../preset/plugins/json.lua"),
"magick" => include_bytes!("../../preset/plugins/magick.lua"),
"mime" => include_bytes!("../../preset/plugins/mime.lua"),
"noop" => include_bytes!("../../preset/plugins/noop.lua"),
"pdf" => include_bytes!("../../preset/plugins/pdf.lua"),
"session" => include_bytes!("../../preset/plugins/session.lua"),
"video" => include_bytes!("../../preset/plugins/video.lua"),
"zoxide" => include_bytes!("../../preset/plugins/zoxide.lua"),
_ => b"",
Expand All @@ -52,19 +51,18 @@ impl Loader {
Ok(())
}

pub fn load(&self, id: &str) -> mlua::Result<Table> {
let globals = LUA.globals();
let loaded: Table = globals.raw_get::<_, Table>("package")?.raw_get("loaded")?;
pub fn load<'a>(&self, lua: &'a Lua, id: &str) -> mlua::Result<Table<'a>> {
let loaded: Table = lua.globals().raw_get::<_, Table>("package")?.raw_get("loaded")?;
if let Ok(t) = loaded.raw_get::<_, Table>(id) {
return Ok(t);
}

let t: Table = match self.read().get(id) {
Some(b) => LUA.load(b.as_ref()).set_name(id).call(())?,
Some(b) => lua.load(b.as_ref()).set_name(id).call(())?,
None => Err(format!("plugin `{id}` not found").into_lua_err())?,
};

t.raw_set("_id", LUA.create_string(id)?)?;
t.raw_set("_id", lua.create_string(id)?)?;
loaded.raw_set(id, t.clone())?;
Ok(t)
}
Expand Down
2 changes: 1 addition & 1 deletion yazi-plugin/src/loader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use require::*;

pub(super) fn init() { LOADER.with(<_>::default); }

pub(super) fn install(lua: &'static mlua::Lua) -> mlua::Result<()> {
pub(super) fn install(lua: &mlua::Lua) -> mlua::Result<()> {
Require::install(lua)?;

Ok(())
Expand Down
Loading

0 comments on commit 2fbcf22

Please sign in to comment.