From 61585be0c37bc57475a88cc391f4b6e98608c060 Mon Sep 17 00:00:00 2001 From: Peter Cardenas <16930781+PeterCardenas@users.noreply.github.com> Date: Tue, 30 Sep 2025 02:42:41 -0700 Subject: [PATCH] fix(blame): get gh blame info asynchronously --- lua/gitsigns/actions/blame_line.lua | 20 ++++++++-- lua/gitsigns/popup.lua | 60 +++++++++++++++++++++-------- 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/lua/gitsigns/actions/blame_line.lua b/lua/gitsigns/actions/blame_line.lua index 7eb1d7d44..8f328bdb5 100644 --- a/lua/gitsigns/actions/blame_line.lua +++ b/lua/gitsigns/actions/blame_line.lua @@ -95,8 +95,9 @@ end --- @param result Gitsigns.BlameInfoPublic --- @param repo Gitsigns.Repo --- @param fileformat string +--- @param with_gh boolean --- @return Gitsigns.LineSpec[] -local function create_blame_linespec(full, result, repo, fileformat) +local function create_blame_linespec(full, result, repo, fileformat, with_gh) local is_committed = result.sha and tonumber('0x' .. result.sha) ~= 0 if not is_committed then @@ -106,7 +107,7 @@ local function create_blame_linespec(full, result, repo, fileformat) end local gh --- @module 'gitsigns.gh'? - if config.gh then + if config.gh and with_gh then gh = require('gitsigns.gh') end @@ -180,11 +181,22 @@ return function(opts) local result = util.convert_blame_info(assert(info)) - local blame_linespec = create_blame_linespec(opts.full, result, bcache.git_obj.repo, fileformat) + local blame_linespec = + create_blame_linespec(opts.full, result, bcache.git_obj.repo, fileformat, false) if not bcache:schedule() then return end - popup.create(blame_linespec, config.preview_config, 'blame') + local popup_winid, popup_bufnr = popup.create(blame_linespec, config.preview_config, 'blame') + + blame_linespec = create_blame_linespec(opts.full, result, bcache.git_obj.repo, fileformat, true) + + if not bcache:schedule() then + return + end + + if vim.api.nvim_win_is_valid(popup_winid) and vim.api.nvim_buf_is_valid(popup_bufnr) then + popup.update(popup_winid, popup_bufnr, blame_linespec, config.preview_config) + end end diff --git a/lua/gitsigns/popup.lua b/lua/gitsigns/popup.lua index f041a7524..46ec952ea 100644 --- a/lua/gitsigns/popup.lua +++ b/lua/gitsigns/popup.lua @@ -140,25 +140,15 @@ end local ns = api.nvim_create_namespace('gitsigns_popup') ---- @param lines string[] ---- @param highlights Gitsigns.HlMark[] ---- @return integer bufnr -local function create_buf(lines, highlights) - local ts = vim.bo.tabstop - local bufnr = api.nvim_create_buf(false, true) - assert(bufnr ~= 0, 'Failed to create buffer') - - vim.bo[bufnr].bufhidden = 'wipe' - +--- @param bufnr integer +--- @param lines_spec Gitsigns.LineSpec[] +local function update_buf(bufnr, lines_spec) + local lines, highlights = partition_linesspec(lines_spec) -- In case nvim was opened with '-M' vim.bo[bufnr].modifiable = true api.nvim_buf_set_lines(bufnr, 0, -1, true, lines) vim.bo[bufnr].modifiable = false - -- Set tabstop before calculating the buffer width so that the correct width - -- is calculated - vim.bo[bufnr].tabstop = ts - for _, hl in ipairs(highlights) do local ok, err = pcall(api.nvim_buf_set_extmark, bufnr, ns, hl.start_row, hl.start_col or 0, { hl_group = hl.hl_group, @@ -171,10 +161,40 @@ local function create_buf(lines, highlights) error(vim.inspect(hl) .. '\n' .. err) end end +end + +--- @param lines_spec Gitsigns.LineSpec[] +--- @return integer bufnr +local function create_buf(lines_spec) + local ts = vim.bo.tabstop + local bufnr = api.nvim_create_buf(false, true) + assert(bufnr ~= 0, 'Failed to create buffer') + + vim.bo[bufnr].bufhidden = 'wipe' + + -- Set tabstop before calculating the buffer width so that the correct width + -- is calculated + vim.bo[bufnr].tabstop = ts + + update_buf(bufnr, lines_spec) return bufnr end +--- @param winid integer +--- @param bufnr integer +--- @param opts vim.api.keyset.win_config +local function update_win(winid, bufnr, opts) + local lines = api.nvim_buf_get_lines(bufnr, 0, -1, true) + local width = opts.width or bufnr_calc_width(bufnr, lines) + local height = opts.height or #lines + api.nvim_win_set_width(winid, width) + api.nvim_win_set_height(winid, height) + if not opts.height then + expand_height(winid, #lines, opts.border) + end +end + --- @param bufnr integer --- @param opts vim.api.keyset.win_config --- @param id? string|true @@ -259,12 +279,20 @@ end --- @param id? string --- @return integer winid, integer bufnr function M.create(lines_spec, opts, id) - local lines, highlights = partition_linesspec(lines_spec) - local bufnr = create_buf(lines, highlights) + local bufnr = create_buf(lines_spec) local winid = create_win(bufnr, opts, id) return winid, bufnr end +--- @param winid integer +--- @param bufnr integer +--- @param lines_spec Gitsigns.LineSpec[] +--- @param opts vim.api.keyset.win_config +function M.update(winid, bufnr, lines_spec, opts) + update_buf(bufnr, lines_spec) + update_win(winid, bufnr, opts) +end + --- @param id string --- @return integer? winid function M.is_open(id)