2021-02-13 00:03:57 +00:00
|
|
|
-- Copyright (c) 2020-2021 hoob3rt
|
|
|
|
-- MIT license, see LICENSE for more details.
|
2021-03-15 23:37:46 +00:00
|
|
|
local M = {}
|
2021-09-03 18:28:20 +00:00
|
|
|
local lualine_require = require 'lualine_require'
|
2021-08-30 11:54:23 +00:00
|
|
|
local require = lualine_require.require
|
2021-09-03 18:28:20 +00:00
|
|
|
local modules = lualine_require.lazy_require {
|
2021-08-30 11:54:23 +00:00
|
|
|
utils = 'lualine.utils.utils',
|
2021-08-30 12:07:24 +00:00
|
|
|
color_utils = 'lualine.utils.color_utils',
|
2021-08-30 11:54:23 +00:00
|
|
|
}
|
2021-09-03 14:16:54 +00:00
|
|
|
|
2021-09-03 18:28:20 +00:00
|
|
|
local section_highlight_map = { x = 'c', y = 'b', z = 'a' }
|
2021-04-07 00:34:36 +00:00
|
|
|
local active_theme = nil
|
2021-08-30 11:54:23 +00:00
|
|
|
local create_cterm_colors = false
|
2020-12-30 14:48:51 +00:00
|
|
|
|
2021-09-03 14:16:54 +00:00
|
|
|
-- table to store the highlight names created by lualine
|
|
|
|
local loaded_highlights = {}
|
|
|
|
|
|
|
|
-- determine if an highlight exist and isn't cleared
|
|
|
|
function M.highlight_exists(highlight_name)
|
|
|
|
return loaded_highlights[highlight_name] or false
|
|
|
|
end
|
|
|
|
|
|
|
|
-- clears loaded_highlights table and highlights
|
|
|
|
local function clear_highlights()
|
|
|
|
for highlight_name, _ in pairs(loaded_highlights) do
|
|
|
|
vim.cmd('highlight clear ' .. highlight_name)
|
|
|
|
loaded_highlights[highlight_name] = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-08-02 14:25:34 +00:00
|
|
|
local function sanitize_color(color)
|
|
|
|
if type(color) == 'string' then
|
2021-09-03 18:28:20 +00:00
|
|
|
if color:sub(1, 1) == '#' then
|
|
|
|
return color
|
|
|
|
end -- RGB value
|
2021-08-30 11:54:23 +00:00
|
|
|
return modules.color_utils.color_name2rgb(color)
|
2021-08-02 14:25:34 +00:00
|
|
|
elseif type(color) == 'number' then
|
|
|
|
if color > 255 then
|
2021-09-03 18:28:20 +00:00
|
|
|
error("What's this it can't be higher then 255 and you've given " .. color)
|
2021-08-02 14:25:34 +00:00
|
|
|
end
|
2021-08-30 11:54:23 +00:00
|
|
|
return modules.color_utils.cterm2rgb(color)
|
2021-08-02 14:25:34 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-09-03 14:16:54 +00:00
|
|
|
function M.highlight(name, foreground, background, gui, link)
|
2021-09-03 18:28:20 +00:00
|
|
|
local command = { 'highlight!' }
|
2021-08-09 07:53:42 +00:00
|
|
|
if link and #link > 0 then
|
2021-09-03 18:28:20 +00:00
|
|
|
vim.list_extend(command, { 'link', name, link })
|
2021-08-09 07:53:42 +00:00
|
|
|
else
|
|
|
|
foreground = sanitize_color(foreground)
|
|
|
|
background = sanitize_color(background)
|
|
|
|
table.insert(command, name)
|
|
|
|
if foreground and foreground ~= 'none' then
|
|
|
|
table.insert(command, 'guifg=' .. foreground)
|
2021-08-30 11:54:23 +00:00
|
|
|
if create_cterm_colors then
|
2021-09-03 18:28:20 +00:00
|
|
|
table.insert(command, 'ctermfg=' .. modules.color_utils.rgb2cterm(foreground))
|
2021-08-09 07:53:42 +00:00
|
|
|
end
|
2021-04-08 02:43:06 +00:00
|
|
|
end
|
2021-08-09 07:53:42 +00:00
|
|
|
if background and background ~= 'none' then
|
|
|
|
table.insert(command, 'guibg=' .. background)
|
2021-08-30 11:54:23 +00:00
|
|
|
if create_cterm_colors then
|
2021-09-03 18:28:20 +00:00
|
|
|
table.insert(command, 'ctermbg=' .. modules.color_utils.rgb2cterm(background))
|
2021-08-09 07:53:42 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
if gui then
|
|
|
|
table.insert(command, 'cterm=' .. gui)
|
|
|
|
table.insert(command, 'gui=' .. gui)
|
2021-04-08 02:43:06 +00:00
|
|
|
end
|
2021-02-20 03:21:05 +00:00
|
|
|
end
|
|
|
|
vim.cmd(table.concat(command, ' '))
|
2021-09-03 14:16:54 +00:00
|
|
|
loaded_highlights[name] = true
|
2021-01-05 15:08:56 +00:00
|
|
|
end
|
|
|
|
|
2021-01-04 01:14:29 +00:00
|
|
|
function M.create_highlight_groups(theme)
|
2021-09-03 14:16:54 +00:00
|
|
|
clear_highlights()
|
2021-04-07 00:34:36 +00:00
|
|
|
active_theme = theme
|
2021-08-30 12:07:24 +00:00
|
|
|
create_cterm_colors = not vim.go.termguicolors
|
2020-12-30 14:48:51 +00:00
|
|
|
for mode, sections in pairs(theme) do
|
2021-08-09 07:53:42 +00:00
|
|
|
for section, color in pairs(sections) do
|
2021-09-03 18:28:20 +00:00
|
|
|
local highlight_group_name = { 'lualine', section, mode }
|
2021-08-09 07:53:42 +00:00
|
|
|
if type(color) == 'string' then -- link to a highlight group
|
2021-09-03 18:28:20 +00:00
|
|
|
M.highlight(table.concat(highlight_group_name, '_'), nil, nil, nil, color)
|
2021-08-09 07:53:42 +00:00
|
|
|
else -- Define a new highlight
|
2021-09-03 18:28:20 +00:00
|
|
|
M.highlight(table.concat(highlight_group_name, '_'), color.fg, color.bg, color.gui, nil)
|
2021-08-09 07:53:42 +00:00
|
|
|
end
|
2020-12-30 14:48:51 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-20 03:21:05 +00:00
|
|
|
-- @description: adds '_mode' at end of highlight_group
|
|
|
|
-- @param highlight_group:(string) name of highlight group
|
|
|
|
-- @return: (string) highlight group name with mode
|
2021-02-15 18:09:12 +00:00
|
|
|
local function append_mode(highlight_group)
|
2021-04-11 08:20:41 +00:00
|
|
|
local mode = require('lualine.utils.mode').get_mode()
|
2021-09-03 18:28:20 +00:00
|
|
|
if
|
|
|
|
mode == 'VISUAL'
|
|
|
|
or mode == 'V-BLOCK'
|
|
|
|
or mode == 'V-LINE'
|
|
|
|
or mode == 'SELECT'
|
|
|
|
or mode == 'S-LINE'
|
|
|
|
or mode == 'S-BLOCK'
|
|
|
|
then
|
2021-02-15 18:09:12 +00:00
|
|
|
highlight_group = highlight_group .. '_visual'
|
|
|
|
elseif mode == 'REPLACE' or mode == 'V-REPLACE' then
|
|
|
|
highlight_group = highlight_group .. '_replace'
|
|
|
|
elseif mode == 'INSERT' then
|
|
|
|
highlight_group = highlight_group .. '_insert'
|
2021-09-03 18:28:20 +00:00
|
|
|
elseif mode == 'COMMAND' or mode == 'EX' or mode == 'MORE' or mode == 'CONFIRM' then
|
2021-02-15 18:09:12 +00:00
|
|
|
highlight_group = highlight_group .. '_command'
|
|
|
|
elseif mode == 'TERMINAL' then
|
|
|
|
highlight_group = highlight_group .. '_terminal'
|
|
|
|
else
|
|
|
|
highlight_group = highlight_group .. '_normal'
|
|
|
|
end
|
|
|
|
return highlight_group
|
|
|
|
end
|
|
|
|
|
2021-08-19 19:23:44 +00:00
|
|
|
-- Helper function for create component highlight
|
|
|
|
-- Handles fall back of colors when crea58ng highlight group
|
|
|
|
-- @param color table color passed for creating component highlight
|
|
|
|
-- @param options_color color set by color option for component
|
|
|
|
-- this is first falk back
|
|
|
|
-- @param default_color Colors et in theme this is 2nd fall back
|
|
|
|
-- @param kind (fg/bg))
|
|
|
|
local function get_default_component_color(color, options_color, default_color, kind)
|
2021-09-03 18:28:20 +00:00
|
|
|
if color[kind] then
|
|
|
|
return color[kind]
|
|
|
|
end
|
2021-08-19 19:23:44 +00:00
|
|
|
if options_color then
|
|
|
|
if type(options_color) == 'table' and options_color[kind] then
|
|
|
|
return options_color[kind]
|
|
|
|
elseif type(options_color) == 'string' then
|
2021-08-30 11:54:23 +00:00
|
|
|
return modules.utils.extract_highlight_colors(options_color, kind)
|
2021-08-19 19:23:44 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
if type(default_color) == 'table' then
|
|
|
|
return default_color[kind]
|
|
|
|
elseif type(default_color) == 'string' then
|
2021-08-30 11:54:23 +00:00
|
|
|
return modules.utils.extract_highlight_colors(default_color, kind)
|
2021-08-19 19:23:44 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-15 18:09:12 +00:00
|
|
|
-- Create highlight group with fg bg and gui from theme
|
2021-04-07 00:34:36 +00:00
|
|
|
-- @color has to be { fg = "#rrggbb", bg="#rrggbb" gui = "effect" }
|
2021-02-15 18:09:12 +00:00
|
|
|
-- all the color elements are optional if fg or bg is not given options must be provided
|
|
|
|
-- So fg and bg can default the themes colors
|
2021-04-07 00:34:36 +00:00
|
|
|
-- @highlight_tag is unique tag for highlight group
|
2021-02-15 18:09:12 +00:00
|
|
|
-- returns the name of highlight group
|
2021-04-07 00:34:36 +00:00
|
|
|
-- @options is parameter of component.init() function
|
2021-02-20 03:21:05 +00:00
|
|
|
-- @return: (string) unique name that can be used by component_format_highlight
|
|
|
|
-- to retrive highlight group
|
2021-03-15 23:37:46 +00:00
|
|
|
function M.create_component_highlight_group(color, highlight_tag, options)
|
2021-07-27 06:57:51 +00:00
|
|
|
local tag_id = 0
|
2021-09-03 18:28:20 +00:00
|
|
|
while
|
|
|
|
M.highlight_exists(table.concat({ 'lualine', highlight_tag, 'no_mode' }, '_'))
|
|
|
|
or (
|
|
|
|
options.self.section
|
|
|
|
and M.highlight_exists(table.concat({ options.self.section, highlight_tag, 'normal' }, '_'))
|
|
|
|
)
|
|
|
|
do
|
2021-07-27 06:57:51 +00:00
|
|
|
highlight_tag = highlight_tag .. '_' .. tostring(tag_id)
|
|
|
|
tag_id = tag_id + 1
|
|
|
|
end
|
2021-08-09 07:53:42 +00:00
|
|
|
if type(color) == 'string' then
|
2021-09-03 18:28:20 +00:00
|
|
|
local highlight_group_name = table.concat({ 'lualine', highlight_tag, 'no_mode' }, '_')
|
2021-08-09 07:53:42 +00:00
|
|
|
M.highlight(highlight_group_name, nil, nil, nil, color) -- l8nk to group
|
|
|
|
return highlight_group_name
|
|
|
|
end
|
2021-02-15 18:09:12 +00:00
|
|
|
if color.bg and color.fg then
|
|
|
|
-- When bg and fg are both present we donn't need to set highlighs for
|
2021-02-20 03:21:05 +00:00
|
|
|
-- each mode as they will surely look the same. So we can work without options
|
2021-09-03 18:28:20 +00:00
|
|
|
local highlight_group_name = table.concat({ 'lualine', highlight_tag, 'no_mode' }, '_')
|
2021-08-09 07:53:42 +00:00
|
|
|
M.highlight(highlight_group_name, color.fg, color.bg, color.gui, nil)
|
2021-02-15 18:09:12 +00:00
|
|
|
return highlight_group_name
|
|
|
|
end
|
|
|
|
|
2021-03-15 23:37:46 +00:00
|
|
|
local modes = {
|
2021-09-03 18:28:20 +00:00
|
|
|
'normal',
|
|
|
|
'insert',
|
|
|
|
'visual',
|
|
|
|
'replace',
|
|
|
|
'command',
|
|
|
|
'terminal',
|
|
|
|
'inactive',
|
2021-03-15 23:37:46 +00:00
|
|
|
}
|
2021-02-20 03:21:05 +00:00
|
|
|
local normal_hl
|
|
|
|
-- convert lualine_a -> a before setting section
|
2021-09-03 18:28:20 +00:00
|
|
|
local section = options.self.section:match 'lualine_(.*)'
|
2021-05-13 16:39:30 +00:00
|
|
|
if section > 'c' and not active_theme.normal[section] then
|
2021-09-03 18:28:20 +00:00
|
|
|
section = section_highlight_map[section]
|
|
|
|
end
|
2021-02-15 18:09:12 +00:00
|
|
|
for _, mode in ipairs(modes) do
|
2021-09-03 18:28:20 +00:00
|
|
|
local highlight_group_name = { options.self.section, highlight_tag, mode }
|
|
|
|
local default_color_table = active_theme[mode] and active_theme[mode][section] or active_theme.normal[section]
|
2021-08-19 19:23:44 +00:00
|
|
|
local bg = get_default_component_color(color, options.color, default_color_table, 'bg')
|
|
|
|
local fg = get_default_component_color(color, options.color, default_color_table, 'fg')
|
2021-02-20 03:21:05 +00:00
|
|
|
-- Check if it's same as normal mode if it is no need to create aditional highlight
|
|
|
|
if mode ~= 'normal' then
|
2021-03-14 14:13:46 +00:00
|
|
|
if bg ~= normal_hl.bg or fg ~= normal_hl.fg then
|
2021-09-03 18:28:20 +00:00
|
|
|
M.highlight(table.concat(highlight_group_name, '_'), fg, bg, color.gui, nil)
|
2021-02-20 03:21:05 +00:00
|
|
|
end
|
|
|
|
else
|
2021-09-03 18:28:20 +00:00
|
|
|
normal_hl = { bg = bg, fg = fg }
|
|
|
|
M.highlight(table.concat(highlight_group_name, '_'), fg, bg, color.gui, nil)
|
2021-02-20 03:21:05 +00:00
|
|
|
end
|
2021-02-15 18:09:12 +00:00
|
|
|
end
|
2021-03-15 23:37:46 +00:00
|
|
|
return options.self.section .. '_' .. highlight_tag
|
2021-02-15 18:09:12 +00:00
|
|
|
end
|
|
|
|
|
2021-02-20 03:21:05 +00:00
|
|
|
-- @description: retrieve highlight_groups for components
|
|
|
|
-- @param highlight_name:(string) highlight group name without mode
|
|
|
|
-- return value of create_component_highlight_group is to be passed in
|
|
|
|
-- this parameter to receive highlight that was created
|
|
|
|
-- @return: (string) formated highlight group name
|
2021-02-15 18:09:12 +00:00
|
|
|
function M.component_format_highlight(highlight_name)
|
2021-02-20 03:21:05 +00:00
|
|
|
local highlight_group = highlight_name
|
2021-09-03 18:28:20 +00:00
|
|
|
if highlight_name:find 'no_mode' == #highlight_name - #'no_mode' + 1 then
|
2021-03-15 23:37:46 +00:00
|
|
|
return '%#' .. highlight_group .. '#'
|
2021-02-15 18:09:12 +00:00
|
|
|
end
|
2021-08-30 11:54:23 +00:00
|
|
|
if modules.utils.is_focused() then
|
2021-02-20 03:21:05 +00:00
|
|
|
highlight_group = append_mode(highlight_group)
|
2021-02-15 18:09:12 +00:00
|
|
|
else
|
2021-03-15 23:37:46 +00:00
|
|
|
highlight_group = highlight_group .. '_inactive'
|
2021-02-20 03:21:05 +00:00
|
|
|
end
|
2021-09-03 14:16:54 +00:00
|
|
|
if M.highlight_exists(highlight_group) then
|
2021-03-15 23:37:46 +00:00
|
|
|
return '%#' .. highlight_group .. '#'
|
2021-02-20 03:21:05 +00:00
|
|
|
else
|
2021-03-15 23:37:46 +00:00
|
|
|
return '%#' .. highlight_name .. '_normal#'
|
2021-02-15 18:09:12 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function M.format_highlight(is_focused, highlight_group)
|
2021-09-03 18:28:20 +00:00
|
|
|
if highlight_group > 'lualine_c' and not M.highlight_exists(highlight_group .. '_normal') then
|
|
|
|
highlight_group = 'lualine_' .. section_highlight_map[highlight_group:match 'lualine_(.)']
|
2021-02-20 03:21:05 +00:00
|
|
|
end
|
2021-04-13 12:36:51 +00:00
|
|
|
local highlight_name
|
2021-01-04 01:14:29 +00:00
|
|
|
if not is_focused then
|
2021-03-15 23:37:46 +00:00
|
|
|
highlight_name = highlight_group .. [[_inactive]]
|
2020-12-30 14:48:51 +00:00
|
|
|
else
|
2021-02-20 03:21:05 +00:00
|
|
|
highlight_name = append_mode(highlight_group)
|
2020-12-30 14:48:51 +00:00
|
|
|
end
|
2021-09-03 14:16:54 +00:00
|
|
|
if M.highlight_exists(highlight_name) then
|
2021-02-21 14:37:59 +00:00
|
|
|
return '%#' .. highlight_name .. '#'
|
|
|
|
end
|
2021-03-15 23:37:46 +00:00
|
|
|
return '%#' .. highlight_group .. '_normal#'
|
2021-02-20 03:21:05 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- @description : Provides transitional highlights for section separators.
|
2021-08-25 11:43:12 +00:00
|
|
|
-- @param left_hl :(string) this highlights bg is used for fg of transitional hl
|
|
|
|
-- @param right_hl:(string) this highlights bg is used for bg of transitional hl
|
|
|
|
-- '▶️' and '◀️' ' eeds reverse colors so the caller should swap left and right
|
2021-02-20 03:21:05 +00:00
|
|
|
-- @return: (string) formated highlight group name
|
2021-08-25 11:43:12 +00:00
|
|
|
function M.get_transitional_highlights(left_hl, right_hl)
|
|
|
|
-- When both left and right highlights are same or one is absent
|
|
|
|
-- nothing to transition to.
|
2021-09-03 18:28:20 +00:00
|
|
|
if left_hl == nil or right_hl == nil or left_hl == right_hl then
|
|
|
|
return nil
|
|
|
|
end
|
2021-02-20 03:21:05 +00:00
|
|
|
|
2021-03-02 12:58:34 +00:00
|
|
|
-- construct the name of hightlight group
|
2021-09-03 18:28:20 +00:00
|
|
|
local highlight_name = table.concat({ 'lualine_transitional', left_hl, 'to', right_hl }, '_')
|
2021-09-03 14:16:54 +00:00
|
|
|
if not M.highlight_exists(highlight_name) then
|
2021-02-20 03:21:05 +00:00
|
|
|
-- Create the highlight_group if needed
|
2021-03-22 14:29:37 +00:00
|
|
|
-- Get colors from highlights
|
2021-08-30 11:54:23 +00:00
|
|
|
local fg = modules.utils.extract_highlight_colors(left_hl, 'bg')
|
|
|
|
local bg = modules.utils.extract_highlight_colors(right_hl, 'bg')
|
2021-09-03 18:28:20 +00:00
|
|
|
if not fg or not bg then
|
|
|
|
return nil
|
|
|
|
end -- Color retrieval failed
|
|
|
|
if bg == fg then
|
|
|
|
return nil
|
|
|
|
end -- Separator won't be visible anyway
|
2021-08-09 07:53:42 +00:00
|
|
|
M.highlight(highlight_name, fg, bg, nil)
|
2021-02-20 03:21:05 +00:00
|
|
|
end
|
|
|
|
return '%#' .. highlight_name .. '#'
|
2020-12-30 14:48:51 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
return M
|