mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 00:31:04 +00:00
feat: make the builtin code previewer handle invalid carriage return chars and binary streams better (#1550)
This commit is contained in:
parent
69c20d4dd3
commit
9cf85c09d2
13 changed files with 94 additions and 115 deletions
|
|
@ -70,7 +70,7 @@ function Entity:symlink()
|
||||||
end
|
end
|
||||||
|
|
||||||
local to = self._file.link_to
|
local to = self._file.link_to
|
||||||
return ui.Line(to and { ui.Span(" -> " .. tostring(to)):italic() } or {})
|
return to and ui.Line(" -> " .. tostring(to)):italic() or ui.Line {}
|
||||||
end
|
end
|
||||||
|
|
||||||
function Entity:render()
|
function Entity:render()
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
function M:peek()
|
function M:peek()
|
||||||
local _, bound = ya.preview_code(self)
|
local err, bound = ya.preview_code(self)
|
||||||
if bound then
|
if bound then
|
||||||
ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
|
ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
|
||||||
|
elseif err then
|
||||||
|
ya.preview_widgets(self, {
|
||||||
|
ui.Paragraph(self.area, { ui.Line(err):reverse() }),
|
||||||
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ local M = {}
|
||||||
|
|
||||||
function M:msg(s)
|
function M:msg(s)
|
||||||
local p = ui.Paragraph(self.area, {
|
local p = ui.Paragraph(self.area, {
|
||||||
ui.Line { ui.Span(s):reverse() },
|
ui.Line(s):reverse(),
|
||||||
})
|
})
|
||||||
ya.preview_widgets(self, { p:wrap(ui.Paragraph.WRAP) })
|
ya.preview_widgets(self, { p:wrap(ui.Paragraph.WRAP) })
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,13 @@ function M:seek(units)
|
||||||
end
|
end
|
||||||
|
|
||||||
function M:fallback_to_builtin()
|
function M:fallback_to_builtin()
|
||||||
local _, bound = ya.preview_code(self)
|
local err, bound = ya.preview_code(self)
|
||||||
if bound then
|
if bound then
|
||||||
ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
|
ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
|
||||||
|
elseif err then
|
||||||
|
ya.preview_widgets(self, {
|
||||||
|
ui.Paragraph(self.area, { ui.Line(err):reverse() }),
|
||||||
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,8 @@ impl Line {
|
||||||
|
|
||||||
impl UserData for Line {
|
impl UserData for Line {
|
||||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
crate::impl_style_shorthands!(methods, 0.style);
|
||||||
|
|
||||||
methods.add_function("width", |_, ud: AnyUserData| Ok(ud.borrow_mut::<Self>()?.0.width()));
|
methods.add_function("width", |_, ud: AnyUserData| Ok(ud.borrow_mut::<Self>()?.0.width()));
|
||||||
methods.add_function("style", |_, (ud, value): (AnyUserData, Value)| {
|
methods.add_function("style", |_, (ud, value): (AnyUserData, Value)| {
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ pub struct Paragraph {
|
||||||
pub area: ratatui::layout::Rect,
|
pub area: ratatui::layout::Rect,
|
||||||
|
|
||||||
pub text: ratatui::text::Text<'static>,
|
pub text: ratatui::text::Text<'static>,
|
||||||
pub style: Option<ratatui::style::Style>,
|
pub style: ratatui::style::Style,
|
||||||
pub alignment: ratatui::layout::Alignment,
|
pub alignment: ratatui::layout::Alignment,
|
||||||
pub wrap: u8,
|
pub wrap: u8,
|
||||||
}
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ impl Paragraph {
|
||||||
let new = lua.create_function(|_, (_, area, lines): (Table, RectRef, Vec<Line>)| {
|
let new = lua.create_function(|_, (_, area, lines): (Table, RectRef, Vec<Line>)| {
|
||||||
Ok(Paragraph {
|
Ok(Paragraph {
|
||||||
area: *area,
|
area: *area,
|
||||||
text: lines.into_iter().map(|s| s.0).collect::<Vec<_>>().into(),
|
text: lines.into_iter().map(|s| s.0).collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
@ -58,13 +58,15 @@ impl Paragraph {
|
||||||
|
|
||||||
impl UserData for Paragraph {
|
impl UserData for Paragraph {
|
||||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
crate::impl_style_shorthands!(methods, style);
|
||||||
|
|
||||||
methods.add_function("style", |_, (ud, value): (AnyUserData, Value)| {
|
methods.add_function("style", |_, (ud, value): (AnyUserData, Value)| {
|
||||||
{
|
{
|
||||||
let mut me = ud.borrow_mut::<Self>()?;
|
let mut me = ud.borrow_mut::<Self>()?;
|
||||||
match value {
|
match value {
|
||||||
Value::Nil => me.style = None,
|
Value::Nil => me.style = ratatui::style::Style::default(),
|
||||||
Value::Table(tb) => me.style = Some(Style::try_from(tb)?.0),
|
Value::Table(tb) => me.style = Style::try_from(tb)?.0,
|
||||||
Value::UserData(ud) => me.style = Some(ud.borrow::<Style>()?.0),
|
Value::UserData(ud) => me.style = ud.borrow::<Style>()?.0,
|
||||||
_ => return Err("expected a Style or Table or nil".into_lua_err()),
|
_ => return Err("expected a Style or Table or nil".into_lua_err()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -92,10 +94,7 @@ impl Renderable for Paragraph {
|
||||||
fn area(&self) -> ratatui::layout::Rect { self.area }
|
fn area(&self) -> ratatui::layout::Rect { self.area }
|
||||||
|
|
||||||
fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) {
|
fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) {
|
||||||
let mut p = ratatui::widgets::Paragraph::new(self.text);
|
let mut p = ratatui::widgets::Paragraph::new(self.text).style(self.style);
|
||||||
if let Some(style) = self.style {
|
|
||||||
p = p.style(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.wrap != WRAP_NO {
|
if self.wrap != WRAP_NO {
|
||||||
p = p.wrap(ratatui::widgets::Wrap { trim: self.wrap == WRAP_TRIM });
|
p = p.wrap(ratatui::widgets::Wrap { trim: self.wrap == WRAP_TRIM });
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use mlua::{AnyUserData, ExternalError, FromLua, Lua, Table, UserData, UserDataMethods, Value};
|
use mlua::{AnyUserData, ExternalError, FromLua, Lua, Table, UserData, UserDataMethods, Value};
|
||||||
use yazi_shared::theme::Color;
|
|
||||||
|
|
||||||
use super::Style;
|
use super::Style;
|
||||||
|
|
||||||
|
|
@ -19,54 +18,7 @@ impl Span {
|
||||||
|
|
||||||
impl UserData for Span {
|
impl UserData for Span {
|
||||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
methods.add_function("fg", |_, (ud, color): (AnyUserData, String)| {
|
crate::impl_style_shorthands!(methods, 0.style);
|
||||||
ud.borrow_mut::<Self>()?.0.style.fg = Color::try_from(color).ok().map(Into::into);
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("bg", |_, (ud, color): (AnyUserData, String)| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.bg = Color::try_from(color).ok().map(Into::into);
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("bold", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier |= ratatui::style::Modifier::BOLD;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("dim", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier |= ratatui::style::Modifier::DIM;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("italic", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier |= ratatui::style::Modifier::ITALIC;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("underline", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier |= ratatui::style::Modifier::UNDERLINED;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("blink", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier |= ratatui::style::Modifier::SLOW_BLINK;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("blink_rapid", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier |= ratatui::style::Modifier::RAPID_BLINK;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("reverse", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier |= ratatui::style::Modifier::REVERSED;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("hidden", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier |= ratatui::style::Modifier::HIDDEN;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("crossed", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier |= ratatui::style::Modifier::CROSSED_OUT;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("reset", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.style.add_modifier = ratatui::style::Modifier::empty();
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
|
|
||||||
methods.add_function("style", |_, (ud, value): (AnyUserData, Value)| {
|
methods.add_function("style", |_, (ud, value): (AnyUserData, Value)| {
|
||||||
ud.borrow_mut::<Self>()?.0.style = match value {
|
ud.borrow_mut::<Self>()?.0.style = match value {
|
||||||
|
|
|
||||||
|
|
@ -40,54 +40,8 @@ impl<'a> TryFrom<Table<'a>> for Style {
|
||||||
|
|
||||||
impl UserData for Style {
|
impl UserData for Style {
|
||||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
methods.add_function("fg", |_, (ud, color): (AnyUserData, String)| {
|
crate::impl_style_shorthands!(methods, 0);
|
||||||
ud.borrow_mut::<Self>()?.0.fg = Color::try_from(color).ok().map(Into::into);
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("bg", |_, (ud, color): (AnyUserData, String)| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.bg = Color::try_from(color).ok().map(Into::into);
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("bold", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier |= ratatui::style::Modifier::BOLD;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("dim", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier |= ratatui::style::Modifier::DIM;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("italic", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier |= ratatui::style::Modifier::ITALIC;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("underline", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier |= ratatui::style::Modifier::UNDERLINED;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("blink", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier |= ratatui::style::Modifier::SLOW_BLINK;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("blink_rapid", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier |= ratatui::style::Modifier::RAPID_BLINK;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("reverse", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier |= ratatui::style::Modifier::REVERSED;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("hidden", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier |= ratatui::style::Modifier::HIDDEN;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("crossed", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier |= ratatui::style::Modifier::CROSSED_OUT;
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("reset", |_, ud: AnyUserData| {
|
|
||||||
ud.borrow_mut::<Self>()?.0.add_modifier = ratatui::style::Modifier::empty();
|
|
||||||
Ok(ud)
|
|
||||||
});
|
|
||||||
methods.add_function("patch", |_, (ud, value): (AnyUserData, Value)| {
|
methods.add_function("patch", |_, (ud, value): (AnyUserData, Value)| {
|
||||||
{
|
{
|
||||||
let mut me = ud.borrow_mut::<Self>()?;
|
let mut me = ud.borrow_mut::<Self>()?;
|
||||||
|
|
|
||||||
8
yazi-plugin/src/external/highlighter.rs
vendored
8
yazi-plugin/src/external/highlighter.rs
vendored
|
|
@ -84,6 +84,14 @@ impl Highlighter {
|
||||||
buf.push(b'\n');
|
buf.push(b'\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for b in &mut buf {
|
||||||
|
match *b {
|
||||||
|
b'\0' => return Err("Binary file".into()),
|
||||||
|
b'\r' => *b = b'\n', // '\r' occurs in the middle of a line
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if i > skip {
|
if i > skip {
|
||||||
after.push(String::from_utf8_lossy(&buf).into_owned());
|
after.push(String::from_utf8_lossy(&buf).into_owned());
|
||||||
} else if !plain {
|
} else if !plain {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ pub mod fs;
|
||||||
pub mod isolate;
|
pub mod isolate;
|
||||||
pub mod loader;
|
pub mod loader;
|
||||||
mod lua;
|
mod lua;
|
||||||
|
mod macros;
|
||||||
mod opt;
|
mod opt;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
pub mod pubsub;
|
pub mod pubsub;
|
||||||
|
|
|
||||||
53
yazi-plugin/src/macros.rs
Normal file
53
yazi-plugin/src/macros.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! impl_style_shorthands {
|
||||||
|
($methods:ident, $($field:tt).+) => {
|
||||||
|
$methods.add_function("fg", |_, (ud, color): (AnyUserData, String)| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.fg = yazi_shared::theme::Color::try_from(color).ok().map(Into::into);
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("bg", |_, (ud, color): (AnyUserData, String)| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.bg = yazi_shared::theme::Color::try_from(color).ok().map(Into::into);
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("bold", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::BOLD;
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("dim", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::DIM;
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("italic", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::ITALIC;
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("underline", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::UNDERLINED;
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("blink", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::SLOW_BLINK;
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("blink_rapid", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::RAPID_BLINK;
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("reverse", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::REVERSED;
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("hidden", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::HIDDEN;
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("crossed", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::CROSSED_OUT;
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
$methods.add_function("reset", |_, ud: AnyUserData| {
|
||||||
|
ud.borrow_mut::<Self>()?.$($field).+.add_modifier = ratatui::style::Modifier::empty();
|
||||||
|
Ok(ud)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -39,13 +39,15 @@ impl Utils {
|
||||||
let text =
|
let text =
|
||||||
match Highlighter::new(&lock.url).highlight(lock.skip, area.height as usize).await {
|
match Highlighter::new(&lock.url).highlight(lock.skip, area.height as usize).await {
|
||||||
Ok(text) => text,
|
Ok(text) => text,
|
||||||
Err(PeekError::Exceed(max)) => return (false, max).into_lua_multi(lua),
|
Err(e @ PeekError::Exceed(max)) => return (e.to_string(), max).into_lua_multi(lua),
|
||||||
Err(_) => return (false, Value::Nil).into_lua_multi(lua),
|
Err(e @ PeekError::Unexpected(_)) => {
|
||||||
|
return (e.to_string(), Value::Nil).into_lua_multi(lua);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
lock.data = vec![Box::new(Paragraph { area: *area, text, ..Default::default() })];
|
lock.data = vec![Box::new(Paragraph { area: *area, text, ..Default::default() })];
|
||||||
|
|
||||||
emit!(Call(Cmd::new("preview").with_any("lock", lock), Layer::Manager));
|
emit!(Call(Cmd::new("preview").with_any("lock", lock), Layer::Manager));
|
||||||
(true, Value::Nil).into_lua_multi(lua)
|
(Value::Nil, Value::Nil).into_lua_multi(lua)
|
||||||
})?,
|
})?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ pub enum PeekError {
|
||||||
impl Display for PeekError {
|
impl Display for PeekError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Exceed(lines) => write!(f, "Exceed: {lines}"),
|
Self::Exceed(lines) => write!(f, "Exceed maximum lines {lines}"),
|
||||||
Self::Unexpected(msg) => write!(f, "Unexpected error: {msg}"),
|
Self::Unexpected(msg) => write!(f, "{msg}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue