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:
parent
788805771c
commit
6d11f9f508
10
README.md
10
README.md
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -16,6 +16,7 @@ local config = {
|
|||
statusline = {},
|
||||
winbar = {},
|
||||
},
|
||||
ignore_focus = {},
|
||||
always_divide_middle = true,
|
||||
globalstatus = vim.go.laststatus == 3,
|
||||
refresh = {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue