feat: allow lualine to ignore focus on specific filetypes. (#767)

* feat: allow lualine to ignore focus on specific filetypes.

closes #710

* fix: extensions on ingnored_focus

* perf: reuse api call results & use local variables instead of vim.g

* make location & progress components behave in ingnored filetypes

* fix: crash when last_focused win gets closed

* fix: location & progress related broken tests
This commit is contained in:
Shadman 2022-07-29 16:54:31 +06:00 committed by GitHub
parent 788805771c
commit 6d11f9f508
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 134 additions and 41 deletions

View File

@ -125,6 +125,7 @@ require('lualine').setup {
statusline = {},
winbar = {},
},
ignore_focus = {},
always_divide_middle = true,
globalstatus = false,
refresh = {
@ -337,7 +338,7 @@ Values set here are treated as default for other options
that work in component level.
For example even though `icons_enabled` is a general component option.
you can set `icons_enabled` to `false` and icons will be disabled on all
You can set `icons_enabled` to `false` and icons will be disabled on all
component. You can still overwrite defaults set in option table by specifying
the option value in component.
@ -351,6 +352,13 @@ options = {
winbar = {}, -- only ignores the ft for winbar.
},
ignore_focus = {}, -- If current filetype is in this list it'll
-- always be drawn as inactive statusline
-- and the last window will be drawn as active statusline.
-- for example if you don't want statusline of
-- your file tree / sidebar window to have active
-- statusline you can add their filetypes here.
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.

View File

@ -109,6 +109,7 @@ For more information, check out `:help lua-heredoc`.
statusline = {},
winbar = {},
},
ignore_focus = {},
always_divide_middle = true,
globalstatus = false,
refresh = {
@ -346,7 +347,7 @@ Global options These are `options` that are used in
Values set here are treated as default for other options that work in component
level.
For example even though `icons_enabled` is a general component option. you can
For example even though `icons_enabled` is a general component option. You can
set `icons_enabled` to `false` and icons will be disabled on all component. You
can still overwrite defaults set in option table by specifying the option value
in component.
@ -361,6 +362,13 @@ in component.
winbar = {}, -- only ignores the ft for winbar.
},
ignore_focus = {}, -- If current filetype is in this list it'll
-- always be drawn as inactive statusline
-- and the last window will be drawn as active statusline.
-- for example if you don't want statusline of
-- your file tree / sidebar window to have active
-- statusline you can add their filetypes here.
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.

View File

@ -19,6 +19,9 @@ local timers = {
wb_timer = vim.loop.new_timer(),
}
local last_focus = {}
local refresh_real_curwin
-- The events on which lualine redraws itself
local default_refresh_events = 'WinEnter,BufEnter,SessionLoadPost,FileChangedShellPost,VimResized,Filetype'
if vim.fn.has('nvim-0.7') == 1 then -- utilize ModeChanged event introduced in 0.7
@ -187,7 +190,7 @@ end)
--- check if any extension matches the filetype and return proper sections
---@param current_ft string : filetype name of current file
---@param is_focused boolean : whether being evaluated for focused window or not
---@return table : (section_table) section config where components are replaced with
---@return table|nil : (section_table) section config where components are replaced with
--- component objects
-- TODO: change this so it uses a hash table instead of iteration over list
-- to improve redraws. Add buftype / bufname for extensions
@ -195,7 +198,11 @@ end)
local function get_extension_sections(current_ft, is_focused, sec_name)
for _, extension in ipairs(config.extensions) do
if vim.tbl_contains(extension.filetypes, current_ft) then
return extension[(is_focused and '' or 'inactive_') .. sec_name]
if is_focused then
return extension[sec_name]
else
return extension['inactive_' .. sec_name] or extension[sec_name]
end
end
end
return nil
@ -267,7 +274,9 @@ end
local function status_dispatch(sec_name)
return function(focused)
local retval
local current_ft = vim.bo.filetype
local current_ft = refresh_real_curwin
and vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(refresh_real_curwin), 'filetype')
or vim.bo.filetype
local is_focused = focused ~= nil and focused or modules.utils.is_focused()
if
vim.tbl_contains(
@ -299,7 +308,7 @@ end
---@class LualineRefreshOpts
---@field kind LualineRefreshOptsKind
---@field place LualineRefreshOptsPlace[]
---@field trigger 'autocmd'|'autocmd_redired|timer'|'unknown'
---@field trigger 'autocmd'|'autocmd_redired'|'timer'|'unknown'
--- Refresh contents of lualine
---@param opts LualineRefreshOpts
local function refresh(opts)
@ -324,7 +333,50 @@ local function refresh(opts)
local wins = {}
local old_actual_curwin = vim.g.actual_curwin
vim.g.actual_curwin = vim.api.nvim_get_current_win()
-- ignore focus on filetypes listes in options.ignore_focus
local curwin = vim.api.nvim_get_current_win()
local curtab = vim.api.nvim_get_current_tabpage()
if last_focus[curtab] == nil or not vim.api.nvim_win_is_valid(last_focus[curtab]) then
if
not vim.tbl_contains(
config.options.ignore_focus,
vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(curwin), 'filetype')
)
then
last_focus[curtab] = curwin
else
local tab_wins = vim.api.nvim_tabpage_list_wins(curtab)
if #tab_wins == 1 then
last_focus[curtab] = curwin
else
local focusable_win = curwin
for _, win in ipairs(tab_wins) do
if
not vim.tbl_contains(
config.options.ignore_focus,
vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(win), 'filetype')
)
then
focusable_win = win
break
end
end
last_focus[curtab] = focusable_win
end
end
else
if
not vim.tbl_contains(
config.options.ignore_focus,
vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(curwin), 'filetype')
)
then
last_focus[curtab] = curwin
end
end
vim.g.actual_curwin = last_focus[curtab]
-- 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
@ -339,13 +391,14 @@ local function refresh(opts)
end, vim.api.nvim_tabpage_list_wins(0))
end
elseif opts.kind == 'window' then
wins = { vim.api.nvim_get_current_win() }
wins = { curwin }
end
-- update them
if vim.tbl_contains(opts.place, 'statusline') then
for _, win in ipairs(wins) do
local stl_cur = vim.api.nvim_win_call(win, M.statusline)
refresh_real_curwin = config.options.globalstatus and last_focus[curtab] or win
local stl_cur = vim.api.nvim_win_call(refresh_real_curwin, M.statusline)
local stl_last = modules.nvim_opts.get_cache('statusline', { window = win })
if stl_cur or stl_last then
modules.nvim_opts.set('statusline', stl_cur, { window = win })
@ -354,8 +407,9 @@ local function refresh(opts)
end
if vim.tbl_contains(opts.place, 'winbar') then
for _, win in ipairs(wins) do
refresh_real_curwin = config.options.globalstatus and last_focus[curtab] or win
if vim.api.nvim_win_get_height(win) > 1 then
local wbr_cur = vim.api.nvim_win_call(win, M.winbar)
local wbr_cur = vim.api.nvim_win_call(refresh_real_curwin, M.winbar)
local wbr_last = modules.nvim_opts.get_cache('winbar', { window = win })
if wbr_cur or wbr_last then
modules.nvim_opts.set('winbar', wbr_cur, { window = win })
@ -364,7 +418,8 @@ local function refresh(opts)
end
end
if vim.tbl_contains(opts.place, 'tabline') then
local tbl_cur = vim.api.nvim_win_call(vim.api.nvim_get_current_win(), tabline)
refresh_real_curwin = curwin
local tbl_cur = vim.api.nvim_win_call(curwin, tabline)
local tbl_last = modules.nvim_opts.get_cache('tabline', { global = true })
if tbl_cur or tbl_last then
modules.nvim_opts.set('tabline', tbl_cur, { global = true })
@ -372,6 +427,7 @@ local function refresh(opts)
end
vim.g.actual_curwin = old_actual_curwin
refresh_real_curwin = nil
end
--- Sets &tabline option to lualine

