summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqkzk <qu3nt1n@gmail.com>2022-10-07 16:09:38 +0200
committerqkzk <qu3nt1n@gmail.com>2022-10-07 16:09:38 +0200
commite747bc2aaf6ada3756f3d40ba0bbd006b34e7ff1 (patch)
tree617c817a4104435ceb31c922cf99140406438177
parent6b219ea85fb7e33fc747f9007b016b16a740bcf2 (diff)
WIP: preview binary files
-rw-r--r--Cargo.lock10
-rw-r--r--Cargo.toml1
-rw-r--r--src/display.rs47
-rw-r--r--src/fileinfo.rs6
-rw-r--r--src/preview.rs43
5 files changed, 102 insertions, 5 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4fac04a8..461a173e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -135,6 +135,15 @@ dependencies = [
]
[[package]]
+name = "content_inspector"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -206,6 +215,7 @@ version = "0.1.0"
dependencies = [
"chrono",
"clap",
+ "content_inspector",
"regex",
"serde_yaml",
"shellexpand",
diff --git a/Cargo.toml b/Cargo.toml
index a4bbd5f4..701b57f2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,3 +21,4 @@ shellexpand = "2.1.2"
syntect = "5.0"
tuikit = "*"
users = "0.11.0"
+content_inspector = "0.2.4"
diff --git a/src/display.rs b/src/display.rs
index 4b2a34ef..4829c378 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -1,4 +1,5 @@
use std::cmp::min;
+use std::io::Read;
use tuikit::attr::*;
use tuikit::term::Term;
@@ -239,8 +240,54 @@ impl Display {
let _ = self.term.print(row, line_number_width + 3, line);
}
}
+ Preview::Binary(bin) => {
+ let mut reader =
+ std::io::BufReader::new(std::fs::File::open(bin.path.clone()).unwrap());
+ let mut buffer = Box::new(vec![]);
+ reader.read_to_end(&mut buffer).unwrap();
+ let mut line: Vec<u8> = vec![];
+ for (i, byte) in buffer
+ .iter()
+ .enumerate()
+ .skip(16 * status.window.top)
+ .take(min(length, 16 * status.window.bottom + 1))
+ {
+ let row = i + ContentWindow::WINDOW_MARGIN_TOP - status.window.top;
+ if line.len() < 16 {
+ line.push(*byte);
+ } else {
+ let _ = self.term.print_with_attr(
+ row / 16,
+ 0,
+ &format_line_nr_hex((i + 1 + status.window.top) / 16),
+ Attr {
+ fg: Color::CYAN,
+ ..Default::default()
+ },
+ );
+ let _ = self.term.print(
+ row / 16,
+ line_number_width + 3,
+ &format_line_of_bytes(line),
+ );
+ line = vec![];
+ }
+ }
+ }
Preview::Empty => (),
}
}
}
}
+
+fn format_line_nr_hex(line_nr: usize) -> String {
+ format!("{:x>}", line_nr)
+}
+
+fn format_line_of_bytes(bytes: Vec<u8>) -> String {
+ bytes
+ .iter()
+ .map(|byte| format!("{:02x}", byte))
+ .collect::<Vec<String>>()
+ .join(" ")
+}
diff --git a/src/fileinfo.rs b/src/fileinfo.rs
index ee91f03e..02f77cf2 100644
--- a/src/fileinfo.rs
+++ b/src/fileinfo.rs
@@ -105,6 +105,8 @@ pub struct FileInfo {
pub path: path::PathBuf,
/// Filename
pub filename: String,
+ /// size (nb of bytes) of the file
+ pub size: u64,
/// File size as a `String`, already human formated.
pub file_size: String,
/// First symbol displaying the kind of file.
@@ -129,7 +131,8 @@ impl FileInfo {
pub fn new(direntry: &DirEntry) -> Result<FileInfo, &'static str> {
let path = direntry.path();
let filename = extract_filename(direntry);
- let file_size = human_size(extract_file_size(direntry));
+ let size = extract_file_size(direntry);
+ let file_size = human_size(size);
let permissions = extract_permissions_string(direntry);
let owner = extract_owner(direntry);
let system_time = extract_datetime(direntry);
@@ -144,6 +147,7 @@ impl FileInfo {
Ok(FileInfo {
path,
filename,
+ size,
file_size,
dir_symbol,
permissions,
diff --git a/src/preview.rs b/src/preview.rs
index 6e56b703..5d1162b8 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -1,5 +1,7 @@
-use std::io::BufRead;
+use std::io::{BufRead, Read};
+use std::path::PathBuf;
+use content_inspector::{inspect, ContentType};
use syntect::easy::HighlightLines;
use syntect::highlighting::{Style, ThemeSet};
use syntect::parsing::{SyntaxReference, SyntaxSet};
@@ -11,6 +13,7 @@ use crate::fileinfo::PathContent;
pub enum Preview {
SyntaxedPreview(SyntaxedContent),
TextPreview(TextContent),
+ Binary(BinaryContent),
Empty,
}
@@ -23,10 +26,21 @@ impl Preview {
let ps = SyntaxSet::load_defaults_nonewlines();
match path_content.selected_file() {
Some(file) => {
- if let Some(syntaxset) = ps.find_syntax_by_extension(&file.extension) {
- Self::SyntaxedPreview(SyntaxedContent::new(ps.clone(), path_content, syntaxset))
+ let mut f = std::fs::File::open(file.path.clone()).unwrap();
+ let mut buffer = vec![0; 1024];
+ f.read_exact(&mut buffer).unwrap();
+ if inspect(&buffer) == ContentType::BINARY {
+ Self::Binary(BinaryContent::new(path_content.to_owned()))
} else {
- Self::TextPreview(TextContent::from_file(path_content))
+ if let Some(syntaxset) = ps.find_syntax_by_extension(&file.extension) {
+ Self::SyntaxedPreview(SyntaxedContent::new(
+ ps.clone(),
+ path_content,
+ syntaxset,
+ ))
+ } else {
+ Self::TextPreview(TextContent::from_file(path_content))
+ }
}
}
None => Self::Empty,
@@ -38,6 +52,7 @@ impl Preview {
Self::SyntaxedPreview(syntaxed) => syntaxed.len(),
Self::TextPreview(text) => text.len(),
Self::Empty => 0,
+ Self::Binary(binary) => binary.len(),
}
}
@@ -173,3 +188,23 @@ impl SyntaxedString {
let _ = term.print_with_attr(row, self.col + offset + 2, &self.content, self.attr);
}
}
+
+pub struct BinaryContent {
+ pub path: PathBuf,
+ length: u64,
+}
+
+impl BinaryContent {
+ fn new(path_content: PathContent) -> Self {
+ let file = path_content.selected_file().unwrap();
+
+ Self {
+ path: file.path.clone(),
+ length: file.size,
+ }
+ }
+
+ fn len(&self) -> usize {
+ self.length as usize
+ }
+}