mirror of
https://github.com/sxyazi/yazi.git
synced 2026-05-13 08:16:40 +00:00
feat: make mimetype matching more robust (#3082)
This commit is contained in:
parent
fe9ce240b5
commit
ae75fc0f7b
11 changed files with 95 additions and 97 deletions
5
.luarc.json
Normal file
5
.luarc.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
||||||
|
"runtime.version": "Lua 5.4",
|
||||||
|
"workspace.library": ["~/.config/yazi/plugins/types.yazi/"]
|
||||||
|
}
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
# this file caused some issues with the build system
|
|
||||||
yazi-plugin/preset/plugins/mime.lua
|
|
||||||
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -2327,9 +2327,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.142"
|
version = "1.0.143"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
|
checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ ratatui = { version = "0.29.0", features = [ "unstable-rendered-line
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
scopeguard = "1.2.0"
|
scopeguard = "1.2.0"
|
||||||
serde = { version = "1.0.219", features = [ "derive" ] }
|
serde = { version = "1.0.219", features = [ "derive" ] }
|
||||||
serde_json = "1.0.142"
|
serde_json = "1.0.143"
|
||||||
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||||
tokio = { version = "1.47.1", features = [ "full" ] }
|
tokio = { version = "1.47.1", features = [ "full" ] }
|
||||||
tokio-stream = "0.1.17"
|
tokio-stream = "0.1.17"
|
||||||
|
|
|
||||||
|
|
@ -103,12 +103,14 @@ module.exports = async ({ github, context, core }) => {
|
||||||
issue_number: id,
|
issue_number: id,
|
||||||
name : LABEL_NAME,
|
name : LABEL_NAME,
|
||||||
})
|
})
|
||||||
|
await hideOldComments(id)
|
||||||
} else if (mark && !marked && !await removedLabelManually(id)) {
|
} else if (mark && !marked && !await removedLabelManually(id)) {
|
||||||
await github.rest.issues.addLabels({
|
await github.rest.issues.addLabels({
|
||||||
...context.repo,
|
...context.repo,
|
||||||
issue_number: id,
|
issue_number: id,
|
||||||
labels : [LABEL_NAME],
|
labels : [LABEL_NAME],
|
||||||
})
|
})
|
||||||
|
await hideOldComments(id)
|
||||||
await github.rest.issues.createComment({
|
await github.rest.issues.createComment({
|
||||||
...context.repo,
|
...context.repo,
|
||||||
issue_number: id,
|
issue_number: id,
|
||||||
|
|
@ -120,6 +122,37 @@ module.exports = async ({ github, context, core }) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function hideOldComments(id) {
|
||||||
|
try {
|
||||||
|
const comments = await github.paginate(github.rest.issues.listComments, {
|
||||||
|
...context.repo,
|
||||||
|
issue_number: id,
|
||||||
|
per_page : 100,
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const c of comments) {
|
||||||
|
const byBot = c.user?.login?.endsWith("[bot]") || c.user?.type === "Bot"
|
||||||
|
const contains = c?.body?.includes("or closed after 2 days of inactivity")
|
||||||
|
if (!byBot || !contains || !c.node_id) continue
|
||||||
|
|
||||||
|
try {
|
||||||
|
await github.graphql(
|
||||||
|
`mutation($subjectId: ID!, $classifier: ReportedContentClassifiers!) {
|
||||||
|
minimizeComment(input: {subjectId: $subjectId, classifier: $classifier}) {
|
||||||
|
minimizedComment { isMinimized }
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
{ subjectId: c.node_id, classifier: "OUTDATED" },
|
||||||
|
)
|
||||||
|
} catch (e) {
|
||||||
|
core.error(`Error minimizing comment ${c.id}: ${e.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
core.error(`Error listing comments: ${e.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function closeOldIssues() {
|
async function closeOldIssues() {
|
||||||
try {
|
try {
|
||||||
const { data: issues } = await github.rest.issues.listForRepo({
|
const { data: issues } = await github.rest.issues.listForRepo({
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
syntax = "Lua54"
|
||||||
indent_width = 2
|
indent_width = 2
|
||||||
call_parentheses = "NoSingleTable"
|
call_parentheses = "NoSingleTable"
|
||||||
collapse_simple_statement = "FunctionOnly"
|
collapse_simple_statement = "FunctionOnly"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use yazi_fs::{File, FilesOp};
|
use yazi_fs::{File, FilesOp};
|
||||||
use yazi_macro::{act, succ};
|
use yazi_macro::{act, render, succ};
|
||||||
use yazi_parser::mgr::RevealOpt;
|
use yazi_parser::mgr::RevealOpt;
|
||||||
use yazi_shared::event::Data;
|
use yazi_shared::event::Data;
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ impl Actor for Reveal {
|
||||||
|
|
||||||
// Try to hover on the child file
|
// Try to hover on the child file
|
||||||
let tab = cx.tab_mut();
|
let tab = cx.tab_mut();
|
||||||
tab.current.hover(child.as_urn());
|
render!(tab.current.hover(child.as_urn()));
|
||||||
|
|
||||||
// If the child is not hovered, which means it doesn't exist,
|
// If the child is not hovered, which means it doesn't exist,
|
||||||
// create a dummy file
|
// create a dummy file
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,6 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{Attribute, Data, DeriveInput, Fields, FnArg, ItemFn, ext::IdentExt, parse_macro_input};
|
use syn::{Attribute, Data, DeriveInput, Fields, parse_macro_input};
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn command(_: TokenStream, item: TokenStream) -> TokenStream {
|
|
||||||
let mut f: ItemFn = syn::parse(item).unwrap();
|
|
||||||
let mut ins = f.sig.inputs.clone();
|
|
||||||
|
|
||||||
// Turn `opt: Opt` into `opt: impl Into<Opt>`
|
|
||||||
ins[1] = {
|
|
||||||
let FnArg::Typed(opt) = &f.sig.inputs[1] else {
|
|
||||||
panic!("Cannot find the `opt` argument in the function signature.");
|
|
||||||
};
|
|
||||||
|
|
||||||
let opt_ty = &opt.ty;
|
|
||||||
syn::parse2(quote! { opt: impl Into<#opt_ty> }).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make the original function private and add a public wrapper
|
|
||||||
assert!(matches!(f.vis, syn::Visibility::Public(_)));
|
|
||||||
f.vis = syn::Visibility::Inherited;
|
|
||||||
|
|
||||||
// Add `__` prefix to the original function name
|
|
||||||
let name_ori = f.sig.ident;
|
|
||||||
f.sig.ident = format_ident!("__{}", name_ori.unraw());
|
|
||||||
let name_new = &f.sig.ident;
|
|
||||||
|
|
||||||
// Collect the rest of the arguments
|
|
||||||
let rest_args = ins.iter().skip(2).map(|arg| match arg {
|
|
||||||
FnArg::Receiver(_) => unreachable!(),
|
|
||||||
FnArg::Typed(t) => &t.pat,
|
|
||||||
});
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#[inline]
|
|
||||||
pub fn #name_ori(#ins) { self.#name_new(opt.into(), #(#rest_args),*); }
|
|
||||||
#f
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[proc_macro_derive(DeserializeOver1)]
|
#[proc_macro_derive(DeserializeOver1)]
|
||||||
pub fn deserialize_over1(input: TokenStream) -> TokenStream {
|
pub fn deserialize_over1(input: TokenStream) -> TokenStream {
|
||||||
|
|
|
||||||
|
|
@ -109,19 +109,19 @@ keymap = [
|
||||||
{ on = "N", run = "find_arrow --previous", desc = "Previous found" },
|
{ on = "N", run = "find_arrow --previous", desc = "Previous found" },
|
||||||
|
|
||||||
# Sorting
|
# Sorting
|
||||||
{ on = [ ",", "m" ], run = [ "sort mtime --reverse=no", "linemode mtime" ], desc = "Sort by modified time" },
|
{ on = [ ",", "m" ], run = [ "sort mtime --reverse=no", "linemode mtime" ], desc = "Sort by modified time" },
|
||||||
{ on = [ ",", "M" ], run = [ "sort mtime --reverse", "linemode mtime" ], desc = "Sort by modified time (reverse)" },
|
{ on = [ ",", "M" ], run = [ "sort mtime --reverse=yes", "linemode mtime" ], desc = "Sort by modified time (reverse)" },
|
||||||
{ on = [ ",", "b" ], run = [ "sort btime --reverse=no", "linemode btime" ], desc = "Sort by birth time" },
|
{ on = [ ",", "b" ], run = [ "sort btime --reverse=no", "linemode btime" ], desc = "Sort by birth time" },
|
||||||
{ on = [ ",", "B" ], run = [ "sort btime --reverse", "linemode btime" ], desc = "Sort by birth time (reverse)" },
|
{ on = [ ",", "B" ], run = [ "sort btime --reverse=yes", "linemode btime" ], desc = "Sort by birth time (reverse)" },
|
||||||
{ on = [ ",", "e" ], run = "sort extension --reverse=no", desc = "Sort by extension" },
|
{ on = [ ",", "e" ], run = "sort extension --reverse=no", desc = "Sort by extension" },
|
||||||
{ on = [ ",", "E" ], run = "sort extension --reverse", desc = "Sort by extension (reverse)" },
|
{ on = [ ",", "E" ], run = "sort extension --reverse=yes", desc = "Sort by extension (reverse)" },
|
||||||
{ on = [ ",", "a" ], run = "sort alphabetical --reverse=no", desc = "Sort alphabetically" },
|
{ on = [ ",", "a" ], run = "sort alphabetical --reverse=no", desc = "Sort alphabetically" },
|
||||||
{ on = [ ",", "A" ], run = "sort alphabetical --reverse", desc = "Sort alphabetically (reverse)" },
|
{ on = [ ",", "A" ], run = "sort alphabetical --reverse=yes", desc = "Sort alphabetically (reverse)" },
|
||||||
{ on = [ ",", "n" ], run = "sort natural --reverse=no", desc = "Sort naturally" },
|
{ on = [ ",", "n" ], run = "sort natural --reverse=no", desc = "Sort naturally" },
|
||||||
{ on = [ ",", "N" ], run = "sort natural --reverse", desc = "Sort naturally (reverse)" },
|
{ on = [ ",", "N" ], run = "sort natural --reverse=yes", desc = "Sort naturally (reverse)" },
|
||||||
{ on = [ ",", "s" ], run = [ "sort size --reverse=no", "linemode size" ], desc = "Sort by size" },
|
{ on = [ ",", "s" ], run = [ "sort size --reverse=no", "linemode size" ], desc = "Sort by size" },
|
||||||
{ on = [ ",", "S" ], run = [ "sort size --reverse", "linemode size" ], desc = "Sort by size (reverse)" },
|
{ on = [ ",", "S" ], run = [ "sort size --reverse=yes", "linemode size" ], desc = "Sort by size (reverse)" },
|
||||||
{ on = [ ",", "r" ], run = "sort random --reverse=no", desc = "Sort randomly" },
|
{ on = [ ",", "r" ], run = "sort random --reverse=no", desc = "Sort randomly" },
|
||||||
|
|
||||||
# Goto
|
# Goto
|
||||||
{ on = [ "g", "h" ], run = "cd ~", desc = "Go home" },
|
{ on = [ "g", "h" ], run = "cd ~", desc = "Go home" },
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ local M = {}
|
||||||
|
|
||||||
function M:peek(job)
|
function M:peek(job)
|
||||||
local limit = job.area.h
|
local limit = job.area.h
|
||||||
|
local files, bound, err = self.list_files({ "-p", tostring(job.file.url) }, job.skip, limit)
|
||||||
|
|
||||||
local files, bound, code = self.list_files({ "-p", tostring(job.file.url) }, job.skip, limit)
|
if err then
|
||||||
if code ~= 0 then
|
return ya.preview_widget(job, err)
|
||||||
return require("empty").msg(
|
elseif job.skip > 0 and bound < job.skip + limit then
|
||||||
job,
|
return ya.emit("peek", { math.max(0, bound - limit), only_if = job.file.url, upper_bound = true })
|
||||||
code == 2 and "File list in this archive is encrypted"
|
elseif #files == 0 then
|
||||||
or "Failed to start either `7zz` or `7z`. Do you have 7-zip installed?"
|
files = { { path = job.file.url.stem, size = 0, attr = "" } }
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local left, right = {}, {}
|
local left, right = {}, {}
|
||||||
|
|
@ -40,14 +40,10 @@ function M:peek(job)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
if job.skip > 0 and bound < job.skip + limit then
|
ya.preview_widget(job, {
|
||||||
ya.emit("peek", { math.max(0, bound - limit), only_if = job.file.url, upper_bound = true })
|
ui.Text(left):area(job.area),
|
||||||
else
|
ui.Text(right):area(job.area):align(ui.Align.RIGHT),
|
||||||
ya.preview_widget(job, {
|
})
|
||||||
ui.Text(left):area(job.area),
|
|
||||||
ui.Text(right):area(job.area):align(ui.Align.RIGHT),
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function M:seek(job) require("code"):seek(job) end
|
function M:seek(job) require("code"):seek(job) end
|
||||||
|
|
@ -76,26 +72,22 @@ end
|
||||||
---@param limit integer
|
---@param limit integer
|
||||||
---@return table files
|
---@return table files
|
||||||
---@return integer bound
|
---@return integer bound
|
||||||
---@return integer code
|
---@return Error? err
|
||||||
--- 0: success
|
|
||||||
--- 1: failed to spawn
|
|
||||||
--- 2: wrong password
|
|
||||||
--- 3: partial success
|
|
||||||
function M.list_files(args, skip, limit)
|
function M.list_files(args, skip, limit)
|
||||||
local child = M.spawn_7z { "l", "-ba", "-slt", "-sccUTF-8", table.unpack(args) }
|
local child = M.spawn_7z { "l", "-ba", "-slt", "-sccUTF-8", table.unpack(args) }
|
||||||
if not child then
|
if not child then
|
||||||
return {}, 0, 1
|
return {}, 0, Err("Failed to start either `7zz` or `7z`. Do you have 7-zip installed?")
|
||||||
end
|
end
|
||||||
|
|
||||||
local i, files, code = 0, { { path = "", size = 0, attr = "" } }, 0
|
local i, files, err = 0, { { path = "", size = 0, attr = "" } }, nil
|
||||||
local key, value = "", ""
|
local key, value, stderr = "", "", {}
|
||||||
repeat
|
repeat
|
||||||
local next, event = child:read_line()
|
local next, event = child:read_line()
|
||||||
if event == 1 and M.is_encrypted(next) then
|
if event == 1 and M.is_encrypted(next) then
|
||||||
code = 2
|
err = Err("File list in this archive is encrypted")
|
||||||
break
|
break
|
||||||
elseif event == 1 then
|
elseif event == 1 then
|
||||||
code = 3
|
stderr[#stderr + 1] = next
|
||||||
goto continue
|
goto continue
|
||||||
elseif event ~= 0 then
|
elseif event ~= 0 then
|
||||||
break
|
break
|
||||||
|
|
@ -127,7 +119,10 @@ function M.list_files(args, skip, limit)
|
||||||
if files[#files].path == "" then
|
if files[#files].path == "" then
|
||||||
files[#files] = nil
|
files[#files] = nil
|
||||||
end
|
end
|
||||||
return files, i, code
|
if #stderr ~= 0 then
|
||||||
|
err = Err("7-zip errored out while listing files, stderr: %s", table.concat(stderr, "\n"))
|
||||||
|
end
|
||||||
|
return files, i, err
|
||||||
end
|
end
|
||||||
|
|
||||||
---List metadata of an archive
|
---List metadata of an archive
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,17 @@
|
||||||
local SUPPORTED_TYPES = "application/audio/biosig/chemical/font/image/inode/message/model/rinex/text/vector/video/x-epoc/"
|
-- stylua: ignore
|
||||||
|
local TYPE_PATS = { "text", "image", "video", "application", "audio", "font", "inode", "message", "model", "vector", "biosig", "chemical", "rinex", "x%-epoc" }
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local function match_mimetype(s)
|
local function match_mimetype(s)
|
||||||
local type, sub = s:match("^([-a-z]+/)([+-.a-zA-Z0-9]+)%s*$")
|
for _, pat in ipairs(TYPE_PATS) do
|
||||||
if type and sub and SUPPORTED_TYPES:find(type, 1, true) then
|
local typ, sub = s:match(string.format("(%s/)([+-.a-z0-9]+)%%s+$", pat))
|
||||||
return type:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
|
if not sub then
|
||||||
|
elseif s:find(typ .. sub, 1, true) == 1 then
|
||||||
|
return typ:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
|
||||||
|
else
|
||||||
|
return nil, true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -32,7 +38,7 @@ function M:fetch(job)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local i, valid, state = 1, nil, {}
|
local i, state, match, ignore = 1, {}, nil, nil
|
||||||
repeat
|
repeat
|
||||||
local line, event = child:read_line_with { timeout = 300 }
|
local line, event = child:read_line_with { timeout = 300 }
|
||||||
if event == 3 then
|
if event == 3 then
|
||||||
|
|
@ -42,15 +48,13 @@ function M:fetch(job)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
valid = match_mimetype(line)
|
match, ignore = match_mimetype(line)
|
||||||
if valid then
|
if match then
|
||||||
updates[urls[i]], state[i] = valid, true
|
updates[urls[i]], state[i], i = match, true, i + 1
|
||||||
flush(false)
|
flush(false)
|
||||||
else
|
elseif not ignore then
|
||||||
state[i] = false
|
state[i], i = false, i + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
i = i + 1
|
|
||||||
::continue::
|
::continue::
|
||||||
until i > #urls
|
until i > #urls
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue