feat(fugitive): line position tracking for keymaps

When pressing `du`/`dU` from a hunk line in the fugitive status buffer
(after expanding with `=`), the unified diff now opens at the
corresponding line instead of line 1.

Implementation:
- `fugitive.get_hunk_position()` returns @@ header and offset when on a hunk line
- `commands.find_hunk_line()` finds matching @@ header in diff buffer
- `commands.gdiff_file()` accepts optional `hunk_position` and jumps after opening

Also updates @phanen's README credit for the previous two fixes.

Closes #65
This commit is contained in:
Barrett Ruth 2026-02-05 00:27:35 -05:00
parent a6d4dcff1f
commit 9e857d4b29
5 changed files with 247 additions and 8 deletions

View file

@ -3,6 +3,18 @@ local M = {}
local git = require('diffs.git')
local dbg = require('diffs.log').dbg
---@param diff_lines string[]
---@param hunk_position { hunk_header: string, offset: integer }
---@return integer?
function M.find_hunk_line(diff_lines, hunk_position)
for i, line in ipairs(diff_lines) do
if line == hunk_position.hunk_header then
return i + hunk_position.offset
end
end
return nil
end
---@param old_lines string[]
---@param new_lines string[]
---@param old_name string
@ -98,6 +110,7 @@ end
---@field staged? boolean
---@field untracked? boolean
---@field old_filepath? string
---@field hunk_position? { hunk_header: string, offset: integer }
---@param filepath string
---@param opts? diffs.GdiffFileOpts
@ -175,6 +188,14 @@ function M.gdiff_file(filepath, opts)
vim.cmd(opts.vertical and 'vsplit' or 'split')
vim.api.nvim_win_set_buf(0, diff_buf)
if opts.hunk_position then
local target_line = M.find_hunk_line(diff_lines, opts.hunk_position)
if target_line then
vim.api.nvim_win_set_cursor(0, { target_line, 0 })
dbg('jumped to line %d for hunk', target_line)
end
end
dbg('opened diff buffer %d for %s (%s)', diff_buf, rel_path, diff_label)
vim.schedule(function()