feat: truncate path for deeply nested directories (#787)

This commit is contained in:
翊小久 2024-03-08 17:54:29 +08:00 committed by GitHub
parent d96af54574
commit 3f80bc56a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 45 additions and 29 deletions

View file

@ -2,16 +2,12 @@ Header = {
area = ui.Rect.default, area = ui.Rect.default,
} }
function Header:cwd() function Header:cwd(max)
local cwd = cx.active.current.cwd local cwd = cx.active.current.cwd
local readable = ya.readable_path(tostring(cwd))
local span local text = cwd.is_search and string.format("%s (search: %s)", readable, cwd:frag()) or readable
if not cwd.is_search then return ui.Span(ya.truncate(text, { max = max, rtl = true })):style(THEME.manager.cwd)
span = ui.Span(ya.readable_path(tostring(cwd)))
else
span = ui.Span(string.format("%s (search: %s)", ya.readable_path(tostring(cwd)), cwd:frag()))
end
return span:style(THEME.manager.cwd)
end end
function Header:count() function Header:count()
@ -49,7 +45,7 @@ function Header:tabs()
for i = 1, tabs do for i = 1, tabs do
local text = i local text = i
if THEME.manager.tab_width > 2 then if THEME.manager.tab_width > 2 then
text = ya.truncate(text .. " " .. cx.tabs[i]:name(), THEME.manager.tab_width) text = ya.truncate(text .. " " .. cx.tabs[i]:name(), { max = THEME.manager.tab_width })
end end
if i == cx.tabs.idx then if i == cx.tabs.idx then
spans[#spans + 1] = ui.Span(" " .. text .. " "):style(THEME.manager.tab_active) spans[#spans + 1] = ui.Span(" " .. text .. " "):style(THEME.manager.tab_active)
@ -60,7 +56,18 @@ function Header:tabs()
return ui.Line(spans) return ui.Line(spans)
end end
-- TODO: remove this function after v0.2.5 release
function Header:layout(area) function Header:layout(area)
if not ya.deprecated_header_layout then
ya.deprecated_header_layout = true
ya.notify {
title = "Deprecated API",
content = "`Header:layout()` is deprecated, please apply the latest `Header:render()` in your `init.lua`",
timeout = 5,
level = "warn",
}
end
self.area = area self.area = area
return ui.Layout() return ui.Layout()
@ -70,12 +77,12 @@ function Header:layout(area)
end end
function Header:render(area) function Header:render(area)
local chunks = self:layout(area) self.area = area
local left = ui.Line { self:cwd() }
local right = ui.Line { self:count(), self:tabs() } local right = ui.Line { self:count(), self:tabs() }
local left = ui.Line { self:cwd(math.max(0, area.w - right:width())) }
return { return {
ui.Paragraph(chunks[1], { left }), ui.Paragraph(area, { left }),
ui.Paragraph(chunks[2], { right }):align(ui.Paragraph.RIGHT), ui.Paragraph(area, { right }):align(ui.Paragraph.RIGHT),
} }
end end

View file

@ -1,7 +1,7 @@
use std::ops::ControlFlow; use std::ops::ControlFlow;
use mlua::{Lua, Table}; use mlua::{Lua, Table};
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; use unicode_width::UnicodeWidthChar;
use super::Utils; use super::Utils;
@ -20,26 +20,35 @@ impl Utils {
ya.raw_set( ya.raw_set(
"truncate", "truncate",
lua.create_function(|_, (text, max): (mlua::String, usize)| { lua.create_function(|_, (text, t): (mlua::String, Table)| {
let mut width = 0; let (max, text) = (t.raw_get("max")?, text.to_string_lossy());
let flow =
text.to_string_lossy().chars().try_fold(String::with_capacity(max), |mut s, c| {
width += c.width().unwrap_or(0);
if s.width() < max {
s.push(c);
ControlFlow::Continue(s)
} else {
ControlFlow::Break(s)
}
});
Ok(match flow { Ok(if t.raw_get("rtl").unwrap_or(false) {
ControlFlow::Break(s) => s, Self::truncate(text.chars().rev(), max).into_iter().rev().collect()
ControlFlow::Continue(s) => s, } else {
Self::truncate(text.chars(), max).into_iter().collect::<String>()
}) })
})?, })?,
)?; )?;
Ok(()) Ok(())
} }
fn truncate(mut chars: impl Iterator<Item = char>, max: usize) -> Vec<char> {
let mut width = 0;
let flow = chars.try_fold(Vec::with_capacity(max), |mut v, c| {
width += c.width().unwrap_or(0);
if width < max {
v.push(c);
ControlFlow::Continue(v)
} else {
ControlFlow::Break(v)
}
});
match flow {
ControlFlow::Break(v) => v,
ControlFlow::Continue(v) => v,
}
}
} }