Skip to content

Commit

Permalink
feat(statusline)!: various improvements:
Browse files Browse the repository at this point in the history
* remove `stl` field in favor of reference `_tree`
* add clear_tree() and traverse() methods
* refactor eval -> _eval; _eval does not return a value
* add eval(), which wraps _eval and traverse and returns a string
* refactor _win_stl -> _win_cache
* improve effectiveness of flexible components (do not wait for next
  iteration)
* improve tabline constructor (pages and buttons)
  • Loading branch information
rebelot committed Aug 28, 2022
1 parent 5b2f174 commit 09bf058
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 131 deletions.
23 changes: 11 additions & 12 deletions lua/heirline/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -61,33 +61,32 @@ function M.eval_statusline()
M.statusline.winnr = vim.api.nvim_win_get_number(0)
M.statusline.flexible_components = {}
local out = M.statusline:eval()
utils.expand_or_contract_flexible_components(M.statusline, vim.o.laststatus == 3, out)
return out
utils.expand_or_contract_flexible_components(M.statusline.flexible_components, vim.o.laststatus == 3, out)
return M.statusline:traverse()
end

---@return string
function M.eval_winbar()
M.winbar.winnr = vim.api.nvim_win_get_number(0)
M.winbar.flexible_components = {}
local out = M.winbar:eval()
utils.expand_or_contract_flexible_components(M.winbar, false, out)
return out
utils.expand_or_contract_flexible_components(M.winbar.flexible_components, false, out)
return M.winbar:traverse()
end

---@return string
function M.eval_tabline()
M.tabline.winnr = 1
M.tabline.flexible_components = {}
M.tabline._buflist = {}
M.tabline._eval_buflist = false
local out = M.tabline:eval()
if vim.tbl_isempty(M.tabline._buflist) then
return out
local buflist = M.tabline._buflist[1]
if buflist then
buflist._maxwidth = vim.o.columns - (utils.count_chars(out) - utils.count_chars(buflist:traverse()))
utils.page_buflist(buflist)
end
-- utils.expand_or_contract_flexible_components(M.tabline, true, out)
M.tabline._maxwidth = vim.o.columns - utils.count_chars(out) + string.len("#BUFLIST#")
M.tabline._eval_buflist = true
M.tabline._buflist[1]:eval()
return vim.fn.substitute(out, "#BUFLIST#", M.tabline._buflist[1].stl, "")
-- utils.expand_or_contract_flexible_components(M.tabline.flexible_components, true, out)
return M.tabline:traverse()
end

-- test [[
Expand Down
91 changes: 62 additions & 29 deletions lua/heirline/statusline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ local default_restrict = {
after = true,
on_click = true,
update = true,
stl = true,
_win_stl = true,
_win_cache = true,
_au_id = true,
}

Expand All @@ -25,11 +24,11 @@ local default_restrict = {
---@field after? function
---@field update? function | table
---@field on_click? function | table
---@field stl string
---@field id table<integer>
---@field winnr integer
---@field _win_stl? table
---@field _win_cache? table
---@field _au_id? integer
---@field _tree table
---@field pick_child? table<integer>
local StatusLine = {
hl = {},
Expand Down Expand Up @@ -146,11 +145,7 @@ end
---@param attr string
---@return any
function StatusLine:local_(attr)
local orig_mt = getmetatable(self)
setmetatable(self, {})
local result = self[attr]
setmetatable(self, orig_mt)
return result
return rawget(self, attr)
end

--- Set window-nr attribute
Expand Down Expand Up @@ -211,7 +206,7 @@ local function register_update_autocmd(component)
local id = vim.api.nvim_create_autocmd(events, {
pattern = pattern,
callback = function(args)
component._win_stl = nil
component._win_cache = nil
if callback then
callback(component, args)
end
Expand All @@ -223,36 +218,46 @@ local function register_update_autocmd(component)
end

---Evaluate component and its children recursively
---@return string
function StatusLine:eval()
---@return nil
function StatusLine:_eval()
if self.condition and not self:condition() then
-- self.stl = ''
return ""
-- return ""
return
end

-- if not self:nonlocal("_tree") then
if not self:local_("_tree") then
-- root component has no parent tree
-- may be "stray" component
self._tree = {}
else
-- clear the tree at each cycle
self:clear_tree()
end

if self.update then
if type(self.update) == "function" then
if self:update() then
self._win_stl = nil
self._win_cahe = nil
end
else
if not self._au_id then
register_update_autocmd(self)
end
end

local win_stl = self:get_win_attr("_win_stl")
if win_stl then
return win_stl
local win_cache = self:get_win_attr("_win_cache")
if win_cache then
table.insert(self._tree, win_cache)
return
end
end

if self.init then
self:init()
end

local stl = {}

local hl = type(self.hl) == "function" and (self:hl() or {}) or self.hl -- self raw hl

if type(hl) == "string" then
Expand All @@ -269,14 +274,16 @@ function StatusLine:eval()

if self.on_click then
local func_name = register_global_function(self)
local minwid = type(self.on_click.minwid) == "function" and self.on_click.minwid(self) or self.on_click.minwid or ""
table.insert(stl, "%" .. minwid .. "@" .. func_name .. "@")
local minwid = type(self.on_click.minwid) == "function" and self.on_click.minwid(self)
or self.on_click.minwid
or ""
table.insert(self._tree, "%" .. minwid .. "@" .. func_name .. "@")
end

if self.provider then
local provider_str = type(self.provider) == "function" and (self:provider() or "") or (self.provider or "")
local hl_str_start, hl_str_end = hi.eval_hl(self.merged_hl)
table.insert(stl, hl_str_start .. provider_str .. hl_str_end)
table.insert(self._tree, hl_str_start .. provider_str .. hl_str_end)
end

local children_i
Expand All @@ -291,25 +298,51 @@ function StatusLine:eval()

for _, i in ipairs(children_i) do
local child = self[i]
local out = child:eval()
table.insert(stl, out)
child._tree = {}
table.insert(self._tree, child._tree)
child:_eval()
end

if self.on_click then
table.insert(stl, "%X")
table.insert(self._tree, "%X")
end

self.stl = table.concat(stl, "")

if self.after then
self:after()
end

if self.update then
self:set_win_attr("_win_stl", self.stl)
self:set_win_attr("_win_cache", self:traverse())
end
end

return self.stl
function StatusLine:traverse(tree, stl)
stl = stl or {}
tree = tree or self._tree

for _, node in ipairs(tree) do
if type(node) ~= "table" then
table.insert(stl, node)
else
self:traverse(node, stl)
end
end
return table.concat(stl, "")
end

function StatusLine:clear_tree()
local tree = rawget(self, "_tree")
if not tree then
return
end
for i, _ in ipairs(tree) do
self._tree[i] = nil
end
end

function StatusLine:eval()
self:_eval()
return self:traverse()
end

return StatusLine

0 comments on commit 09bf058

Please sign in to comment.