2021-02-13 00:03:57 +00:00
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
2021-02-15 18:09:12 +00:00
local utils = require ( ' lualine.utils.utils ' )
2021-03-18 00:57:59 +00:00
local utils_section = require ( ' lualine.utils.section ' )
2020-12-30 14:48:51 +00:00
local highlight = require ( ' lualine.highlight ' )
2021-03-18 01:13:40 +00:00
local config = require ( ' lualine.defaults ' )
2020-12-30 14:48:51 +00:00
2021-03-15 23:37:46 +00:00
local M = { }
2020-12-30 14:48:51 +00:00
2021-03-10 23:07:38 +00:00
local function apply_configuration ( config_table )
if not config_table then return end
local function parse_sections ( section_group_name )
if not config_table [ section_group_name ] then return end
for section_name , section in pairs ( config_table [ section_group_name ] ) do
2021-03-17 00:02:13 +00:00
config [ section_group_name ] [ section_name ] =
2021-03-15 23:37:46 +00:00
config_table [ section_group_name ] [ section_name ]
2021-03-10 23:07:38 +00:00
if type ( section ) == ' table ' then
for _ , component in pairs ( section ) do
if type ( component ) == ' table ' and type ( component [ 2 ] ) == ' table ' then
local options = component [ 2 ]
component [ 2 ] = nil
2021-03-15 23:37:46 +00:00
for key , val in pairs ( options ) do component [ key ] = val end
2021-03-10 23:07:38 +00:00
end
end
end
end
end
parse_sections ( ' options ' )
parse_sections ( ' sections ' )
parse_sections ( ' inactive_sections ' )
2021-03-06 15:03:00 +00:00
parse_sections ( ' tabline ' )
2021-03-17 00:02:13 +00:00
if config_table.extensions then config.extensions = config_table.extensions end
2021-03-10 23:07:38 +00:00
end
2020-12-30 14:48:51 +00:00
2021-02-20 03:21:05 +00:00
local function check_single_separator ( )
2021-03-17 00:02:13 +00:00
local compoennt_separator = config.options . component_separators
local section_separator = config.options . section_separators
if config.options . component_separators ~= nil then
if type ( config.options . component_separators ) == ' string ' then
config.options . component_separators =
{ compoennt_separator , compoennt_separator }
elseif # config.options . component_separators == 1 then
config.options . component_separators =
{
config.options . component_separators [ 1 ] ,
config.options . component_separators [ 1 ]
}
2021-02-22 19:48:23 +00:00
end
2021-02-20 03:21:05 +00:00
end
2021-03-17 00:02:13 +00:00
if config.options . section_separators ~= nil then
if type ( config.options . section_separators ) == ' string ' then
config.options . section_separators = { section_separator , section_separator }
elseif # config.options . section_separators == 1 then
config.options . section_separators =
{
config.options . section_separators [ 1 ] ,
config.options . section_separators [ 1 ]
}
2021-02-22 19:48:23 +00:00
end
2021-02-20 03:21:05 +00:00
end
end
2021-02-10 10:40:29 +00:00
local function load_special_components ( component )
return function ( )
-- precedence lualine_component > vim_var > lua_var > vim_function
if component : find ( ' [gvtwb]?o?: ' ) == 1 then
-- vim veriable component
-- accepts g:, v:, t:, w:, b:, o, go:, vo:, to:, wo:, bo:
-- filters g portion from g:var
local scope = component : match ( ' [gvtwb]?o? ' )
-- filters var portion from g:var
-- For some reason overwriting component var from outer scope causes the
-- component not to work . So creating a new local name component to use:/
local component = component : sub ( # scope + 2 , # component )
-- Displays nothing when veriable aren't present
local return_val = vim [ scope ] [ component ]
if return_val == nil then return ' ' end
local ok
2021-03-15 23:37:46 +00:00
ok , return_val = pcall ( tostring , return_val )
2021-02-10 10:40:29 +00:00
if ok then return return_val end
return ' '
elseif loadstring ( string.format ( ' return %s ~= nil ' , component ) ) and
2021-03-15 23:37:46 +00:00
loadstring ( string.format ( [[return %s ~= nil]] , component ) ) ( ) then
2021-02-10 10:40:29 +00:00
-- lua veriable component
return loadstring ( string.format ( [ [
2021-02-20 03:21:05 +00:00
local ok , return_val = pcall ( tostring , % s )
if ok then return return_val end
return ' ' ] ] , component ) ) ( )
2021-02-10 10:40:29 +00:00
else
-- vim function component
local ok , return_val = pcall ( vim.fn [ component ] )
if not ok then return ' ' end -- function call failed
2021-03-15 23:37:46 +00:00
ok , return_val = pcall ( tostring , return_val )
if ok then
return return_val
else
return ' '
end
2021-02-10 10:40:29 +00:00
end
end
end
2021-02-15 18:09:12 +00:00
local function component_loader ( component )
if type ( component [ 1 ] ) == ' function ' then return component end
if type ( component [ 1 ] ) == ' string ' then
-- Keep component name for later use as component[1] will be overwritten
-- With component function
component.component_name = component [ 1 ]
-- apply default args
2021-03-17 00:02:13 +00:00
for opt_name , opt_val in pairs ( config.options ) do
2021-03-15 23:37:46 +00:00
if component [ opt_name ] == nil then component [ opt_name ] = opt_val end
2021-02-15 18:09:12 +00:00
end
-- load the component
2021-03-15 23:37:46 +00:00
local ok , loaded_component = pcall ( require , ' lualine.components. ' ..
component.component_name )
2021-02-15 18:09:12 +00:00
if not ok then
loaded_component = load_special_components ( component.component_name )
end
component [ 1 ] = loaded_component
if type ( component [ 1 ] ) == ' table ' then
component [ 1 ] = component [ 1 ] . init ( component )
end
-- set custom highlights
if component.color then
local function update_color ( )
component.color_highlight = highlight.create_component_highlight_group (
2021-03-15 23:37:46 +00:00
component.color ,
component.component_name , component )
2021-02-15 18:09:12 +00:00
end
update_color ( )
utils.expand_set_theme ( update_color )
end
end
end
2021-03-10 23:07:38 +00:00
local function load_sections ( sections )
for section_name , section in pairs ( sections ) do
for index , component in pairs ( section ) do
if type ( component ) == ' string ' or type ( component ) == ' function ' then
component = { component }
2020-12-30 14:48:51 +00:00
end
2021-03-10 23:07:38 +00:00
component.self = { }
component.self . section = section_name
component_loader ( component )
section [ index ] = component
2020-12-30 14:48:51 +00:00
end
end
2021-03-10 23:07:38 +00:00
end
local function load_components ( )
2021-03-17 00:02:13 +00:00
load_sections ( config.sections )
load_sections ( config.inactive_sections )
load_sections ( config.tabline )
2020-12-30 14:48:51 +00:00
end
2021-03-15 23:37:46 +00:00
local function load_extensions ( )
2021-03-17 00:02:13 +00:00
for index , extension in pairs ( config.extensions ) do
2021-03-10 23:07:38 +00:00
local local_extension = require ( ' lualine.extensions. ' .. extension )
load_sections ( local_extension.sections )
load_sections ( local_extension.inactive_sections )
2021-03-17 00:02:13 +00:00
config.extensions [ index ] = local_extension
2020-12-30 14:48:51 +00:00
end
end
2021-02-20 03:21:05 +00:00
local function lualine_set_theme ( )
2021-03-17 00:02:13 +00:00
if type ( config.options . theme ) == ' string ' then
config.options . theme = require ( ' lualine.themes. ' .. config.options . theme )
2021-02-21 14:37:59 +00:00
-- change the theme table in component so their custom
-- highlights can reflect theme change
2021-02-20 03:21:05 +00:00
local function reset_component_theme ( sections )
2021-03-15 23:37:46 +00:00
for _ , section in pairs ( sections ) do
2021-02-20 03:21:05 +00:00
for _ , component in pairs ( section ) do
if type ( component ) == ' table ' then
2021-03-17 00:02:13 +00:00
component.theme = config.options . theme
2021-02-20 03:21:05 +00:00
end
end
end
end
2021-03-17 00:02:13 +00:00
reset_component_theme ( config.sections )
reset_component_theme ( config.inactive_sections )
2021-01-04 00:17:51 +00:00
end
2021-02-21 14:37:59 +00:00
utils.clear_highlights ( )
2021-03-17 00:02:13 +00:00
highlight.create_highlight_groups ( config.options . theme )
2021-01-04 00:17:51 +00:00
end
2021-03-13 00:21:37 +00:00
local function statusline ( sections , is_focused )
2021-02-20 03:21:05 +00:00
local function create_status_builder ( )
-- The sequence sections should maintain
local section_sequence = { ' a ' , ' b ' , ' c ' , ' x ' , ' y ' , ' z ' }
local status_builder = { }
for _ , section_name in ipairs ( section_sequence ) do
2021-03-15 23:37:46 +00:00
if sections [ ' lualine_ ' .. section_name ] then
2021-02-20 03:21:05 +00:00
-- insert highlight+components of this section to status_builder
local section_highlight = highlight.format_highlight ( is_focused ,
2021-03-15 23:37:46 +00:00
' lualine_ ' ..
section_name )
2021-03-18 00:57:59 +00:00
local section_data = utils_section.draw_section (
2021-03-15 23:37:46 +00:00
sections [ ' lualine_ ' .. section_name ] ,
section_highlight )
2021-02-20 03:21:05 +00:00
if # section_data > 0 then
2021-03-15 23:37:46 +00:00
table.insert ( status_builder ,
{ name = section_name , data = section_data } )
2021-02-20 03:21:05 +00:00
end
end
end
return status_builder
2020-12-30 14:48:51 +00:00
end
2021-02-20 03:21:05 +00:00
-- status_builder stores statusline without section_separators
local status_builder = create_status_builder ( )
-- Actual statusline
local status = { }
local half_passed = false
2021-03-15 23:37:46 +00:00
for i = 1 , # status_builder do
2021-02-20 03:21:05 +00:00
-- midsection divider
if not half_passed and status_builder [ i ] . name > ' c ' then
2021-03-15 23:37:46 +00:00
table.insert ( status ,
highlight.format_highlight ( is_focused , ' lualine_c ' ) .. ' %= ' )
2021-02-20 03:21:05 +00:00
half_passed = true
end
-- provide section_separators when statusline is in focus
if is_focused then
-- component separator needs to have fg = current_section.bg
-- and bg = adjacent_section.bg
2021-03-15 23:37:46 +00:00
local previous_section = status_builder [ i - 1 ] or { }
2021-02-20 03:21:05 +00:00
local current_section = status_builder [ i ]
2021-03-15 23:37:46 +00:00
local next_section = status_builder [ i + 1 ] or { }
2021-02-20 03:21:05 +00:00
-- For 2nd half we need to show separator before section
if current_section.name > ' x ' then
2021-03-15 23:37:46 +00:00
local transitional_highlight = highlight.get_transitional_highlights (
previous_section.data ,
current_section.data , true )
2021-03-17 00:02:13 +00:00
if transitional_highlight and config.options . section_separators and
config.options . section_separators [ 2 ] then
2021-03-15 23:37:46 +00:00
table.insert ( status , transitional_highlight ..
2021-03-17 00:02:13 +00:00
config.options . section_separators [ 2 ] )
2021-02-20 03:21:05 +00:00
end
end
-- **( insert the actual section in the middle )** --
table.insert ( status , status_builder [ i ] . data )
-- For 1st half we need to show separator after section
if current_section.name < ' c ' then
2021-03-15 23:37:46 +00:00
local transitional_highlight = highlight.get_transitional_highlights (
current_section.data ,
next_section.data )
2021-03-17 00:02:13 +00:00
if transitional_highlight and config.options . section_separators and
config.options . section_separators [ 1 ] then
2021-03-15 23:37:46 +00:00
table.insert ( status , transitional_highlight ..
2021-03-17 00:02:13 +00:00
config.options . section_separators [ 1 ] )
2021-02-20 03:21:05 +00:00
end
end
else -- when not in focus
table.insert ( status , status_builder [ i ] . data )
end
2020-12-30 14:48:51 +00:00
end
2021-02-20 03:21:05 +00:00
-- incase none of x,y,z was configured lets not fill whole statusline with a,b,c section
if not half_passed then
2021-03-15 23:37:46 +00:00
table.insert ( status ,
highlight.format_highlight ( is_focused , ' lualine_c ' ) .. ' %= ' )
2020-12-30 14:48:51 +00:00
end
2021-01-03 19:11:22 +00:00
return table.concat ( status )
2020-12-30 14:48:51 +00:00
end
2021-03-13 00:21:37 +00:00
-- check if any extension matches the filetype and return proper sections
local function get_extension_sections ( )
local sections , inactive_sections = nil , nil
2021-03-17 00:02:13 +00:00
for _ , extension in ipairs ( config.extensions ) do
2021-03-13 00:21:37 +00:00
for _ , filetype in ipairs ( extension.filetypes ) do
if vim.bo . filetype == filetype then
sections = extension.sections
inactive_sections = extension.inactive_sections
break
end
end
end
return { sections = sections , inactive_sections = inactive_sections }
end
2021-02-05 12:29:34 +00:00
local function status_dispatch ( )
2021-03-13 00:21:37 +00:00
local extension_sections = get_extension_sections ( )
2021-02-05 12:29:34 +00:00
if vim.g . statusline_winid == vim.fn . win_getid ( ) then
2021-03-13 00:21:37 +00:00
local sections = extension_sections.sections
2021-03-17 00:02:13 +00:00
if sections == nil then sections = config.sections end
2021-03-13 00:21:37 +00:00
return statusline ( sections , true )
2021-02-05 12:29:34 +00:00
else
2021-03-13 00:21:37 +00:00
local inactive_sections = extension_sections.inactive_sections
2021-03-17 00:02:13 +00:00
if inactive_sections == nil then
inactive_sections = config.inactive_sections
end
2021-03-13 00:21:37 +00:00
return statusline ( inactive_sections , false )
2021-02-05 12:29:34 +00:00
end
2021-01-05 23:43:36 +00:00
end
2021-03-17 00:02:13 +00:00
local function tabline ( ) return statusline ( config.tabline , true ) end
2021-03-06 15:03:00 +00:00
local function setup_theme ( )
lualine_set_theme ( )
2021-02-20 03:21:05 +00:00
_G.lualine_set_theme = lualine_set_theme
2021-01-15 04:15:04 +00:00
vim.api . nvim_exec ( [ [
2021-02-20 03:21:05 +00:00
augroup lualine
autocmd !
autocmd ColorScheme * call v : lua.lualine_set_theme ( )
augroup END
2021-01-15 04:15:04 +00:00
] ] , false )
2021-01-04 00:17:51 +00:00
end
2021-03-06 15:03:00 +00:00
local function set_tabline ( )
2021-03-17 00:02:13 +00:00
if next ( config.tabline ) ~= nil then
2021-03-06 15:03:00 +00:00
_G.lualine_tabline = tabline
vim.o . tabline = ' %!v:lua.lualine_tabline() '
vim.o . showtabline = 2
end
end
local function set_statusline ( )
2021-03-17 00:02:13 +00:00
if next ( config.sections ) ~= nil or next ( config.inactive_sections ) ~= nil then
2021-03-06 15:03:00 +00:00
_G.lualine_statusline = status_dispatch
vim.o . statusline = ' %!v:lua.lualine_statusline() '
vim.api . nvim_exec ( [ [
autocmd lualine WinLeave , BufLeave * lua vim.wo . statusline = lualine_statusline ( )
autocmd lualine WinEnter , BufEnter * setlocal statusline =% ! v : lua.lualine_statusline ( )
] ] , false )
end
end
2021-03-17 00:02:13 +00:00
function M . setup ( user_config )
if M.options ~= nil or M.sections ~= nil or M.inactive_sections ~= nil or
M.tabline ~= nil or M.extensions ~= nil then
if vim.api . nvim_echo then
vim.api . nvim_echo ( {
{
' lualine.nvim: lualine is moving to setup function to be consistent with other lua plugins, all other configuration options will be removed by 24.03.2021, please change your configuration(example in readme) ' ,
' WarningMsg '
}
} , true , { } )
else
print (
' lualine.nvim: lualine is moving to setup function to be consistent with other lua plugins, all other configuration options will be removed by 24.03.2021, please change your configuration(example in readme) ' )
end
2021-03-18 01:13:40 +00:00
if M.options ~= nil then user_config.options = M.options end
if M.sections ~= nil then user_config.sections = M.sections end
if M.inactive_sections ~= nil then
2021-03-17 00:02:13 +00:00
user_config.inactive_sections = M.inactive_sections
end
2021-03-18 01:13:40 +00:00
if M.tabline ~= nil then user_config.tabline = M.tabline end
if M.extensions ~= nil then user_config.extensions = M.extensions end
2021-03-17 00:02:13 +00:00
end
2021-03-02 12:58:34 +00:00
apply_configuration ( vim.g . lualine )
2021-03-17 00:02:13 +00:00
apply_configuration ( user_config )
2021-02-20 03:21:05 +00:00
check_single_separator ( )
2021-03-06 15:03:00 +00:00
setup_theme ( )
2021-02-15 18:09:12 +00:00
load_components ( )
load_extensions ( )
2021-03-06 15:03:00 +00:00
set_statusline ( )
set_tabline ( )
2020-12-30 14:48:51 +00:00
end
2021-03-17 00:02:13 +00:00
function M . status ( user_config )
if vim.api . nvim_echo then
vim.api . nvim_echo ( {
{
' lualine.nvim: status function has been ranamed to setup and will be removed by 24.03.2021, please change your configuration ' ,
' WarningMsg '
}
} , true , { } )
else
print (
' lualine.nvim: status function has been ranamed to setup and will be removed by 24.03.2021, please change your configuration ' )
end
return M.setup ( user_config )
end
2020-12-30 14:48:51 +00:00
return M