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 = {},
|
statusline = {},
|
||||||
winbar = {},
|
winbar = {},
|
||||||
},
|
},
|
||||||
|
ignore_focus = {},
|
||||||
always_divide_middle = true,
|
always_divide_middle = true,
|
||||||
globalstatus = false,
|
globalstatus = false,
|
||||||
refresh = {
|
refresh = {
|
||||||
|
@ -337,7 +338,7 @@ Values set here are treated as default for other options
|
||||||
that work in component level.
|
that work in component level.
|
||||||
|
|
||||||
For example even though `icons_enabled` is a general component option.
|
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
|
component. You can still overwrite defaults set in option table by specifying
|
||||||
the option value in component.
|
the option value in component.
|
||||||
|
|
||||||
|
@ -351,6 +352,13 @@ options = {
|
||||||
winbar = {}, -- only ignores the ft for winbar.
|
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'
|
always_divide_middle = true, -- When set to true, left sections i.e. 'a','b' and 'c'
|
||||||
-- can't take over the entire statusline even
|
-- can't take over the entire statusline even
|
||||||
-- if neither of 'x', 'y' or 'z' are present.
|
-- if neither of 'x', 'y' or 'z' are present.
|
||||||
|
|
|
@ -109,6 +109,7 @@ For more information, check out `:help lua-heredoc`.
|
||||||
statusline = {},
|
statusline = {},
|
||||||
winbar = {},
|
winbar = {},
|
||||||
},
|
},
|
||||||
|
ignore_focus = {},
|
||||||
always_divide_middle = true,
|
always_divide_middle = true,
|
||||||
globalstatus = false,
|
globalstatus = false,
|
||||||
refresh = {
|
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
|
Values set here are treated as default for other options that work in component
|
||||||
level.
|
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
|
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
|
can still overwrite defaults set in option table by specifying the option value
|
||||||
in component.
|
in component.
|
||||||
|
@ -361,6 +362,13 @@ in component.
|
||||||
winbar = {}, -- only ignores the ft for winbar.
|
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'
|
always_divide_middle = true, -- When set to true, left sections i.e. 'a','b' and 'c'
|
||||||
-- can't take over the entire statusline even
|
-- can't take over the entire statusline even
|
||||||
-- if neither of 'x', 'y' or 'z' are present.
|
-- if neither of 'x', 'y' or 'z' are present.
|
||||||
|
|
|
@ -19,6 +19,9 @@ local timers = {
|
||||||
wb_timer = vim.loop.new_timer(),
|
wb_timer = vim.loop.new_timer(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local last_focus = {}
|
||||||
|
local refresh_real_curwin
|
||||||
|
|
||||||
-- The events on which lualine redraws itself
|
-- The events on which lualine redraws itself
|
||||||
local default_refresh_events = 'WinEnter,BufEnter,SessionLoadPost,FileChangedShellPost,VimResized,Filetype'
|
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
|
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
|
--- check if any extension matches the filetype and return proper sections
|
||||||
---@param current_ft string : filetype name of current file
|
---@param current_ft string : filetype name of current file
|
||||||
---@param is_focused boolean : whether being evaluated for focused window or not
|
---@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
|
--- component objects
|
||||||
-- TODO: change this so it uses a hash table instead of iteration over list
|
-- TODO: change this so it uses a hash table instead of iteration over list
|
||||||
-- to improve redraws. Add buftype / bufname for extensions
|
-- to improve redraws. Add buftype / bufname for extensions
|
||||||
|
@ -195,7 +198,11 @@ end)
|
||||||
local function get_extension_sections(current_ft, is_focused, sec_name)
|
local function get_extension_sections(current_ft, is_focused, sec_name)
|
||||||
for _, extension in ipairs(config.extensions) do
|
for _, extension in ipairs(config.extensions) do
|
||||||
if vim.tbl_contains(extension.filetypes, current_ft) then
|
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
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
|
@ -267,7 +274,9 @@ end
|
||||||
local function status_dispatch(sec_name)
|
local function status_dispatch(sec_name)
|
||||||
return function(focused)
|
return function(focused)
|
||||||
local retval
|
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()
|
local is_focused = focused ~= nil and focused or modules.utils.is_focused()
|
||||||
if
|
if
|
||||||
vim.tbl_contains(
|
vim.tbl_contains(
|
||||||
|
@ -299,7 +308,7 @@ end
|
||||||
---@class LualineRefreshOpts
|
---@class LualineRefreshOpts
|
||||||
---@field kind LualineRefreshOptsKind
|
---@field kind LualineRefreshOptsKind
|
||||||
---@field place LualineRefreshOptsPlace[]
|
---@field place LualineRefreshOptsPlace[]
|
||||||
---@field trigger 'autocmd'|'autocmd_redired|timer'|'unknown'
|
---@field trigger 'autocmd'|'autocmd_redired'|'timer'|'unknown'
|
||||||
--- Refresh contents of lualine
|
--- Refresh contents of lualine
|
||||||
---@param opts LualineRefreshOpts
|
---@param opts LualineRefreshOpts
|
||||||
local function refresh(opts)
|
local function refresh(opts)
|
||||||
|
@ -324,7 +333,50 @@ local function refresh(opts)
|
||||||
|
|
||||||
local wins = {}
|
local wins = {}
|
||||||
local old_actual_curwin = vim.g.actual_curwin
|
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
|
-- gather which windows needs update
|
||||||
if opts.kind == 'all' then
|
if opts.kind == 'all' then
|
||||||
if vim.tbl_contains(opts.place, 'statusline') or vim.tbl_contains(opts.place, 'winbar') 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, vim.api.nvim_tabpage_list_wins(0))
|
||||||
end
|
end
|
||||||
elseif opts.kind == 'window' then
|
elseif opts.kind == 'window' then
|
||||||
wins = { vim.api.nvim_get_current_win() }
|
wins = { curwin }
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update them
|
-- update them
|
||||||
if vim.tbl_contains(opts.place, 'statusline') then
|
if vim.tbl_contains(opts.place, 'statusline') then
|
||||||
for _, win in ipairs(wins) do
|
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 })
|
local stl_last = modules.nvim_opts.get_cache('statusline', { window = win })
|
||||||
if stl_cur or stl_last then
|
if stl_cur or stl_last then
|
||||||
modules.nvim_opts.set('statusline', stl_cur, { window = win })
|
modules.nvim_opts.set('statusline', stl_cur, { window = win })
|
||||||
|
@ -354,8 +407,9 @@ local function refresh(opts)
|
||||||
end
|
end
|
||||||
if vim.tbl_contains(opts.place, 'winbar') then
|
if vim.tbl_contains(opts.place, 'winbar') then
|
||||||
for _, win in ipairs(wins) do
|
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
|
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 })
|
local wbr_last = modules.nvim_opts.get_cache('winbar', { window = win })
|
||||||
if wbr_cur or wbr_last then
|
if wbr_cur or wbr_last then
|
||||||
modules.nvim_opts.set('winbar', wbr_cur, { window = win })
|
modules.nvim_opts.set('winbar', wbr_cur, { window = win })
|
||||||
|
@ -364,7 +418,8 @@ local function refresh(opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if vim.tbl_contains(opts.place, 'tabline') then
|
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 })
|
local tbl_last = modules.nvim_opts.get_cache('tabline', { global = true })
|
||||||
if tbl_cur or tbl_last then
|
if tbl_cur or tbl_last then
|
||||||
modules.nvim_opts.set('tabline', tbl_cur, { global = true })
|
modules.nvim_opts.set('tabline', tbl_cur, { global = true })
|
||||||
|
@ -372,6 +427,7 @@ local function refresh(opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
vim.g.actual_curwin = old_actual_curwin
|
vim.g.actual_curwin = old_actual_curwin
|
||||||
|
refresh_real_curwin = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets &tabline option to lualine
|
--- Sets &tabline option to lualine
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
-- Copyright (c) 2020-2021 hoob3rt
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local function location()
|
local function location()
|
||||||
return '%3l:%-2v'
|
local line = vim.fn.line('.')
|
||||||
|
local col = vim.fn.col('.')
|
||||||
|
return string.format('%3d:%-2d', line, col)
|
||||||
end
|
end
|
||||||
|
|
||||||
return location
|
return location
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
-- Copyright (c) 2020-2021 hoob3rt
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local function progress()
|
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
|
end
|
||||||
|
|
||||||
return progress
|
return progress
|
||||||
|
|
|
@ -16,6 +16,7 @@ local config = {
|
||||||
statusline = {},
|
statusline = {},
|
||||||
winbar = {},
|
winbar = {},
|
||||||
},
|
},
|
||||||
|
ignore_focus = {},
|
||||||
always_divide_middle = true,
|
always_divide_middle = true,
|
||||||
globalstatus = vim.go.laststatus == 3,
|
globalstatus = vim.go.laststatus == 3,
|
||||||
refresh = {
|
refresh = {
|
||||||
|
|
|
@ -400,7 +400,12 @@ describe('Location component', function()
|
||||||
component_separators = { left = '', right = '' },
|
component_separators = { left = '', right = '' },
|
||||||
padding = 0,
|
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)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -410,7 +415,12 @@ describe('Progress component', function()
|
||||||
component_separators = { left = '', right = '' },
|
component_separators = { left = '', right = '' },
|
||||||
padding = 0,
|
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)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ describe('Lualine', function()
|
||||||
statusline = {},
|
statusline = {},
|
||||||
winbar = {},
|
winbar = {},
|
||||||
},
|
},
|
||||||
|
ignore_focus = {},
|
||||||
always_divide_middle = true,
|
always_divide_middle = true,
|
||||||
globalstatus = false,
|
globalstatus = false,
|
||||||
refresh = {
|
refresh = {
|
||||||
|
@ -84,9 +85,9 @@ describe('Lualine', function()
|
||||||
{5: }
|
{5: }
|
||||||
{5: }
|
{5: }
|
||||||
{4:}
|
{4:}
|
||||||
{3: 100% }
|
{3: Top }
|
||||||
{2:}
|
{2:}
|
||||||
{1: 0:1 }|
|
{1: 1:1 }|
|
||||||
]===])
|
]===])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -97,7 +98,7 @@ describe('Lualine', function()
|
||||||
}
|
}
|
||||||
|{1: [No Name] }
|
|{1: [No Name] }
|
||||||
{1: }
|
{1: }
|
||||||
{1: 0:1 }|
|
{1: 1:1 }|
|
||||||
]===])
|
]===])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -123,9 +124,9 @@ describe('Lualine', function()
|
||||||
{3: }
|
{3: }
|
||||||
{3: }
|
{3: }
|
||||||
{2:}
|
{2:}
|
||||||
{1: 100% }
|
{1: Top }
|
||||||
{4:}
|
{4:}
|
||||||
{5: 0:1 }|
|
{5: 1:1 }|
|
||||||
]===])
|
]===])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -143,8 +144,8 @@ describe('Lualine', function()
|
||||||
{3: [No Name] }
|
{3: [No Name] }
|
||||||
{3: }
|
{3: }
|
||||||
{3: }
|
{3: }
|
||||||
{2: 100% }
|
{2: Top }
|
||||||
{1: 0:1 }|
|
{1: 1:1 }|
|
||||||
]===])
|
]===])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -174,9 +175,9 @@ describe('Lualine', function()
|
||||||
{5: }
|
{5: }
|
||||||
{5: }
|
{5: }
|
||||||
{4:}
|
{4:}
|
||||||
{3: 100% }
|
{3: Top }
|
||||||
{2:}
|
{2:}
|
||||||
{1: 0:1 }
|
{1: 1:1 }
|
||||||
{1: test_comp2 }|
|
{1: test_comp2 }|
|
||||||
]===])
|
]===])
|
||||||
|
|
||||||
|
@ -199,9 +200,9 @@ describe('Lualine', function()
|
||||||
{5: }
|
{5: }
|
||||||
{5: }
|
{5: }
|
||||||
{4:}
|
{4:}
|
||||||
{3: 100% }
|
{3: Top }
|
||||||
{2:}
|
{2:}
|
||||||
{1: 0:1 }
|
{1: 1:1 }
|
||||||
{1: test_comp2 }|
|
{1: test_comp2 }|
|
||||||
]===])
|
]===])
|
||||||
end)
|
end)
|
||||||
|
@ -243,8 +244,8 @@ describe('Lualine', function()
|
||||||
{3: [No Name] }
|
{3: [No Name] }
|
||||||
{3: }
|
{3: }
|
||||||
{3: unix }
|
{3: unix }
|
||||||
{2: 100% }
|
{2: Top }
|
||||||
{1: 0:1 }|
|
{1: 1:1 }|
|
||||||
]===])
|
]===])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -325,11 +326,10 @@ describe('Lualine', function()
|
||||||
{5: }
|
{5: }
|
||||||
{5: }
|
{5: }
|
||||||
{4:}
|
{4:}
|
||||||
{3: 100% }
|
{3: Top }
|
||||||
{2:}
|
{2:}
|
||||||
{1: 0:1 }|
|
{1: 1:1 }|
|
||||||
]===])
|
]===])
|
||||||
|
|
||||||
vim.bo.ft = 'test_ft2'
|
vim.bo.ft = 'test_ft2'
|
||||||
statusline:expect([===[
|
statusline:expect([===[
|
||||||
highlights = {
|
highlights = {
|
||||||
|
@ -406,9 +406,9 @@ describe('Lualine', function()
|
||||||
{5: }
|
{5: }
|
||||||
{5: }
|
{5: }
|
||||||
{4:}
|
{4:}
|
||||||
{3: 100% }
|
{3: Top }
|
||||||
{2:}
|
{2:}
|
||||||
{1: 0:1 }|
|
{1: 1:1 }|
|
||||||
]===])
|
]===])
|
||||||
end)
|
end)
|
||||||
describe('tabs component', function()
|
describe('tabs component', function()
|
||||||
|
|
Loading…
Reference in New Issue