mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
add fallback mime guess in case file(1) is not available
This commit is contained in:
parent
e6fccf9d17
commit
e00d943a63
4 changed files with 66 additions and 3 deletions
26
Cargo.lock
generated
26
Cargo.lock
generated
|
|
@ -379,6 +379,7 @@ dependencies = [
|
|||
"futures",
|
||||
"indexmap 2.0.0",
|
||||
"libc",
|
||||
"mime_guess",
|
||||
"natord",
|
||||
"notify",
|
||||
"parking_lot",
|
||||
|
|
@ -1051,6 +1052,22 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
|
||||
dependencies = [
|
||||
"mime",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
|
|
@ -2004,6 +2021,15 @@ version = "1.16.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ tracing = "^0"
|
|||
trash = "^3"
|
||||
unicode-width = "^0"
|
||||
yazi-prebuild = "^0"
|
||||
mime_guess = "2.0.4"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
clipboard-win = "^4"
|
||||
|
|
|
|||
40
core/src/external/file.rs
vendored
40
core/src/external/file.rs
vendored
|
|
@ -3,7 +3,7 @@ use std::collections::BTreeMap;
|
|||
use anyhow::{bail, Result};
|
||||
use futures::TryFutureExt;
|
||||
use shared::{MimeKind, Url};
|
||||
use tokio::process::Command;
|
||||
use tokio::{fs, io::AsyncReadExt, process::Command};
|
||||
use tracing::error;
|
||||
|
||||
async fn _file(files: &[&Url]) -> Result<BTreeMap<Url, String>> {
|
||||
|
|
@ -36,5 +36,41 @@ async fn _file(files: &[&Url]) -> Result<BTreeMap<Url, String>> {
|
|||
}
|
||||
|
||||
pub async fn file(files: &[impl AsRef<Url>]) -> Result<BTreeMap<Url, String>> {
|
||||
_file(&files.iter().map(AsRef::as_ref).collect::<Vec<_>>()).await
|
||||
let _files = &files.iter().map(AsRef::as_ref).collect::<Vec<_>>();
|
||||
_file(_files).or_else(move |_| fallback(_files)).await
|
||||
}
|
||||
|
||||
async fn fallback(files: &[&Url]) -> Result<BTreeMap<Url, String>> {
|
||||
let mut mimes = BTreeMap::new();
|
||||
for &file in files {
|
||||
if let Ok(mime) = guess_mime(file).await {
|
||||
mimes.insert(file.clone(), mime);
|
||||
}
|
||||
}
|
||||
|
||||
if mimes.is_empty() {
|
||||
error!("failed to get mime types: {:?}", files);
|
||||
bail!("failed to get mime types");
|
||||
}
|
||||
|
||||
Ok(mimes)
|
||||
}
|
||||
|
||||
async fn guess_mime(file: impl AsRef<Url>) -> Result<String> {
|
||||
// First, try to guess mime type from file extenstion.
|
||||
// If fail, either return "text/plain" or "application/octet-stream" by
|
||||
// trying to convert 1kb of data to utf8 string
|
||||
let file = file.as_ref();
|
||||
match mime_guess::from_path(file).first() {
|
||||
Some(mime) => Ok(mime.to_string()),
|
||||
None => {
|
||||
let mut buf = [0; 1024];
|
||||
let num_bytes = fs::File::open(file).await?.read(&mut buf).await?;
|
||||
if String::from_utf8(buf[..num_bytes].to_vec()).is_ok() {
|
||||
Ok(String::from("text/plain"))
|
||||
} else {
|
||||
Ok(String::from("application/octet-stream"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub enum MimeKind {
|
|||
|
||||
impl MimeKind {
|
||||
pub fn new(s: &str) -> Self {
|
||||
if s.starts_with("text/") || s.ends_with("/xml") || s.ends_with("/javascript") {
|
||||
if s.starts_with("text/") || s.ends_with("/xml") || s.ends_with("/javascript") || s.ends_with("/x-sh") {
|
||||
Self::Text
|
||||
} else if s.starts_with("image/") {
|
||||
Self::Image
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue