perf(git): stash sidebar window in state

This commit is contained in:
2026-04-27 13:59:20 +02:00
parent 3b87d84ca9
commit c9b02989da
+34 -15
View File
@@ -32,6 +32,7 @@ local SIDEBAR_WIDTH = 50
---@field gitdir string ---@field gitdir string
---@field worktree string ---@field worktree string
---@field lines table<integer, ow.Git.StatusEntry> ---@field lines table<integer, ow.Git.StatusEntry>
---@field sidebar_win integer?
---@field diff_left_win integer? ---@field diff_left_win integer?
---@field diff_right_win integer? ---@field diff_right_win integer?
---@field user_aucmd integer? ---@field user_aucmd integer?
@@ -44,6 +45,8 @@ local group =
vim.api.nvim_create_augroup("ow.git.status_win", { clear = false }) vim.api.nvim_create_augroup("ow.git.status_win", { clear = false })
local ns = vim.api.nvim_create_namespace("ow.git.status_win") local ns = vim.api.nvim_create_namespace("ow.git.status_win")
---Find the sidebar window in the current tabpage by filetype. Used as a
---fallback when we don't have a `StatusState` handy (e.g. M.toggle).
---@return integer? win ---@return integer? win
---@return integer? bufnr ---@return integer? bufnr
local function find_sidebar() local function find_sidebar()
@@ -55,6 +58,20 @@ local function find_sidebar()
end end
end end
---Return the sidebar window stashed on `s`, validating that it's still
---live. Falls back to `find_sidebar` if the stashed handle is gone.
---@param s ow.Git.StatusState
---@return integer?
local function sidebar_win_for(s)
local win = s.sidebar_win
if win and vim.api.nvim_win_is_valid(win) then
return win
end
win = find_sidebar()
s.sidebar_win = win
return win
end
---@param entry ow.Git.StatusEntry ---@param entry ow.Git.StatusEntry
---@return string? ---@return string?
local function entry_code(entry) local function entry_code(entry)
@@ -325,15 +342,13 @@ local function refresh(bufnr)
end end
local saved_path, saved_sha local saved_path, saved_sha
for _, win in ipairs(vim.api.nvim_list_wins()) do local sidebar_win = sidebar_win_for(s)
if vim.api.nvim_win_get_buf(win) == bufnr then if sidebar_win then
local lnum = vim.api.nvim_win_get_cursor(win)[1] local lnum = vim.api.nvim_win_get_cursor(sidebar_win)[1]
local entry = s.lines[lnum] local entry = s.lines[lnum]
if entry then if entry then
saved_path = entry.path saved_path = entry.path
saved_sha = entry.sha saved_sha = entry.sha
end
break
end end
end end
@@ -350,10 +365,9 @@ local function refresh(bufnr)
(saved_path and entry.path == saved_path) (saved_path and entry.path == saved_path)
or (saved_sha and entry.sha == saved_sha) or (saved_sha and entry.sha == saved_sha)
then then
for _, win in ipairs(vim.api.nvim_list_wins()) do local win = sidebar_win_for(s)
if vim.api.nvim_win_get_buf(win) == bufnr then if win then
pcall(vim.api.nvim_win_set_cursor, win, { lnum, 0 }) pcall(vim.api.nvim_win_set_cursor, win, { lnum, 0 })
end
end end
break break
end end
@@ -554,7 +568,7 @@ local function show_diff(s, entry, focus_left)
return return
end end
---@cast entry ow.Git.FileEntry ---@cast entry ow.Git.FileEntry
local sidebar_win = find_sidebar() local sidebar_win = sidebar_win_for(s)
if not sidebar_win then if not sidebar_win then
return return
end end
@@ -788,7 +802,12 @@ local function open(worktree)
vim.wo[win].winfixwidth = true vim.wo[win].winfixwidth = true
vim.api.nvim_win_set_width(win, SIDEBAR_WIDTH) vim.api.nvim_win_set_width(win, SIDEBAR_WIDTH)
state[bufnr] = { gitdir = gitdir, worktree = worktree, lines = {} } state[bufnr] = {
gitdir = gitdir,
worktree = worktree,
lines = {},
sidebar_win = win,
}
local function k(lhs, rhs, desc) local function k(lhs, rhs, desc)
vim.keymap.set( vim.keymap.set(