View File

@ -1,7 +1,9 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local function location()
return '%3l:%-2v'
local line = vim.fn.line('.')
local col = vim.fn.col('.')
return string.format('%3d:%-2d', line, col)
end
return location

View File

@ -1,7 +1,15 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local function progress()
return '%3p%%'
local cur = vim.fn.line('.')
local total = vim.fn.line('$')
if cur == 1 then
return 'Top'
elseif cur == total then
return 'Bot'
else
return math.floor(cur / total * 100) .. '%%'
end
end
return progress

View File

@ -16,6 +16,7 @@ local config = {
statusline = {},
winbar = {},
},
ignore_focus = {},
always_divide_middle = true,
globalstatus = vim.go.laststatus == 3,
refresh = {

View File

@ -400,7 +400,12 @@ describe('Location component', function()
component_separators = { left = '', right = '' },
padding = 0,
}
assert_component('location', opts, '%3l:%-2v')
assert_component('location', opts, ' 1:1 ')
vim.cmd('normal! 9o')
assert_component('location', opts, ' 10:1 ')
vim.api.nvim_win_set_cursor(0, {5, 0})
assert_component('location', opts, ' 5:1 ')
vim.cmd('bdelete!')
end)
end)
@ -410,7 +415,12 @@ describe('Progress component', function()
component_separators = { left = '', right = '' },
padding = 0,
}
assert_component('progress', opts, '%3p%%')
assert_component('progress', opts, 'Top')
vim.cmd('normal! 9o')
assert_component('progress', opts, 'Bot')
vim.api.nvim_win_set_cursor(0, {5, 0})
assert_component('progress', opts, '50%%')
vim.cmd('bdelete!')
end)
end)

