Skip to content

Commit

Permalink
feat: pinned buffers stay visible
Browse files Browse the repository at this point in the history
  • Loading branch information
Iron-E committed Apr 2, 2023
1 parent 74a78ac commit 0cc06a7
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 43 deletions.
49 changes: 30 additions & 19 deletions lua/barbar/layout.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
local floor = math.floor
local max = math.max
local min = math.min
local table_insert = table.insert

local get_option = vim.api.nvim_get_option --- @type function
local strwidth = vim.api.nvim_strwidth --- @type function
Expand All @@ -26,13 +25,13 @@ local SLASH_LEN = #'/'
local SPACE_LEN = #' '

--- @class barbar.layout.data
--- @field actual_width integer the `used_width` plus the `padding_width` allocated to each buffer
--- @field actual_width integer the sum of the `base_widths` plus the `padding_width` allocated to each buffer
--- @field base_widths integer[] the minimum amount of space taken up by each buffer
--- @field buffers_width integer the amount of space available to be taken up by buffers
--- @field padding_width integer the amount of padding used on each side of each buffer
--- @field tabpages_width integer the amount of space taken up by the tabpage indicator
--- @field pinned_widths integer[] the minimum amount of space taken up by each pinned buffer
--- @field scroll_max integer the maximum position which can be scrolled to
--- @field used_width integer the sum of the `base_widths`
--- @field tabpages_width integer the amount of space taken up by the tabpage indicator

--- @class barbar.Layout
--- @field buffers integer[] different from `state.buffers` in that the `hide` option is respected. Only updated when calling `calculate_buffers_width`.
Expand All @@ -44,24 +43,26 @@ function Layout.calculate()
local available_width = get_option'columns'
available_width = available_width - state.offset.width

local used_width, base_widths = Layout.calculate_buffers_width()
local pinned_count, pinned_sum, pinned_widths, count, sum, widths = Layout.calculate_buffers_width()
local tabpages_width = Layout.calculate_tabpages_width()

