From 193fb6fcd5bd4d2917b1c4fff82bab6ec8819128 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 10 Apr 2023 15:55:33 -0400 Subject: [PATCH 01/11] refactor: move move_buffer to render.lua --- lua/barbar/api.lua | 104 +--------------------------- lua/barbar/ui/render.lua | 142 ++++++++++++++++++++++++++++++++------- 2 files changed, 119 insertions(+), 127 deletions(-) diff --git a/lua/barbar/api.lua b/lua/barbar/api.lua index baf6d046..2ed48e58 100644 --- a/lua/barbar/api.lua +++ b/lua/barbar/api.lua @@ -1,8 +1,6 @@ local char = string.char local max = math.max local min = math.min -local table_insert = table.insert -local table_remove = table.remove local table_sort = table.sort local buf_get_name = vim.api.nvim_buf_get_name --- @type function @@ -16,12 +14,9 @@ local set_current_buf = vim.api.nvim_set_current_buf --- @type function -- TODO: remove `vim.fs and` after 0.8 release local normalize = vim.fs and vim.fs.normalize -local animate = require'barbar.animate' local bbye = require'barbar.bbye' local Buffer = require'barbar.buffer' -local config = require'barbar.config' local JumpMode = require'barbar.jump_mode' -local Layout = require'barbar.ui.layout' local render = require'barbar.ui.render' local state = require'barbar.state' local utils = require'barbar.utils' @@ -213,101 +208,6 @@ function api.goto_buffer_relative(steps) set_current_buf(state.buffers[(idx + steps - 1) % #state.buffers + 1]) end -local move_animation = nil --- @type nil|barbar.animate.state -local move_animation_data = { - next_positions = nil, --- @type nil|integer[] - previous_positions = nil --- @type nil|integer[] -} - ---- An incremental animation for `move_buffer_animated`. ---- @return nil -local function move_buffer_animated_tick(ratio, current_animation) - for _, current_number in ipairs(Layout.buffers) do - local current_data = state.get_buffer_data(current_number) - - if current_animation.running == true then - current_data.position = animate.lerp( - ratio, - (move_animation_data.previous_positions or {})[current_number], - (move_animation_data.next_positions or {})[current_number] - ) - else - current_data.position = nil - current_data.moving = false - end - end - - render.update() - - if current_animation.running == false then - move_animation = nil - move_animation_data.next_positions = nil - move_animation_data.previous_positions = nil - end -end - -local MOVE_DURATION = 150 - ---- Move a buffer (with animation, if configured). ---- @param from_idx integer the buffer's original index. ---- @param to_idx integer the buffer's new index. ---- @return nil -local function move_buffer(from_idx, to_idx) - to_idx = max(1, min(#state.buffers, to_idx)) - if to_idx == from_idx then - return - end - - local animation = config.options.animation - local buffer_number = state.buffers[from_idx] - - local previous_positions - if animation == true then - previous_positions = Layout.calculate_buffers_position_by_buffer_number() - end - - table_remove(state.buffers, from_idx) - table_insert(state.buffers, to_idx, buffer_number) - state.sort_pins_to_left() - - if animation == true then - local current_index = utils.index_of(Layout.buffers, buffer_number) - local start_index = min(from_idx, current_index) - local end_index = max(from_idx, current_index) - - if start_index == end_index then - return - elseif move_animation ~= nil then - animate.stop(move_animation) - end - - local next_positions = Layout.calculate_buffers_position_by_buffer_number() - - for _, layout_bufnr in ipairs(Layout.buffers) do - local current_data = state.get_buffer_data(layout_bufnr) - - local previous_position = previous_positions[layout_bufnr] - local next_position = next_positions[layout_bufnr] - - if next_position ~= previous_position then - current_data.position = previous_positions[layout_bufnr] - current_data.moving = true - end - end - - move_animation_data = { - previous_positions = previous_positions, - next_positions = next_positions, - } - - move_animation = - animate.start(MOVE_DURATION, 0, 1, vim.v.t_float, - function(ratio, current_animation) move_buffer_animated_tick(ratio, current_animation) end) - end - - render.update() -end - --- Move the current buffer to the index specified. --- @param idx integer --- @return nil @@ -325,7 +225,7 @@ function api.move_current_buffer_to(idx) return notify_buffer_not_found(current_bufnr) end - move_buffer(from_idx, idx) + render.move_buffer(from_idx, idx) end --- Move the current buffer a certain number of times over. @@ -341,7 +241,7 @@ function api.move_current_buffer(steps) return notify_buffer_not_found(current_bufnr) end - move_buffer(idx, idx + steps) + render.move_buffer(idx, idx + steps) end --- Order the buffers by their buffer number. diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index fd32fe74..6d67c099 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -5,6 +5,7 @@ local max = math.max local min = math.min local table_insert = table.insert +local table_remove = table.remove local buf_get_option = vim.api.nvim_buf_get_option --- @type function local buf_is_valid = vim.api.nvim_buf_is_valid --- @type function @@ -37,36 +38,35 @@ local Layout = require'barbar.ui.layout' local state = require'barbar.state' local utils = require'barbar.utils' +--- @class barbar.ui.render +local render = {} + + +-- Animation durations & delays +local OPEN_DELAY = 10 +local OPEN_DURATION = 150 +local MOVE_DURATION = 150 +local CLOSE_DURATION = 150 +local SCROLL_DURATION = 200 + + --- Last value for tabline --- @type string local last_tabline = '' ---- Create valid `&tabline` syntax which highlights the next item in the tabline with the highlight `group` specified. ---- @param group string ---- @return string syntax -local function wrap_hl(group) - return '%#' .. group .. '#' -end - ---- @class barbar.ui.render.animation ---- @field OPEN_DELAY integer ---- @field OPEN_DURATION integer ---- @field CLOSE_DURATION integer ---- @field SCROLL_DURATION integer -local ANIMATION = { - OPEN_DELAY = 10, - OPEN_DURATION = 150, - CLOSE_DURATION = 150, - SCROLL_DURATION = 200, -} - --- @class barbar.ui.render.scroll --- @field current integer the place where the bufferline is currently scrolled to --- @field target integer the place where the bufferline is scrolled/wants to scroll to. local scroll = { current = 0, target = 0 } ---- @class barbar.ui.render -local render = {} +--- @type nil|barbar.animate.state +local current_animation = nil + +local move_animation_data = { + next_positions = nil, --- @type nil|integer[] + previous_positions = nil --- @type nil|integer[] +} + --- An incremental animation for `close_buffer_animated`. --- @param bufnr integer @@ -107,7 +107,7 @@ function render.close_buffer_animated(bufnr) buffer_data.width = current_width animate.start( - ANIMATION.CLOSE_DURATION, current_width, 0, vim.v.t_number, + CLOSE_DURATION, current_width, 0, vim.v.t_number, function(new_width, m) close_buffer_animated_tick(bufnr, new_width, m) end) @@ -144,11 +144,11 @@ local function open_buffer_start_animation(layout, bufnr) defer_fn(function() animate.start( - ANIMATION.OPEN_DURATION, 1, target_width, vim.v.t_number, + OPEN_DURATION, 1, target_width, vim.v.t_number, function(new_width, animation) open_buffer_animated_tick(bufnr, new_width, animation) end) - end, ANIMATION.OPEN_DELAY) + end, OPEN_DELAY) end --- Open the `new_buffers` in the bufferline. @@ -215,6 +215,91 @@ local function open_buffers(new_buffers) end end +--- An incremental animation for `move_buffer_animated`. +--- @return nil +local function move_buffer_animated_tick(ratio, current_state) + for _, current_number in ipairs(Layout.buffers) do + local current_data = state.get_buffer_data(current_number) + + if current_state.running == true then + current_data.position = animate.lerp( + ratio, + (move_animation_data.previous_positions or {})[current_number], + (move_animation_data.next_positions or {})[current_number] + ) + else + current_data.position = nil + end + end + + render.update() + + if current_state.running == false then + current_animation = nil + move_animation_data.next_positions = nil + move_animation_data.previous_positions = nil + end +end + +--- Move a buffer (with animation, if configured). +--- @param from_idx integer the buffer's original index. +--- @param to_idx integer the buffer's new index. +--- @return nil +function render.move_buffer(from_idx, to_idx) + to_idx = math.max(1, math.min(#state.buffers, to_idx)) + if to_idx == from_idx then + return + end + + local animation = config.options.animation + local buffer_number = state.buffers[from_idx] + + local previous_positions + if animation == true then + previous_positions = Layout.calculate_buffers_position_by_buffer_number() + end + + table_remove(state.buffers, from_idx) + table_insert(state.buffers, to_idx, buffer_number) + state.sort_pins_to_left() + + if animation == true then + local current_index = utils.index_of(Layout.buffers, buffer_number) + local start_index = min(from_idx, current_index) + local end_index = max(from_idx, current_index) + + if start_index == end_index then + return + elseif current_animation ~= nil then + animate.stop(current_animation) + end + + local next_positions = Layout.calculate_buffers_position_by_buffer_number() + + for _, layout_bufnr in ipairs(Layout.buffers) do + local current_data = state.get_buffer_data(layout_bufnr) + + local previous_position = previous_positions[layout_bufnr] + local next_position = next_positions[layout_bufnr] + + if next_position ~= previous_position then + current_data.position = previous_positions[layout_bufnr] + end + end + + move_animation_data = { + previous_positions = previous_positions, + next_positions = next_positions, + } + + current_animation = + animate.start(MOVE_DURATION, 0, 1, vim.v.t_float, + move_buffer_animated_tick) + end + + render.update() +end + --- Refresh the buffer list. --- @return integer[] state.buffers function render.get_updated_buffers(update_names) @@ -322,7 +407,7 @@ function render.set_scroll(target) end scroll_animation = animate.start( - ANIMATION.SCROLL_DURATION, scroll.current, target, vim.v.t_number, + SCROLL_DURATION, scroll.current, target, vim.v.t_number, set_scroll_tick) end @@ -338,6 +423,13 @@ function render.set_tabline(s) end end +--- Create valid `&tabline` syntax which highlights the next item in the tabline with the highlight `group` specified. +--- @param group string +--- @return string syntax +local function wrap_hl(group) + return '%#' .. group .. '#' +end + --- Compute the buffer hl-groups --- @param layout barbar.ui.layout.data --- @param bufnrs integer[] From bec4509fefce69c2cbedbc7abdad26cbb73b4b36 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 10 Apr 2023 16:02:20 -0400 Subject: [PATCH 02/11] refactor: use current_animation --- lua/barbar/animate.lua | 5 ++++- lua/barbar/ui/render.lua | 10 +++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lua/barbar/animate.lua b/lua/barbar/animate.lua index 9ba4603c..0b47e384 100644 --- a/lua/barbar/animate.lua +++ b/lua/barbar/animate.lua @@ -92,9 +92,12 @@ function animate.start(duration, initial, final, type, callback) return state end ---- @param state barbar.animate.state +--- @param state barbar.animate.state|nil --- @return nil function animate.stop(state) + if state == nil then + return + end if state.timer then state.timer:stop() state.timer:close() diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index 6d67c099..b4c340c6 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -106,7 +106,8 @@ function render.close_buffer_animated(bufnr) buffer_data.closing = true buffer_data.width = current_width - animate.start( + current_animation = animate.stop(current_animation) + current_animation = animate.start( CLOSE_DURATION, current_width, 0, vim.v.t_number, function(new_width, m) close_buffer_animated_tick(bufnr, new_width, m) @@ -143,7 +144,8 @@ local function open_buffer_start_animation(layout, bufnr) buffer_data.width = 1 defer_fn(function() - animate.start( + current_animation = animate.stop(current_animation) + current_animation = animate.start( OPEN_DURATION, 1, target_width, vim.v.t_number, function(new_width, animation) open_buffer_animated_tick(bufnr, new_width, animation) @@ -235,7 +237,6 @@ local function move_buffer_animated_tick(ratio, current_state) render.update() if current_state.running == false then - current_animation = nil move_animation_data.next_positions = nil move_animation_data.previous_positions = nil end @@ -270,8 +271,6 @@ function render.move_buffer(from_idx, to_idx) if start_index == end_index then return - elseif current_animation ~= nil then - animate.stop(current_animation) end local next_positions = Layout.calculate_buffers_position_by_buffer_number() @@ -292,6 +291,7 @@ function render.move_buffer(from_idx, to_idx) next_positions = next_positions, } + current_animation = animate.stop(current_animation) current_animation = animate.start(MOVE_DURATION, 0, 1, vim.v.t_float, move_buffer_animated_tick) From 6c6ef29d24e8534733a9c93a024fdddf9ba826d8 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 10 Apr 2023 16:19:01 -0400 Subject: [PATCH 03/11] refactor: move pin code in render.lua --- lua/barbar/api.lua | 3 +- lua/barbar/ui/render.lua | 89 ++++++++++++++++++++++------------------ 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/lua/barbar/api.lua b/lua/barbar/api.lua index 2ed48e58..76598720 100644 --- a/lua/barbar/api.lua +++ b/lua/barbar/api.lua @@ -372,8 +372,7 @@ end --- @param buffer_number? integer --- @return nil function api.toggle_pin(buffer_number) - state.toggle_pin(buffer_number or 0) - render.update() + render.toggle_pin(buffer_number or 0) end return api diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index b4c340c6..e13d4a15 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -300,6 +300,56 @@ function render.move_buffer(from_idx, to_idx) render.update() end + +--- Toggle the `bufnr`'s "pin" state, visually. +--- @param buffer_number integer +--- @return nil +function render.toggle_pin(buffer_number) + state.toggle_pin(buffer_number) + render.update() +end + + +--- Scroll the bufferline relative to its current position. +--- @param n integer the amount to scroll by. Use negative numbers to scroll left, and positive to scroll right. +--- @return nil +function render.scroll(n) + render.set_scroll(max(0, scroll.target + n)) +end + +local scroll_animation = nil + +--- An incremental animation for `set_scroll`. +--- @return nil +local function set_scroll_tick(new_scroll, animation) + scroll.current = new_scroll + if animation.running == false then + scroll_animation = nil + end + render.update(nil, false) +end + +--- Scrolls the bufferline to the `target`. +--- @param target integer where to scroll to +--- @return nil +function render.set_scroll(target) + scroll.target = target + + if not config.options.animation then + scroll.current = target + return render.update(nil, false) + end + + if scroll_animation ~= nil then + animate.stop(scroll_animation) + end + + scroll_animation = animate.start( + SCROLL_DURATION, scroll.current, target, vim.v.t_number, + set_scroll_tick) +end + + --- Refresh the buffer list. --- @return integer[] state.buffers function render.get_updated_buffers(update_names) @@ -372,45 +422,6 @@ function render.set_current_win_listed_buffer() return current end ---- Scroll the bufferline relative to its current position. ---- @param n integer the amount to scroll by. Use negative numbers to scroll left, and positive to scroll right. ---- @return nil -function render.scroll(n) - render.set_scroll(max(0, scroll.target + n)) -end - -local scroll_animation = nil - ---- An incremental animation for `set_scroll`. ---- @return nil -local function set_scroll_tick(new_scroll, animation) - scroll.current = new_scroll - if animation.running == false then - scroll_animation = nil - end - render.update(nil, false) -end - ---- Scrolls the bufferline to the `target`. ---- @param target integer where to scroll to ---- @return nil -function render.set_scroll(target) - scroll.target = target - - if not config.options.animation then - scroll.current = target - return render.update(nil, false) - end - - if scroll_animation ~= nil then - animate.stop(scroll_animation) - end - - scroll_animation = animate.start( - SCROLL_DURATION, scroll.current, target, vim.v.t_number, - set_scroll_tick) -end - --- Sets and redraws `'tabline'` if `s` does not match the cached value. --- @param s? string --- @return nil From fdf59acd4ee5fa0e66c95e85bc8a74d2a7843eea Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 10 Apr 2023 16:31:46 -0400 Subject: [PATCH 04/11] feat: pin/unpin animation --- lua/barbar/state.lua | 12 ++++++++---- lua/barbar/ui/render.lua | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/lua/barbar/state.lua b/lua/barbar/state.lua index d2ba105e..876d1dd1 100644 --- a/lua/barbar/state.lua +++ b/lua/barbar/state.lua @@ -69,16 +69,20 @@ local state = { --- Get the state of the `id` --- @param bufnr integer the `bufnr` +--- @param data_by_bufnr? {[integer]: barbar.state.data} --- @return barbar.state.data -function state.get_buffer_data(bufnr) +function state.get_buffer_data(bufnr, data_by_bufnr) if bufnr == 0 then bufnr = get_current_buf() end + if data_by_bufnr == nil then + data_by_bufnr = state.data_by_bufnr + end - local data = state.data_by_bufnr[bufnr] + local data = data_by_bufnr[bufnr] if data == nil then - data = {closing = false, pinned = false} - state.data_by_bufnr[bufnr] = data + data = { closing = false, pinned = false } + data_by_bufnr[bufnr] = data end return data diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index e13d4a15..4d1e9904 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -48,6 +48,7 @@ local OPEN_DURATION = 150 local MOVE_DURATION = 150 local CLOSE_DURATION = 150 local SCROLL_DURATION = 200 +local PIN_DURATION = 150 --- Last value for tabline @@ -305,8 +306,38 @@ end --- @param buffer_number integer --- @return nil function render.toggle_pin(buffer_number) + local previous_data_by_bufnr = vim.deepcopy(state.data_by_bufnr) + state.toggle_pin(buffer_number) - render.update() + + current_animation = animate.stop(current_animation) + current_animation = animate.start(PIN_DURATION, 0, 1, vim.v.t_float, + function (ratio, current_state) + for _, current_number in ipairs(Layout.buffers) do + local previous_data = state.get_buffer_data(current_number, previous_data_by_bufnr) + local current_data = state.get_buffer_data(current_number) + + local previous_width = previous_data.width or previous_data.computed_width + local previous_position = previous_data.position or previous_data.computed_position + + local next_width = current_data.computed_width + local next_position = current_data.computed_position + + if current_state.running == true then + if previous_width and next_width then + current_data.width = animate.lerp(ratio, previous_width, next_width) + end + if previous_position and next_position then + current_data.position = animate.lerp(ratio, previous_position, next_position) + end + else + current_data.width = nil + current_data.position = nil + end + end + + render.update() + end) end From 763608b91c869a775932182e520fdd274ccdb2c5 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 10 Apr 2023 16:35:32 -0400 Subject: [PATCH 05/11] lint --- lua/barbar/ui/render.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index 4d1e9904..1672bcff 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -248,7 +248,7 @@ end --- @param to_idx integer the buffer's new index. --- @return nil function render.move_buffer(from_idx, to_idx) - to_idx = math.max(1, math.min(#state.buffers, to_idx)) + to_idx = max(1, min(#state.buffers, to_idx)) if to_idx == from_idx then return end From ee8c66e563f6db3e816df4775691b7164d5553f6 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 10 Apr 2023 16:58:55 -0400 Subject: [PATCH 06/11] fix: respect options.animation = false --- lua/barbar/ui/render.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index 1672bcff..87e85410 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -310,6 +310,10 @@ function render.toggle_pin(buffer_number) state.toggle_pin(buffer_number) + if config.options.animation == false then + return + end + current_animation = animate.stop(current_animation) current_animation = animate.start(PIN_DURATION, 0, 1, vim.v.t_float, function (ratio, current_state) From 55244c96e1047a822566eac20b3d996532d8f87d Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 10 Apr 2023 17:04:01 -0400 Subject: [PATCH 07/11] refactor: move stuff around --- lua/barbar/ui/render.lua | 102 ++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 56 deletions(-) diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index 87e85410..986fee09 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -63,11 +63,6 @@ local scroll = { current = 0, target = 0 } --- @type nil|barbar.animate.state local current_animation = nil -local move_animation_data = { - next_positions = nil, --- @type nil|integer[] - previous_positions = nil --- @type nil|integer[] -} - --- An incremental animation for `close_buffer_animated`. --- @param bufnr integer @@ -218,31 +213,6 @@ local function open_buffers(new_buffers) end end ---- An incremental animation for `move_buffer_animated`. ---- @return nil -local function move_buffer_animated_tick(ratio, current_state) - for _, current_number in ipairs(Layout.buffers) do - local current_data = state.get_buffer_data(current_number) - - if current_state.running == true then - current_data.position = animate.lerp( - ratio, - (move_animation_data.previous_positions or {})[current_number], - (move_animation_data.next_positions or {})[current_number] - ) - else - current_data.position = nil - end - end - - render.update() - - if current_state.running == false then - move_animation_data.next_positions = nil - move_animation_data.previous_positions = nil - end -end - --- Move a buffer (with animation, if configured). --- @param from_idx integer the buffer's original index. --- @param to_idx integer the buffer's new index. @@ -265,40 +235,60 @@ function render.move_buffer(from_idx, to_idx) table_insert(state.buffers, to_idx, buffer_number) state.sort_pins_to_left() - if animation == true then - local current_index = utils.index_of(Layout.buffers, buffer_number) - local start_index = min(from_idx, current_index) - local end_index = max(from_idx, current_index) + if animation == false then + return render.update() + end - if start_index == end_index then - return - end + local current_index = utils.index_of(Layout.buffers, buffer_number) + local start_index = min(from_idx, current_index) + local end_index = max(from_idx, current_index) - local next_positions = Layout.calculate_buffers_position_by_buffer_number() + if start_index == end_index then + return + end - for _, layout_bufnr in ipairs(Layout.buffers) do - local current_data = state.get_buffer_data(layout_bufnr) + local next_positions = Layout.calculate_buffers_position_by_buffer_number() - local previous_position = previous_positions[layout_bufnr] - local next_position = next_positions[layout_bufnr] + for _, layout_bufnr in ipairs(Layout.buffers) do + local current_data = state.get_buffer_data(layout_bufnr) - if next_position ~= previous_position then - current_data.position = previous_positions[layout_bufnr] - end + local previous_position = previous_positions[layout_bufnr] + local next_position = next_positions[layout_bufnr] + + if next_position ~= previous_position then + current_data.position = previous_positions[layout_bufnr] end + end - move_animation_data = { - previous_positions = previous_positions, - next_positions = next_positions, - } + local move_animation_data = { + previous_positions = previous_positions, + next_positions = next_positions, + } - current_animation = animate.stop(current_animation) - current_animation = - animate.start(MOVE_DURATION, 0, 1, vim.v.t_float, - move_buffer_animated_tick) - end + current_animation = animate.stop(current_animation) + current_animation = animate.start(MOVE_DURATION, 0, 1, vim.v.t_float, + function(ratio, current_state) + for _, current_number in ipairs(Layout.buffers) do + local current_data = state.get_buffer_data(current_number) - render.update() + if current_state.running == true then + current_data.position = animate.lerp( + ratio, + (move_animation_data.previous_positions or {})[current_number], + (move_animation_data.next_positions or {})[current_number] + ) + else + current_data.position = nil + end + end + + render.update() + + if current_state.running == false then + move_animation_data.next_positions = nil + move_animation_data.previous_positions = nil + end + end) end @@ -311,7 +301,7 @@ function render.toggle_pin(buffer_number) state.toggle_pin(buffer_number) if config.options.animation == false then - return + return render.update() end current_animation = animate.stop(current_animation) From a963a8313ed66e646ccb6d89dab8e104ff09ae14 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 10 Apr 2023 17:18:00 -0400 Subject: [PATCH 08/11] fix: last separator logic --- lua/barbar/ui/render.lua | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index 986fee09..30c08a05 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -43,12 +43,14 @@ local render = {} -- Animation durations & delays -local OPEN_DELAY = 10 -local OPEN_DURATION = 150 -local MOVE_DURATION = 150 -local CLOSE_DURATION = 150 +local BUFFER_OP_DURATION = 150 + +local OPEN_DELAY = 10 -- Let autocmds & other plugins run, avoids jank +local OPEN_DURATION = BUFFER_OP_DURATION +local MOVE_DURATION = BUFFER_OP_DURATION +local CLOSE_DURATION = BUFFER_OP_DURATION +local PIN_DURATION = BUFFER_OP_DURATION local SCROLL_DURATION = 200 -local PIN_DURATION = 150 --- Last value for tabline @@ -687,6 +689,7 @@ local function generate_tabline(bufnrs, refocus) do --- @type barbar.ui.container local content = { { hl = HL.FILL, text = (' '):rep(layout.buffers.width) } } + local max_used_position = 0 do local current_container = nil @@ -697,6 +700,7 @@ local function generate_tabline(bufnrs, refocus) content, container.position - scroll.current, container.nodes) + max_used_position = max(max_used_position, container.position + container.width) else current_container = container end @@ -708,17 +712,19 @@ local function generate_tabline(bufnrs, refocus) content, container.position - scroll.current, container.nodes) + max_used_position = max(max_used_position, container.position + container.width) end end do local inactive_separator = config.options.icons.inactive.separator.left + local max_actual_position = max_used_position - scroll.current if inactive_separator ~= nil and #containers > 0 and - layout.buffers.unpinned_width + strwidth(inactive_separator) <= layout.buffers.unpinned_allocated_width + max_actual_position + strwidth(inactive_separator) <= layout.buffers.width then content = Nodes.insert( content, - layout.buffers.used_width, + max_actual_position, { text = inactive_separator, hl = HL.SIGN_INACTIVE }) end end From 64bb3707716ee7be1c99c67bb681823cb282e7db Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Tue, 11 Apr 2023 08:46:32 -0400 Subject: [PATCH 09/11] fix: rendering order --- lua/barbar/ui/render.lua | 55 +++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index 30c08a05..d1e95fdb 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -321,10 +321,10 @@ function render.toggle_pin(buffer_number) if current_state.running == true then if previous_width and next_width then - current_data.width = animate.lerp(ratio, previous_width, next_width) + current_data.width = math.floor(animate.lerp(ratio, previous_width, next_width, vim.v.t_float)) end if previous_position and next_position then - current_data.position = animate.lerp(ratio, previous_position, next_position) + current_data.position = math.ceil(animate.lerp(ratio, previous_position, next_position, vim.v.t_float)) end else current_data.width = nil @@ -638,6 +638,10 @@ local function get_bufferline_containers(layout, bufnrs, refocus) local right_separator = { hl = left_separator.hl, text = icons_option.separator.right } list_extend(container.nodes, { padding, button, right_separator }) + if container_width then + container.nodes = Nodes.slice_right(container.nodes, container_width) + end + table_insert(pinned and pinned_containers or containers, container) if done then @@ -663,7 +667,7 @@ local HL = { --- @return nil|string syntax local function generate_tabline(bufnrs, refocus) local layout = Layout.calculate() - local pinned_containers, containers = get_bufferline_containers(layout, bufnrs, refocus) + local pinned_containers, unpinned_containers = get_bufferline_containers(layout, bufnrs, refocus) -- Create actual tabline string local result = '' @@ -689,11 +693,22 @@ local function generate_tabline(bufnrs, refocus) do --- @type barbar.ui.container local content = { { hl = HL.FILL, text = (' '):rep(layout.buffers.width) } } + + local current_container = nil local max_used_position = 0 + if #pinned_containers > 0 then + for _, container in ipairs(pinned_containers) do + if container.activity ~= Buffer.activities.Current then + content = Nodes.insert_many(content, container.position, container.nodes) + else + current_container = container + end + end + end + do - local current_container = nil - for _, container in ipairs(containers) do + for _, container in ipairs(unpinned_containers) do -- We insert the current buffer after the others so it's always on top if container.activity ~= Buffer.activities.Current then content = Nodes.insert_many( @@ -705,21 +720,18 @@ local function generate_tabline(bufnrs, refocus) current_container = container end end + end - if current_container ~= nil then - local container = current_container - content = Nodes.insert_many( - content, - container.position - scroll.current, - container.nodes) - max_used_position = max(max_used_position, container.position + container.width) - end + if current_container ~= nil then + local container = current_container + content = Nodes.insert_many(content, container.position, container.nodes) + max_used_position = max(max_used_position, container.position + container.width) end do local inactive_separator = config.options.icons.inactive.separator.left local max_actual_position = max_used_position - scroll.current - if inactive_separator ~= nil and #containers > 0 and + if inactive_separator ~= nil and #unpinned_containers > 0 and max_actual_position + strwidth(inactive_separator) <= layout.buffers.width then content = Nodes.insert( @@ -729,21 +741,6 @@ local function generate_tabline(bufnrs, refocus) end end - if #pinned_containers > 0 then - local current_container = nil - for _, container in ipairs(pinned_containers) do - if container.activity ~= Buffer.activities.Current then - content = Nodes.insert_many(content, container.position, container.nodes) - else - current_container = container - end - end - if current_container ~= nil then - local container = current_container - content = Nodes.insert_many(content, container.position, container.nodes) - end - end - local filler = { { hl = HL.FILL, text = (' '):rep(layout.buffers.width) } } content = Nodes.insert_many(filler, 0, content) content = Nodes.slice_right(content, layout.buffers.width) From 0d2263cd647b1107a965741f9cb495fd5088be08 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Tue, 11 Apr 2023 08:56:00 -0400 Subject: [PATCH 10/11] feat: improve pin animation --- lua/barbar/state.lua | 10 ++++++---- lua/barbar/ui/render.lua | 28 +++++++++++++++++----------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/lua/barbar/state.lua b/lua/barbar/state.lua index 876d1dd1..4170e5e0 100644 --- a/lua/barbar/state.lua +++ b/lua/barbar/state.lua @@ -31,13 +31,15 @@ local CACHE_PATH = vim.fn.stdpath('cache') .. '/barbar.json' -------------------------------- --- @class barbar.state.data ---- @field closing boolean whether the buffer is being closed --- @field name? string the name of the buffer ---- @field position? integer the absolute position of the buffer ---- @field computed_position? integer the real position of the buffer ---- @field computed_width? integer the width of the buffer plus invisible characters --- @field pinned boolean whether the buffer is pinned +--- @field closing boolean whether the buffer is being closed --- @field width? integer the width of the buffer minus invisible characters +--- @field padding? integer the padding width for one side +--- @field position? integer the absolute position of the buffer +--- @field computed_width? integer the logical width of the buffer plus invisible characters +--- @field computed_padding? integer the logical padding of the buffer +--- @field computed_position? integer the logical position of the buffer --- @class barbar.state.offset.side --- @field hl? string the highlight group to use diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index d1e95fdb..1721ee4d 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -314,20 +314,26 @@ function render.toggle_pin(buffer_number) local current_data = state.get_buffer_data(current_number) local previous_width = previous_data.width or previous_data.computed_width + local previous_padding = previous_data.padding or previous_data.computed_padding local previous_position = previous_data.position or previous_data.computed_position local next_width = current_data.computed_width + local next_padding = current_data.computed_padding local next_position = current_data.computed_position if current_state.running == true then if previous_width and next_width then current_data.width = math.floor(animate.lerp(ratio, previous_width, next_width, vim.v.t_float)) end + if previous_padding and next_padding then + current_data.padding = math.floor(animate.lerp(ratio, previous_padding, next_padding, vim.v.t_float)) + end if previous_position and next_position then current_data.position = math.ceil(animate.lerp(ratio, previous_position, next_position, vim.v.t_float)) end else current_data.width = nil + current_data.padding = nil current_data.position = nil end end @@ -495,10 +501,12 @@ local function get_bufferline_containers(layout, bufnrs, refocus) if pinned then buffer_data.computed_position = accumulated_pinned_width - buffer_data.computed_width = Layout.calculate_width(layout.buffers.base_widths[i], config.options.minimum_padding) + buffer_data.computed_padding = config.options.minimum_padding + buffer_data.computed_width = Layout.calculate_width(layout.buffers.base_widths[i], buffer_data.computed_padding) else buffer_data.computed_position = accumulated_unpinned_width + layout.buffers.pinned_width - buffer_data.computed_width = Layout.calculate_width(layout.buffers.base_widths[i], layout.buffers.padding) + buffer_data.computed_padding = layout.buffers.padding + buffer_data.computed_width = Layout.calculate_width(layout.buffers.base_widths[i], buffer_data.computed_padding) end local container_width = buffer_data.width or buffer_data.computed_width @@ -616,7 +624,10 @@ local function get_bufferline_containers(layout, bufnrs, refocus) local left_separator = { hl = clickable .. hl_sign, text = icons_option.separator.left } --- @type barbar.ui.node - local padding = { hl = buffer_hl, text = pinned and pinned_pad_text or unpinned_pad_text } + local padding = { hl = buffer_hl, text = + buffer_data.padding and (' '):rep(buffer_data.padding) or + pinned and pinned_pad_text or + unpinned_pad_text } local container = { --- @type barbar.ui.container activity = activity, @@ -793,14 +804,9 @@ local function generate_tabline(bufnrs, refocus) end -- NOTE: For development or debugging purposes, the following code can be used: - -- ```lua - -- local text = Nodes.to_raw_string(bufferline_nodes, true) - -- if layout.buffers.unpinned_width + strwidth(inactive_separator) <= layout.buffers.unpinned_allocated_width and #items > 0 then - -- text = text .. Nodes.to_raw_string({{ text = inactive_separator or '', hl = wrap_hl('BufferInactiveSign') }}, true) - -- end - -- local data = vim.json.encode({ metadata = 42 }) - -- fs.write('barbar.debug.txt', text .. ':' .. data .. '\n', 'a') - -- ``` + -- local containers = { unpack(pinned_containers), unpack(unpinned_containers) } + -- local data = vim.json.encode(containers) + -- fs.write('barbar.debug.txt', result .. ':' .. data .. '\n', 'a') return result .. HL.FILL end From f2fedbd92a49bed0fe4ca096264f846ab489f741 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Tue, 11 Apr 2023 09:00:57 -0400 Subject: [PATCH 11/11] fix: last separator --- lua/barbar/ui/render.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lua/barbar/ui/render.lua b/lua/barbar/ui/render.lua index 1721ee4d..169674ab 100644 --- a/lua/barbar/ui/render.lua +++ b/lua/barbar/ui/render.lua @@ -742,7 +742,10 @@ local function generate_tabline(bufnrs, refocus) do local inactive_separator = config.options.icons.inactive.separator.left local max_actual_position = max_used_position - scroll.current - if inactive_separator ~= nil and #unpinned_containers > 0 and + local total_containers = #pinned_containers + #unpinned_containers + if + inactive_separator ~= nil and + total_containers > 0 and max_actual_position + strwidth(inactive_separator) <= layout.buffers.width then content = Nodes.insert(