Skip to content

Commit 4750b9c

Browse files
committed
feat(ProjectDiffScreen): Jump to file position on quit
The diff view is a projection of the file's state. Quitting from the diff pane now jumps to the corresponding file position, keeping context stable.
1 parent cc961d9 commit 4750b9c

3 files changed

Lines changed: 50 additions & 2 deletions

File tree

lua/vgit/features/screens/ProjectDiffScreen/init.lua

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,31 @@ function ProjectDiffScreen:create()
821821
return true
822822
end
823823

824+
-- Called when quit key is pressed. Returns true if quit was handled.
825+
function ProjectDiffScreen:on_quit()
826+
local diff_component = self.scene:get('current')
827+
if not diff_component:is_focused() then
828+
return false
829+
end
830+
831+
local filepath = self.model:get_filepath()
832+
if not filepath then
833+
return false
834+
end
835+
836+
local file_lnum = self.diff_view:get_file_lnum()
837+
loop.free_textlock()
838+
839+
self:destroy()
840+
fs.open(filepath)
841+
842+
if file_lnum then
843+
Window(0):set_lnum(file_lnum):position_cursor('center')
844+
end
845+
846+
return true
847+
end
848+
824849
function ProjectDiffScreen:destroy()
825850
-- Clean up timer handles from debounced keymap handlers
826851
loop.close_debounced_handlers(self.diff_keymaps)

lua/vgit/ui/screen_manager.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,10 @@ function screen_manager.create(screen_name, ...)
120120
{
121121
mode = 'n',
122122
key = scene_setting:get('keymaps').quit,
123-
handler = function()
123+
handler = loop.coroutine(function()
124+
if screen.on_quit and screen:on_quit() then return end
124125
screen_manager.destroy_active_screen()
125-
end
126+
end)
126127
}
127128
})
128129
end

lua/vgit/ui/views/DiffView.lua

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,28 @@ function DiffView:get_hunk_under_cursor()
500500
if selected then return hunks[selected], selected end
501501
end
502502

503+
-- Returns the actual file line number for the current cursor position.
504+
-- For removed lines (which don't exist in the file), returns the closest
505+
-- valid line number above.
506+
function DiffView:get_file_lnum()
507+
local lines_changes = self.state.current_lines_changes
508+
if not lines_changes or #lines_changes == 0 then return nil end
509+
510+
local lnum = self.scene:get('current'):get_lnum()
511+
if lnum > #lines_changes then lnum = #lines_changes end
512+
513+
-- Search current line and above for a valid line number
514+
for i = lnum, 1, -1 do
515+
local entry = lines_changes[i]
516+
if entry and entry.line_number then
517+
local file_lnum = tonumber(entry.line_number:match('%d+'))
518+
if file_lnum then return file_lnum end
519+
end
520+
end
521+
522+
return nil
523+
end
524+
503525
function DiffView:set_lnum(lnum, position)
504526
if self.props.layout_type() == 'split' then self.scene:get('previous'):set_lnum(lnum):position_cursor(position) end
505527
self.scene:get('current'):set_lnum(lnum):position_cursor(position)

0 commit comments

Comments
 (0)