From 3f7c2fab78e204564192b017eee299a49a40f1a8 Mon Sep 17 00:00:00 2001 From: Alexandre Pasmantier Date: Sat, 23 Nov 2024 00:35:09 +0100 Subject: [PATCH 1/2] build(infer): drop infer dependency and refactor code to a simpler heuristic --- Cargo.lock | 28 ---- .../television-channels/src/channels/text.rs | 5 +- crates/television-previewers/Cargo.toml | 1 - .../src/previewers/files.rs | 126 +++++------------- crates/television-utils/Cargo.toml | 1 - crates/television-utils/src/files.rs | 57 +++++--- 6 files changed, 69 insertions(+), 149 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1eb2a1..7fd9137 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -264,12 +264,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" version = "1.8.0" @@ -364,17 +358,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cfb" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" -dependencies = [ - "byteorder", - "fnv", - "uuid", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -1761,15 +1744,6 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" -[[package]] -name = "infer" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847" -dependencies = [ - "cfb", -] - [[package]] name = "instability" version = "0.3.2" @@ -2889,7 +2863,6 @@ version = "0.0.5" dependencies = [ "color-eyre", "devicons", - "infer", "parking_lot", "syntect", "television-channels", @@ -2908,7 +2881,6 @@ dependencies = [ "directories", "gag", "ignore", - "infer", "lazy_static", "syntect", "tracing", diff --git a/crates/television-channels/src/channels/text.rs b/crates/television-channels/src/channels/text.rs index 812b4b5..654b63f 100644 --- a/crates/television-channels/src/channels/text.rs +++ b/crates/television-channels/src/channels/text.rs @@ -9,9 +9,7 @@ use std::{ sync::{atomic::AtomicUsize, Arc}, }; use television_fuzzy::matcher::{config::Config, injector::Injector, Matcher}; -use television_utils::files::{ - is_not_text, walk_builder, DEFAULT_NUM_THREADS, -}; +use television_utils::files::{walk_builder, DEFAULT_NUM_THREADS}; use television_utils::strings::{ preprocess_line, proportion_of_printable_ascii_characters, PRINTABLE_ASCII_THRESHOLD, @@ -298,7 +296,6 @@ fn try_inject_lines( match reader.read(&mut buffer) { Ok(bytes_read) => { if (bytes_read == 0) - || is_not_text(&buffer).unwrap_or(false) || proportion_of_printable_ascii_characters(&buffer) < PRINTABLE_ASCII_THRESHOLD { diff --git a/crates/television-previewers/Cargo.toml b/crates/television-previewers/Cargo.toml index 576d992..0457454 100644 --- a/crates/television-previewers/Cargo.toml +++ b/crates/television-previewers/Cargo.toml @@ -22,5 +22,4 @@ tokio = "1.41.1" termtree = "0.5.1" devicons = "0.6.11" color-eyre = "0.6.3" -infer = "0.16.0" diff --git a/crates/television-previewers/src/previewers/files.rs b/crates/television-previewers/src/previewers/files.rs index b29aaa2..588a0f7 100644 --- a/crates/television-previewers/src/previewers/files.rs +++ b/crates/television-previewers/src/previewers/files.rs @@ -3,8 +3,8 @@ use color_eyre::Result; //use ratatui_image::picker::Picker; use parking_lot::Mutex; use std::fs::File; -use std::io::{BufRead, BufReader, Read, Seek}; -use std::path::{Path, PathBuf}; +use std::io::{BufRead, BufReader, Seek}; +use std::path::PathBuf; use std::sync::Arc; use syntect::{ @@ -16,12 +16,9 @@ use tracing::{debug, warn}; use super::cache::PreviewCache; use crate::previewers::{meta, Preview, PreviewContent}; use television_channels::entry; +use television_utils::files::get_file_size; use television_utils::files::FileType; -use television_utils::files::{get_file_size, is_known_text_extension}; -use television_utils::strings::{ - preprocess_line, proportion_of_printable_ascii_characters, - PRINTABLE_ASCII_THRESHOLD, -}; +use television_utils::strings::preprocess_line; use television_utils::syntax::{ self, load_highlighting_assets, HighlightingAssetsExt, }; @@ -69,6 +66,10 @@ impl FilePreviewer { } } + /// The maximum file size that we will try to preview. + /// 4 MB + const MAX_FILE_SIZE: u64 = 4 * 1024 * 1024; + /// Get a preview for a file entry. /// /// # Panics @@ -93,53 +94,32 @@ impl FilePreviewer { // try to determine file type debug!("Computing preview for {:?}", entry.name); - match self.get_file_type(&path_buf) { - FileType::Text => { - match File::open(&path_buf) { - Ok(file) => { - // insert a loading preview into the cache - let preview = meta::loading(&entry.name); - self.cache_preview( - entry.name.clone(), - preview.clone(), - ); - - // compute the highlighted version in the background - let mut reader = BufReader::new(file); - reader.seek(std::io::SeekFrom::Start(0)).unwrap(); - self.compute_highlighted_text_preview(entry, reader); - preview - } - Err(e) => { - warn!("Error opening file: {:?}", e); - let p = meta::not_supported(&entry.name); - self.cache_preview(entry.name.clone(), p.clone()); - p - } + if let FileType::Text = FileType::from(&path_buf) { + debug!("File is text-based: {:?}", entry.name); + match File::open(&path_buf) { + Ok(file) => { + // insert a loading preview into the cache + let preview = meta::loading(&entry.name); + self.cache_preview(entry.name.clone(), preview.clone()); + + // compute the highlighted version in the background + let mut reader = BufReader::new(file); + reader.seek(std::io::SeekFrom::Start(0)).unwrap(); + self.compute_highlighted_text_preview(entry, reader); + preview + } + Err(e) => { + warn!("Error opening file: {:?}", e); + let p = meta::not_supported(&entry.name); + self.cache_preview(entry.name.clone(), p.clone()); + p } } - FileType::Image => { - debug!("Previewing image file: {:?}", entry.name); - // insert a loading preview into the cache - //let preview = loading(&entry.name); - let preview = meta::not_supported(&entry.name); - self.cache_preview(entry.name.clone(), preview.clone()); - //// compute the image preview in the background - //self.compute_image_preview(entry).await; - preview - } - FileType::Other => { - debug!("Previewing other file: {:?}", entry.name); - let preview = meta::not_supported(&entry.name); - self.cache_preview(entry.name.clone(), preview.clone()); - preview - } - FileType::Unknown => { - debug!("Unknown file type: {:?}", entry.name); - let preview = meta::not_supported(&entry.name); - self.cache_preview(entry.name.clone(), preview.clone()); - preview - } + } else { + debug!("File isn't text-based: {:?}", entry.name); + let preview = meta::not_supported(&entry.name); + self.cache_preview(entry.name.clone(), preview.clone()); + preview } } @@ -218,48 +198,6 @@ impl FilePreviewer { }); } - /// The maximum file size that we will try to preview. - /// 4 MB - const MAX_FILE_SIZE: u64 = 4 * 1024 * 1024; - - fn get_file_type(&self, path: &Path) -> FileType { - debug!("Getting file type for {:?}", path); - let mut file_type = match infer::get_from_path(path) { - Ok(Some(t)) => { - let mime_type = t.mime_type(); - if mime_type.contains("image") { - FileType::Image - } else if mime_type.contains("text") { - FileType::Text - } else { - FileType::Other - } - } - _ => FileType::Unknown, - }; - - // if the file type is unknown, try to determine it from the extension or the content - if matches!(file_type, FileType::Unknown) { - if is_known_text_extension(path) { - file_type = FileType::Text; - } else if let Ok(mut f) = File::open(path) { - let mut buffer = [0u8; 256]; - if let Ok(bytes_read) = f.read(&mut buffer) { - if bytes_read > 0 - && proportion_of_printable_ascii_characters( - &buffer[..bytes_read], - ) > PRINTABLE_ASCII_THRESHOLD - { - file_type = FileType::Text; - } - } - } - } - debug!("File type for {:?}: {:?}", path, file_type); - - file_type - } - fn cache_preview(&mut self, key: String, preview: Arc) { self.cache.lock().insert(key, preview); } diff --git a/crates/television-utils/Cargo.toml b/crates/television-utils/Cargo.toml index e8eca83..4394b4e 100644 --- a/crates/television-utils/Cargo.toml +++ b/crates/television-utils/Cargo.toml @@ -14,7 +14,6 @@ rust-version.workspace = true [dependencies] ignore = "0.4.23" -infer = "0.16.0" lazy_static = "1.5.0" tracing = "0.1.40" color-eyre = "0.6.3" diff --git a/crates/television-utils/src/files.rs b/crates/television-utils/src/files.rs index 1545a22..c9a4ff7 100644 --- a/crates/television-utils/src/files.rs +++ b/crates/television-utils/src/files.rs @@ -1,11 +1,16 @@ +use std::fmt::Debug; +use std::fs::File; +use std::io::Read; use std::path::Path; use std::{collections::HashSet, path::PathBuf}; use ignore::{overrides::Override, types::TypesBuilder, WalkBuilder}; -use infer::Infer; use lazy_static::lazy_static; -use tracing::debug; +use tracing::{debug, warn}; +use crate::strings::{ + proportion_of_printable_ascii_characters, PRINTABLE_ASCII_THRESHOLD, +}; use crate::threads::default_num_threads; lazy_static::lazy_static! { @@ -51,34 +56,44 @@ pub fn get_file_size(path: &Path) -> Option { #[derive(Debug)] pub enum FileType { Text, - Image, Other, Unknown, } -pub fn is_not_text(bytes: &[u8]) -> Option { - let infer = Infer::new(); - match infer.get(bytes) { - Some(t) => { - let mime_type = t.mime_type(); - if mime_type.contains("image") - || mime_type.contains("video") - || mime_type.contains("audio") - || mime_type.contains("archive") - || mime_type.contains("book") - || mime_type.contains("font") - { - Some(true) - } else { - None +impl