local buffers_width = available_width - tabpages_width
local remaining_width = max(0, buffers_width - used_width)
local remaining_width_per_buffer = floor(remaining_width / #base_widths)
local pinned_width = pinned_sum + (pinned_count * config.options.minimum_padding * SIDES_OF_BUFFER)
local buffers_width = available_width - pinned_width - tabpages_width

local remaining_width = max(0, buffers_width - sum)
local remaining_width_per_buffer = floor(remaining_width / count)
local remaining_padding_per_buffer = floor(remaining_width_per_buffer / SIDES_OF_BUFFER)
local padding_width = max(config.options.minimum_padding, min(remaining_padding_per_buffer, config.options.maximum_padding))
local actual_width = used_width + (#base_widths * padding_width * SIDES_OF_BUFFER)
local actual_width = sum + (count * padding_width * SIDES_OF_BUFFER)

return {
actual_width = actual_width,
base_widths = base_widths,
base_widths = widths,
buffers_width = buffers_width,
padding_width = padding_width,
pinned_widths = pinned_widths,
scroll_max = max(0, actual_width - buffers_width),
tabpages_width = tabpages_width,
used_width = used_width,
}
end

Expand Down Expand Up @@ -124,28 +125,38 @@ function Layout.calculate_buffers_position_by_buffer_number()

for i, buffer_number in ipairs(Layout.buffers) do
positions[buffer_number] = current_position
local width = layout.base_widths[i] + (2 * layout.padding_width)
current_position = current_position + width
current_position = current_position + Layout.calculate_width(
layout.base_widths[i] or layout.pinned_widths[i],
layout.padding_width
)
end

return positions
end

--- Calculate the width of the buffers
--- @return integer sum, integer[] widths
--- @return integer pinned_count, integer pinned_sum, integer[] pinned_widths, integer count, integer sum, integer[] widths
function Layout.calculate_buffers_width()
Layout.buffers = Buffer.hide(state.buffers)

local sum = 0
local widths = {}
local pinned_count, count = 0, 0
local pinned_sum, sum = 0, 0
local pinned_widths, widths = {}, {}

for i, bufnr in ipairs(Layout.buffers) do
local width = Layout.calculate_buffer_width(bufnr, i)
sum = sum + width
table_insert(widths, width)
if state.get_buffer_data(bufnr).pinned then
pinned_count = pinned_count + 1
pinned_sum = pinned_sum + width
pinned_widths[i] = width
else
count = count + 1
sum = sum + width
widths[i] = width
end
end

return sum, widths
return pinned_count, pinned_sum, pinned_widths, count, sum, widths
end

--- The number of characters needed to represent the tabpages.
Expand Down
59 changes: 35 additions & 24 deletions lua/barbar/render.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ local defer_fn = vim.defer_fn
local get_current_buf = vim.api.nvim_get_current_buf --- @type function
local get_option = vim.api.nvim_get_option --- @type function
local has = vim.fn.has --- @type function
local list_extend = vim.list_extend
local list_tabpages = vim.api.nvim_list_tabpages --- @type function
local list_wins = vim.api.nvim_list_wins --- @type function
local set_current_win = vim.api.nvim_set_current_win --- @type function
Expand Down Expand Up @@ -282,7 +283,8 @@ local function open_buffer_start_animation(layout, bufnr)
local index = utils.index_of(Layout.buffers, bufnr)

buffer_data.real_width = Layout.calculate_width(
layout.base_widths[index] or Layout.calculate_buffer_width(bufnr, #Layout.buffers + 1),
(buffer_data.pinned and layout.pinned_widths[index] or layout.base_widths[index])
or Layout.calculate_buffer_width(bufnr, #Layout.buffers + 1),
layout.padding_width
)

Expand Down Expand Up @@ -526,18 +528,30 @@ local function generate_tabline(bufnrs, refocus)
local accumulated_width = 0 --- the amount of width that has been accumulated while iterating
local current_buffer_index = nil --- @type nil|integer
local groups = {} --- @type barbar.render.group[]
local pinned_items = {} --- @type barbar.render.group[]

--- The padding
--- @type barbar.render.group.item
local padding = {hl = '', text = (' '):rep(layout.padding_width)}

--- The padding of a pinned buffer
--- @type barbar.render.group.item
local pinned_padding = {hl = padding.hl, text = (' '):rep(config.options.minimum_padding)}

for i, bufnr in ipairs(bufnrs) do
local activity = Buffer.activities[Buffer.get_activity(bufnr)]
local buffer_data = state.get_buffer_data(bufnr)

local buffer_name = buffer_data.name or '[no name]'
local buffer_hl = hl_tabline('Buffer' .. activity .. (
buf_get_option(bufnr, 'modified') and 'Mod' or '')
)
local buffer_name = buffer_data.name or '[no name]'

buffer_data.real_width = Layout.calculate_width(layout.base_widths[i], layout.padding_width)
buffer_data.real_position = accumulated_width
buffer_data.real_width = Layout.calculate_width(
buffer_data.pinned and layout.pinned_widths[i] or layout.base_widths[i],
layout.padding_width
)

local icons_option = state.icons(bufnr, activity)

Expand Down Expand Up @@ -566,14 +580,14 @@ local function generate_tabline(bufnrs, refocus)

--- The close icon
--- @type barbar.render.group.item
local close = {hl = buffer_hl, text = ''}
local button = {hl = buffer_hl, text = ''}

local button = icons_option.button
if button and #button > 1 then
close.text = icons_option.button .. ' '
local button_icon = icons_option.button
if button_icon and #button_icon > 1 then
button.text = button_icon .. ' '

if click_enabled then
close.hl = '%' .. bufnr .. '@barbar#events#close_click_handler@' .. close.hl
button.hl = '%' .. bufnr .. '@barbar#events#close_click_handler@' .. button.hl
end
end

Expand Down Expand Up @@ -614,21 +628,19 @@ local function generate_tabline(bufnrs, refocus)
icon.text = #name.text > 0 and iconChar .. ' ' or iconChar
end

--- The padding
--- @type barbar.render.group.item
local padding = {hl = '', text = (' '):rep(layout.padding_width)}

--- The separator
--- @type barbar.render.group.item
local left_separator = {
hl = clickable .. hl_tabline('Buffer' .. activity .. 'Sign'),
text = icons_option.separator.left,
}

local pad = buffer_data.pinned and pinned_padding or padding
local group = { --- @type barbar.render.group
items = {left_separator, padding, buffer_index, buffer_number, icon, jump_letter, name},
items = {left_separator, pad, buffer_index, buffer_number, icon, jump_letter, name},
position = buffer_data.position or accumulated_width,
width = buffer_data.width or Layout.calculate_width(layout.base_widths[i], layout.padding_width)
--- @diagnostic disable-next-line: assign-type-mismatch it is assigned just earlier
width = buffer_data.width or buffer_data.real_width,
}

Buffer.for_each_counted_enabled_diagnostic(bufnr, icons_option.diagnostics, function(count, idx, option)
Expand All @@ -641,7 +653,7 @@ local function generate_tabline(bufnrs, refocus)
--- @type barbar.render.group.item
local right_separator = {hl = left_separator.hl, text = icons_option.separator.right}

vim.list_extend(group.items, {padding, close, right_separator})
vim.list_extend(group.items, {pad, button, right_separator})

if activity == 'Current' and refocus ~= false then
current_buffer_index = i
Expand All @@ -657,6 +669,11 @@ local function generate_tabline(bufnrs, refocus)
end
end

if buffer_data.pinned then
list_extend(pinned_items, group.items)
goto continue -- HACK: there is no `continue` keyword
end

accumulated_width = accumulated_width + group.width

local scroll_current = min(scroll.current, layout.scroll_max)
Expand Down Expand Up @@ -715,15 +732,9 @@ local function generate_tabline(bufnrs, refocus)
end
end

-- TODO: put pinned buffers here
-- if #scroll_locked.left > 0 then
-- local items = scroll_locked.left[1].items
-- for i = #scroll_locked.left, 2, -1 do
-- list_extend(items, scroll_locked.left[i].items)
-- end
--
-- result = result .. items_to_string(items)
-- end
if #pinned_items > 0 then
result = result .. items_to_string(pinned_items)
end

-- Render bufferline string
result = result .. items_to_string(bufferline_items)
Expand Down

0 comments on commit 0cc06a7

Please sign in to comment.