mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat!: redesign tabs (#2745)
This commit is contained in:
parent
41cba40072
commit
ea90b0477e
8 changed files with 113 additions and 42 deletions
|
|
@ -38,11 +38,6 @@ marker_cut = { fg = "lightred", bg = "lightred" }
|
|||
marker_marked = { fg = "lightcyan", bg = "lightcyan" }
|
||||
marker_selected = { fg = "lightyellow", bg = "lightyellow" }
|
||||
|
||||
# Tab
|
||||
tab_active = { reversed = true }
|
||||
tab_inactive = {}
|
||||
tab_width = 1
|
||||
|
||||
# Count
|
||||
count_copied = { fg = "white", bg = "green" }
|
||||
count_cut = { fg = "white", bg = "red" }
|
||||
|
|
@ -58,6 +53,19 @@ syntect_theme = ""
|
|||
# : }}}
|
||||
|
||||
|
||||
# : Tabs {{{
|
||||
|
||||
[tabs]
|
||||
active = { bg = "blue", bold = true }
|
||||
inactive = { fg = "blue", bg = "gray" }
|
||||
|
||||
# Separator
|
||||
sep_inner = { open = "", close = "" }
|
||||
sep_outer = { open = "", close = "" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Mode {{{
|
||||
|
||||
[mode]
|
||||
|
|
|
|||
|
|
@ -38,11 +38,6 @@ marker_cut = { fg = "lightred", bg = "lightred" }
|
|||
marker_marked = { fg = "lightcyan", bg = "lightcyan" }
|
||||
marker_selected = { fg = "lightyellow", bg = "lightyellow" }
|
||||
|
||||
# Tab
|
||||
tab_active = { reversed = true }
|
||||
tab_inactive = {}
|
||||
tab_width = 1
|
||||
|
||||
# Count
|
||||
count_copied = { fg = "white", bg = "green" }
|
||||
count_cut = { fg = "white", bg = "red" }
|
||||
|
|
@ -58,6 +53,19 @@ syntect_theme = ""
|
|||
# : }}}
|
||||
|
||||
|
||||
# : Tabs {{{
|
||||
|
||||
[tabs]
|
||||
active = { bg = "blue", bold = true }
|
||||
inactive = { fg = "blue", bg = "gray" }
|
||||
|
||||
# Separator
|
||||
sep_inner = { open = "", close = "" }
|
||||
sep_outer = { open = "", close = "" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Mode {{{
|
||||
|
||||
[mode]
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ pub struct Theme {
|
|||
pub flavor: Flavor,
|
||||
#[serde(rename = "manager")]
|
||||
pub mgr: Mgr, // TODO: Remove `serde(rename)`
|
||||
pub tabs: Tabs,
|
||||
pub mode: Mode,
|
||||
pub status: Status,
|
||||
pub which: Which,
|
||||
|
|
@ -53,11 +54,6 @@ pub struct Mgr {
|
|||
marker_marked: Style,
|
||||
marker_selected: Style,
|
||||
|
||||
// Tab
|
||||
tab_active: Style,
|
||||
tab_inactive: Style,
|
||||
tab_width: u8,
|
||||
|
||||
// Count
|
||||
count_copied: Style,
|
||||
count_cut: Style,
|
||||
|
|
@ -71,6 +67,21 @@ pub struct Mgr {
|
|||
pub syntect_theme: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
pub struct Tabs {
|
||||
pub active: Style,
|
||||
pub inactive: Style,
|
||||
|
||||
pub sep_inner: TabsSep,
|
||||
pub sep_outer: TabsSep,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
pub struct TabsSep {
|
||||
pub open: String,
|
||||
pub close: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
pub struct Mode {
|
||||
pub normal_main: Style,
|
||||
|
|
@ -197,9 +208,7 @@ pub struct Help {
|
|||
|
||||
impl Theme {
|
||||
pub(crate) fn reshape(mut self, light: bool) -> Result<Self> {
|
||||
if self.mgr.tab_width < 1 {
|
||||
bail!("[mgr].tab_width must be greater than 0");
|
||||
} else if self.which.cols < 1 || self.which.cols > 3 {
|
||||
if self.which.cols < 1 || self.which.cols > 3 {
|
||||
bail!("[which].cols must be between 1 and 3");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ Header = {
|
|||
},
|
||||
_right = {
|
||||
{ "count", id = 1, order = 1000 },
|
||||
{ "tabs", id = 2, order = 2000 },
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -74,27 +73,6 @@ function Header:count()
|
|||
}
|
||||
end
|
||||
|
||||
function Header:tabs()
|
||||
local tabs = #cx.tabs
|
||||
if tabs == 1 then
|
||||
return ""
|
||||
end
|
||||
|
||||
local spans = {}
|
||||
for i = 1, tabs do
|
||||
local text = i
|
||||
if th.mgr.tab_width > 2 then
|
||||
text = ya.truncate(text .. " " .. cx.tabs[i].name, { max = th.mgr.tab_width })
|
||||
end
|
||||
if i == cx.tabs.idx then
|
||||
spans[#spans + 1] = ui.Span(" " .. text .. " "):style(th.mgr.tab_active)
|
||||
else
|
||||
spans[#spans + 1] = ui.Span(" " .. text .. " "):style(th.mgr.tab_inactive)
|
||||
end
|
||||
end
|
||||
return ui.Line(spans)
|
||||
end
|
||||
|
||||
function Header:reflow() return { self } end
|
||||
|
||||
function Header:redraw()
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ function Root:layout()
|
|||
:direction(ui.Layout.VERTICAL)
|
||||
:constraints({
|
||||
ui.Constraint.Length(1),
|
||||
ui.Constraint.Length(#cx.tabs > 1 and 1 or 0),
|
||||
ui.Constraint.Fill(1),
|
||||
ui.Constraint.Length(1),
|
||||
})
|
||||
|
|
@ -24,8 +25,9 @@ end
|
|||
function Root:build()
|
||||
self._children = {
|
||||
Header:new(self._chunks[1], cx.active),
|
||||
Tab:new(self._chunks[2], cx.active),
|
||||
Status:new(self._chunks[3], cx.active),
|
||||
Tabs:new(self._chunks[2]),
|
||||
Tab:new(self._chunks[3], cx.active),
|
||||
Status:new(self._chunks[4], cx.active),
|
||||
Modal:new(self._area),
|
||||
}
|
||||
end
|
||||
|
|
|
|||
64
yazi-plugin/preset/components/tabs.lua
Normal file
64
yazi-plugin/preset/components/tabs.lua
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
Tabs = {
|
||||
_id = "tabs",
|
||||
_offsets = {},
|
||||
}
|
||||
|
||||
function Tabs:new(area)
|
||||
return setmetatable({
|
||||
_area = area,
|
||||
}, { __index = self })
|
||||
end
|
||||
|
||||
function Tabs:reflow() return { self } end
|
||||
|
||||
function Tabs:redraw()
|
||||
local len = #cx.tabs
|
||||
if len < 2 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local lines = {
|
||||
ui.Line(th.tabs.sep_outer.open):fg(th.tabs.inactive.bg),
|
||||
}
|
||||
|
||||
local pos = lines[1]:width()
|
||||
local max = math.floor(self:inner_width() / len)
|
||||
for i = 1, len do
|
||||
local name = ya.truncate(string.format(" %d %s ", i, cx.tabs[i].name), { max = max })
|
||||
if i == cx.tabs.idx then
|
||||
lines[#lines + 1] = ui.Line {
|
||||
ui.Span(th.tabs.sep_inner.open):style(th.tabs.inactive),
|
||||
ui.Span(name):style(th.tabs.active),
|
||||
ui.Span(th.tabs.sep_inner.close):style(th.tabs.inactive),
|
||||
}
|
||||
else
|
||||
lines[#lines + 1] = ui.Line(name):style(th.tabs.inactive)
|
||||
end
|
||||
self._offsets[i], pos = pos, pos + lines[#lines]:width()
|
||||
end
|
||||
|
||||
lines[#lines + 1] = ui.Line(th.tabs.sep_outer.close):fg(th.tabs.inactive.bg)
|
||||
return { ui.Line(lines):area(self._area) }
|
||||
end
|
||||
|
||||
function Tabs:inner_width()
|
||||
local si, so = th.tabs.sep_inner, th.tabs.sep_outer
|
||||
return math.max(0, self._area.w - ui.Line({ si.open, si.close, so.open, so.close }):width())
|
||||
end
|
||||
|
||||
-- Mouse events
|
||||
function Tabs:click(event, up)
|
||||
if up or event.is_middle then
|
||||
return
|
||||
end
|
||||
for i = #self._offsets, 1, -1 do
|
||||
if event.x >= self._offsets[i] then
|
||||
ya.emit("tab_switch", { i - 1 })
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Tabs:scroll(event, step) end
|
||||
|
||||
function Tabs:touch(event, step) end
|
||||
|
|
@ -11,6 +11,7 @@ impl Theme {
|
|||
Composer::make(lua, 15, |lua, key| {
|
||||
match key {
|
||||
b"mgr" => lua.to_value_with(&THEME.mgr, OPTS)?,
|
||||
b"tabs" => lua.to_value_with(&THEME.tabs, OPTS)?,
|
||||
b"mode" => lua.to_value_with(&THEME.mode, OPTS)?,
|
||||
b"status" => lua.to_value_with(&THEME.status, OPTS)?,
|
||||
b"which" => lua.to_value_with(&THEME.which, OPTS)?,
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ fn stage_1(lua: &'static Lua) -> Result<()> {
|
|||
lua.load(preset!("components/root")).set_name("root.lua").exec()?;
|
||||
lua.load(preset!("components/status")).set_name("status.lua").exec()?;
|
||||
lua.load(preset!("components/tab")).set_name("tab.lua").exec()?;
|
||||
lua.load(preset!("components/tabs")).set_name("tabs.lua").exec()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue