perf(git): bounded upward search in show.diff_section

This commit is contained in:
2026-04-27 14:21:30 +02:00
parent 2ef9cb7c9e
commit 15909e3ca1
+17 -16
View File
@@ -26,22 +26,21 @@ local function context()
return { worktree = worktree, ref = ref, parent_ref = vim.b.git_parent_ref } return { worktree = worktree, ref = ref, parent_ref = vim.b.git_parent_ref }
end end
---Walk upward from the cursor to the enclosing `diff --git` line and parse ---Find the enclosing `diff --git` line and parse the section's pre/post
---the section's pre/post paths plus the pre/post blob SHAs from the `index` ---paths plus the pre/post blob SHAs from the `index` line.
---line. ---
---@param cursor_lnum integer 1-indexed ---Uses `vim.fn.search('bcnW')` (backward, accept cursor pos, no move, no
---wrap) so a giant `git show <merge>` buffer doesn't pay an O(cursor_lnum)
---array allocation on every <CR>.
---@return ow.Git.DiffSection? ---@return ow.Git.DiffSection?
local function diff_section(cursor_lnum) local function diff_section()
local lines = vim.api.nvim_buf_get_lines(0, 0, cursor_lnum, false) local diff_lnum = vim.fn.search("^diff --git ", "bcnW")
local diff_lnum, diff_line if diff_lnum == 0 then
for i = #lines, 1, -1 do return nil
if lines[i]:match("^diff %-%-git ") then
diff_lnum = i
diff_line = lines[i]
break
end
end end
if not diff_lnum or not diff_line then local diff_line =
vim.api.nvim_buf_get_lines(0, diff_lnum - 1, diff_lnum, false)[1]
if not diff_line then
return nil return nil
end end
local pre_path, post_path = diff_line:match("^diff %-%-git a/(.-) b/(.+)$") local pre_path, post_path = diff_line:match("^diff %-%-git a/(.-) b/(.+)$")
@@ -49,6 +48,9 @@ local function diff_section(cursor_lnum)
return nil return nil
end end
-- Header lines (mode/index/oldfile/newfile/etc) sit between the
-- `diff --git` line and the first `@@` hunk; cap the read at 20 to
-- bound work even for unusual diff headers.
local header = local header =
vim.api.nvim_buf_get_lines(0, diff_lnum, diff_lnum + 20, false) vim.api.nvim_buf_get_lines(0, diff_lnum, diff_lnum + 20, false)
local pre_blob, post_blob local pre_blob, post_blob
@@ -165,8 +167,7 @@ function M.open_at_cursor()
if not ctx then if not ctx then
return false return false
end end
local cursor_lnum = vim.api.nvim_win_get_cursor(0)[1] local section = diff_section()
local section = diff_section(cursor_lnum)
if not section then if not section then
return false return false
end end