Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(offsets): use wininfo to calculate offset #800

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
101 changes: 28 additions & 73 deletions lua/bufferline/offset.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,6 @@ local api = vim.api
local fn = vim.fn
local padding = constants.padding

local t = {
LEAF = "leaf",
ROW = "row",
COLUMN = "col",
}

local supported_win_types = {
[t.LEAF] = true,
[t.COLUMN] = true,
}

---Format the content of a neighbouring offset's text
---@param size integer
---@param highlight table<string, string>
Expand Down Expand Up @@ -80,57 +69,23 @@ local function guess_window_highlight(win_id, attribute, match)
return match
end

--- This helper checks to see if bufferline supports creating an offset for the given layout
--- Valid window layouts can be
--- * A list of full height splits in a row:
--- `{'row', ['leaf', id], ['leaf', id]}`
--- * A row of splits where one on either edge is not full height but the matching
--- split is on the top:
--- e.g. the vertical tool bar is split in two such as for undo tree
--- `{'row', ['col', ['leaf', id], ['leaf', id]], ['leaf', id]}`
---
---@param windows any[]
---@return boolean, number
local function is_valid_layout(windows)
local win_type, win_id = windows[1], windows[2]
if utils.is_list(win_id) and win_type == t.COLUMN then win_id = win_id[1][2] end
return supported_win_types[win_type] and type(win_id) == "number", win_id
end

--- Test if the windows within a layout row contain the correct panel buffer
--- NOTE: this only tests the first and last windows as those are the only
--- ones that it makes sense to add a panel for
---@param windows any[]
---@param windows {wincol: number, winrow: number, bufnr: number, winid: number, width: number}[]
---@param offset table
---@return boolean
---@return number?
---@return boolean?
---@return boolean valid
---@return number? win_id
---@return boolean? is_left
local function is_offset_section(windows, offset)
local wins = { windows[1] }
if #windows > 1 then wins[#wins + 1] = windows[#windows] end
for idx, win in ipairs(wins) do
local valid_layout, win_id = is_valid_layout(win)
if valid_layout then
local buf = api.nvim_win_get_buf(win_id)
local valid = buf and vim.bo[buf].filetype == offset.filetype
local is_left = idx == 1
if valid then return valid, win_id, is_left end
local last = windows[1]
for _, win in ipairs(windows) do
if win.winrow == 2 then
if vim.bo[win.bufnr].filetype == offset.filetype then
if win.wincol > last.wincol then last = win end
if win.wincol == 1 then return true, win.winid, true end
end
end
end
return false, nil, nil
end

--- Iterate over COLUMN layout by always picking the first element.
--- Assuming this is the topmost window, it's the one that should
--- dictate the tabline offset.
---@param layout any[]
---@return any[]
local function iterate_col_layout(layout)
if layout[1] == t.COLUMN then
return iterate_col_layout(layout[2][1])
else
return layout
end
if last.wincol > 1 then return true, last.winid, false end
return false
end

---@class OffsetData
Expand All @@ -151,28 +106,28 @@ function M.get()
local total_size = 0
local sep_hl = highlights.hl(hls.offset_separator.hl_group)

if offsets and #offsets > 0 then
local layout = iterate_col_layout(fn.winlayout())
-- wininfo tells us whether or not a window is on the top level or not of the layout
-- if it is on the top level and it is at the end or beginning it is an offset
local wininfo = vim.tbl_filter(function(win) return fn.win_gettype(win.winnr) == "" end, fn.getwininfo())

if offsets and #offsets > 0 then
for _, offset in ipairs(offsets) do
-- don't bother proceeding if there are no vertical splits
if layout[1] == t.ROW then
local is_valid, win_id, is_left = is_offset_section(layout[2], offset)
if is_valid and win_id then
local width = api.nvim_win_get_width(win_id) + (offset.padding or 0)
local is_valid, win_id, is_left = is_offset_section(wininfo, offset)
if is_valid and win_id then
local width = api.nvim_win_get_width(win_id) + (offset.padding or 0)

local hl_name = offset.highlight or guess_window_highlight(win_id) or config.highlights.fill.hl_group
local hl_name = offset.highlight or guess_window_highlight(win_id) or config.highlights.fill.hl_group

local hl = highlights.hl(hl_name)
local component = get_section_text(width, { text = hl, sep = sep_hl }, offset, is_left)
local hl = highlights.hl(hl_name)
local component = get_section_text(width, { text = hl, sep = sep_hl }, offset, is_left)

total_size = total_size + width
total_size = total_size + width

if is_left then
left, left_size = component, left_size + width
else
right, right_size = component, right_size + width
end
if is_left then
left, left_size = component, left_size + width
else
right, right_size = component, right_size + width
end
end
end
Expand Down