Skip to content

Commit

Permalink
refactor(statusline): set 'statusline' once (and not update on events)
Browse files Browse the repository at this point in the history
Details:
- Setting targeted window-local values of 'statusline' on appropriate
  events is (on paper) better for performance. However, this introduces
  issues when those targeted events don't trigger (like `noautocmd` with
  floating windows). Although blocking important events is more or less
  a fault of what's blocking them, working around various issues doesn't
  really worth a performance boost.

  Instead set 'statusline' option once globally to a Vimscript value
  which will dynamically decide which content (active or inactive) to
  show. The computation overhead is pretty minimal (around 0.13
  microseconds for every 'statusline' evaluation) but the increase in
  robustness seems to be worth it (as now type of content will be
  decided just at the time when it is needed).

  This is made possible by a deeply hidden `g:actual_curwin` variable
  which is set during `%{%...%}` statusline evaluation specifically for
  this reason (to be able for the statusline to be both evaluated inside
  its target window and decide if that target is actually current).
  • Loading branch information
echasnovski committed Feb 12, 2025
1 parent f6747ee commit b628477
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 22 deletions.
24 changes: 3 additions & 21 deletions lua/mini/statusline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,12 @@ MiniStatusline.config = {
--- Compute content for active window
MiniStatusline.active = function()
if H.is_disabled() then return '' end

return (H.get_config().content.active or H.default_content_active)()
end

--- Compute content for inactive window
MiniStatusline.inactive = function()
if H.is_disabled() then return '' end

return (H.get_config().content.inactive or H.default_content_inactive)()
end

Expand Down Expand Up @@ -506,12 +504,9 @@ H.apply_config = function(config)
-- Set settings to ensure statusline is displayed properly
if config.set_vim_settings and (vim.o.laststatus == 0 or vim.o.laststatus == 1) then vim.o.laststatus = 2 end

-- Ensure proper 'statusline' values (to not rely on autocommands trigger)
H.ensure_content()

-- Set global value to reduce flickering when first time entering buffer, as
-- it is used by default before content is ensured on next loop
vim.go.statusline = '%{%v:lua.MiniStatusline.active()%}'
-- Set statusline globally and dynamically decide which content to use
vim.go.statusline =
'%{%(nvim_get_current_win()==#g:actual_curwin || &laststatus==3) ? v:lua.MiniStatusline.active() : v:lua.MiniStatusline.inactive()%}'
end

H.create_autocommands = function()
Expand All @@ -521,8 +516,6 @@ H.create_autocommands = function()
vim.api.nvim_create_autocmd(event, { group = gr, pattern = pattern, callback = callback, desc = desc })
end

au({ 'WinEnter', 'BufWinEnter' }, '*', H.ensure_content, 'Ensure statusline content')

-- Use `schedule_wrap()` because at `LspDetach` server is still present
local track_lsp = vim.schedule_wrap(function(data)
H.attached_lsp[data.buf] = vim.api.nvim_buf_is_valid(data.buf) and H.compute_attached_lsp(data.buf) or nil
Expand Down Expand Up @@ -567,17 +560,6 @@ H.get_config = function(config)
return vim.tbl_deep_extend('force', MiniStatusline.config, vim.b.ministatusline_config or {}, config or {})
end

-- Content --------------------------------------------------------------------
H.ensure_content = vim.schedule_wrap(function()
-- NOTE: Use `schedule_wrap()` to properly work inside autocommands because
-- they might temporarily change current window
local cur_win_id, is_global_stl = vim.api.nvim_get_current_win(), vim.o.laststatus == 3
for _, win_id in ipairs(vim.api.nvim_list_wins()) do
vim.wo[win_id].statusline = (win_id == cur_win_id or is_global_stl) and '%{%v:lua.MiniStatusline.active()%}'
or '%{%v:lua.MiniStatusline.inactive()%}'
end
end)

-- Mode -----------------------------------------------------------------------
-- Custom `^V` and `^S` symbols to make this file appropriate for copy-paste
-- (otherwise those symbols are not displayed).
Expand Down
5 changes: 4 additions & 1 deletion tests/test_statusline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ T['setup()']['creates side effects'] = function()
has_highlight('MiniStatuslineInactive', 'links to StatusLineNC')

-- Sets global value of 'statusline'
eq(child.go.statusline, '%{%v:lua.MiniStatusline.active()%}')
eq(
child.go.statusline,
'%{%(nvim_get_current_win()==#g:actual_curwin || &laststatus==3) ? v:lua.MiniStatusline.active() : v:lua.MiniStatusline.inactive()%}'
)
end

T['setup()']['creates `config` field'] = function()
Expand Down

0 comments on commit b628477

Please sign in to comment.