fix: bar separators use FloatBorder (bright), 3-row bars frame both edges

User kept complaining the status bar's separator looked dark while
dapui's pane dividers looked bright. I had WinSeparator vs
FloatBorder backwards.

Actual values in nightfox (and most dark colorschemes):
  WinSeparator.fg = #131721 (very dark — what I was using, the dark
                             look user objected to)
  FloatBorder.fg  = #71839B (bright grey — what user wants, matches
                             WinBar.fg which is what dapui's pane
                             header text renders in)

Switched TurboDebugBarSeparator back to FloatBorder. Also restored
3-row bars for BOTH status and control bars so each has separators
on BOTH top AND bottom edges in the bright color. Symmetric framing
top to bottom of the debug UI.

Also: Watches pane icon switched from 👁️ (eye, U+1F441+VS16) to 👀
(eyes, U+1F440) per user preference. Supplementary-plane emoji with
no VS16 dependency, always renders as color emoji.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
swaitsandClaude Opus 4.6 committed 2026-04-12 15:36:47 -06:00
1 parent c420acd599
commit c8f37bcb7e
1 file changed
+37 -30
+37 -30
View File
@@ -54,7 +54,7 @@ local ICON = {
-- pane-title emoji (supplementary plane — reliably colorful) -- pane-title emoji (supplementary plane — reliably colorful)
scopes = "\xf0\x9f\x94\x8e", -- 🔎 magnifier (U+1F50E) scopes = "\xf0\x9f\x94\x8e", -- 🔎 magnifier (U+1F50E)
watches = "\xf0\x9f\x91\x81\xef\xb8\x8f", -- 👁️ eye (U+1F441 + VS16) watches = "\xf0\x9f\x91\x80", -- 👀 eyes (U+1F440)
stacks = "\xf0\x9f\x93\x9a", -- 📚 books (U+1F4DA) stacks = "\xf0\x9f\x93\x9a", -- 📚 books (U+1F4DA)
breakpoints = "\xf0\x9f\x94\xb4", -- 🔴 red circle (U+1F534) breakpoints = "\xf0\x9f\x94\xb4", -- 🔴 red circle (U+1F534)
terminal = "\xf0\x9f\x92\xbb", -- 💻 laptop (U+1F4BB) terminal = "\xf0\x9f\x92\xbb", -- 💻 laptop (U+1F4BB)
@@ -134,11 +134,12 @@ local function define_highlights()
-- default background). StatusLine was too dark and created a visible -- default background). StatusLine was too dark and created a visible
-- seam between the bar and the surrounding panes. -- seam between the bar and the surrounding panes.
hl(0, "TurboDebugBar", { default = true, link = "Normal" }) hl(0, "TurboDebugBar", { default = true, link = "Normal" })
-- WinSeparator (not FloatBorder) so the bar edges match the dividers -- FloatBorder — the bright grey most colorschemes use for chrome
-- dapui draws between its own panes. FloatBorder tends to read darker -- dividers (nightfox: #71839B, same as WinBar.fg so dapui's pane
-- than WinSeparator in most colorschemes, which created a visible -- header text and our bar separators match). WinSeparator is
-- mismatch between our bar's bottom and the adjacent dapui pane top. -- typically much darker (nightfox: #131721) which produced the
hl(0, "TurboDebugBarSeparator", { default = true, link = "WinSeparator" }) -- visible "dark line vs bright line" mismatch the user kept hitting.
hl(0, "TurboDebugBarSeparator", { default = true, link = "FloatBorder" })
-- Control labels: link to Normal so the text blends with the bar's -- Control labels: link to Normal so the text blends with the bar's
-- Normal-bg surface. StatusLine bg was creating a visible color patch -- Normal-bg surface. StatusLine bg was creating a visible color patch
-- behind each label. The key letter still pops via TurboDebugBarKey -- behind each label. The key letter still pops via TurboDebugBarKey
@@ -281,18 +282,22 @@ local function render_sbar()
local pad_right = remain - pad_left local pad_right = remain - pad_left
local content_line = brand_text .. string.rep(" ", pad_left) .. status_msg .. string.rep(" ", pad_right) .. state_chip local content_line = brand_text .. string.rep(" ", pad_left) .. status_msg .. string.rep(" ", pad_right) .. state_chip
-- 2 rows: sep / content. No bottom separator — dapui renders its own -- 3 rows: sep / content / sep. Both separators use
-- pane border above its top elements, which serves as our bottom -- TurboDebugBarSeparator (→ FloatBorder, the bright grey) so the
-- edge. Drawing ours too was producing two stacked separator rows. -- bar is visibly framed top and bottom matching the window-
-- separator color the rest of the dapui chrome uses.
vim.bo[sbar_buf].modifiable = true vim.bo[sbar_buf].modifiable = true
vim.api.nvim_buf_set_lines(sbar_buf, 0, -1, false, { sep, content_line }) vim.api.nvim_buf_set_lines(sbar_buf, 0, -1, false, { sep, content_line, sep })
vim.bo[sbar_buf].modifiable = false vim.bo[sbar_buf].modifiable = false
vim.api.nvim_buf_clear_namespace(sbar_buf, bar_ns, 0, -1) vim.api.nvim_buf_clear_namespace(sbar_buf, bar_ns, 0, -1)
pcall(vim.api.nvim_buf_set_extmark, sbar_buf, bar_ns, 0, 0, { pcall(vim.api.nvim_buf_set_extmark, sbar_buf, bar_ns, 0, 0, {
end_row = 0, end_col = #sep, hl_group = "TurboDebugBarSeparator", end_row = 0, end_col = #sep, hl_group = "TurboDebugBarSeparator",
}) })
-- content pcall(vim.api.nvim_buf_set_extmark, sbar_buf, bar_ns, 2, 0, {
end_row = 2, end_col = #sep, hl_group = "TurboDebugBarSeparator",
})
-- content row
pcall(vim.api.nvim_buf_set_extmark, sbar_buf, bar_ns, 1, 0, { pcall(vim.api.nvim_buf_set_extmark, sbar_buf, bar_ns, 1, 0, {
end_row = 1, end_col = #brand_text, hl_group = "TurboDebugBarBrand", end_row = 1, end_col = #brand_text, hl_group = "TurboDebugBarBrand",
}) })
@@ -371,35 +376,37 @@ local function render_cbar()
if ctrl_pad_right < 1 then ctrl_pad_right = 1 end if ctrl_pad_right < 1 then ctrl_pad_right = 1 end
local content_line = string.rep(" ", ctrl_pad_left) .. controls_text .. string.rep(" ", ctrl_pad_right) .. help_text local content_line = string.rep(" ", ctrl_pad_left) .. controls_text .. string.rep(" ", ctrl_pad_right) .. help_text
-- 2 rows: content / sep (no top separator — the source/dapui area -- 3 rows: sep / content / sep. Both separators use the bright
-- above has its own pane borders as the visual break) -- FloatBorder color so the control bar is visibly framed top AND
-- bottom, matching the status bar treatment.
vim.bo[cbar_buf].modifiable = true vim.bo[cbar_buf].modifiable = true
vim.api.nvim_buf_set_lines(cbar_buf, 0, -1, false, { content_line, sep }) vim.api.nvim_buf_set_lines(cbar_buf, 0, -1, false, { sep, content_line, sep })
vim.bo[cbar_buf].modifiable = false vim.bo[cbar_buf].modifiable = false
vim.api.nvim_buf_clear_namespace(cbar_buf, bar_ns, 0, -1) vim.api.nvim_buf_clear_namespace(cbar_buf, bar_ns, 0, -1)
-- bottom separator (on row 1 now since content is on row 0) pcall(vim.api.nvim_buf_set_extmark, cbar_buf, bar_ns, 0, 0, {
pcall(vim.api.nvim_buf_set_extmark, cbar_buf, bar_ns, 1, 0, { end_row = 0, end_col = #sep, hl_group = "TurboDebugBarSeparator",
end_row = 1, end_col = #sep, hl_group = "TurboDebugBarSeparator", })
pcall(vim.api.nvim_buf_set_extmark, cbar_buf, bar_ns, 2, 0, {
end_row = 2, end_col = #sep, hl_group = "TurboDebugBarSeparator",
}) })
-- control labels on row 0 (content row) -- control labels on row 1 (content row)
local ctrl_byte_offset = ctrl_pad_left local ctrl_byte_offset = ctrl_pad_left
for _, span in ipairs(ctrl_spans) do for _, span in ipairs(ctrl_spans) do
pcall(vim.api.nvim_buf_set_extmark, cbar_buf, bar_ns, 0, ctrl_byte_offset + span[1], { pcall(vim.api.nvim_buf_set_extmark, cbar_buf, bar_ns, 1, ctrl_byte_offset + span[1], {
end_row = 0, end_col = ctrl_byte_offset + span[2], hl_group = span[3], end_row = 1, end_col = ctrl_byte_offset + span[2], hl_group = span[3],
}) })
end end
for _, span in ipairs(ctrl_key_spans) do for _, span in ipairs(ctrl_key_spans) do
pcall(vim.api.nvim_buf_set_extmark, cbar_buf, bar_ns, 0, ctrl_byte_offset + span[1], { pcall(vim.api.nvim_buf_set_extmark, cbar_buf, bar_ns, 1, ctrl_byte_offset + span[1], {
end_row = 0, end_col = ctrl_byte_offset + span[2], hl_group = "TurboDebugBarKey", end_row = 1, end_col = ctrl_byte_offset + span[2], hl_group = "TurboDebugBarKey",
}) })
end end
-- help (right-anchored) on row 0
local help_byte_start = #content_line - #help_text local help_byte_start = #content_line - #help_text
pcall(vim.api.nvim_buf_set_extmark, cbar_buf, bar_ns, 0, help_byte_start, { pcall(vim.api.nvim_buf_set_extmark, cbar_buf, bar_ns, 1, help_byte_start, {
end_row = 0, end_col = #content_line, hl_group = "TurboDebugBarCtrl", end_row = 1, end_col = #content_line, hl_group = "TurboDebugBarCtrl",
}) })
cbar_zones = {} cbar_zones = {}
@@ -408,12 +415,12 @@ local function render_cbar()
local byte_end = ctrl_byte_offset + z[2] local byte_end = ctrl_byte_offset + z[2]
local dcol_start = vim.fn.strdisplaywidth(content_line:sub(1, byte_start)) local dcol_start = vim.fn.strdisplaywidth(content_line:sub(1, byte_start))
local dcol_end = vim.fn.strdisplaywidth(content_line:sub(1, byte_end)) local dcol_end = vim.fn.strdisplaywidth(content_line:sub(1, byte_end))
-- content is on buffer row 0 = window line 1 -- content is on buffer row 1 = window line 2
cbar_zones[#cbar_zones + 1] = { 1, dcol_start, dcol_end, z[3] } cbar_zones[#cbar_zones + 1] = { 2, dcol_start, dcol_end, z[3] }
end end
local help_dcol_start = vim.fn.strdisplaywidth(content_line:sub(1, help_byte_start)) local help_dcol_start = vim.fn.strdisplaywidth(content_line:sub(1, help_byte_start))
local help_dcol_end = vim.fn.strdisplaywidth(content_line) local help_dcol_end = vim.fn.strdisplaywidth(content_line)
cbar_zones[#cbar_zones + 1] = { 1, help_dcol_start, help_dcol_end, cbar_zones[#cbar_zones + 1] = { 2, help_dcol_start, help_dcol_end,
function() require("turbo-debug.help").open() end } function() require("turbo-debug.help").open() end }
end end
@@ -496,7 +503,7 @@ local function open_bars()
sbar_win = vim.api.nvim_get_current_win() sbar_win = vim.api.nvim_get_current_win()
sbar_buf = vim.api.nvim_create_buf(false, true) sbar_buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_win_set_buf(sbar_win, sbar_buf) vim.api.nvim_win_set_buf(sbar_win, sbar_buf)
vim.api.nvim_win_set_height(sbar_win, 2) vim.api.nvim_win_set_height(sbar_win, 3)
setup_bar_buf(sbar_buf) setup_bar_buf(sbar_buf)
setup_bar_win(sbar_win) setup_bar_win(sbar_win)
vim.wo[sbar_win].winfixheight = true vim.wo[sbar_win].winfixheight = true
@@ -515,7 +522,7 @@ local function open_bars()
cbar_win = vim.api.nvim_get_current_win() cbar_win = vim.api.nvim_get_current_win()
cbar_buf = vim.api.nvim_create_buf(false, true) cbar_buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_win_set_buf(cbar_win, cbar_buf) vim.api.nvim_win_set_buf(cbar_win, cbar_buf)
vim.api.nvim_win_set_height(cbar_win, 2) vim.api.nvim_win_set_height(cbar_win, 3)
setup_bar_buf(cbar_buf) setup_bar_buf(cbar_buf)
setup_bar_win(cbar_win) setup_bar_win(cbar_win)
vim.wo[cbar_win].winfixheight = true vim.wo[cbar_win].winfixheight = true