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,
}
function Header:cwd()
function Header:cwd(max)
local cwd = cx.active.current.cwd
local readable = ya.readable_path(tostring(cwd))
local span
if not cwd.is_search then
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)
local text = cwd.is_search and string.format("%s (search: %s)", readable, cwd:frag()) or readable
return ui.Span(ya.truncate(text, { max = max, rtl = true })):style(THEME.manager.cwd)
end
function Header:count()
@ -49,7 +45,7 @@ function Header:tabs()
for i = 1, tabs do
local text = i
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
if i == cx.tabs.idx then
spans[#spans + 1] = ui.Span(" " .. text .. " "):style(THEME.manager.tab_active)
@ -60,7 +56,18 @@ function Header:tabs()
return ui.Line(spans)
end
-- TODO: remove this function after v0.2.5 release
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
return ui.Layout()
@ -70,12 +77,12 @@ function Header:layout(area)
end
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 left = ui.Line { self:cwd(math.max(0, area.w - right:width())) }
return {
ui.Paragraph(chunks[1], { left }),
ui.Paragraph(chunks[2], { right }):align(ui.Paragraph.RIGHT),
ui.Paragraph(area, { left }),
ui.Paragraph(area, { right }):align(ui.Paragraph.RIGHT),
}
end

View file

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