From 15909e3ca16b89ea536010fecb44fdf2d7e50939 Mon Sep 17 00:00:00 2001 From: Oscar Wallberg Date: Mon, 27 Apr 2026 14:21:30 +0200 Subject: [PATCH] perf(git): bounded upward search in show.diff_section --- lua/git/show.lua | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/lua/git/show.lua b/lua/git/show.lua index 331c5d5..bf419a7 100644 --- a/lua/git/show.lua +++ b/lua/git/show.lua @@ -26,22 +26,21 @@ local function context() return { worktree = worktree, ref = ref, parent_ref = vim.b.git_parent_ref } end ----Walk upward from the cursor to the enclosing `diff --git` line and parse ----the section's pre/post paths plus the pre/post blob SHAs from the `index` ----line. ----@param cursor_lnum integer 1-indexed +---Find the enclosing `diff --git` line and parse the section's pre/post +---paths plus the pre/post blob SHAs from the `index` line. +--- +---Uses `vim.fn.search('bcnW')` (backward, accept cursor pos, no move, no +---wrap) so a giant `git show ` buffer doesn't pay an O(cursor_lnum) +---array allocation on every . ---@return ow.Git.DiffSection? -local function diff_section(cursor_lnum) - local lines = vim.api.nvim_buf_get_lines(0, 0, cursor_lnum, false) - local diff_lnum, diff_line - for i = #lines, 1, -1 do - if lines[i]:match("^diff %-%-git ") then - diff_lnum = i - diff_line = lines[i] - break - end +local function diff_section() + local diff_lnum = vim.fn.search("^diff --git ", "bcnW") + if diff_lnum == 0 then + return nil 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 end local pre_path, post_path = diff_line:match("^diff %-%-git a/(.-) b/(.+)$") @@ -49,6 +48,9 @@ local function diff_section(cursor_lnum) return nil 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 = vim.api.nvim_buf_get_lines(0, diff_lnum, diff_lnum + 20, false) local pre_blob, post_blob @@ -165,8 +167,7 @@ function M.open_at_cursor() if not ctx then return false end - local cursor_lnum = vim.api.nvim_win_get_cursor(0)[1] - local section = diff_section(cursor_lnum) + local section = diff_section() if not section then return false end