Skip to content

Commit ef54bc2

Browse files
authored
feat: separate highlight option for title of Borders (#260)
* wip: minimal setup for separate title highlights * fix: out of bounds index when title is max size * refactor: factor out `set_title_highlights` * refactor: move check inside `set_title_highlights` * fix: do refactor of `set_title_highlights` everywhere
1 parent b8c8d23 commit ef54bc2

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

lua/plenary/popup/init.lua

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ function popup.create(what, vim_options)
379379
local border = nil
380380
if should_show_border then
381381
border_options.focusable = vim_options.border_focusable
382+
border_options.highlight = vim_options.borderhighlight and string.format("Normal:%s", vim_options.borderhighlight)
383+
border_options.titlehighlight = vim_options.titlehighlight
382384
border = Border:new(bufnr, win_id, win_opts, border_options)
383385
popup._borders[win_id] = border
384386
end
@@ -387,10 +389,6 @@ function popup.create(what, vim_options)
387389
vim.api.nvim_win_set_option(win_id, "winhl", string.format("Normal:%s", vim_options.highlight))
388390
end
389391

390-
if should_show_border and vim_options.borderhighlight then
391-
vim.api.nvim_win_set_option(border.win_id, "winhl", string.format("Normal:%s", vim_options.borderhighlight))
392-
end
393-
394392
-- enter
395393
local should_enter = vim_options.enter
396394
if should_enter == nil then

lua/plenary/window/border.lua

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ local create_horizontal_line = function(title, pos, width, left_char, mid_char,
4646
string.rep(mid_char, width - title_len - left_start),
4747
right_char
4848
)
49-
return horizontal_line
49+
local ranges
50+
if title_len ~= 0 then
51+
-- Need to calculate again due to multi-byte characters
52+
local r_start = string.len(left_char) + math.max(left_start, 0) * string.len(mid_char)
53+
ranges = { { r_start, r_start + string.len(title) } }
54+
end
55+
return horizontal_line, ranges
5056
end
5157

5258
function Border._create_lines(content_win_options, border_win_options)
@@ -59,6 +65,7 @@ function Border._create_lines(content_win_options, border_win_options)
5965
local left_enabled = thickness.left == 1
6066

6167
local border_lines = {}
68+
local ranges = {}
6269

6370
local topline = nil
6471

@@ -85,14 +92,18 @@ function Border._create_lines(content_win_options, border_win_options)
8592
then
8693
for _, title in ipairs(titles) do
8794
if string.find(title.pos, "N") then
88-
topline = create_horizontal_line(
95+
local top_ranges
96+
topline, top_ranges = create_horizontal_line(
8997
title.text,
9098
title.pos,
9199
content_win_options.width,
92100
topleft,
93101
border_win_options.top or "",
94102
topright
95103
)
104+
for _, r in pairs(top_ranges) do
105+
table.insert(ranges, { 0, r[1], r[2] })
106+
end
96107
break
97108
end
98109
end
@@ -126,14 +137,18 @@ function Border._create_lines(content_win_options, border_win_options)
126137
local botright = (right_enabled and border_win_options.botright) or ""
127138
for _, title in ipairs(titles) do
128139
if string.find(title.pos, "S") then
129-
botline = create_horizontal_line(
140+
local bot_ranges
141+
botline, bot_ranges = create_horizontal_line(
130142
title.text,
131143
title.pos,
132144
content_win_options.width,
133145
botleft,
134146
border_win_options.bot or "",
135147
botright
136148
)
149+
for _, r in pairs(bot_ranges) do
150+
table.insert(ranges, { content_win_options.height + 1, r[1], r[2] })
151+
end
137152
break
138153
end
139154
end
@@ -145,7 +160,15 @@ function Border._create_lines(content_win_options, border_win_options)
145160
table.insert(border_lines, botline)
146161
end
147162

148-
return border_lines
163+
return border_lines, ranges
164+
end
165+
166+
local set_title_highlights = function(bufnr, ranges, hl)
167+
if hl and ranges then
168+
for _, r in pairs(ranges) do
169+
vim.api.nvim_buf_add_highlight(bufnr, -1, hl, r[1], r[2], r[3])
170+
end
171+
end
149172
end
150173

151174
function Border:change_title(new_title)
@@ -154,8 +177,10 @@ function Border:change_title(new_title)
154177
end
155178

156179
self._border_win_options.title = new_title
157-
self.contents = Border._create_lines(self.content_win_options, self._border_win_options)
180+
self.contents, self.title_ranges = Border._create_lines(self.content_win_options, self._border_win_options)
158181
vim.api.nvim_buf_set_lines(self.bufnr, 0, -1, false, self.contents)
182+
183+
set_title_highlights(self.bufnr, self.title_ranges, self._border_win_options.titlehighlight)
159184
end
160185

161186
-- Updates characters for border lines, and returns nvim_win_config
@@ -192,7 +217,8 @@ function Border:__align_calc_config(content_win_options, border_win_options)
192217
-- Ensure the relevant contests and border win_options are set
193218
self._border_win_options = border_win_options
194219
self.content_win_options = content_win_options
195-
self.contents = Border._create_lines(content_win_options, border_win_options)
220+
-- Update border characters and title_ranges
221+
self.contents, self.title_ranges = Border._create_lines(content_win_options, border_win_options)
196222

197223
vim.api.nvim_buf_set_lines(self.bufnr, 0, -1, false, self.contents)
198224

@@ -225,6 +251,12 @@ function Border:new(content_bufnr, content_win_id, content_win_options, border_w
225251
local nvim_win_config = Border.__align_calc_config(obj, content_win_options, border_win_options)
226252
obj.win_id = vim.api.nvim_open_win(obj.bufnr, false, nvim_win_config)
227253

254+
if border_win_options.highlight then
255+
vim.api.nvim_win_set_option(obj.win_id, "winhl", border_win_options.highlight)
256+
end
257+
258+
set_title_highlights(obj.bufnr, obj.title_ranges, obj._border_win_options.titlehighlight)
259+
228260
vim.cmd(
229261
string.format(
230262
"autocmd BufDelete <buffer=%s> ++nested ++once :lua require('plenary.window').close_related_win(%s, %s)",

0 commit comments

Comments
 (0)