Skip to content

Commit

Permalink
fix: transparent background with custom backgroundColor (#185)
Browse files Browse the repository at this point in the history
## 📃 Summary

contributes to #184

we might fall in the nil background case even when custom background is
defined, this should cover this case.
  • Loading branch information
shortcuts committed Feb 13, 2023
1 parent c797ae3 commit 6dde6dd
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 35 deletions.
53 changes: 42 additions & 11 deletions lua/no-neck-pain/color.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,25 @@ local Co = require("no-neck-pain.util.constants")

local C = {}

-- converts an hex color code to RGB, values are returned independently.
---Converts an hex color code to RGB, values are returned independently.
---
---@param hex string: the hex color to conver to rgb.
---@return number?: the r color
---@return number?: the g color
---@return number?: the b color
---@private
local function hexToRGB(hex)
local r, g, b = hex:sub(2, 3), hex:sub(4, 5), hex:sub(6, 7)

return tonumber("0x" .. r), tonumber("0x" .. g), tonumber("0x" .. b)
end

-- blend the given `colorCode` RGB for the given `factor`.
---Blend the given `colorCode` RGB for the given `factor`.
---
---@param colorCode string: the color code string, e.g. #ffffff.
---@param factor number: Brighten (positive) or darken (negative) the side buffers background color. Accepted values are [-1..1].
---@return string: the blended color code.
---@private
local function blend(colorCode, factor)
local r, g, b = hexToRGB(colorCode)
local format = "#%02x%02x%02x"
Expand All @@ -30,8 +41,13 @@ local function blend(colorCode, factor)
)
end

-- tries to match the given `colorCode` to an integration name, defaults to the given `colorCode` if not found.
-- if a `factor` is provided, the color will be blended (brighten/darken) before being returned.
---Tries to match the given `colorCode` to an integration name, defaults to the given `colorCode` if not found.
---if a `factor` is provided, the color will be blended (brighten/darken) before being returned.
---
---@param colorCode string: the color code string, e.g. #ffffff.
---@param factor number: Brighten (positive) or darken (negative) the side buffers background color. Accepted values are [-1..1].
---@return string?: the blended color code.
---@private
local function matchAndBlend(colorCode, factor)
if colorCode == nil then
return nil
Expand Down Expand Up @@ -63,14 +79,23 @@ local function matchAndBlend(colorCode, factor)
return colorCode
end

return blend(colorCode, factor)
return blend(colorCode, factor or 0)
end

---Parses to color for each buffer parameters, considering transparent backgrounds.
---
---@param buffers table: the buffers table to parse.
---@return table: the parsed buffers.
---@private
function C.parse(buffers)
local defaultBackground = vim.api.nvim_get_hl_by_name("Normal", true).background

-- if the user has transparent bg and did not provided a custom one
if defaultBackground == nil then
-- if the user did not provided a custom background color, and have a transparent bg,
-- we set it to the global options and let the loop do the spread below.
if
buffers.backgroundColor == nil
and (defaultBackground == nil or string.lower(defaultBackground) == "none")
then
buffers.backgroundColor = "NONE"
buffers.textColor = "#ffffff"
else
Expand All @@ -82,6 +107,7 @@ function C.parse(buffers)

