@@ -16,6 +16,8 @@ local mappings = require("blame.mappings")
1616--- @field file_path string
1717--- @field cwd string
1818--- @field commit_stack Porcelain[]
19+ --- @field cursor_stack unknown[]
20+ --- @field original_cursor unknown
1921local BlameStack = {}
2022
2123--- @return BlameStack
@@ -43,6 +45,7 @@ function BlameStack:new(config, blame_view, file_path, cwd)
4345 end )
4446
4547 o .commit_stack = {}
48+ o .cursor_stack = {}
4649
4750 return o
4851end
@@ -55,7 +58,7 @@ function BlameStack:push(commit)
5558 return
5659 end
5760
58- self :get_show_file_content (commit , true , function (file_content )
61+ self :get_prev_file_content (commit , function (file_content , line )
5962 self :get_blame_for_commit (commit , true , function (blame_lines )
6063 if self .stack_buffer == nil then
6164 self :create_blame_buf ()
@@ -72,9 +75,16 @@ function BlameStack:push(commit)
7275 file_content
7376 )
7477 table.insert (self .commit_stack , commit )
78+ table.insert (self .cursor_stack , vim .api .nvim_win_get_cursor (self .blame_window ))
79+ if # self .cursor_stack == 1 then
80+ self .original_cursor = self .cursor_stack [1 ]
81+ end
7582 self :open_stack_info_float ()
7683
7784 self .blame_view :open (blame_lines )
85+ if line ~= nil then
86+ vim .api .nvim_win_set_cursor (self .blame_window , { line , 0 })
87+ end
7888 end )
7989 end , function ()
8090 vim .notify (
@@ -93,11 +103,11 @@ function BlameStack:pop()
93103 return
94104 end
95105 table.remove (self .commit_stack , nil )
106+ local cursor = table.remove (self .cursor_stack , nil )
96107 self :open_stack_info_float ()
97- self :get_show_file_content (
108+ self :get_prev_file_content (
98109 self .commit_stack [# self .commit_stack ],
99- true ,
100- function (file_content )
110+ function (file_content , line )
101111 vim .api .nvim_buf_set_lines (
102112 self .stack_buffer ,
103113 0 ,
@@ -112,6 +122,7 @@ function BlameStack:pop()
112122 function (blame_lines )
113123 vim .schedule (function ()
114124 self .blame_view :open (blame_lines )
125+ vim .api .nvim_win_set_cursor (self .blame_window , cursor )
115126 end )
116127 end
117128 )
162173
163174function BlameStack :reset_to_original_buf ()
164175 self .commit_stack = {}
176+ self .cursor_stack = {}
165177 vim .api .nvim_set_current_win (self .original_window )
166178 vim .api .nvim_set_current_buf (self .original_buffer )
167179 if self .stack_buffer and vim .api .nvim_buf_is_valid (self .stack_buffer ) then
@@ -171,6 +183,9 @@ function BlameStack:reset_to_original_buf()
171183 self :get_blame_for_commit ({}, false , function (blame_lines )
172184 vim .schedule (function ()
173185 self .blame_view :open (blame_lines )
186+ if self .original_cursor ~= nil then
187+ vim .api .nvim_win_set_cursor (self .blame_window , self .original_cursor )
188+ end
174189 end )
175190 end )
176191 self .stack_buffer = nil
@@ -324,20 +339,35 @@ function BlameStack:get_blame_for_commit(commit, prev, cb, err_cb)
324339end
325340
326341--- @param commit Porcelain
327- --- @param prev boolean should show previous commit
328- --- @param cb fun ( any ) callback on show command end
342+ --- @param cb fun ( any , number ?) callback on show command end
329343--- @param err_cb nil | fun ( err ) callback on error show command
330- function BlameStack :get_show_file_content (commit , prev , cb , err_cb )
331- local hash , filepath = self :get_hash_and_filepath (commit , prev )
344+ function BlameStack :get_prev_file_content (commit , cb , err_cb )
345+ local hash , filepath = self :get_hash_and_filepath (commit , true )
332346 self .git_client :show (filepath , self .git_root , hash , function (file_content )
333- vim . schedule ( function ()
347+ self . git_client : diff ( filepath , self . git_root , hash , commit . hash , function (diff )
334348 -- most of the time empty line is inserted from git-show. Might create issues but for now this crude check works
335349 if file_content [# file_content ] == " " then
336350 table.remove (file_content )
337351 end
338352
339- if cb ~= nil then
340- cb (file_content )
353+ local line
354+ for _ , hunk in ipairs (porcelain_parser .parse_hunks (diff )) do
355+ if hunk .curr_line <= commit .original_line and commit .original_line < hunk .curr_line + hunk .curr_count then
356+ line = hunk .prev_line
357+ break
358+ end
359+ end
360+
361+ vim .schedule (function ()
362+ if cb ~= nil then
363+ cb (file_content , line )
364+ end
365+ end )
366+ end , function (err )
367+ if err_cb then
368+ err_cb (err )
369+ else
370+ vim .notify (err , vim .log .levels .INFO )
341371 end
342372 end )
343373 end , function (err )
0 commit comments