View File

@ -19,6 +19,7 @@ describe('Lualine', function()
statusline = {},
winbar = {},
},
ignore_focus = {},
always_divide_middle = true,
globalstatus = false,
refresh = {
@ -84,9 +85,9 @@ describe('Lualine', function()
{5: }
{5: }
{4:}
{3: 100% }
{3: Top }
{2:}
{1: 0:1 }|
{1: 1:1 }|
]===])
end)
@ -97,7 +98,7 @@ describe('Lualine', function()
}
|{1: [No Name] }
{1: }
{1: 0:1 }|
{1: 1:1 }|
]===])
end)
@ -123,9 +124,9 @@ describe('Lualine', function()
{3: }
{3: }
{2:}
{1: 100% }
{1: Top }
{4:}
{5: 0:1 }|
{5: 1:1 }|
]===])
end)
@ -143,8 +144,8 @@ describe('Lualine', function()
{3: [No Name] }
{3: }
{3: }
{2: 100% }
{1: 0:1 }|
{2: Top }
{1: 1:1 }|
]===])
end)
@ -174,9 +175,9 @@ describe('Lualine', function()
{5: }
{5: }
{4:}
{3: 100% }
{3: Top }
{2:}
{1: 0:1 }
{1: 1:1 }
{1: test_comp2 }|
]===])
@ -199,9 +200,9 @@ describe('Lualine', function()
{5: }
{5: }
{4:}
{3: 100% }
{3: Top }
{2:}
{1: 0:1 }
{1: 1:1 }
{1: test_comp2 }|
]===])
end)
@ -243,8 +244,8 @@ describe('Lualine', function()
{3: [No Name] }
{3: }
{3: unix }
{2: 100% }
{1: 0:1 }|
{2: Top }
{1: 1:1 }|
]===])
end)
@ -325,11 +326,10 @@ describe('Lualine', function()
{5: }
{5: }
{4:}
{3: 100% }
{3: Top }
{2:}
{1: 0:1 }|
{1: 1:1 }|
]===])
vim.bo.ft = 'test_ft2'
statusline:expect([===[
highlights = {
@ -406,9 +406,9 @@ describe('Lualine', function()
{5: }
{5: }
{4:}
{3: 100% }
{3: Top }
{2:}
{1: 0:1 }|
{1: 1:1 }|
]===])
end)
describe('tabs component', function()