for _, side in pairs(Co.SIDES) do
if buffers[side].enabled then
-- if the side buffer backgroundColor is not defined, we fallback to the common option.
buffers[side].backgroundColor = matchAndBlend(
buffers[side].backgroundColor,
buffers[side].blend or buffers.blend
Expand All @@ -104,10 +130,15 @@ function C.parse(buffers)
return buffers
end

-- Creates highlight groups for a given `win` in a `tab` named:
-- - `NoNeckPain_background_tab_$ID_side_$SIDE` for the background colors.
-- - `NoNeckPain_text_tab_$ID_side_$SIDE` for the text colors.
-- note: `cmd` is used instead of native commands for backward compatibility with Neovim 0.7
---Creates highlight groups for a given `win` in a `tab` named:
---- `NoNeckPain_background_tab_$ID_side_$SIDE` for the background colors.
---- `NoNeckPain_text_tab_$ID_side_$SIDE` for the text colors.
---note: `cmd` is used instead of native commands for backward compatibility with Neovim 0.7
---
---@param win number: the id of the win to init.
---@param tab table: the table where the tab information are stored.
---@param side "left"|"right": the side of the window being resized, used for logging only.
---@private
function C.init(win, tab, side)
local backgroundGroup = string.format("NoNeckPain_background_tab_%s_side_%s", tab, side)
local textGroup = string.format("NoNeckPain_text_tab_%s_side_%s", tab, side)
Expand Down
12 changes: 6 additions & 6 deletions lua/no-neck-pain/tabs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ end

---Inserts a new tab to the `tabs` state, with the given `id`.
---
---@param tabs table|nil: the `tabs` state list.
---@param tabs table?: the `tabs` state list.
---@return table: the updated tabs state.
---@return table: the newly initialized tab.
---@private
Expand Down Expand Up @@ -73,7 +73,7 @@ end
---
---@param tabs table: the `tabs` state list.
---@param id number: the id of the tab to remove.
---@return table|nil: the updated tabs state list or nil if there's no remaining tabs active.
---@return table?: the updated tabs state list or nil if there's no remaining tabs active.
---@private
function Ta.remove(tabs, id)
local newTabs = {}
Expand All @@ -95,9 +95,9 @@ end

---Gets the tab with the given `id` for the state
---
---@param tabs table|nil: the `tabs` state list.
---@param id number: the id of the tab to get.
---@return table|nil: the `tab` information, or `nil` if it's not found.
---@param tabs table?: the `tabs` state list.
---@param id number?: the id of the tab to get, fallbacks to the current page when `nil`.
---@return table?: the `tab` information, or `nil` if it's not found.
---@private
function Ta.get(tabs, id)
if tabs == nil then
Expand All @@ -120,7 +120,7 @@ end
---@param tabs table: the `tabs` state list.
---@param id number: the id of the tab to update.
---@param updatedTab table: the table where the updated tab information are stored.
---@return table|nil: the `tab` information, or `nil` if it's not found.
---@return table?: the `tab` information, or `nil` if it's not found.
---@private
function Ta.update(tabs, id, updatedTab)
local updatedTabs = {}
Expand Down
4 changes: 2 additions & 2 deletions lua/no-neck-pain/util/event.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ local E = {}
--- - we are focusing a floating window
--- - we are focusing one of the side buffer
---
---@param tab table|nil: the table where the tab information are stored.
---@param tab table?: the table where the tab information are stored.
---@param skipSplit boolean: whether we should consider a relative window or not.
---@private
function E.skip(tab, skipSplit)
Expand Down Expand Up @@ -45,7 +45,7 @@ end
--- - we are focusing a floating window
--- - we are focusing one of the side buffer
---
---@param tab table|nil: the table where the tab information are stored.
---@param tab table?: the table where the tab information are stored.
---@private
function E.skipEnable(tab)
if tab ~= nil then
Expand Down
8 changes: 4 additions & 4 deletions lua/no-neck-pain/wins.lua
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ end

---Determines if the given `win` or the current window is relative.
---
---@param win number|nil: the id of the window.
---@param win number?: the id of the window.
---@return boolean: true if the window is relative.
---@private
function W.isRelativeWindow(win)
Expand Down Expand Up @@ -192,8 +192,8 @@ end
---@param scope string: the scope from where this function is called.
---@param wins table: the state wins for the current tab.
---@param paddings table: the paddings of each side window.
---@return number|nil: the left window id.
---@return number|nil: the right window id.
---@return number?: the left window id.
---@return number?: the right window id.
---@private
function W.resizeOrCloseSideBuffers(scope, wins, paddings)
for _, side in pairs(Co.SIDES) do
Expand Down Expand Up @@ -286,7 +286,7 @@ end
---
---@param main table: the `main` window state.
---@param splits table: the `splits` window state.
---@param trees table|nil: the `external.trees` window state.
---@param trees table?: the `external.trees` window state.
---@return table: the state window IDs.
---@private
function W.mergeState(main, splits, trees)
Expand Down
36 changes: 24 additions & 12 deletions tests/test_colors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,6 @@ local T = MiniTest.new_set({

T["setup"] = MiniTest.new_set()

T["setup"]["supports transparent bgs"] = function()
child.lua([[require('no-neck-pain').setup()]])

eq_config(child, "buffers.backgroundColor", "NONE")
eq_config(child, "buffers.textColor", "#ffffff")

for _, scope in pairs(Co.SIDES) do
eq_config(child, "buffers." .. scope .. ".backgroundColor", "NONE")
eq_config(child, "buffers." .. scope .. ".textColor", "#ffffff")
end
end

T["setup"]["overrides default values"] = function()
child.cmd([[
highlight Normal guibg=black guifg=white
Expand Down Expand Up @@ -127,6 +115,30 @@ T["setup"]["`common` options spreads it to `left` and `right` buffers"] = functi
eq_config(child, "buffers.right.textColor", "#000000")
end

T["setup"]["supports transparent bgs"] = function()
child.lua([[require('no-neck-pain').setup()]])

eq_config(child, "buffers.backgroundColor", "NONE")
eq_config(child, "buffers.textColor", "#ffffff")

for _, scope in pairs(Co.SIDES) do
eq_config(child, "buffers." .. scope .. ".backgroundColor", "NONE")
eq_config(child, "buffers." .. scope .. ".textColor", "#ffffff")
end
end

T["setup"]["backgroundColor overrides a nil background when defined"] = function()
child.lua([[require('no-neck-pain').setup({buffers={backgroundColor="#abcabc"}})]])

eq_config(child, "buffers.backgroundColor", "#abcabc")
eq_config(child, "buffers.textColor", vim.NIL)

for _, scope in pairs(Co.SIDES) do
eq_config(child, "buffers." .. scope .. ".backgroundColor", "#abcabc")
eq_config(child, "buffers." .. scope .. ".textColor", "#d5e4dd")
end
end

T["color"] = MiniTest.new_set()

T["color"]["map integration name to a value"] = function()
Expand Down

0 comments on commit 6dde6dd

Please sign in to comment.