[Deprection] Enhance: Provide an uniform interface for color options
- Now all color related options and themes color definition have same semantics. They can either be a table containing values like bg,fg,gui or a string. When it's a string it's treated as a highlight group name and newly created group is linked to that group. - Using string values to define foreground colors in options like color_error/color_added in diagnostics and diff component has been deprecated. - Added a decent way of notifying affected users of deprecations and breaking changes.
This commit is contained in:
parent
d541574028
commit
f68d81d351
|
@ -16,6 +16,9 @@ lualine theme at lua/lualine/themes/{your_colorscheme}.lua in you repo.
|
|||
|
||||
To create a custom theme you need to define a colorscheme for each of vim's modes. Each mode has a `fg` and `bg` field for every lualine section.
|
||||
To specify colors you can use #rrggbb/color_name(like: red)/cterm_color(0-255).
|
||||
Instead of defining colors as table containing values you can define it as a
|
||||
string. This string is considered a highlight group name and lualines highlight
|
||||
is linked to that group.
|
||||
You can add special effects with `gui`.
|
||||
|
||||
Though the example shows a,b,c being set you can specify theme for x, y, z too.
|
||||
|
|
|
@ -39,13 +39,11 @@ local Component = {
|
|||
|
||||
create_option_highlights = function(self)
|
||||
-- set custom highlights
|
||||
if type(self.options.color) == 'table' then
|
||||
if self.options.color then
|
||||
self.options.color_highlight = highlight.create_component_highlight_group(
|
||||
self.options.color,
|
||||
self.options.component_name,
|
||||
self.options)
|
||||
elseif type(self.options.color) == 'string' then
|
||||
self.options.color_highlight_link = self.options.color
|
||||
end
|
||||
end,
|
||||
|
||||
|
@ -84,9 +82,6 @@ local Component = {
|
|||
if self.options.color_highlight then
|
||||
self.status = highlight.component_format_highlight(
|
||||
self.options.color_highlight) .. self.status
|
||||
elseif self.options.color_highlight_link then
|
||||
self.status = '%#' .. self.options.color_highlight_link .. '#' ..
|
||||
self.status
|
||||
end
|
||||
self.status = self.status .. default_highlight
|
||||
end,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
-- MIT license, see LICENSE for more details.
|
||||
local highlight = require('lualine.highlight')
|
||||
local utils = require('lualine.utils.utils')
|
||||
local utils_notices = require('lualine.utils.notices')
|
||||
|
||||
local Diagnostics = require('lualine.component'):new()
|
||||
|
||||
|
@ -14,6 +15,34 @@ Diagnostics.default_colors = {
|
|||
}
|
||||
-- LuaFormatter on
|
||||
|
||||
local function color_deprecation_notice(color, opt_name)
|
||||
utils_notices.add_notice(string.format([[
|
||||
### Diagnostics component
|
||||
Using option `%s` as string to set foreground color has been deprecated
|
||||
and will soon be removed. Now this option has same semantics as regular
|
||||
`color` option for components. Means now you can set bg/fg or both.
|
||||
String value is still valid but it's interpreted differemtly. When a
|
||||
string is used for this option it's treated as a highlight group name.
|
||||
In that case `%s` will be linked to that highlight group.
|
||||
|
||||
You have something like this in your config.
|
||||
|
||||
```lua
|
||||
{'diagnostics',
|
||||
%s = '%s',
|
||||
}
|
||||
```
|
||||
|
||||
You'll have to change it to this to retain previous behavior
|
||||
|
||||
```lua
|
||||
{'diagnostics',
|
||||
%s = { fg = '%s'},
|
||||
}
|
||||
```
|
||||
]], opt_name, opt_name, opt_name, color, opt_name, color))
|
||||
end
|
||||
|
||||
-- Initializer
|
||||
Diagnostics.new = function(self, options, child)
|
||||
local new_diagnostics = self._parent:new(options, child or Diagnostics)
|
||||
|
@ -41,43 +70,59 @@ Diagnostics.new = function(self, options, child)
|
|||
new_diagnostics.last_update = ''
|
||||
-- apply colors
|
||||
if not new_diagnostics.options.color_error then
|
||||
new_diagnostics.options.color_error =
|
||||
new_diagnostics.options.color_error = {fg =
|
||||
utils.extract_highlight_colors('LspDiagnosticsDefaultError', 'fg') or
|
||||
utils.extract_highlight_colors('DiffDelete', 'fg') or
|
||||
Diagnostics.default_colors.error
|
||||
Diagnostics.default_colors.error }
|
||||
elseif type(new_diagnostics.options.color_error) == 'string'
|
||||
and vim.fn.hlexists(new_diagnostics.options.color_error) == 0 then
|
||||
new_diagnostics.options.color_error = {fg = new_diagnostics.options.color_error}
|
||||
color_deprecation_notice(new_diagnostics.options.color_error.fg, 'color_error')
|
||||
end
|
||||
if not new_diagnostics.options.color_warn then
|
||||
new_diagnostics.options.color_warn =
|
||||
new_diagnostics.options.color_warn = {fg =
|
||||
utils.extract_highlight_colors('LspDiagnosticsDefaultWarning', 'fg') or
|
||||
utils.extract_highlight_colors('DiffText', 'fg') or
|
||||
Diagnostics.default_colors.warn
|
||||
Diagnostics.default_colors.warn }
|
||||
elseif type(new_diagnostics.options.color_warn) == 'string'
|
||||
and vim.fn.hlexists(new_diagnostics.options.color_warn) == 0 then
|
||||
new_diagnostics.options.color_warn = {fg = new_diagnostics.options.color_warn}
|
||||
color_deprecation_notice(new_diagnostics.options.color_warn.fg, 'color_warn')
|
||||
end
|
||||
if not new_diagnostics.options.color_info then
|
||||
new_diagnostics.options.color_info =
|
||||
new_diagnostics.options.color_info = {fg =
|
||||
utils.extract_highlight_colors('LspDiagnosticsDefaultInformation', 'fg') or
|
||||
utils.extract_highlight_colors('Normal', 'fg') or
|
||||
Diagnostics.default_colors.info
|
||||
Diagnostics.default_colors.info}
|
||||
elseif type(new_diagnostics.options.color_info) == 'string'
|
||||
and vim.fn.hlexists(new_diagnostics.options.color_info) == 0 then
|
||||
new_diagnostics.options.color_info = {fg = new_diagnostics.options.color_info}
|
||||
color_deprecation_notice(new_diagnostics.options.color_info.fg, 'color_info')
|
||||
end
|
||||
if not new_diagnostics.options.color_hint then
|
||||
new_diagnostics.options.color_hint =
|
||||
new_diagnostics.options.color_hint = {fg =
|
||||
utils.extract_highlight_colors('LspDiagnosticsDefaultHint', 'fg') or
|
||||
utils.extract_highlight_colors('DiffChange', 'fg') or
|
||||
Diagnostics.default_colors.hint
|
||||
Diagnostics.default_colors.hint}
|
||||
elseif type(new_diagnostics.options.color_hint) == 'string'
|
||||
and vim.fn.hlexists(new_diagnostics.options.color_hint) == 0 then
|
||||
new_diagnostics.options.color_hint = {fg = new_diagnostics.options.color_hint}
|
||||
color_deprecation_notice(new_diagnostics.options.color_hint.fg, 'color_hint')
|
||||
end
|
||||
|
||||
if new_diagnostics.options.colored then
|
||||
new_diagnostics.highlight_groups = {
|
||||
error = highlight.create_component_highlight_group(
|
||||
{fg = new_diagnostics.options.color_error}, 'diagnostics_error',
|
||||
new_diagnostics.options.color_error, 'diagnostics_error',
|
||||
new_diagnostics.options),
|
||||
warn = highlight.create_component_highlight_group(
|
||||
{fg = new_diagnostics.options.color_warn}, 'diagnostics_warn',
|
||||
new_diagnostics.options.color_warn, 'diagnostics_warn',
|
||||
new_diagnostics.options),
|
||||
info = highlight.create_component_highlight_group(
|
||||
{fg = new_diagnostics.options.color_info}, 'diagnostics_info',
|
||||
new_diagnostics.options.color_info, 'diagnostics_info',
|
||||
new_diagnostics.options),
|
||||
hint = highlight.create_component_highlight_group(
|
||||
{fg = new_diagnostics.options.color_hint}, 'diagnostics_hint',
|
||||
new_diagnostics.options.color_hint, 'diagnostics_hint',
|
||||
new_diagnostics.options)
|
||||
}
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
-- Copyright (c) 2020-2021 shadmansaleh
|
||||
-- MIT license, see LICENSE for more details.
|
||||
local utils = require 'lualine.utils.utils'
|
||||
local utils_notices = require('lualine.utils.notices')
|
||||
local highlight = require 'lualine.highlight'
|
||||
local Job = require'lualine.utils.job'
|
||||
|
||||
|
@ -22,6 +23,33 @@ Diff.default_colors = {
|
|||
|
||||
local diff_cache = {} -- Stores last known value of diff of a buffer
|
||||
|
||||
local function color_deprecation_notice(color, opt_name)
|
||||
utils_notices.add_notice(string.format([[
|
||||
### Diff component
|
||||
Using option `%s` as string to set foreground color has been deprecated
|
||||
and will soon be removed. Now this option has same semantics as regular
|
||||
`color` option for components. Means now you can set bg/fg or both.
|
||||
String value is still valid but it's interpreted differemtly. When a
|
||||
string is used for this option it's treated as a highlight group name.
|
||||
In that case `%s` will be linked to that highlight group.
|
||||
|
||||
You have something like this in your config.
|
||||
|
||||
```lua
|
||||
{'diff',
|
||||
%s = '%s',
|
||||
}
|
||||
```
|
||||
|
||||
You'll have to change it to this to retain previous behavior
|
||||
|
||||
```lua
|
||||
{'diff',
|
||||
%s = { fg = '%s'},
|
||||
}
|
||||
```
|
||||
]], opt_name, opt_name, opt_name, color, opt_name, color))
|
||||
end
|
||||
-- Initializer
|
||||
Diff.new = function(self, options, child)
|
||||
local new_instance = self._parent:new(options, child or Diff)
|
||||
|
@ -34,32 +62,44 @@ Diff.new = function(self, options, child)
|
|||
end
|
||||
-- apply colors
|
||||
if not new_instance.options.color_added then
|
||||
new_instance.options.color_added = utils.extract_highlight_colors('DiffAdd',
|
||||
'fg') or
|
||||
Diff.default_colors.added
|
||||
new_instance.options.color_added = {fg =
|
||||
utils.extract_highlight_colors('DiffAdd', 'fg') or
|
||||
Diff.default_colors.added}
|
||||
elseif type(new_instance.options.color_added) == 'string'
|
||||
and vim.fn.hlexists(new_instance.options.color_added) == 0 then
|
||||
new_instance.options.color_added = {fg = new_instance.options.color_added}
|
||||
color_deprecation_notice(new_instance.options.color_added.fg, 'color_added')
|
||||
end
|
||||
if not new_instance.options.color_modified then
|
||||
new_instance.options.color_modified =
|
||||
new_instance.options.color_modified = {fg =
|
||||
utils.extract_highlight_colors('DiffChange', 'fg') or
|
||||
Diff.default_colors.modified
|
||||
Diff.default_colors.modified}
|
||||
elseif type(new_instance.options.color_modified) == 'string'
|
||||
and vim.fn.hlexists(new_instance.options.color_modified) == 0 then
|
||||
new_instance.options.color_modified = {fg = new_instance.options.color_modified}
|
||||
color_deprecation_notice(new_instance.options.color_modified.fg, 'color_modified')
|
||||
end
|
||||
if not new_instance.options.color_removed then
|
||||
new_instance.options.color_removed =
|
||||
new_instance.options.color_removed = {fg =
|
||||
utils.extract_highlight_colors('DiffDelete', 'fg') or
|
||||
Diff.default_colors.removed
|
||||
Diff.default_colors.removed}
|
||||
elseif type(new_instance.options.color_removed) == 'string'
|
||||
and vim.fn.hlexists(new_instance.options.color_removed) == 0 then
|
||||
new_instance.options.color_removed = {fg = new_instance.options.color_removed}
|
||||
color_deprecation_notice(new_instance.options.color_removed.fg, 'color_removed')
|
||||
end
|
||||
|
||||
-- create highlights and save highlight_name in highlights table
|
||||
if new_instance.options.colored then
|
||||
new_instance.highlights = {
|
||||
added = highlight.create_component_highlight_group(
|
||||
{fg = new_instance.options.color_added}, 'diff_added',
|
||||
new_instance.options.color_added, 'diff_added',
|
||||
new_instance.options),
|
||||
modified = highlight.create_component_highlight_group(
|
||||
{fg = new_instance.options.color_modified}, 'diff_modified',
|
||||
new_instance.options.color_modified, 'diff_modified',
|
||||
new_instance.options),
|
||||
removed = highlight.create_component_highlight_group(
|
||||
{fg = new_instance.options.color_removed}, 'diff_removed',
|
||||
new_instance.options.color_removed, 'diff_removed',
|
||||
new_instance.options)
|
||||
}
|
||||
end
|
||||
|
|
|
@ -20,10 +20,14 @@ local function sanitize_color(color)
|
|||
end
|
||||
end
|
||||
|
||||
function M.highlight(name, foreground, background, gui, reload)
|
||||
function M.highlight(name, foreground, background, gui, link, reload)
|
||||
local command = {'highlight!'}
|
||||
if link and #link > 0 then
|
||||
vim.list_extend(command, {'link', name, link})
|
||||
else
|
||||
foreground = sanitize_color(foreground)
|
||||
background = sanitize_color(background)
|
||||
local command = {'highlight', name}
|
||||
table.insert(command, name)
|
||||
if foreground and foreground ~= 'none' then
|
||||
table.insert(command, 'guifg=' .. foreground)
|
||||
if cterm_colors then
|
||||
|
@ -42,9 +46,10 @@ function M.highlight(name, foreground, background, gui, reload)
|
|||
table.insert(command, 'cterm=' .. gui)
|
||||
table.insert(command, 'gui=' .. gui)
|
||||
end
|
||||
end
|
||||
vim.cmd(table.concat(command, ' '))
|
||||
if not reload then
|
||||
utils.save_highlight(name, {name, foreground, background, gui, true})
|
||||
utils.save_highlight(name, {name, foreground, background, gui, link, true})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -55,10 +60,15 @@ function M.create_highlight_groups(theme)
|
|||
cterm_colors = require 'lualine.utils.cterm_colors'
|
||||
end
|
||||
for mode, sections in pairs(theme) do
|
||||
for section, colorscheme in pairs(sections) do
|
||||
for section, color in pairs(sections) do
|
||||
local highlight_group_name = {'lualine', section, mode}
|
||||
M.highlight(table.concat(highlight_group_name, '_'), colorscheme.fg,
|
||||
colorscheme.bg, colorscheme.gui)
|
||||
if type(color) == 'string' then -- link to a highlight group
|
||||
M.highlight(table.concat(highlight_group_name, '_'), nil,
|
||||
nil, nil, color)
|
||||
else -- Define a new highlight
|
||||
M.highlight(table.concat(highlight_group_name, '_'), color.fg,
|
||||
color.bg, color.gui, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -105,12 +115,18 @@ function M.create_component_highlight_group(color, highlight_tag, options)
|
|||
highlight_tag = highlight_tag .. '_' .. tostring(tag_id)
|
||||
tag_id = tag_id + 1
|
||||
end
|
||||
if type(color) == 'string' then
|
||||
local highlight_group_name = table.concat(
|
||||
{'lualine', highlight_tag, 'no_mode'}, '_')
|
||||
M.highlight(highlight_group_name, nil, nil, nil, color) -- l8nk to group
|
||||
return highlight_group_name
|
||||
end
|
||||
if color.bg and color.fg then
|
||||
-- When bg and fg are both present we donn't need to set highlighs for
|
||||
-- each mode as they will surely look the same. So we can work without options
|
||||
local highlight_group_name = table.concat(
|
||||
{'lualine', highlight_tag, 'no_mode'}, '_')
|
||||
M.highlight(highlight_group_name, color.fg, color.bg, color.gui)
|
||||
M.highlight(highlight_group_name, color.fg, color.bg, color.gui, nil)
|
||||
return highlight_group_name
|
||||
end
|
||||
|
||||
|
@ -134,11 +150,13 @@ function M.create_component_highlight_group(color, highlight_tag, options)
|
|||
-- Check if it's same as normal mode if it is no need to create aditional highlight
|
||||
if mode ~= 'normal' then
|
||||
if bg ~= normal_hl.bg or fg ~= normal_hl.fg then
|
||||
M.highlight(table.concat(highlight_group_name, '_'), fg, bg, color.gui)
|
||||
M.highlight(table.concat(highlight_group_name, '_'), fg, bg, color.gui,
|
||||
nil)
|
||||
end
|
||||
else
|
||||
normal_hl = {bg = bg, fg = fg}
|
||||
M.highlight(table.concat(highlight_group_name, '_'), fg, bg, color.gui)
|
||||
M.highlight(table.concat(highlight_group_name, '_'), fg, bg, color.gui,
|
||||
nil)
|
||||
end
|
||||
end
|
||||
return options.self.section .. '_' .. highlight_tag
|
||||
|
@ -238,7 +256,7 @@ function M.get_transitional_highlights(left_section_data, right_section_data,
|
|||
if reverse then fg, bg = bg, fg end
|
||||
if not fg or not bg then return '' end -- Color retrieval failed
|
||||
if bg == fg then return '' end -- Separatoe won't be visible anyway
|
||||
M.highlight(highlight_name, fg, bg)
|
||||
M.highlight(highlight_name, fg, bg, nil)
|
||||
end
|
||||
return '%#' .. highlight_name .. '#'
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ local highlight = require('lualine.highlight')
|
|||
local loader = require('lualine.utils.loader')
|
||||
local utils_section = require('lualine.utils.section')
|
||||
local utils = require('lualine.utils.utils')
|
||||
local utils_notices = require('lualine.utils.notices')
|
||||
local config_module = require('lualine.config')
|
||||
|
||||
local config = config_module.config
|
||||
|
@ -218,12 +219,14 @@ local function setup_augroup()
|
|||
end
|
||||
|
||||
local function setup(user_config)
|
||||
utils_notices.clear_notices()
|
||||
config = config_module.apply_configuration(user_config)
|
||||
setup_augroup()
|
||||
setup_theme()
|
||||
loader.load_all(config)
|
||||
set_statusline()
|
||||
set_tabline()
|
||||
utils_notices.notice_message_startup()
|
||||
end
|
||||
|
||||
return {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
-- To provide notices for user
|
||||
local M = {}
|
||||
local notices = {}
|
||||
|
||||
function M.add_notice(notice)
|
||||
if type(notice) == 'string' then notice = vim.split(notice, "\n") end
|
||||
table.insert(notices, notice)
|
||||
end
|
||||
|
||||
function M.notice_message_startup()
|
||||
if #notices > 0 then
|
||||
vim.cmd('command! -nargs=0 LualineNotices lua require"lualine.utils.notices".show_notices()')
|
||||
vim.schedule(function()
|
||||
vim.notify(
|
||||
"lualine: There are some issues with your config. Run :LualineNotices for details",
|
||||
vim.log.levels.WARN, {})
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function M.show_notices()
|
||||
vim.cmd [[
|
||||
:silent! new
|
||||
:silent! setl ft=markdown bt=nofile nobuflisted bh=wipe
|
||||
:silent! nnoremap <silent><buffer> q <cmd>bd<cr>
|
||||
:silent! normal ggdG
|
||||
]]
|
||||
local ok, _ = pcall(vim.api.nvim_buf_set_name, 0, "Lualine Notices")
|
||||
if not ok then
|
||||
vim.notify("Lualine Notices is already open in another window",
|
||||
vim.log.levels.ERROR, {})
|
||||
vim.cmd('normal q')
|
||||
return
|
||||
end
|
||||
local notice = vim.tbl_flatten(notices)
|
||||
vim.fn.append(0, notice)
|
||||
vim.api.nvim_win_set_cursor(0, {1, 0})
|
||||
end
|
||||
|
||||
function M.clear_notices()
|
||||
notices = {}
|
||||
end
|
||||
|
||||
return M
|
|
@ -47,10 +47,21 @@ describe('Component:', function()
|
|||
.component_name,
|
||||
comp1.options)
|
||||
hl.create_component_highlight_group:revert()
|
||||
local opts2 = build_component_opts({color = 'MyHl'})
|
||||
color = 'MyHl'
|
||||
local opts2 = build_component_opts({color = color})
|
||||
stub(hl, 'create_component_highlight_group')
|
||||
hl.create_component_highlight_group.returns('MyCompLinkedHl')
|
||||
local comp2 = require('lualine.components.special.function_component'):new(
|
||||
opts2)
|
||||
eq('MyHl', comp2.options.color_highlight_link)
|
||||
eq('MyCompLinkedHl', comp2.options.color_highlight)
|
||||
-- color highlight wan't in options when create_comp_hl was
|
||||
-- called so remove it before assert
|
||||
comp2.options.color_highlight = nil
|
||||
assert.stub(hl.create_component_highlight_group).was_called_with(color,
|
||||
comp2.options
|
||||
.component_name,
|
||||
comp2.options)
|
||||
hl.create_component_highlight_group:revert()
|
||||
end)
|
||||
|
||||
it('can draw', function()
|
||||
|
@ -186,7 +197,9 @@ describe('Component:', function()
|
|||
padding = 0,
|
||||
color = 'MyHl'
|
||||
})
|
||||
assert_component(nil, opts, '%#MyHl#test')
|
||||
local comp = require('lualine.components.special.function_component'):new(opts)
|
||||
local custom_link_hl_name = 'lualine_'..comp.options.component_name..'_no_mode'
|
||||
eq('%#'..custom_link_hl_name..'#test', comp:draw(opts.hl))
|
||||
local opts2 = build_component_opts(
|
||||
{
|
||||
component_separators = {'', ''},
|
||||
|
|
|
@ -8,7 +8,7 @@ describe('Utils', function()
|
|||
local utils = require('lualine.utils.utils')
|
||||
|
||||
it('can save and restore highlights', function()
|
||||
local hl1 = {'hl1', '#122233', '#445566', 'italic', true}
|
||||
local hl1 = {'hl1', '#122233', '#445566', 'italic', nil, true}
|
||||
utils.save_highlight(hl1[1], hl1)
|
||||
-- highlight loaded in loaded_highlights table
|
||||
eq(utils.loaded_highlights[hl1[1]], hl1)
|
||||
|
@ -101,9 +101,11 @@ describe('Section genarator', function()
|
|||
require('lualine.components.special.function_component'):new(opts_colored),
|
||||
require('lualine.components.special.function_component'):new(opts)
|
||||
}
|
||||
local highlight_name2 = 'lualine_'..section[2].options.component_name..'_no_mode'
|
||||
-- Removes separator on string color
|
||||
eq(
|
||||
'%#lualine_MySection_normal# test %#lualine_MySection_normal#%#MyColor#'
|
||||
'%#lualine_MySection_normal# test %#lualine_MySection_normal#%#'
|
||||
..highlight_name2..'#'
|
||||
.. ' test %#lualine_MySection_normal# test %#lualine_MySection_normal#',
|
||||
sec.draw_section(section, 'MySection'))
|
||||
section[2] =
|
||||
|
@ -119,7 +121,7 @@ describe('Section genarator', function()
|
|||
section[2] =
|
||||
require('lua.lualine.components.special.function_component'):new(
|
||||
opts_colored3)
|
||||
local highlight_name2 =
|
||||
highlight_name2 =
|
||||
'%#lualine_c_' .. section[2].options.component_name .. '_normal#'
|
||||
-- Doesn't remove separator on color without bg
|
||||
eq('%#lualine_MySection_normal# test %#lualine_MySection_normal#' ..
|
||||
|
|
Loading…
Reference in New Issue