mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
fix: replace control characters to printable characters in plain text preview (#1704)
This commit is contained in:
parent
a7b9275c06
commit
40211df219
2 changed files with 40 additions and 10 deletions
17
yazi-plugin/src/external/highlighter.rs
vendored
17
yazi-plugin/src/external/highlighter.rs
vendored
|
|
@ -5,7 +5,7 @@ use ratatui::{layout::Rect, text::{Line, Span, Text}};
|
|||
use syntect::{LoadingError, dumps, easy::HighlightLines, highlighting::{self, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}};
|
||||
use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}, sync::OnceCell};
|
||||
use yazi_config::{PREVIEW, THEME, preview::PreviewWrap};
|
||||
use yazi_shared::PeekError;
|
||||
use yazi_shared::{PeekError, replace_to_printable};
|
||||
|
||||
static INCR: AtomicUsize = AtomicUsize::new(0);
|
||||
static SYNTECT: OnceCell<(Theme, SyntaxSet)> = OnceCell::const_new();
|
||||
|
|
@ -58,7 +58,7 @@ impl Highlighter {
|
|||
return Err("Binary file".into());
|
||||
}
|
||||
|
||||
if !plain && (buf.len() > 5000 || buf.contains(&0x1b)) {
|
||||
if !plain && (buf.len() > 5000 || Self::contains_control_chars(&buf)) {
|
||||
plain = true;
|
||||
drop(mem::take(&mut before));
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ impl Highlighter {
|
|||
}
|
||||
|
||||
Ok(if plain {
|
||||
Text::from(after.join("").replace('\x1b', "^[").replace('\t', &PREVIEW.indent()))
|
||||
Text::from(replace_to_printable(&after.join(""), PREVIEW.tab_size))
|
||||
} else {
|
||||
Self::highlight_with(before, after, syntax.unwrap()).await?
|
||||
})
|
||||
|
|
@ -186,9 +186,14 @@ impl Highlighter {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn carriage_return_to_line_feed(c: &mut u8) {
|
||||
if *c == b'\r' {
|
||||
*c = b'\n';
|
||||
fn contains_control_chars(buf: &[u8]) -> bool {
|
||||
buf.iter().any(|&b| b.is_ascii_control() && !matches!(b, b'\t' | b'\n' | b'\r'))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn carriage_return_to_line_feed(b: &mut u8) {
|
||||
if *b == b'\r' {
|
||||
*b = b'\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use core::str;
|
||||
|
||||
pub const MIME_DIR: &str = "inode/directory";
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
|
|
@ -20,11 +22,34 @@ impl CharKind {
|
|||
}
|
||||
|
||||
pub fn strip_trailing_newline(mut s: String) -> String {
|
||||
if s.ends_with('\n') {
|
||||
s.pop();
|
||||
}
|
||||
if s.ends_with('\r') {
|
||||
while s.ends_with('\n') || s.ends_with('\r') {
|
||||
s.pop();
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
pub fn replace_to_printable(s: &str, tab_size: u8) -> String {
|
||||
let mut buf = Vec::new();
|
||||
buf.try_reserve_exact(s.len() | 15).unwrap_or_else(|_| panic!());
|
||||
|
||||
for &b in s.as_bytes() {
|
||||
match b {
|
||||
b'\n' => buf.push(b'\n'),
|
||||
b'\t' => {
|
||||
for _ in 0..tab_size {
|
||||
buf.push(b' ');
|
||||
}
|
||||
}
|
||||
b'\0'..=b'\x1F' => {
|
||||
buf.push(b'^');
|
||||
buf.push(b + b'@');
|
||||
}
|
||||
0x7f => {
|
||||
buf.push(b'^');
|
||||
buf.push(b'?');
|
||||
}
|
||||
_ => buf.push(b),
|
||||
}
|
||||
}
|
||||
unsafe { String::from_utf8_unchecked(buf) }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue