mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: show file extension for truncated file list items (#2759)
This commit is contained in:
parent
9a0ef6bb20
commit
464acfe47b
9 changed files with 122 additions and 44 deletions
36
Cargo.lock
generated
36
Cargo.lock
generated
|
|
@ -252,9 +252,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.0"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "bitstream-io"
|
||||
|
|
@ -572,7 +572,7 @@ version = "0.28.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"crossterm_winapi",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
|
|
@ -588,7 +588,7 @@ version = "0.29.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"crossterm_winapi",
|
||||
"derive_more",
|
||||
"document-features",
|
||||
|
|
@ -1163,7 +1163,7 @@ version = "0.11.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
|
|
@ -1305,7 +1305,7 @@ version = "0.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
|
@ -1527,7 +1527,7 @@ version = "8.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"filetime",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
|
|
@ -1658,7 +1658,7 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
|
|
@ -1998,7 +1998,7 @@ version = "0.29.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"cassowary",
|
||||
"compact_str",
|
||||
"crossterm 0.28.1",
|
||||
|
|
@ -2078,7 +2078,7 @@ version = "0.5.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2169,7 +2169,7 @@ version = "0.38.44"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
|
|
@ -2182,7 +2182,7 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
|
|
@ -3006,9 +3006,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
|
||||
checksum = "78c888f2a25014723b17ac60a626d626549f773e0d702b1320956f8d769ae1f8"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
|
|
@ -3278,7 +3278,7 @@ version = "0.39.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3377,7 +3377,7 @@ name = "yazi-config"
|
|||
version = "25.5.14"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"crossterm 0.29.0",
|
||||
"dirs",
|
||||
"globset",
|
||||
|
|
@ -3399,7 +3399,7 @@ name = "yazi-core"
|
|||
version = "25.5.14"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"crossterm 0.29.0",
|
||||
"dirs",
|
||||
"futures",
|
||||
|
|
@ -3509,7 +3509,7 @@ version = "25.5.14"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"core-foundation-sys",
|
||||
"dirs",
|
||||
"foldhash",
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ lto = false
|
|||
ansi-to-tui = "7.0.0"
|
||||
anyhow = "1.0.98"
|
||||
base64 = "0.22.1"
|
||||
bitflags = "2.9.0"
|
||||
bitflags = "2.9.1"
|
||||
clap = { version = "4.5.38", features = [ "derive" ] }
|
||||
core-foundation-sys = "0.8.7"
|
||||
crossterm = { version = "0.29.0", features = [ "event-stream" ] }
|
||||
|
|
|
|||
|
|
@ -34,9 +34,11 @@ function Current:redraw()
|
|||
|
||||
local left, right = {}, {}
|
||||
for _, f in ipairs(files) do
|
||||
left[#left + 1] = Entity:new(f):redraw()
|
||||
right[#right + 1] = Linemode:new(f):redraw()
|
||||
left[#left]:truncate { max = math.max(0, self._area.w - right[#right]:width()) }
|
||||
local entity = Entity:new(f)
|
||||
left[#left + 1], right[#right + 1] = entity:redraw(), Linemode:new(f):redraw()
|
||||
|
||||
local max = math.max(0, self._area.w - right[#right]:width())
|
||||
left[#left]:truncate { max = max, ellipsis = entity:ellipsis(max) }
|
||||
end
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ end
|
|||
function Entity:redraw()
|
||||
local lines = {}
|
||||
for _, c in ipairs(self._children) do
|
||||
lines[#lines + 1] = (type(c[1]) == "string" and self[c[1]] or c[1])(self)
|
||||
local line = ui.Line((type(c[1]) == "string" and self[c[1]] or c[1])(self))
|
||||
c.width, lines[#lines + 1] = line:width(), line
|
||||
end
|
||||
return ui.Line(lines):style(self:style())
|
||||
end
|
||||
|
|
@ -95,6 +96,19 @@ function Entity:style()
|
|||
end
|
||||
end
|
||||
|
||||
function Entity:ellipsis(max)
|
||||
local adv, f = 0, self._file
|
||||
for _, child in ipairs(self._children) do
|
||||
adv = adv + child.width
|
||||
if adv > max then
|
||||
return not f.cha.is_dir and f.url.ext and "…." .. f.url.ext or "…"
|
||||
elseif child.id == 4 then
|
||||
break
|
||||
end
|
||||
end
|
||||
return "…"
|
||||
end
|
||||
|
||||
-- Children
|
||||
function Entity:children_add(fn, order)
|
||||
self._inc = self._inc + 1
|
||||
|
|
|
|||
|
|
@ -19,7 +19,11 @@ function Parent:redraw()
|
|||
|
||||
local items = {}
|
||||
for _, f in ipairs(self._folder.window) do
|
||||
items[#items + 1] = Entity:new(f):redraw():truncate { max = self._area.w }
|
||||
local entity = Entity:new(f)
|
||||
items[#items + 1] = entity:redraw():truncate {
|
||||
max = self._area.w,
|
||||
ellipsis = entity:ellipsis(self._area.w),
|
||||
}
|
||||
end
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,11 @@ function M:peek(job)
|
|||
|
||||
local items = {}
|
||||
for _, f in ipairs(folder.window) do
|
||||
items[#items + 1] = Entity:new(f):redraw():truncate { max = job.area.w }
|
||||
local entity = Entity:new(f)
|
||||
items[#items + 1] = entity:redraw():truncate {
|
||||
max = job.area.w,
|
||||
ellipsis = entity:ellipsis(job.area.w),
|
||||
}
|
||||
end
|
||||
|
||||
ya.preview_widget(job, {
|
||||
|
|
|
|||
|
|
@ -133,27 +133,46 @@ impl UserData for Line {
|
|||
});
|
||||
methods.add_function_mut("truncate", |_, (ud, t): (AnyUserData, Table)| {
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
let max = t.raw_get("max")?;
|
||||
|
||||
let mut width = 0;
|
||||
let max = t.raw_get("max")?;
|
||||
if max < 1 {
|
||||
me.inner.spans.clear();
|
||||
return Ok(ud);
|
||||
}
|
||||
|
||||
let ellipsis = match t.raw_get::<Value>("ellipsis")? {
|
||||
Value::Nil => (1, ratatui::text::Span::raw("…")),
|
||||
v => {
|
||||
let mut span = Span::try_from(v)?;
|
||||
(span.truncate(max), span.0)
|
||||
}
|
||||
};
|
||||
|
||||
let (mut width, mut last) = (0, None);
|
||||
'outer: for (x, span) in me.inner.iter_mut().enumerate() {
|
||||
for (y, c) in span.content.char_indices() {
|
||||
width += c.width().unwrap_or(0);
|
||||
if width < max {
|
||||
continue;
|
||||
} else if width == max && span.content[y..].chars().nth(1).is_none() {
|
||||
continue;
|
||||
match last {
|
||||
None if width > max - ellipsis.0 => last = Some((false, x, y)),
|
||||
Some((false, x, y)) if width > max => {
|
||||
last = Some((true, x, y));
|
||||
break 'outer;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match &mut span.content {
|
||||
Cow::Borrowed(s) => span.content = Cow::Borrowed(&s[..y]),
|
||||
Cow::Owned(s) => s.truncate(y),
|
||||
}
|
||||
me.inner.spans.truncate(x + 1);
|
||||
me.inner.spans.push(ratatui::text::Span::raw("…"));
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((true, x, y)) = last {
|
||||
let spans = &mut me.inner.spans;
|
||||
match &mut spans[x].content {
|
||||
Cow::Borrowed(s) => spans[x].content = Cow::Borrowed(&s[..y]),
|
||||
Cow::Owned(s) => s.truncate(y),
|
||||
}
|
||||
spans.truncate(x + 1);
|
||||
spans.push(ellipsis.1);
|
||||
}
|
||||
|
||||
Ok(ud)
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use mlua::{ExternalError, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use unicode_width::UnicodeWidthChar;
|
||||
|
||||
const EXPECTED: &str = "expected a string or Span";
|
||||
|
|
@ -14,6 +16,36 @@ impl Span {
|
|||
|
||||
Ok(span)
|
||||
}
|
||||
|
||||
pub(super) fn truncate(&mut self, max: usize) -> usize {
|
||||
if max < 1 {
|
||||
match &mut self.0.content {
|
||||
Cow::Borrowed(_) => self.0.content = Cow::Borrowed(""),
|
||||
Cow::Owned(s) => s.clear(),
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut adv = 0;
|
||||
let mut last;
|
||||
for (i, c) in self.0.content.char_indices() {
|
||||
(last, adv) = (adv, adv + c.width().unwrap_or(0));
|
||||
if adv < max {
|
||||
continue;
|
||||
} else if adv == max && self.0.content[i..].chars().nth(1).is_none() {
|
||||
return max;
|
||||
}
|
||||
match &mut self.0.content {
|
||||
Cow::Borrowed(s) => self.0.content = format!("{}…", &s[..i]).into(),
|
||||
Cow::Owned(s) => {
|
||||
s.truncate(i);
|
||||
s.push('…');
|
||||
}
|
||||
}
|
||||
return last + 1;
|
||||
}
|
||||
adv
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Value> for Span {
|
||||
|
|
@ -42,5 +74,9 @@ impl UserData for Span {
|
|||
methods.add_method("visible", |_, Span(me), ()| {
|
||||
Ok(me.content.chars().any(|c| c.width().unwrap_or(0) > 0))
|
||||
});
|
||||
methods.add_function_mut("truncate", |_, (ud, t): (AnyUserData, Table)| {
|
||||
ud.borrow_mut::<Self>()?.truncate(t.raw_get("max")?);
|
||||
Ok(ud)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,10 +68,9 @@ impl Utils {
|
|||
|
||||
pub(super) fn confirm(lua: &Lua) -> mlua::Result<Function> {
|
||||
fn content(t: &Table) -> mlua::Result<ratatui::widgets::Paragraph<'static>> {
|
||||
Ok(match t.raw_get::<Value>("content") {
|
||||
Ok(v) if v.is_nil() => Default::default(),
|
||||
Ok(v) => Text::try_from(v)?.into(),
|
||||
Err(e) => Err(e)?,
|
||||
Ok(match t.raw_get::<Value>("content")? {
|
||||
Value::Nil => Default::default(),
|
||||
v => Text::try_from(v)?.into(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue