Skip to content
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
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ Take a look at the default shortcuts for navigating between buffers, changing th
shortcut = "#CC7832",
active = "#51afef",
unsaved_indicator = "#f70067",
transparent = false,
},
leader_key = ";",
mapping_chars = "qweryuiop",
Expand Down Expand Up @@ -238,6 +239,22 @@ vim.api.nvim_set_hl(0, "BuffonUnloadedBuffer", { fg = "#404040" })
> [!NOTE]
> If a highlight group exists in Neovim, it will take precendence over the one specified in Buffon's configuration. Therefore, if you want to change the color of a highlight group, you must first remove it with `vim.api.nvim_set_hl(0, "BuffonUnloadedBuffer", { fg = nil })` and then specify the new color. This is because if a colorscheme is installed that has a defined highlight group, it will take precedence over the one specified in Buffon's configuration.

### Transparent background

If you want the Buffon window (and the help window) to render with a transparent background, set `theme.transparent = true`:

```lua
{
opts = {
theme = {
transparent = true,
},
},
}
```

When enabled, Buffon creates a `BuffonWindow` highlight group with `bg = "NONE"` and applies it to the floating window's `Normal`, `FloatBorder`, `FloatTitle`, `FloatFooter`, and `EndOfBuffer` groups via `winhighlight`. The foreground colors are kept from your colorscheme, so the text and border remain visible — only the background becomes transparent.

## 📸 Screenshots

Buffon window, showing the buffer list:
Expand Down
5 changes: 5 additions & 0 deletions lua/buffon/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ local default = {
shortcut = "#CC7832",
active = "#51afef",
unsaved_indicator = "#f70067",
transparent = false,
},
leader_key = ";",
mapping_chars = "qweryuiop",
Expand Down Expand Up @@ -93,6 +94,7 @@ local default = {
---@field shortcut string
---@field active string
---@field unsaved_indicator string
---@field transparent boolean

---@class BuffonConfig
---@field cyclic_navigation boolean -- If true, navigation between buffers will wrap around (cyclic navigation).
Expand Down Expand Up @@ -133,6 +135,9 @@ function Config:load_theme()
set_hl("BuffonShortcut", self.theme.shortcut)
set_hl("BuffonLineActive", self.theme.active)
set_hl("BuffonUnsavedIndicator", self.theme.unsaved_indicator)
if self.theme.transparent then
vim.api.nvim_set_hl(0, "BuffonWindow", { bg = "NONE", default = true })
end
end

M.Config = Config
Expand Down
7 changes: 6 additions & 1 deletion lua/buffon/ui/help.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ function HelpWindow:new(cfg, main_window)
local o = {
config = cfg,
main_window = main_window,
window = window.Window:new(" Buffon Help ", window.WIN_POSITIONS.BOTTOM_RIGHT, cfg.open.offset),
window = window.Window:new(
" Buffon Help ",
window.WIN_POSITIONS.BOTTOM_RIGHT,
cfg.open.offset,
cfg.theme.transparent
),
}

setmetatable(o, self)
Expand Down
2 changes: 1 addition & 1 deletion lua/buffon/ui/mainwindow.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ local MainWindow = {}
function MainWindow:new(config, page_controller)
local title = " Buffon (" .. utils.replace_leader(config, config.keybindings.show_help) .. ") "
local o = {
window = window.Window:new(title, config.open.default_position, config.open.offset),
window = window.Window:new(title, config.open.default_position, config.open.offset, config.theme.transparent),
page_controller = page_controller,
config = config,
}
Expand Down
11 changes: 10 additions & 1 deletion lua/buffon/ui/window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ local WIN_POSITION = {
---@field buf_id number | nil
---@field position win_position
---@field offset Vector2
---@field transparent boolean
local Window = {
title = "",
footer = "",
Expand All @@ -29,19 +30,22 @@ local Window = {
x = 0,
y = 0,
},
transparent = false,
}

---@param title string
---@param position win_position
---@param offset Vector2
---@param transparent boolean
---@return BuffonWindow
function Window:new(title, position, offset)
function Window:new(title, position, offset, transparent)
local o = {
title = title,
win_id = nil,
buf_id = nil,
position = position,
offset = offset,
transparent = transparent or false,
}
setmetatable(o, self)
self.__index = self
Expand All @@ -68,6 +72,11 @@ function Window:show()
zindex = 21,
focusable = false,
})
if self.transparent then
local hl = "Normal:BuffonWindow,FloatBorder:BuffonWindow,FloatTitle:BuffonWindow,FloatFooter:BuffonWindow,"
.. "EndOfBuffer:BuffonWindow"
vim.api.nvim_set_option_value("winhighlight", hl, { win = self.win_id })
end
self:refresh_dimensions()
end

Expand Down
29 changes: 29 additions & 0 deletions tests/config_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe("config", function()
shortcut = "#CC7832",
active = "#51afef",
unsaved_indicator = "#f70067",
transparent = false,
},
leader_key = ";",
mapping_chars = "qweryuiop",
Expand Down Expand Up @@ -65,4 +66,32 @@ describe("config", function()
local cfg2 = config.Config:new({ num_pages = 5 })
eq(cfg2.num_pages, 1)
end)

it("theme.transparent defaults to false", function()
local cfg = config.Config:new()
eq(cfg.theme.transparent, false)
end)

it("theme.transparent can be set to true", function()
local cfg = config.Config:new({ theme = { transparent = true } })
eq(cfg.theme.transparent, true)
end)

it("creates BuffonWindow hl group when transparent is true", function()
config.Config:new({ theme = { transparent = true } })
local ns = vim.api.nvim_get_hl_ns({})
local hl = vim.api.nvim_get_hl(ns, { name = "BuffonWindow" })
-- bg = "NONE" is represented as default = true in nvim_get_hl output
eq(hl.default, true)
end)

it("does not override BuffonWindow hl when transparent is false", function()
-- set a known bg first
vim.api.nvim_set_hl(0, "BuffonWindow", { bg = "#123456" })
config.Config:new({ theme = { transparent = false } })
local ns = vim.api.nvim_get_hl_ns({})
local hl = vim.api.nvim_get_hl(ns, { name = "BuffonWindow" })
-- nvim normalizes #123456 to integer 0x123456 = 1193046
eq(hl.bg, 1193046)
end)
end)
37 changes: 37 additions & 0 deletions tests/window_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
local eq = assert.are.same
local window = require("buffon.ui.window")

describe("window", function()
local function close_win(win_id)
if win_id and vim.api.nvim_win_is_valid(win_id) then
vim.api.nvim_win_close(win_id, false)
end
end

it("applies winhighlight when transparent is true", function()
local w = window.Window:new(" Buffon ", window.WIN_POSITIONS.TOP_RIGHT, { x = 0, y = 0 }, true)
w:show()
local wh = vim.api.nvim_get_option_value("winhighlight", { win = w.win_id })
eq(
wh,
"Normal:BuffonWindow,FloatBorder:BuffonWindow,FloatTitle:BuffonWindow,FloatFooter:BuffonWindow,EndOfBuffer:BuffonWindow"
)
close_win(w.win_id)
end)

it("does not include BuffonWindow in winhighlight when transparent is false", function()
local w = window.Window:new(" Buffon ", window.WIN_POSITIONS.TOP_RIGHT, { x = 0, y = 0 }, false)
w:show()
local wh = vim.api.nvim_get_option_value("winhighlight", { win = w.win_id })
eq(wh:find("BuffonWindow", 1, true) == nil, true)
close_win(w.win_id)
end)

it("does not include BuffonWindow in winhighlight when transparent is not provided", function()
local w = window.Window:new(" Buffon ", window.WIN_POSITIONS.TOP_RIGHT, { x = 0, y = 0 })
w:show()
local wh = vim.api.nvim_get_option_value("winhighlight", { win = w.win_id })
eq(wh:find("BuffonWindow", 1, true) == nil, true)
close_win(w.win_id)
end)
end)