yazi/yazi-plugin/preset/components/status.lua

181 lines
4.2 KiB
Lua

Status = {
LEFT = 0,
RIGHT = 1,
_id = "status",
_inc = 1000,
_left = {
{ "mode", id = 1, order = 1000 },
{ "size", id = 2, order = 2000 },
{ "name", id = 3, order = 3000 },
},
_right = {
{ "permissions", id = 4, order = 1000 },
{ "percentage", id = 5, order = 2000 },
{ "position", id = 6, order = 3000 },
},
}
function Status:new(area, tab)
return setmetatable({
_area = area,
_tab = tab,
}, { __index = self })
end
function Status:style()
if self._tab.mode.is_select then
return THEME.status.mode_select
elseif self._tab.mode.is_unset then
return THEME.status.mode_unset
else
return THEME.status.mode_normal
end
end
function Status:mode()
local mode = tostring(self._tab.mode):sub(1, 3):upper()
local style = self:style()
return ui.Line {
ui.Span(THEME.status.separator_open):fg(style.bg),
ui.Span(" " .. mode .. " "):style(style),
ui.Span(THEME.status.separator_close):fg(style.bg):bg(THEME.status.separator_style.fg),
}
end
function Status:size()
local h = self._tab.current.hovered
if not h then
return ui.Line {}
end
local style = self:style()
return ui.Line {
ui.Span(" " .. ya.readable_size(h:size() or h.cha.len) .. " "):fg(style.bg):bg(THEME.status.separator_style.bg),
ui.Span(THEME.status.separator_close):fg(THEME.status.separator_style.fg),
}
end
function Status:name()
local h = self._tab.current.hovered
if not h then
return ui.Line {}
end
return ui.Line(" " .. h.name)
end
function Status:permissions()
local h = self._tab.current.hovered
if not h then
return ui.Line {}
end
local perm = h.cha:perm()
if not perm then
return ui.Line {}
end
local spans = {}
for i = 1, #perm do
local c = perm:sub(i, i)
local style = THEME.status.permissions_t
if c == "-" or c == "?" then
style = THEME.status.permissions_s
elseif c == "r" then
style = THEME.status.permissions_r
elseif c == "w" then
style = THEME.status.permissions_w
elseif c == "x" or c == "s" or c == "S" or c == "t" or c == "T" then
style = THEME.status.permissions_x
end
spans[i] = ui.Span(c):style(style)
end
return ui.Line(spans)
end
function Status:percentage()
local percent = 0
local cursor = self._tab.current.cursor
local length = #self._tab.current.files
if cursor ~= 0 and length ~= 0 then
percent = math.floor((cursor + 1) * 100 / length)
end
if percent == 0 then
percent = " Top "
elseif percent == 100 then
percent = " Bot "
else
percent = string.format(" %2d%% ", percent)
end
local style = self:style()
return ui.Line {
ui.Span(" " .. THEME.status.separator_open):fg(THEME.status.separator_style.fg),
ui.Span(percent):fg(style.bg):bg(THEME.status.separator_style.bg),
}
end
function Status:position()
local cursor = self._tab.current.cursor
local length = #self._tab.current.files
local style = self:style()
return ui.Line {
ui.Span(THEME.status.separator_open):fg(style.bg):bg(THEME.status.separator_style.fg),
ui.Span(string.format(" %2d/%-2d ", cursor + 1, length)):style(style),
ui.Span(THEME.status.separator_close):fg(style.bg),
}
end
function Status:render()
local left = self:children_render(self.LEFT)
local right = self:children_render(self.RIGHT)
local right_width = right:width()
return {
ui.Text(left):area(self._area),
ui.Text(right):area(self._area):align(ui.Text.RIGHT),
table.unpack(Progress:render(self._area, right_width)),
}
end
-- Mouse events
function Status:click(event, up) end
function Status:scroll(event, step) end
function Status:touch(event, step) end
-- Children
function Status:children_add(fn, order, side)
self._inc = self._inc + 1
local children = side == self.RIGHT and self._right or self._left
children[#children + 1] = { fn, id = self._inc, order = order }
table.sort(children, function(a, b) return a.order < b.order end)
return self._inc
end
function Status:children_remove(id, side)
local children = side == self.RIGHT and self._right or self._left
for i, child in ipairs(children) do
if child.id == id then
table.remove(children, i)
break
end
end
end
function Status:children_render(side)
local lines = {}
for _, c in ipairs(side == self.RIGHT and self._right or self._left) do
lines[#lines + 1] = (type(c[1]) == "string" and self[c[1]] or c[1])(self)
end
return ui.Line(lines)
end