mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: dedicated mime fetcher, previewer, and spotter for VFS (#3203)
This commit is contained in:
parent
6b09f2b665
commit
d905cbf2d7
12 changed files with 83 additions and 51 deletions
10
.github/workflows/draft.yml
vendored
10
.github/workflows/draft.yml
vendored
|
|
@ -45,8 +45,9 @@ jobs:
|
|||
if: matrix.gcc != ''
|
||||
run: sudo apt update && sudo apt install -yq ${{ matrix.gcc }}
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
run: rustup toolchain install stable --profile minimal --target ${{ matrix.target }}
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.9
|
||||
|
|
@ -79,8 +80,9 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
run: rustup toolchain install stable --profile minimal --target ${{ matrix.target }}
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.9
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@ pub(super) struct File {
|
|||
v_cha: Option<Value>,
|
||||
v_url: Option<Value>,
|
||||
v_link_to: Option<Value>,
|
||||
v_name: Option<Value>,
|
||||
|
||||
v_name: Option<Value>,
|
||||
v_cache: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for File {
|
||||
|
|
@ -48,7 +50,9 @@ impl File {
|
|||
v_cha: None,
|
||||
v_url: None,
|
||||
v_link_to: None,
|
||||
|
||||
v_name: None,
|
||||
v_cache: None,
|
||||
})?;
|
||||
ve.insert(ud.clone());
|
||||
ud
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ pub struct File {
|
|||
v_cha: Option<Value>,
|
||||
v_url: Option<Value>,
|
||||
v_link_to: Option<Value>,
|
||||
v_name: Option<Value>,
|
||||
|
||||
v_name: Option<Value>,
|
||||
v_cache: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for File {
|
||||
|
|
@ -27,7 +29,7 @@ impl From<File> for yazi_fs::File {
|
|||
|
||||
impl File {
|
||||
pub fn new(inner: yazi_fs::File) -> Self {
|
||||
Self { inner, v_cha: None, v_url: None, v_link_to: None, v_name: None }
|
||||
Self { inner, v_cha: None, v_url: None, v_link_to: None, v_name: None, v_cache: None }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,6 +156,9 @@ macro_rules! impl_file_fields {
|
|||
$crate::cached_field!($fields, name, |lua, me| {
|
||||
me.name().map(|s| lua.create_string(s.as_encoded_bytes())).transpose()
|
||||
});
|
||||
$crate::cached_field!($fields, cache, |_, me| Ok(
|
||||
yazi_fs::provider::cache(&me.url).map($crate::Url::new)
|
||||
));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -223,31 +223,23 @@ footer = { fg = "black", bg = "white" }
|
|||
|
||||
[filetype]
|
||||
rules = [
|
||||
# Images
|
||||
# Image
|
||||
{ mime = "image/*", fg = "yellow" },
|
||||
|
||||
# Media
|
||||
{ mime = "{audio,video}/*", fg = "magenta" },
|
||||
|
||||
# Archives
|
||||
# Archive
|
||||
{ mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "red" },
|
||||
|
||||
# Documents
|
||||
# Document
|
||||
{ mime = "application/{pdf,doc,rtf}", fg = "cyan" },
|
||||
|
||||
# Empty files
|
||||
# { mime = "inode/empty", fg = "red" },
|
||||
|
||||
# Special files
|
||||
# Virtual file system
|
||||
{ mime = "vfs/*", fg = "gray" },
|
||||
# Special file
|
||||
{ url = "*", is = "orphan", bg = "red" },
|
||||
{ url = "*", is = "exec" , fg = "green" },
|
||||
|
||||
# Dummy files
|
||||
# Dummy file
|
||||
{ url = "*", is = "dummy", bg = "red" },
|
||||
{ url = "*/", is = "dummy", bg = "red" },
|
||||
|
||||
# Fallback
|
||||
# { url = "*", fg = "white" },
|
||||
{ url = "*/", fg = "blue" }
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -223,31 +223,23 @@ footer = { fg = "black", bg = "white" }
|
|||
|
||||
[filetype]
|
||||
rules = [
|
||||
# Images
|
||||
# Image
|
||||
{ mime = "image/*", fg = "yellow" },
|
||||
|
||||
# Media
|
||||
{ mime = "{audio,video}/*", fg = "magenta" },
|
||||
|
||||
# Archives
|
||||
# Archive
|
||||
{ mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "red" },
|
||||
|
||||
# Documents
|
||||
# Document
|
||||
{ mime = "application/{pdf,doc,rtf}", fg = "cyan" },
|
||||
|
||||
# Empty files
|
||||
# { mime = "inode/empty", fg = "red" },
|
||||
|
||||
# Special files
|
||||
# Virtual file system
|
||||
{ mime = "vfs/*", fg = "darkgray" },
|
||||
# Special file
|
||||
{ url = "*", is = "orphan", bg = "red" },
|
||||
{ url = "*", is = "exec" , fg = "green" },
|
||||
|
||||
# Dummy files
|
||||
# Dummy file
|
||||
{ url = "*", is = "dummy", bg = "red" },
|
||||
{ url = "*/", is = "dummy", bg = "red" },
|
||||
|
||||
# Fallback
|
||||
# { url = "*", fg = "white" },
|
||||
{ url = "*/", fg = "blue" }
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ spotters = [
|
|||
{ mime = "image/*", run = "image" },
|
||||
# Video
|
||||
{ mime = "video/*", run = "video" },
|
||||
# Virtual file system
|
||||
{ mime = "vfs/*", run = "vfs" },
|
||||
# Fallback
|
||||
{ url = "*", run = "file" },
|
||||
]
|
||||
|
|
@ -149,6 +151,8 @@ previewers = [
|
|||
{ mime = "application/ms-opentype", run = "font" },
|
||||
# Empty file
|
||||
{ mime = "inode/empty", run = "empty" },
|
||||
# Virtual file system
|
||||
{ mime = "vfs/*", run = "vfs" },
|
||||
# Fallback
|
||||
{ url = "*", run = "file" },
|
||||
]
|
||||
|
|
|
|||
|
|
@ -43,8 +43,9 @@ impl Term {
|
|||
)?;
|
||||
|
||||
let resp = Emulator::read_until_da1();
|
||||
yazi_term::RestoreCursor::store(&resp);
|
||||
Mux::tmux_drain()?;
|
||||
|
||||
yazi_term::RestoreCursor::store(&resp);
|
||||
CSI_U.store(resp.contains("\x1b[?0u"), Ordering::Relaxed);
|
||||
if CSI_U.load(Ordering::Relaxed) {
|
||||
PushKeyboardEnhancementFlags(
|
||||
|
|
@ -61,7 +62,6 @@ impl Term {
|
|||
term.hide_cursor()?;
|
||||
term.clear()?;
|
||||
term.flush()?;
|
||||
Mux::tmux_drain()?;
|
||||
Ok(term)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,10 +56,12 @@ impl FilesOp {
|
|||
for (o, n) in map {
|
||||
let Some(o_p) = o.parent() else { continue };
|
||||
let Some(n_p) = n.url.parent() else { continue };
|
||||
if o_p != n_p {
|
||||
if o_p == n_p {
|
||||
parents.entry_ref(&o_p).or_default().1.insert(o.urn().to_owned(), n);
|
||||
} else {
|
||||
parents.entry_ref(&o_p).or_default().0.insert(o.urn().to_owned());
|
||||
parents.entry_ref(&n_p).or_default().1.insert(n.urn().to_owned(), n);
|
||||
}
|
||||
parents.entry_ref(&n_p).or_default().1.insert(n.urn().to_owned(), n);
|
||||
}
|
||||
for (p, (o, n)) in parents {
|
||||
match (o.is_empty(), n.is_empty()) {
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ local TYPE_PATS = { "text", "image", "video", "application", "audio", "font", "i
|
|||
|
||||
local M = {}
|
||||
|
||||
local function match_mimetype(s)
|
||||
local function match_mimetype(line)
|
||||
for _, pat in ipairs(TYPE_PATS) do
|
||||
local typ, sub = s:match(string.format("(%s/)([+-.a-z0-9]+)%%s+$", pat))
|
||||
local typ, sub = line:match(string.format("(%s/)([+-.a-z0-9]+)%%s+$", pat))
|
||||
if not sub then
|
||||
elseif s:find(typ .. sub, 1, true) == 1 then
|
||||
elseif line:find(typ .. sub, 1, true) == 1 then
|
||||
return typ:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
|
||||
else
|
||||
return nil, true
|
||||
|
|
@ -15,14 +15,27 @@ local function match_mimetype(s)
|
|||
end
|
||||
end
|
||||
|
||||
local function miss_cache(cache, line)
|
||||
if line:match("^cannot open `.+' %(No such file or directory%)%s+$") then
|
||||
return true
|
||||
else
|
||||
local _, err = fs.cha(Url(cache))
|
||||
return err and err.code == 2
|
||||
end
|
||||
end
|
||||
|
||||
function M:fetch(job)
|
||||
local urls = {}
|
||||
for _, file in ipairs(job.files) do
|
||||
urls[#urls + 1] = tostring(file.url)
|
||||
local paths, origins = {}, {}
|
||||
for i, file in ipairs(job.files) do
|
||||
if file.cache then
|
||||
paths[i], origins[i] = tostring(file.cache), tostring(file.url)
|
||||
else
|
||||
paths[i] = tostring(file.url)
|
||||
end
|
||||
end
|
||||
|
||||
local cmd = os.getenv("YAZI_FILE_ONE") or "file"
|
||||
local child, err = Command(cmd):arg({ "-bL", "--mime-type", "--" }):arg(urls):stdout(Command.PIPED):spawn()
|
||||
local child, err = Command(cmd):arg({ "-bL", "--mime-type", "--" }):arg(paths):stdout(Command.PIPED):spawn()
|
||||
if not child then
|
||||
return true, Err("Failed to start `%s`, error: %s", cmd, err)
|
||||
end
|
||||
|
|
@ -50,13 +63,18 @@ function M:fetch(job)
|
|||
|
||||
match, ignore = match_mimetype(line)
|
||||
if match then
|
||||
updates[urls[i]], state[i], i = match, true, i + 1
|
||||
updates[origins[i] or paths[i]], state[i], i = match, true, i + 1
|
||||
flush(false)
|
||||
elseif not ignore then
|
||||
elseif ignore then
|
||||
goto continue
|
||||
elseif origins[i] and miss_cache(paths[i], line) then
|
||||
updates[origins[i]], state[i], i = "vfs/todo", true, i + 1
|
||||
flush(false)
|
||||
else
|
||||
state[i], i = false, i + 1
|
||||
end
|
||||
::continue::
|
||||
until i > #urls
|
||||
until i > #paths
|
||||
|
||||
flush(true)
|
||||
return state
|
||||
|
|
|
|||
12
yazi-plugin/preset/plugins/vfs.lua
Normal file
12
yazi-plugin/preset/plugins/vfs.lua
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
local M = {}
|
||||
|
||||
function M:peek(job)
|
||||
local line = ui.Line("Remote file, download to preview"):reverse()
|
||||
ya.preview_widget(job, ui.Text(line):area(job.area):wrap(ui.Wrap.YES))
|
||||
end
|
||||
|
||||
function M:seek() end
|
||||
|
||||
function M:spot(job) require("file"):spot(job) end
|
||||
|
||||
return M
|
||||
|
|
@ -43,6 +43,7 @@ impl Default for Loader {
|
|||
("pdf".to_owned(), preset!("plugins/pdf").into()),
|
||||
("session".to_owned(), preset!("plugins/session").into()),
|
||||
("svg".to_owned(), preset!("plugins/svg").into()),
|
||||
("vfs".to_owned(), preset!("plugins/vfs").into()),
|
||||
("video".to_owned(), preset!("plugins/video").into()),
|
||||
("zoxide".to_owned(), preset!("plugins/zoxide").into()),
|
||||
]);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue