From f8ca75bc45b324192f5a524155fba0e57daae979 Mon Sep 17 00:00:00 2001 From: Venkata Krishna Annam Date: Tue, 27 Jul 2021 00:29:11 +0530 Subject: [PATCH] Optimize highlights using global highlight group cache Instead of creating all highlight groups, the commands for them are generated and cached in a global variable. While rendering statusline and tabline, the highlight groups used are created on demand. --- lua/bubbly/factories/bubble.lua | 11 +++++----- lua/bubbly/factories/highlight.lua | 32 +++++++++++++++++++++--------- lua/bubbly/utils/highlight.lua | 16 +++++++++++++++ 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/lua/bubbly/factories/bubble.lua b/lua/bubbly/factories/bubble.lua index 44e41fc..5ae92ed 100644 --- a/lua/bubbly/factories/bubble.lua +++ b/lua/bubbly/factories/bubble.lua @@ -4,6 +4,7 @@ -- Created by 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, @@ -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 @@ -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 diff --git a/lua/bubbly/factories/highlight.lua b/lua/bubbly/factories/highlight.lua index 5995553..20138a1 100644 --- a/lua/bubbly/factories/highlight.lua +++ b/lua/bubbly/factories/highlight.lua @@ -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 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 diff --git a/lua/bubbly/utils/highlight.lua b/lua/bubbly/utils/highlight.lua index fdaa4e3..277743b 100644 --- a/lua/bubbly/utils/highlight.lua +++ b/lua/bubbly/utils/highlight.lua @@ -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