From 13a959d64fcea261461c6aa1daaec8eaa80d5f25 Mon Sep 17 00:00:00 2001 From: Akin Sowemimo <22454918+akinsho@users.noreply.github.com> Date: Wed, 2 Aug 2023 09:57:13 +0100 Subject: [PATCH] refactor(offsets): use wininfo to calculate offset fixes #789 --- lua/bufferline/offset.lua | 101 +++++++++++--------------------------- 1 file changed, 28 insertions(+), 73 deletions(-) diff --git a/lua/bufferline/offset.lua b/lua/bufferline/offset.lua index 0315107d..725bb326 100644 --- a/lua/bufferline/offset.lua +++ b/lua/bufferline/offset.lua @@ -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 @@ -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 @@ -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