mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: truncate long paths in archive preview file list (#2778)
This commit is contained in:
parent
70e459a011
commit
b6ae5d3ca9
22 changed files with 257 additions and 87 deletions
|
|
@ -79,8 +79,8 @@ end
|
||||||
function Entity:redraw()
|
function Entity:redraw()
|
||||||
local lines = {}
|
local lines = {}
|
||||||
for _, c in ipairs(self._children) do
|
for _, c in ipairs(self._children) do
|
||||||
local line = ui.Line((type(c[1]) == "string" and self[c[1]] or c[1])(self))
|
local line = (type(c[1]) == "string" and self[c[1]] or c[1])(self)
|
||||||
c.width, lines[#lines + 1] = line:width(), line
|
c.width, lines[#lines + 1] = ui.width(line), line
|
||||||
end
|
end
|
||||||
return ui.Line(lines):style(self:style())
|
return ui.Line(lines):style(self:style())
|
||||||
end
|
end
|
||||||
|
|
@ -101,12 +101,11 @@ function Entity:ellipsis(max)
|
||||||
for _, child in ipairs(self._children) do
|
for _, child in ipairs(self._children) do
|
||||||
adv = adv + child.width
|
adv = adv + child.width
|
||||||
if adv >= max then
|
if adv >= max then
|
||||||
return not f.cha.is_dir and f.url.ext and "…." .. f.url.ext or "…"
|
return not f.cha.is_dir and f.url.ext and "…." .. f.url.ext or nil
|
||||||
elseif child.id == 4 then
|
elseif child.id == 4 then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return "…"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Children
|
-- Children
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ local M = {}
|
||||||
|
|
||||||
function M:peek(job)
|
function M:peek(job)
|
||||||
local limit = job.area.h
|
local limit = job.area.h
|
||||||
local paths, sizes = {}, {}
|
|
||||||
|
|
||||||
local files, bound, code = self.list_files({ "-p", tostring(job.file.url) }, job.skip, limit)
|
local files, bound, code = self.list_files({ "-p", tostring(job.file.url) }, job.skip, limit)
|
||||||
if code ~= 0 then
|
if code ~= 0 then
|
||||||
|
|
@ -13,31 +12,40 @@ function M:peek(job)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local left, right = {}, {}
|
||||||
for _, f in ipairs(files) do
|
for _, f in ipairs(files) do
|
||||||
local icon = File({
|
local icon = File({
|
||||||
url = Url(f.path),
|
url = Url(f.path),
|
||||||
cha = Cha { kind = f.attr:sub(1, 1) == "D" and 1 or 0 },
|
cha = Cha { kind = f.attr:sub(1, 1) == "D" and 1 or 0 },
|
||||||
}):icon()
|
}):icon()
|
||||||
|
|
||||||
if icon then
|
if f.size > 0 then
|
||||||
paths[#paths + 1] = ui.Line { ui.Span(" " .. icon.text .. " "):style(icon.style), f.path }
|
right[#right + 1] = string.format(" %s ", ya.readable_size(f.size))
|
||||||
else
|
else
|
||||||
paths[#paths + 1] = f.path
|
right[#right + 1] = " "
|
||||||
end
|
end
|
||||||
|
|
||||||
if f.size > 0 then
|
if icon then
|
||||||
sizes[#sizes + 1] = string.format(" %s ", ya.readable_size(f.size))
|
left[#left + 1] = ui.Span(" " .. icon.text .. " "):style(icon.style)
|
||||||
else
|
else
|
||||||
sizes[#sizes + 1] = ""
|
left[#left + 1] = " "
|
||||||
end
|
end
|
||||||
|
|
||||||
|
left[#left] = ui.Line {
|
||||||
|
left[#left],
|
||||||
|
ya.truncate(f.path, {
|
||||||
|
rtl = true,
|
||||||
|
max = math.max(0, job.area.w - ui.width(left[#left]) - ui.width(right[#right])),
|
||||||
|
}),
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
if job.skip > 0 and bound < job.skip + limit then
|
if job.skip > 0 and bound < job.skip + limit then
|
||||||
ya.emit("peek", { math.max(0, bound - limit), only_if = job.file.url, upper_bound = true })
|
ya.emit("peek", { math.max(0, bound - limit), only_if = job.file.url, upper_bound = true })
|
||||||
else
|
else
|
||||||
ya.preview_widget(job, {
|
ya.preview_widget(job, {
|
||||||
ui.Text(paths):area(job.area),
|
ui.Text(left):area(job.area),
|
||||||
ui.Text(sizes):area(job.area):align(ui.Text.RIGHT),
|
ui.Text(right):area(job.area):align(ui.Text.RIGHT),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use mlua::{AnyUserData, Lua, MetaMethod, Table, UserData};
|
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||||
use ratatui::widgets::Borders;
|
use ratatui::widgets::Borders;
|
||||||
|
|
||||||
use super::Area;
|
use super::Area;
|
||||||
|
|
@ -13,7 +13,7 @@ pub struct Bar {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bar {
|
impl Bar {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, direction): (Table, u8)| {
|
let new = lua.create_function(|_, (_, direction): (Table, u8)| {
|
||||||
Ok(Self { direction: Borders::from_bits_truncate(direction), ..Default::default() })
|
Ok(Self { direction: Borders::from_bits_truncate(direction), ..Default::default() })
|
||||||
})?;
|
})?;
|
||||||
|
|
@ -29,7 +29,7 @@ impl Bar {
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
bar.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
bar.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
Ok(bar)
|
bar.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn render(
|
pub(super) fn render(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use mlua::{AnyUserData, Lua, MetaMethod, Table, UserData, Value};
|
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||||
use ratatui::widgets::{Borders, Widget};
|
use ratatui::widgets::{Borders, Widget};
|
||||||
|
|
||||||
use super::Area;
|
use super::Area;
|
||||||
|
|
@ -24,7 +24,7 @@ pub struct Border {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Border {
|
impl Border {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, position): (Table, u8)| {
|
let new = lua.create_function(|_, (_, position): (Table, u8)| {
|
||||||
Ok(Border {
|
Ok(Border {
|
||||||
position: ratatui::widgets::Borders::from_bits_truncate(position),
|
position: ratatui::widgets::Borders::from_bits_truncate(position),
|
||||||
|
|
@ -50,7 +50,7 @@ impl Border {
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
border.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
border.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
Ok(border)
|
border.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn render(
|
pub(super) fn render(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use mlua::{Lua, MetaMethod, Table, UserData};
|
use mlua::{IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||||
use yazi_adapter::ADAPTOR;
|
use yazi_adapter::ADAPTOR;
|
||||||
|
|
||||||
use super::Area;
|
use super::Area;
|
||||||
|
|
@ -13,13 +13,13 @@ pub struct Clear {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clear {
|
impl Clear {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, area): (Table, Area)| Ok(Clear { area }))?;
|
let new = lua.create_function(|_, (_, area): (Table, Area)| Ok(Clear { area }))?;
|
||||||
|
|
||||||
let clear = lua.create_table()?;
|
let clear = lua.create_table()?;
|
||||||
clear.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
clear.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
|
|
||||||
Ok(clear)
|
clear.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn render(
|
pub(super) fn render(
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,22 @@
|
||||||
use mlua::{FromLua, Lua, Table, UserData};
|
use mlua::{FromLua, IntoLua, Lua, UserData, Value};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, FromLua)]
|
#[derive(Clone, Copy, Default, FromLua)]
|
||||||
pub struct Constraint(pub(super) ratatui::layout::Constraint);
|
pub struct Constraint(pub(super) ratatui::layout::Constraint);
|
||||||
|
|
||||||
impl Constraint {
|
impl Constraint {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
use ratatui::layout::Constraint as C;
|
use ratatui::layout::Constraint as C;
|
||||||
|
|
||||||
lua.create_table_from([
|
lua
|
||||||
("Min", lua.create_function(|_, n: u16| Ok(Self(C::Min(n))))?),
|
.create_table_from([
|
||||||
("Max", lua.create_function(|_, n: u16| Ok(Self(C::Max(n))))?),
|
("Min", lua.create_function(|_, n: u16| Ok(Self(C::Min(n))))?),
|
||||||
("Length", lua.create_function(|_, n: u16| Ok(Self(C::Length(n))))?),
|
("Max", lua.create_function(|_, n: u16| Ok(Self(C::Max(n))))?),
|
||||||
("Percentage", lua.create_function(|_, n: u16| Ok(Self(C::Percentage(n))))?),
|
("Length", lua.create_function(|_, n: u16| Ok(Self(C::Length(n))))?),
|
||||||
("Ratio", lua.create_function(|_, (a, b): (u32, u32)| Ok(Self(C::Ratio(a, b))))?),
|
("Percentage", lua.create_function(|_, n: u16| Ok(Self(C::Percentage(n))))?),
|
||||||
("Fill", lua.create_function(|_, n: u16| Ok(Self(C::Fill(n))))?),
|
("Ratio", lua.create_function(|_, (a, b): (u32, u32)| Ok(Self(C::Ratio(a, b))))?),
|
||||||
])
|
("Fill", lua.create_function(|_, n: u16| Ok(Self(C::Fill(n))))?),
|
||||||
|
])?
|
||||||
|
.into_lua(lua)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
b"Style" => super::Style::compose(lua)?,
|
b"Style" => super::Style::compose(lua)?,
|
||||||
b"Table" => super::Table::compose(lua)?,
|
b"Table" => super::Table::compose(lua)?,
|
||||||
b"Text" => super::Text::compose(lua)?,
|
b"Text" => super::Text::compose(lua)?,
|
||||||
|
|
||||||
|
b"width" => super::Utils::width(lua)?,
|
||||||
_ => return Ok(Value::Nil),
|
_ => return Ok(Value::Nil),
|
||||||
}
|
}
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||||
use ratatui::widgets::Widget;
|
use ratatui::widgets::Widget;
|
||||||
|
|
||||||
use super::{Area, Span};
|
use super::{Area, Span};
|
||||||
|
|
@ -15,13 +15,13 @@ pub struct Gauge {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gauge {
|
impl Gauge {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, _: Table| Ok(Gauge::default()))?;
|
let new = lua.create_function(|_, _: Table| Ok(Gauge::default()))?;
|
||||||
|
|
||||||
let gauge = lua.create_table()?;
|
let gauge = lua.create_table()?;
|
||||||
gauge.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
gauge.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
|
|
||||||
Ok(gauge)
|
gauge.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn render(
|
pub(super) fn render(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use mlua::{AnyUserData, Lua, MetaMethod, Table, UserData, UserDataMethods};
|
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||||
|
|
||||||
use super::{Constraint, Rect};
|
use super::{Constraint, Rect};
|
||||||
|
|
||||||
|
|
@ -13,13 +13,13 @@ pub struct Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layout {
|
impl Layout {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, _: Table| Ok(Self::default()))?;
|
let new = lua.create_function(|_, _: Table| Ok(Self::default()))?;
|
||||||
|
|
||||||
let layout = lua.create_table_from([("HORIZONTAL", HORIZONTAL), ("VERTICAL", VERTICAL)])?;
|
let layout = lua.create_table_from([("HORIZONTAL", HORIZONTAL), ("VERTICAL", VERTICAL)])?;
|
||||||
layout.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
layout.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
|
|
||||||
Ok(layout)
|
layout.into_lua(lua)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ pub struct Line {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Line {
|
impl Line {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, value): (Table, Value)| Line::try_from(value))?;
|
let new = lua.create_function(|_, (_, value): (Table, Value)| Line::try_from(value))?;
|
||||||
|
|
||||||
let parse = lua.create_function(|_, code: mlua::String| {
|
let parse = lua.create_function(|_, code: mlua::String| {
|
||||||
|
|
@ -47,7 +47,7 @@ impl Line {
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
line.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
line.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
Ok(line)
|
line.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn render(
|
pub(super) fn render(
|
||||||
|
|
@ -148,26 +148,70 @@ impl UserData for Line {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mut width, mut last) = (0, None);
|
fn traverse(
|
||||||
'outer: for (x, span) in me.inner.iter_mut().enumerate() {
|
max: usize,
|
||||||
for (y, c) in span.content.char_indices() {
|
threshold: usize,
|
||||||
width += c.width().unwrap_or(0);
|
it: impl Iterator<Item = (usize, usize, char)>,
|
||||||
match last {
|
) -> (Option<(usize, usize, usize)>, bool) {
|
||||||
None if width > max - ellipsis.0 => last = Some((false, x, y)),
|
let (mut adv, mut cut) = (0, None);
|
||||||
Some((false, x, y)) if width > max => {
|
for (x, y, c) in it {
|
||||||
last = Some((true, x, y));
|
adv += c.width().unwrap_or(0);
|
||||||
break 'outer;
|
if adv <= threshold {
|
||||||
}
|
cut = Some((x, y, adv));
|
||||||
_ => {}
|
} else if adv > max {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(cut, adv > max)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((true, x, y)) = last {
|
let rtl = t.raw_get("rtl")?;
|
||||||
let spans = &mut me.inner.spans;
|
let (cut, remain) = if rtl {
|
||||||
|
traverse(
|
||||||
|
max,
|
||||||
|
max - ellipsis.0,
|
||||||
|
me.inner
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.rev()
|
||||||
|
.flat_map(|(x, s)| s.content.char_indices().rev().map(move |(y, c)| (x, y, c))),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
traverse(
|
||||||
|
max,
|
||||||
|
max - ellipsis.0,
|
||||||
|
me.inner
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(x, s)| s.content.char_indices().map(move |(y, c)| (x, y, c))),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some((x, y, width)) = cut else {
|
||||||
|
me.inner.spans.clear();
|
||||||
|
me.inner.spans.push(ellipsis.1);
|
||||||
|
return Ok(ud);
|
||||||
|
};
|
||||||
|
if !remain {
|
||||||
|
return Ok(ud);
|
||||||
|
}
|
||||||
|
|
||||||
|
let spans = &mut me.inner.spans;
|
||||||
|
let len = match (rtl, width == max) {
|
||||||
|
(a, b) if a == b => spans[x].content[y..].chars().next().map_or(0, |c| c.len_utf8()),
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
if rtl {
|
||||||
match &mut spans[x].content {
|
match &mut spans[x].content {
|
||||||
Cow::Borrowed(s) => spans[x].content = Cow::Borrowed(&s[..y]),
|
Cow::Borrowed(s) => spans[x].content = Cow::Borrowed(&s[y + len..]),
|
||||||
Cow::Owned(s) => s.truncate(y),
|
Cow::Owned(s) => _ = s.drain(..y + len),
|
||||||
|
}
|
||||||
|
spans.splice(..x, [ellipsis.1]);
|
||||||
|
} else {
|
||||||
|
match &mut spans[x].content {
|
||||||
|
Cow::Borrowed(s) => spans[x].content = Cow::Borrowed(&s[..y + len]),
|
||||||
|
Cow::Owned(s) => s.truncate(y + len),
|
||||||
}
|
}
|
||||||
spans.truncate(x + 1);
|
spans.truncate(x + 1);
|
||||||
spans.push(ellipsis.1);
|
spans.push(ellipsis.1);
|
||||||
|
|
@ -177,3 +221,80 @@ impl UserData for Line {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use mlua::{UserDataRef, chunk};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn truncate(s: &str, max: usize, rtl: bool) -> String {
|
||||||
|
let lua = Lua::new();
|
||||||
|
let comp = Line::compose(&lua).unwrap();
|
||||||
|
let line: UserDataRef<Line> = lua
|
||||||
|
.load(chunk! {
|
||||||
|
return $comp($s):truncate { max = $max, rtl = $rtl }
|
||||||
|
})
|
||||||
|
.call(())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
line.inner.spans.iter().map(|s| s.content.as_ref()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_truncate() {
|
||||||
|
assert_eq!(truncate("你好,world", 0, false), "");
|
||||||
|
assert_eq!(truncate("你好,world", 1, false), "…");
|
||||||
|
assert_eq!(truncate("你好,world", 2, false), "…");
|
||||||
|
|
||||||
|
assert_eq!(truncate("你好,世界", 3, false), "你…");
|
||||||
|
assert_eq!(truncate("你好,世界", 4, false), "你…");
|
||||||
|
assert_eq!(truncate("你好,世界", 5, false), "你好…");
|
||||||
|
|
||||||
|
assert_eq!(truncate("Hello, world", 5, false), "Hell…");
|
||||||
|
assert_eq!(truncate("Ni好,世界", 3, false), "Ni…");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_truncate_rtl() {
|
||||||
|
assert_eq!(truncate("world,你好", 0, true), "");
|
||||||
|
assert_eq!(truncate("world,你好", 1, true), "…");
|
||||||
|
assert_eq!(truncate("world,你好", 2, true), "…");
|
||||||
|
|
||||||
|
assert_eq!(truncate("你好,世界", 3, true), "…界");
|
||||||
|
assert_eq!(truncate("你好,世界", 4, true), "…界");
|
||||||
|
assert_eq!(truncate("你好,世界", 5, true), "…世界");
|
||||||
|
|
||||||
|
assert_eq!(truncate("Hello, world", 5, true), "…orld");
|
||||||
|
assert_eq!(truncate("你好,Shi界", 3, true), "…界");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_truncate_oboe() {
|
||||||
|
assert_eq!(truncate("Hello, world", 11, false), "Hello, wor…");
|
||||||
|
assert_eq!(truncate("你好,世界", 9, false), "你好,世…");
|
||||||
|
assert_eq!(truncate("你好,世Jie", 9, false), "你好,世…");
|
||||||
|
|
||||||
|
assert_eq!(truncate("Hello, world", 11, true), "…llo, world");
|
||||||
|
assert_eq!(truncate("你好,世界", 9, true), "…好,世界");
|
||||||
|
assert_eq!(truncate("Ni好,世界", 9, true), "…好,世界");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_truncate_exact() {
|
||||||
|
assert_eq!(truncate("Hello, world", 12, false), "Hello, world");
|
||||||
|
assert_eq!(truncate("你好,世界", 10, false), "你好,世界");
|
||||||
|
|
||||||
|
assert_eq!(truncate("Hello, world", 12, true), "Hello, world");
|
||||||
|
assert_eq!(truncate("你好,世界", 10, true), "你好,世界");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_truncate_overflow() {
|
||||||
|
assert_eq!(truncate("Hello, world", 13, false), "Hello, world");
|
||||||
|
assert_eq!(truncate("你好,世界", 11, false), "你好,世界");
|
||||||
|
|
||||||
|
assert_eq!(truncate("Hello, world", 13, true), "Hello, world");
|
||||||
|
assert_eq!(truncate("你好,世界", 11, true), "你好,世界");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use mlua::{ExternalError, Lua, MetaMethod, Table, UserData, Value};
|
use mlua::{ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||||
use ratatui::widgets::Widget;
|
use ratatui::widgets::Widget;
|
||||||
|
|
||||||
use super::{Area, Text};
|
use super::{Area, Text};
|
||||||
|
|
@ -14,7 +14,7 @@ pub struct List {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl List {
|
impl List {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, seq): (Table, Table)| {
|
let new = lua.create_function(|_, (_, seq): (Table, Table)| {
|
||||||
let mut items = Vec::with_capacity(seq.raw_len());
|
let mut items = Vec::with_capacity(seq.raw_len());
|
||||||
for v in seq.sequence_values::<Value>() {
|
for v in seq.sequence_values::<Value>() {
|
||||||
|
|
@ -27,7 +27,7 @@ impl List {
|
||||||
let list = lua.create_table()?;
|
let list = lua.create_table()?;
|
||||||
list.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
list.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
|
|
||||||
Ok(list)
|
list.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn render(
|
pub(super) fn render(
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
#![allow(clippy::module_inception)]
|
#![allow(clippy::module_inception)]
|
||||||
|
|
||||||
yazi_macro::mod_flat!(area bar border cell clear constraint elements gauge layout line list pad pos rect renderable row span style table text);
|
yazi_macro::mod_flat!(area bar border cell clear constraint elements gauge layout line list pad pos rect renderable row span style table text utils);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::{Add, AddAssign, Deref};
|
use std::ops::{Add, AddAssign, Deref};
|
||||||
|
|
||||||
use mlua::{FromLua, Lua, MetaMethod, Table, UserData};
|
use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, FromLua)]
|
#[derive(Clone, Copy, Default, FromLua)]
|
||||||
pub struct Pad(ratatui::widgets::Padding);
|
pub struct Pad(ratatui::widgets::Padding);
|
||||||
|
|
@ -16,7 +16,7 @@ impl From<ratatui::widgets::Padding> for Pad {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pad {
|
impl Pad {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new =
|
let new =
|
||||||
lua.create_function(|_, (_, top, right, bottom, left): (Table, u16, u16, u16, u16)| {
|
lua.create_function(|_, (_, top, right, bottom, left): (Table, u16, u16, u16, u16)| {
|
||||||
Ok(Self(ratatui::widgets::Padding::new(left, right, top, bottom)))
|
Ok(Self(ratatui::widgets::Padding::new(left, right, top, bottom)))
|
||||||
|
|
@ -47,7 +47,7 @@ impl Pad {
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
pad.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
pad.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
Ok(pad)
|
pad.into_lua(lua)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{ops::Deref, str::FromStr};
|
use std::{ops::Deref, str::FromStr};
|
||||||
|
|
||||||
use mlua::{AnyUserData, ExternalResult, Lua, MetaMethod, Table, UserData};
|
use mlua::{AnyUserData, ExternalResult, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||||
|
|
||||||
use super::Pad;
|
use super::Pad;
|
||||||
|
|
||||||
|
|
@ -46,13 +46,13 @@ impl TryFrom<mlua::Table> for Pos {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pos {
|
impl Pos {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, t): (Table, Table)| Self::try_from(t))?;
|
let new = lua.create_function(|_, (_, t): (Table, Table)| Self::try_from(t))?;
|
||||||
|
|
||||||
let position = lua.create_table()?;
|
let position = lua.create_table()?;
|
||||||
position.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
position.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
|
|
||||||
Ok(position)
|
position.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_input(t: mlua::Table) -> mlua::Result<Self> {
|
pub fn new_input(t: mlua::Table) -> mlua::Result<Self> {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use mlua::{FromLua, Lua, MetaMethod, Table, UserData};
|
use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||||
|
|
||||||
use super::Pad;
|
use super::Pad;
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ impl From<ratatui::layout::Size> for Rect {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rect {
|
impl Rect {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, args): (Table, Table)| {
|
let new = lua.create_function(|_, (_, args): (Table, Table)| {
|
||||||
Ok(Self(ratatui::layout::Rect {
|
Ok(Self(ratatui::layout::Rect {
|
||||||
x: args.raw_get("x").unwrap_or_default(),
|
x: args.raw_get("x").unwrap_or_default(),
|
||||||
|
|
@ -37,7 +37,7 @@ impl Rect {
|
||||||
let rect = lua.create_table_from([("default", Self(ratatui::layout::Rect::default()))])?;
|
let rect = lua.create_table_from([("default", Self(ratatui::layout::Rect::default()))])?;
|
||||||
|
|
||||||
rect.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
rect.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
Ok(rect)
|
rect.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn pad(self, pad: Pad) -> Self {
|
pub(super) fn pad(self, pad: Pad) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, Table, UserData, Value};
|
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||||
|
|
||||||
use super::Cell;
|
use super::Cell;
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@ pub struct Row {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Row {
|
impl Row {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, cells): (Table, Vec<Cell>)| {
|
let new = lua.create_function(|_, (_, cells): (Table, Vec<Cell>)| {
|
||||||
Ok(Self { cells, ..Default::default() })
|
Ok(Self { cells, ..Default::default() })
|
||||||
})?;
|
})?;
|
||||||
|
|
@ -22,7 +22,7 @@ impl Row {
|
||||||
let row = lua.create_table()?;
|
let row = lua.create_table()?;
|
||||||
row.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
row.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
|
|
||||||
Ok(row)
|
row.into_lua(lua)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||||
use unicode_width::UnicodeWidthChar;
|
use unicode_width::UnicodeWidthChar;
|
||||||
|
|
||||||
const EXPECTED: &str = "expected a string or Span";
|
const EXPECTED: &str = "expected a string or Span";
|
||||||
|
|
@ -8,13 +8,13 @@ const EXPECTED: &str = "expected a string or Span";
|
||||||
pub struct Span(pub(super) ratatui::text::Span<'static>);
|
pub struct Span(pub(super) ratatui::text::Span<'static>);
|
||||||
|
|
||||||
impl Span {
|
impl Span {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, value): (Table, Value)| Span::try_from(value))?;
|
let new = lua.create_function(|_, (_, value): (Table, Value)| Span::try_from(value))?;
|
||||||
|
|
||||||
let span = lua.create_table()?;
|
let span = lua.create_table()?;
|
||||||
span.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
span.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
|
|
||||||
Ok(span)
|
span.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn truncate(&mut self, max: usize) -> usize {
|
pub(super) fn truncate(&mut self, max: usize) -> usize {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use mlua::{AnyUserData, ExternalError, ExternalResult, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||||
use yazi_shared::theme::Color;
|
use yazi_shared::theme::Color;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub struct Style(pub(super) ratatui::style::Style);
|
pub struct Style(pub(super) ratatui::style::Style);
|
||||||
|
|
||||||
impl Style {
|
impl Style {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, value): (Table, Value)| Self::try_from(value))?;
|
let new = lua.create_function(|_, (_, value): (Table, Value)| Self::try_from(value))?;
|
||||||
|
|
||||||
let style = lua.create_table()?;
|
let style = lua.create_table()?;
|
||||||
style.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
style.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
|
|
||||||
Ok(style)
|
style.into_lua(lua)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, UserData, Value};
|
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, UserData, Value};
|
||||||
use ratatui::widgets::StatefulWidget;
|
use ratatui::widgets::StatefulWidget;
|
||||||
|
|
||||||
use super::{Area, Row};
|
use super::{Area, Row};
|
||||||
|
|
@ -32,7 +32,7 @@ pub struct Table {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Table {
|
impl Table {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<mlua::Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, seq): (mlua::Table, mlua::Table)| {
|
let new = lua.create_function(|_, (_, seq): (mlua::Table, mlua::Table)| {
|
||||||
let mut rows = Vec::with_capacity(seq.raw_len());
|
let mut rows = Vec::with_capacity(seq.raw_len());
|
||||||
for v in seq.sequence_values::<Value>() {
|
for v in seq.sequence_values::<Value>() {
|
||||||
|
|
@ -45,7 +45,7 @@ impl Table {
|
||||||
let table = lua.create_table()?;
|
let table = lua.create_table()?;
|
||||||
table.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
table.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
|
|
||||||
Ok(table)
|
table.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn selected_cell(&self) -> Option<&ratatui::text::Text> {
|
pub fn selected_cell(&self) -> Option<&ratatui::text::Text> {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ pub struct Text {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Text {
|
impl Text {
|
||||||
pub fn compose(lua: &Lua) -> mlua::Result<Table> {
|
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let new = lua.create_function(|_, (_, value): (Table, Value)| Text::try_from(value))?;
|
let new = lua.create_function(|_, (_, value): (Table, Value)| Text::try_from(value))?;
|
||||||
|
|
||||||
let parse = lua.create_function(|_, code: mlua::String| {
|
let parse = lua.create_function(|_, code: mlua::String| {
|
||||||
|
|
@ -49,7 +49,7 @@ impl Text {
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
text.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
text.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||||
Ok(text)
|
text.into_lua(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn render(
|
pub(super) fn render(
|
||||||
|
|
|
||||||
35
yazi-plugin/src/elements/utils.rs
Normal file
35
yazi-plugin/src/elements/utils.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
use mlua::{ExternalError, IntoLua, Lua, Value};
|
||||||
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
|
use super::{Line, Span};
|
||||||
|
|
||||||
|
pub(super) struct Utils;
|
||||||
|
|
||||||
|
impl Utils {
|
||||||
|
pub(super) fn width(lua: &Lua) -> mlua::Result<Value> {
|
||||||
|
let f = lua.create_function(|_, v: Value| match v {
|
||||||
|
Value::String(s) => {
|
||||||
|
let (mut acc, b) = (0, s.as_bytes());
|
||||||
|
for c in b.utf8_chunks() {
|
||||||
|
acc += c.valid().width();
|
||||||
|
if !c.invalid().is_empty() {
|
||||||
|
acc += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(acc)
|
||||||
|
}
|
||||||
|
Value::UserData(ud) => {
|
||||||
|
if let Ok(line) = ud.borrow::<Line>() {
|
||||||
|
Ok(line.inner.width())
|
||||||
|
} else if let Ok(span) = ud.borrow::<Span>() {
|
||||||
|
Ok(span.0.width())
|
||||||
|
} else {
|
||||||
|
Err("expected a string, Line, or Span".into_lua_err())?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err("expected a string, Line, or Span".into_lua_err())?,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
f.into_lua(lua)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -96,17 +96,20 @@ impl Utils {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use mlua::Value;
|
use mlua::chunk;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn truncate(s: &str, max: usize, rtl: bool) -> String {
|
fn truncate(s: &str, max: usize, rtl: bool) -> String {
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
let t = lua
|
let f = Utils::truncate(&lua).unwrap();
|
||||||
.create_table_from([("max", Value::Integer(max as i64)), ("rtl", Value::Boolean(rtl))])
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Utils::truncate(&lua).unwrap().call((s, t)).unwrap()
|
lua
|
||||||
|
.load(chunk! {
|
||||||
|
return $f($s, { max = $max, rtl = $rtl })
|
||||||
|
})
|
||||||
|
.call(())
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue