feat: refresh lualine based on timer + winbar support. (#736)

* feat: refresh lualine based on timer.

* fix config test

* fix lag on win change issue

* handle errors in timer callback

* feat: add winbar support

Pull in winbar changes form pr #689 and adapt them
Co-authored-by: shadmansaleh <13149513+shadmansaleh@users.noreply.github.com>

* make winbar disapear when winbar evals empty

* only update stl of curwin with globalstatus

* properly clear win local stl and wbr opts

* add version guards for winbar feature

* only add winbar if height > 1

* fix tests?

* refresh lualine on ModeChanged event

* ignore floating windows for refresh

* properply restore options to previous state

* fix stl not updating in cmd mode + some optimizations

* fix tests on <nvim-0.7

* merge status_dispatch & winbar_dispatch + winbar support for extensions

* fix globalstatus option not live updating

* update docs

* feat: allow disabling winbar and statusline separately

* fix tests

* fix: winbar some times oddly throwing errors

about not having space in floating windows.

This implements a temporary workaround the issue(https://github.com/neovim/neovim/issues/19464)
until the bug in neovim gets fixed.

Co-authored-by: Diego Fujii <android.mxdiego9@gmail.com>
This commit is contained in:
Shadman 2022-07-22 19:29:55 +06:00 committed by GitHub
parent 8d956c1825
commit 53aa3d82d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 475 additions and 79 deletions

View File

@ -121,9 +121,17 @@ require('lualine').setup {
theme = 'auto',
component_separators = { left = '', right = ''},
section_separators = { left = '', right = ''},
disabled_filetypes = {},
disabled_filetypes = {
statusline = {},
winbar = {},
},
always_divide_middle = true,
globalstatus = false,
refresh = {
statusline = 1000,
tabline = 1000,
winbar = 1000,
}
},
sections = {
lualine_a = {'mode'},
@ -142,6 +150,8 @@ require('lualine').setup {
lualine_z = {}
},
tabline = {},
winbar = {},
inactive_winbar = {},
extensions = {}
}
```
@ -336,13 +346,28 @@ options = {
theme = 'auto', -- lualine theme
component_separators = { left = '', right = '' },
section_separators = { left = '', right = '' },
disabled_filetypes = {}, -- Filetypes to disable lualine for.
disabled_filetypes = { -- Filetypes to disable lualine for.
statusline = {}, -- only ignores the ft for statusline.
winbar = {}, -- only ignores the ft for winbar.
},
always_divide_middle = true, -- When set to true, left sections i.e. 'a','b' and 'c'
-- can't take over the entire statusline even
-- if neither of 'x', 'y' or 'z' are present.
globalstatus = false, -- enable global statusline (have a single statusline
-- at bottom of neovim instead of one for every window).
-- This feature is only available in neovim 0.7 and higher.
refresh = { -- sets how often lualine should refreash it's contents (in ms)
statusline = 1000, -- The refresh option sets minimum time that lualine tries
tabline = 1000, -- to maintain between refresh. It's not guarantied if situation
winbar = 1000 -- arises that lualine needs to refresh itself before this time
-- it'll do it.
-- Also you can force lualine's refresh by calling refresh function
-- like require('lualine').refresh()
}
}
```
@ -689,6 +714,34 @@ tabline = {
}
```
### Winbar
From neovim-0.8 you can customize your winbar with lualine.
Winbar configuration is similar to statusline.
```lua
winbar = {
lualine_a = {},
lualine_b = {},
lualine_c = {'filename'},
lualine_x = {},
lualine_y = {},
lualine_z = {}
}
inactive_winbar = {
lualine_a = {},
lualine_b = {},
lualine_c = {'filename'},
lualine_x = {},
lualine_y = {},
lualine_z = {}
}
```
Just like statusline you can separately specify winbar for active and inactive
windows. Any lualine component can be placed in winbar. All kinds of custom
components supported in statusline are also suported for winbar too. In general
You can treat winbar as another lualine statusline that just appears on top
of windows instead of at bottom.
#### Buffers
Shows currently open buffers. Like bufferline . See

View File

@ -1,5 +1,7 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local M = {}
local lualine_require = require('lualine_require')
local modules = lualine_require.lazy_require {
highlight = 'lualine.highlight',
@ -8,9 +10,20 @@ local modules = lualine_require.lazy_require {
utils = 'lualine.utils.utils',
utils_notices = 'lualine.utils.notices',
config_module = 'lualine.config',
nvim_opts = 'lualine.utils.nvim_opts'
}
local config -- Stores currently applied config
local timers = {
stl_timer = vim.loop.new_timer(),
tal_timer = vim.loop.new_timer(),
wb_timer = vim.loop.new_timer(),
}
-- The events on which lualine redraws itself
local default_refresh_events = 'WinEnter,BufEnter,SessionLoadPost,FileChangedShellPost,VimResized'
if vim.fn.has('nvim-0.7') == 1 then -- utilize ModeChanged event introduced in 0.7
default_refresh_events = default_refresh_events..',ModeChanged'
end
-- Helper for apply_transitional_separators()
--- finds first applied highlight group after str_checked in status
---@param status string : unprocessed statusline string
@ -140,7 +153,7 @@ end
--- component objects
---@param is_focused boolean : whether being evaluated for focused window or not
---@return string statusline string
local statusline = modules.utils.retry_call_wrap(function(sections, is_focused)
local statusline = modules.utils.retry_call_wrap(function(sections, is_focused, is_winbar)
-- The sequence sections should maintain [SECTION_SEQUENCE]
local section_sequence = { 'a', 'b', 'c', 'x', 'y', 'z' }
local status = {}
@ -167,7 +180,7 @@ local statusline = modules.utils.retry_call_wrap(function(sections, is_focused)
end
end
end
if applied_midsection_divider == false and config.options.always_divide_middle ~= false then
if applied_midsection_divider == false and config.options.always_divide_middle ~= false and not is_winbar then
-- When non of section x,y,z is present
table.insert(status, modules.highlight.format_highlight('c', is_focused) .. '%=')
end
@ -182,15 +195,10 @@ end)
-- TODO: change this so it uses a hash table instead of iteration over list
-- to improve redraws. Add buftype / bufname for extensions
-- or some kind of cond ?
local function get_extension_sections(current_ft, is_focused)
local function get_extension_sections(current_ft, is_focused, sec_name)
for _, extension in ipairs(config.extensions) do
for _, filetype in ipairs(extension.filetypes) do
if current_ft == filetype then
if is_focused == false and extension.inactive_sections then
return extension.inactive_sections
end
return extension.sections
end
if vim.tbl_contains(extension.filetypes, current_ft) then
return extension[(is_focused and '' or 'inactive_') .. sec_name]
end
end
return nil
@ -252,63 +260,192 @@ local function setup_theme()
autocmd lualine OptionSet background lua require'lualine'.setup()]])
end
---@alias StatusDispatchSecs
---| 'sections'
---| 'winbar'
--- generates lualine.statusline & lualine.winbar function
--- creates a closer that can draw sections of sec_name.
---@param sec_name StatusDispatchSecs
---@return function(focused:bool):string
local function status_dispatch(sec_name)
return function(focused)
local retval
local current_ft = vim.bo.filetype
local is_focused = focused ~= nil and focused or modules.utils.is_focused()
if vim.tbl_contains(config.options.disabled_filetypes[(sec_name == 'sections' and 'statusline' or sec_name)],
current_ft) then
-- disable on specific filetypes
return ''
end
local extension_sections = get_extension_sections(current_ft, is_focused, sec_name)
if extension_sections ~= nil then
retval = statusline(extension_sections, is_focused, sec_name == 'winbar')
else
retval = statusline(config[(is_focused and '' or 'inactive_')..sec_name], is_focused, sec_name == 'winbar')
end
return retval
end
end
---@alias LualineRefreshOptsKind
---| 'all'
---| 'tabpage'
---| 'window'
---@alias LualineRefreshOptsPlace
---| 'statusline'
---| 'tabline'
---| 'winbar'
---@class LualineRefreshOpts
---@field kind LualineRefreshOptsKind
---@field place LualineRefreshOptsPlace[]
---@field trigger 'autocmd'|'timer'|'unknown'
--- Refresh contents of lualine
---@param opts LualineRefreshOpts
local function refresh(opts)
if opts == nil then
opts = {kind = 'tabpage', place = {'statusline', 'winbar', 'tabline'}, trigger='unknown'}
end
-- workaround for https://github.com/neovim/neovim/issues/19464
if (opts.trigger == 'autocmd'
and vim.api.nvim_win_get_height(vim.api.nvim_get_current_win()) <= 1
and vim.tbl_contains(opts.place, 'winbar')
) then
local id
for index, value in ipairs(opts.place) do
if value == 'winbar' then
id = index
break
end
end
table.remove(opts.place, id)
end
local wins = {}
local old_actual_curwin = vim.g.actual_curwin
vim.g.actual_curwin = vim.api.nvim_get_current_win()
-- gather which windows needs update
if opts.kind == 'all' then
if vim.tbl_contains(opts.place, 'statusline')
or vim.tbl_contains(opts.place, 'winbar') then
wins = vim.tbl_filter(function (win)
return vim.fn.win_gettype(win) ~= 'popup'
end, vim.api.nvim_list_wins())
end
elseif opts.kind == 'tabpage' then
if vim.tbl_contains(opts.place, 'statusline')
or vim.tbl_contains(opts.place, 'winbar') then
wins = vim.tbl_filter(function (win)
return vim.fn.win_gettype(win) ~= 'popup'
end, vim.api.nvim_tabpage_list_wins(0))
end
elseif opts.kind == 'window' then
wins = {vim.api.nvim_get_current_win()}
end
-- update them
if vim.tbl_contains(opts.place, 'statusline') then
for _, win in ipairs(wins) do
modules.nvim_opts.set('statusline',
vim.api.nvim_win_call(win, M.statusline), {window=win})
end
end
if vim.tbl_contains(opts.place, 'winbar') then
for _, win in ipairs(wins) do
if vim.api.nvim_win_get_height(win) > 1 then
modules.nvim_opts.set('winbar',
vim.api.nvim_win_call(win, M.winbar), {window=win})
end
end
end
if vim.tbl_contains(opts.place, 'tabline') then
modules.nvim_opts.set('tabline',
vim.api.nvim_win_call(vim.api.nvim_get_current_win(), tabline),
{global=true})
end
-- call redraw
if vim.tbl_contains(opts.place, 'statusline')
or vim.tbl_contains(opts.place, 'winbar') then
vim.cmd('redrawstatus')
elseif vim.tbl_contains(opts.place, 'tabline') then
vim.cmd('redrawtabline')
end
vim.g.actual_curwin = old_actual_curwin
end
--- Sets &tabline option to lualine
local function set_tabline()
vim.loop.timer_stop(timers.tal_timer)
vim.cmd([[augroup lualine_tal_refresh | exe "autocmd!" | augroup END]])
if next(config.tabline) ~= nil then
vim.go.tabline = "%{%v:lua.require'lualine'.tabline()%}"
vim.go.showtabline = 2
elseif vim.go.tabline == "%{%v:lua.require'lualine'.tabline()%}" then
vim.go.tabline = ''
vim.go.showtabline = 1
vim.loop.timer_start(timers.tal_timer, 0, config.options.refresh.tabline,
modules.utils.timer_call(timers.stl_timer, 'lualine_tal_refresh', function ()
refresh({kind='tabpage', place={'tabline'}, trigger='timer'})
end, 3, "lualine: Failed to refresh tabline"))
modules.utils.define_autocmd(default_refresh_events,
'*', "call v:lua.require'lualine'.refresh({'kind': 'tabpage', 'place': ['tabline'], 'trigger': 'autocmd'})",
'lualine_tal_refresh')
modules.nvim_opts.set('showtabline', 2, {global=true})
else
modules.nvim_opts.restore('tabline', {global=true})
modules.nvim_opts.restore('showtabline', {global=true})
end
end
--- Sets &statusline option to lualine
--- adds auto command to redraw lualine on VimResized event
local function set_statusline()
vim.loop.timer_stop(timers.stl_timer)
vim.cmd([[augroup lualine_stl_refresh | exe "autocmd!" | augroup END]])
if next(config.sections) ~= nil or next(config.inactive_sections) ~= nil then
vim.cmd('autocmd lualine VimResized * redrawstatus')
vim.go.statusline = "%{%v:lua.require'lualine'.statusline()%}"
if config.options.globalstatus then
vim.go.laststatus = 3
modules.nvim_opts.set('laststatus', 3, {global=true})
vim.loop.timer_start(timers.stl_timer, 0, config.options.refresh.statusline,
modules.utils.timer_call(timers.stl_timer, 'lualine_stl_refresh', function ()
refresh({kind='window', place={'statusline'}, trigger='timer'})
end, 3, "lualine: Failed to refresh statusline"))
modules.utils.define_autocmd(default_refresh_events,
'*', "call v:lua.require'lualine'.refresh({'kind': 'window', 'place': ['statusline'], 'trigger': 'autocmd'})",
'lualine_stl_refresh')
else
modules.nvim_opts.set('laststatus', 2, {global=true})
vim.loop.timer_start(timers.stl_timer, 0, config.options.refresh.statusline,
modules.utils.timer_call(timers.stl_timer, 'lualine_stl_refresh', function ()
refresh({kind='tabpage', place={'statusline'}, trigger='timer'})
end, 3, "lualine: Failed to refresh statusline"))
modules.utils.define_autocmd(default_refresh_events,
'*', "call v:lua.require'lualine'.refresh({'kind': 'tabpage', 'place': ['statusline'], 'trigger': 'autocmd'})",
'lualine_stl_refresh')
end
elseif vim.go.statusline == "%{%v:lua.require'lualine'.statusline()%}" then
vim.go.statusline = ''
if config.options.globalstatus then
vim.go.laststatus = 2
else
modules.nvim_opts.restore('statusline', {global=true})
for _, win in ipairs(vim.api.nvim_list_wins()) do
modules.nvim_opts.restore('statusline', {window=win})
end
modules.nvim_opts.restore('laststatus', {global=true})
end
end
-- lualine.statusline function
--- Draw correct statusline for current window
---@param focused boolean : force the value of is_focused . Useful for debugging
---@return string statusline string
local function status_dispatch(focused)
local retval
local current_ft = vim.bo.filetype
local is_focused = focused ~= nil and focused or modules.utils.is_focused()
for _, ft in pairs(config.options.disabled_filetypes) do
-- disable on specific filetypes
if ft == current_ft then
return ''
--- Sets &winbar option to lualine
local function set_winbar()
vim.loop.timer_stop(timers.wb_timer)
vim.cmd([[augroup lualine_wb_refresh | exe "autocmd!" | augroup END]])
if next(config.winbar) ~= nil or next(config.inactive_winbar) ~= nil then
vim.loop.timer_start(timers.stl_timer, 0, config.options.refresh.winbar,
modules.utils.timer_call(timers.stl_timer, 'lualine_wb_refresh', function ()
refresh({kind='tabpage', place={'winbar'}, trigger='timer'})
end, 3, "lualine: Failed to refresh winbar"))
modules.utils.define_autocmd(default_refresh_events,
'*', "call v:lua.require'lualine'.refresh({'kind': 'tabpage', 'place': ['winbar'], 'trigger': 'autocmd'})",
'lualine_wb_refresh')
elseif vim.fn.has('nvim-0.8') == 1 then
modules.nvim_opts.restore('winbar', {global=true})
for _, win in ipairs(vim.api.nvim_list_wins()) do
modules.nvim_opts.restore('winbar', {window=win})
end
end
local extension_sections = get_extension_sections(current_ft, is_focused)
if is_focused then
if extension_sections ~= nil then
retval = statusline(extension_sections, is_focused)
else
retval = statusline(config.sections, is_focused)
end
else
if extension_sections ~= nil then
retval = statusline(extension_sections, is_focused)
else
retval = statusline(config.inactive_sections, is_focused)
end
end
return retval
end
-- lualine.setup function
@ -332,14 +469,19 @@ local function setup(user_config)
modules.loader.load_all(config)
set_statusline()
set_tabline()
set_winbar()
if package.loaded['lualine.utils.notices'] then
modules.utils_notices.notice_message_startup()
end
end
return {
M = {
setup = setup,
statusline = status_dispatch,
statusline = status_dispatch('sections'),
tabline = tabline,
get_config = modules.config_module.get_config,
refresh = refresh,
winbar = status_dispatch('winbar'),
}
return M

View File

@ -12,9 +12,17 @@ local config = {
theme = 'auto',
component_separators = { left = '', right = '' },
section_separators = { left = '', right = '' },
disabled_filetypes = {},
disabled_filetypes = {
statusline = {},
winbar = {}
},
always_divide_middle = true,
globalstatus = false,
globalstatus = vim.go.laststatus == 3,
refresh = {
statusline = 1000,
tabline = 1000,
winbar = 1000,
}
},
sections = {
lualine_a = { 'mode' },
@ -33,6 +41,8 @@ local config = {
lualine_z = {},
},
tabline = {},
winbar = {},
inactive_winbar = {},
extensions = {},
}
@ -48,6 +58,24 @@ local function fix_separators(separators)
return separators
end
---copy raw disabled_filetypes to inner statusline & winbar tables.
---@param disabled_filetypes table
---@return table
local function fix_disabled_filetypes(disabled_filetypes)
if disabled_filetypes == nil then return end
if disabled_filetypes.statusline == nil then
disabled_filetypes.statusline = {}
end
if disabled_filetypes.winbar == nil then
disabled_filetypes.winbar = {}
end
for k, disabled_ft in ipairs(disabled_filetypes) do
table.insert(disabled_filetypes.statusline, disabled_ft)
table.insert(disabled_filetypes.winbar, disabled_ft)
disabled_filetypes[k] = nil
end
return disabled_filetypes
end
---extends config based on config_table
---@param config_table table
---@return table copy of config
@ -73,15 +101,25 @@ local function apply_configuration(config_table)
)
config_table.options.globalstatus = false
end
if vim.fn.has('nvim-0.8') == 0 and (next(config_table.winbar or {}) or next(config_table.inactive_winbar or {})) then
modules.utils_notices.add_notice(
'### winbar\nSorry `winbar can only be used in neovim 0.8 or higher.\n'
)
config_table.winbar = {}
config_table.inactive_winbar = {}
end
parse_sections('options')
parse_sections('sections')
parse_sections('inactive_sections')
parse_sections('tabline')
parse_sections('winbar')
parse_sections('inactive_winbar')
if config_table.extensions then
config.extensions = utils.deepcopy(config_table.extensions)
end
config.options.section_separators = fix_separators(config.options.section_separators)
config.options.component_separators = fix_separators(config.options.component_separators)
config.options.disabled_filetypes = fix_disabled_filetypes(config.options.disabled_filetypes)
return utils.deepcopy(config)
end

View File

@ -154,29 +154,22 @@ end
---loads all the configs (active, inactive, tabline)
---@param config table user config
local function load_components(config)
load_sections(config.sections, config.options)
load_sections(config.inactive_sections, config.options)
load_sections(config.tabline, config.options)
local sec_names = {'sections', 'inactive_sections', 'tabline', 'winbar', 'inactive_winbar'}
for _, section in ipairs(sec_names) do
load_sections(config[section], config.options)
end
end
---loads all the extensions
---@param config table user config
local function load_extensions(config)
local loaded_extensions = {}
local sec_names = {'sections', 'inactive_sections', 'winbar', 'inactive_winbar'}
for _, extension in pairs(config.extensions) do
if type(extension) == 'string' then
local ok, local_extension = pcall(require, 'lualine.extensions.' .. extension)
if ok then
local_extension = modules.utils.deepcopy(local_extension)
load_sections(local_extension.sections, config.options)
if local_extension.inactive_sections then
load_sections(local_extension.inactive_sections, config.options)
end
if type(local_extension.init) == 'function' then
local_extension.init()
end
table.insert(loaded_extensions, local_extension)
else
local ok
ok, extension = pcall(require, 'lualine.extensions.' .. extension)
if not ok then
modules.notice.add_notice(string.format(
[[
### Extensions
@ -185,11 +178,13 @@ Extension named `%s` was not found . Check if spelling is correct.
extension
))
end
elseif type(extension) == 'table' then
end
if type(extension) == 'table' then
local local_extension = modules.utils.deepcopy(extension)
load_sections(local_extension.sections, config.options)
if local_extension.inactive_sections then
load_sections(local_extension.inactive_sections, config.options)
for _, section in ipairs(sec_names) do
if local_extension[section] then
load_sections(local_extension[section], config.options)
end
end
if type(local_extension.init) == 'function' then
local_extension.init()
@ -205,6 +200,7 @@ end
local function load_all(config)
require('lualine.component')._reset_components()
modules.fn_store.clear_fns()
require('lualine.utils.nvim_opts').reset_cache()
load_components(config)
load_extensions(config)
end

View File

@ -0,0 +1,126 @@
local M = {}
-- keeps backup of options that we cahge so we can restore it.
-- format:
-- options {
-- global = <1> {
-- name = {prev, set}
-- },
-- buffer = {
-- buf1 = <1>,
-- buf2 = <1>
-- },
-- window = {
-- win1 = <1>,
-- win2 = <1>
-- }
-- }
---@class LualineNvimOptCacheOptStore
---@field prev any
---@field set any
---@alias LualineNvimOptCacheOpt table<string, LualineNvimOptCacheOptStore>
---@class LualineNvimOptCache
---@field global LualineNvimOptCacheOpt[]
---@field buffer table<number, LualineNvimOptCacheOpt[]>
---@field window table<number, LualineNvimOptCacheOpt[]>
---@type LualineNvimOptCache
local options = {global={}, buffer={}, window={}}
-- helper function for M.set
local function set_opt(name, val, getter_fn, setter_fn, cache_tbl)
-- before nvim 0.7 nvim_win_get_option... didn't return default value when
-- the option wasn't set instead threw error.
-- So we need pcall (probably just for test)
local ok, cur = pcall(getter_fn, name)
if not ok then cur = nil end
if cur == val then return end
if cache_tbl[name] == nil then cache_tbl[name] = {} end
if cache_tbl[name].set ~= cur then
cache_tbl[name].prev = cur
end
cache_tbl[name].set = val
setter_fn(name, val)
end
-- set a option value
---@param name string
---@param val any
---@param opts table|nil when table can be {global=true | buffer = bufnr | window = winnr}
--- when nil it's treated as {global = true}
function M.set(name, val, opts)
if opts == nil or opts.global then
set_opt(name, val, vim.api.nvim_get_option, vim.api.nvim_set_option, options.global)
elseif opts.buffer then
if options.buffer[opts.buffer] == nil then
options.buffer[opts.buffer] = {}
end
set_opt(name, val, function (nm)
return vim.api.nvim_buf_get_option(opts.buffer, nm)
end, function (nm, vl)
vim.api.nvim_buf_set_option(opts.buffer, nm, vl)
end, options.buffer[opts.buffer])
elseif opts.window then
if options.window[opts.window] == nil then
options.window[opts.window] = {}
end
set_opt(name, val, function (nm)
return vim.api.nvim_win_get_option(opts.window, nm)
end, function (nm, vl)
vim.api.nvim_win_set_option(opts.window, nm, vl)
end, options.window[opts.window])
end
end
-- resoters old value of option name
---@param name string
---@param opts table|nil same as M.set
function M.restore(name, opts)
if opts == nil or opts.global then
if options.global[name] ~= nil and options.global[name].prev ~= nil then
vim.api.nvim_set_option(name, options.global[name].prev)
end
elseif opts.buffer then
if options.buffer[opts.buffer] ~= nil
and options.buffer[opts.buffer][name] ~= nil
and options.buffer[opts.buffer][name].prev ~= nil then
vim.api.nvim_buf_set_option(opts.buffer, name, options.buffer[opts.buffer][name].prev)
end
elseif opts.window then
if options.window[opts.window] ~= nil
and options.window[opts.window][name] ~= nil
and options.window[opts.window][name].prev ~= nil then
vim.api.nvim_win_set_option(opts.window, name, options.window[opts.window][name].prev)
end
end
end
-- returns cache for the option name
---@param name string
---@param opts table|nil same as M.set
function M.get_cache(name, opts)
if opts == nil or opts.global then
if options.global[name] ~= nil and options.global[name].prev ~= nil then
return options.global[name].prev
end
elseif opts.buffer then
if options.buffer[opts.buffer] ~= nil
and options.buffer[opts.buffer][name] ~= nil
and options.buffer[opts.buffer][name].prev ~= nil then
return options.buffer[opts.buffer][name].prev
end
elseif opts.window then
if options.window[opts.window] ~= nil
and options.window[opts.window][name] ~= nil
and options.window[opts.window][name].prev ~= nil then
return options.window[opts.window][name].prev
end
end
end
-- resets cache for options
function M.reset_cache()
options = {global={}, buffer={}, window={}}
end
return M

View File

@ -81,13 +81,14 @@ end
---@param event string event name
---@param pattern string event pattern
---@param cmd string command to run on event
function M.define_autocmd(event, pattern, cmd)
---@param group string group name defaults to lualine
function M.define_autocmd(event, pattern, cmd, group)
if not cmd then
cmd = pattern
pattern = '*'
end
if not autocmd_is_defined(event, pattern, cmd) then
vim.cmd(string.format('autocmd lualine %s %s %s', event, pattern, cmd))
vim.cmd(string.format('autocmd %s %s %s %s', group or 'lualine', event, pattern, cmd))
end
end
@ -183,4 +184,34 @@ function M.stl_escape(str)
return str:gsub('%%', '%%%%')
end
---A safe call inside a timmer
---@param timer userdata
---@param augroup string|nil autocmd group to reset too on error.
---@param fn function
---@param max_err integer
---@param err_msg string
---@return function a wraped fn that can be called inside a timer and that
---stops the timer after max_err errors in calling fn
function M.timer_call(timer, augroup, fn, max_err, err_msg)
local err_cnt, ret = 0, nil
max_err = max_err or 3
return vim.schedule_wrap(function(...)
if err_cnt > max_err then
vim.loop.timer_stop(timer)
if augroup then
vim.cmd(string.format([[augroup %s | exe "autocmd!" | augroup END]], augroup))
end
error(err_msg..':\n'..tostring(ret))
end
local ok
ok, ret = pcall(fn, ...)
if ok then
err_cnt = 0
else
err_cnt = err_cnt + 1
end
return ret
end)
end
return M

View File

@ -86,12 +86,12 @@ describe('config parsing', function()
describe('disabled filetypes', function()
it('default', function()
local config = config_module.apply_configuration {}
eq(config.options.disabled_filetypes, {})
eq(config.options.disabled_filetypes, {statusline={}, winbar={}})
end)
it('custom', function()
local config = { options = { disabled_filetypes = { 'lua' } } }
config = config_module.apply_configuration(config)
eq(config.options.disabled_filetypes, { 'lua' })
eq(config.options.disabled_filetypes, {statusline={'lua'}, winbar={'lua'}})
end)
end)

View File

@ -15,9 +15,17 @@ describe('Lualine', function()
theme = 'gruvbox',
component_separators = { left = '', right = '' },
section_separators = { left = '', right = '' },
disabled_filetypes = {},
disabled_filetypes = {
statusline = {},
winbar = {},
},
always_divide_middle = true,
globalstatus = false,
refresh = {
statusline = 1000,
tabline = 1000,
winbar = 1000,
}
},
sections = {
lualine_a = { 'mode' },
@ -48,6 +56,8 @@ describe('Lualine', function()
lualine_z = {},
},
tabline = {},
winbar = {},
inactive_winbar = {},
extensions = {},
}