From

for FileType +where + P: AsRef + Debug, +{ + fn from(path: P) -> Self { + debug!("Getting file type for {:?}", path); + let p = path.as_ref(); + if is_known_text_extension(p) { + return FileType::Text; + } + if let Ok(mut f) = File::open(p) { + let mut buffer = [0u8; 256]; + if let Ok(bytes_read) = f.read(&mut buffer) { + if bytes_read > 0 + && proportion_of_printable_ascii_characters( + &buffer[..bytes_read], + ) > PRINTABLE_ASCII_THRESHOLD + { + return FileType::Text; + } } + } else { + warn!("Error opening file: {:?}", path); } - None => None, + FileType::Other } } -pub fn is_known_text_extension(path: &Path) -> bool { - path.extension() +pub fn is_known_text_extension

(path: P) -> bool +where + P: AsRef, +{ + path.as_ref() + .extension() .and_then(|ext| ext.to_str()) .is_some_and(|ext| KNOWN_TEXT_FILE_EXTENSIONS.contains(ext)) } From f2e3b764c8773e9be14c7e47c9d29fed3a844b58 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 22 Nov 2024 23:36:33 +0000 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f32f37d..5eae0dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ All notable changes to this project will be documented in this file. ### 🚜 Refactor -- *(picker)* Refactor picker logic and add tests for picker, cli and events +- *(picker)* Refactor picker logic and add tests to picker, cli, and events (#57) ### 📚 Documentation @@ -20,6 +20,10 @@ All notable changes to this project will be documented in this file. - Add readme version update to github actions (#55) +### Build + +- *(infer)* Drop infer dependency and refactor code to a simpler heuristic + ## [0.5.1] - 2024-11-20 ### 📚 Documentation