Skip to content
This repository has been archived by the owner on Jan 7, 2023. It is now read-only.

feat: optimization of highlights using global highlight-group cache #109

Merged
merged 2 commits into from
Jul 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions lua/bubbly/factories/bubble.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
-- Created by datwaft <github.com/datwaft>

local gethighlight = require'bubbly.utils.highlight'.gethighlight
local ensure_highlight_exists = require'bubbly.utils.highlight'.ensure_highlight_exists

local settings = {
left_character = vim.g.bubbly_characters.left,
Expand Down Expand Up @@ -32,9 +33,9 @@ return function(list)
-- Render delimiter of the bubble
local function render_delimiter(delimiter, color)
if type(color) == 'string' then
return '%#'..gethighlight(nil, color) ..'Delimiter#'..delimiter
return '%#'..ensure_highlight_exists(gethighlight(nil, color)..'Delimiter')..'#'..delimiter
else
return '%#'..gethighlight(color.foreground, color.background)..'Delimiter#'..delimiter
return '%#'..ensure_highlight_exists(gethighlight(color.foreground, color.background)..'Delimiter')..'#'..delimiter
end
end
-- Auxiliar function to know if data is last in the list
Expand Down Expand Up @@ -73,16 +74,16 @@ return function(list)
if isfirst then bubble = bubble..render_delimiter(e.left, e.color) end
-- render data style
if type(e.color) == 'string' then
bubble = bubble..'%#'..gethighlight(nil, e.color, e.style) ..'#'
bubble = bubble..'%#'..ensure_highlight_exists(gethighlight(nil, e.color, e.style))..'#'
else
bubble = bubble..'%#'..gethighlight(e.color.foreground, e.color.background, e.style)..'#'
bubble = bubble..'%#'..ensure_highlight_exists(gethighlight(e.color.foreground, e.color.background, e.style))..'#'
end
-- render data
if not isfirst then bubble = bubble..' ' end
bubble = bubble..e.data:gsub('^%s*(.-)%s*$', '%1')
if not islast then bubble = bubble..' ' end
-- render right delimiter
if islast then bubble = bubble..render_delimiter(e.right, e.color)..'%#BubblyStatusLine#' end
if islast then bubble = bubble..render_delimiter(e.right, e.color)..'%#'..ensure_highlight_exists('BubblyStatusLine')..'#' end
-- render post
bubble = bubble..e.post
-- disable isfirst
Expand Down
32 changes: 23 additions & 9 deletions lua/bubbly/factories/highlight.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,50 @@ local function execute_command(name, foreground, background, style)
vim.cmd(highlight(name, foreground, background, style))
end

-- Executes highlight vim command for normal, bold, italic and delimiter highlight
-- Creates highlight config to be used in global highlight cache
---@param command string - vim highlight command
local function highlight_config(command)
return { exists = false, cmd = command }
end

-- Returns highlight configs wrapping vim commands for normal, bold, italic and
-- delimiter highlight
---@param name string
---@param foreground string
---@param background string
---@param default_background string
local function define_bubble_highlight(name, foreground, background, default_background)
execute_command(name, background, foreground)
execute_command(name..'Bold', background, foreground, 'bold')
execute_command(name..'Italic', background, foreground, 'italic')
execute_command(name..'Delimiter', foreground, default_background)
return {
[name] = highlight_config(highlight(name, background, foreground)),
[name..'Bold'] = highlight_config(highlight(name..'Bold', background, foreground, 'bold')),
[name..'Italic'] = highlight_config(highlight(name..'Italic', background, foreground, 'italic')),
[name..'Delimiter'] = highlight_config(highlight(name..'Delimiter', foreground, default_background)),
}
end

-- Generates all vim highlights following :help :highlight for a palette
-- Generates all vim highlight configs following :help :highlight for a palette
-- and saves them in a global variable
---@param palette table<string, string>
return function(palette)
local fg = hlparser(palette.foreground)
local bg = hlparser(palette.background)
local highlights = {}
for k1, v1 in pairs(palette) do
v1 = hlparser(v1)
for k2, v2 in pairs(palette) do
if k1 ~= k2 then
v2 = hlparser(v2)
local name = 'Bubbly'..titlecase(k2)..titlecase(k1)
define_bubble_highlight(name, v1, v2, bg)
local bubble_highlights = define_bubble_highlight(name, v1, v2, bg)
highlights = vim.tbl_extend('force', highlights, bubble_highlights)
end
end
if k1 ~= 'background' then
define_bubble_highlight('Bubbly'..titlecase(k1), v1, bg, bg)
local bubble_highlights = define_bubble_highlight('Bubbly'..titlecase(k1), v1, bg, bg)
highlights = vim.tbl_extend('force', highlights, bubble_highlights)
end
end
execute_command('BubblyStatusLine', fg, bg)
highlights['BubblyStatusLine'] = highlight_config(highlight('BubblyStatusLine', fg, bg))
execute_command('BubblyTabLine', fg, bg)
vim.g._bubbly_highlight_cache = highlights
end
16 changes: 16 additions & 0 deletions lua/bubbly/utils/highlight.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ function M.gethighlight(foreground, background, special)
titlecase(special)
end

-- Ensures that a highlight with given name exists.
---@param name string | nil
---@return string
function M.ensure_highlight_exists(name)
local highlight_cache = vim.g._bubbly_highlight_cache or {}
local highlight = highlight_cache[name]
if highlight and not highlight.exists then
vim.cmd(highlight.cmd)
highlight.exists = true
highlight_cache[name] = highlight
vim.g._bubbly_highlight_cache = highlight_cache
end
-- Return the highlight name to be able to wrap 'name' with this function call
return name
end

-- Parses a palette value
---@param usercolor string
---@return string
Expand Down