Skip to content

Commit a7ddcb2

Browse files
committed
fix: Stay at next hunk/file after staging
Hunk operations (stage/unstage/reset) stay at the same index position, effectively moving to the next hunk. When a file is fully staged or unstaged, jump to the next file of the same type rather than the first.
1 parent d8b55c0 commit a7ddcb2

1 file changed

Lines changed: 35 additions & 4 deletions

File tree

  • lua/vgit/features/screens/ProjectDiffScreen

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

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,23 @@ function ProjectDiffScreen:move_to(query_fn)
8787
return self.status_list_view:move_to(query_fn)
8888
end
8989

90+
-- Find the next file of given entry_type after current filename
91+
function ProjectDiffScreen:find_next_file(filename, target_entry_type)
92+
local next_filename = nil
93+
local found_current = false
94+
self.status_list_view:each_status(function(status, entry_type)
95+
if entry_type == target_entry_type then
96+
if found_current and not next_filename then
97+
next_filename = status.filename
98+
end
99+
if status.filename == filename then
100+
found_current = true
101+
end
102+
end
103+
end)
104+
return next_filename
105+
end
106+
90107
function ProjectDiffScreen:stage_hunk()
91108
local entry = self.model:get_entry()
92109
if not entry then return end
@@ -97,6 +114,8 @@ function ProjectDiffScreen:stage_hunk()
97114
if not hunk then return end
98115

99116
local filename = entry.status.filename
117+
local next_file = self:find_next_file(filename, 'unstaged')
118+
100119
local _, err = self.model:stage_hunk(filename, hunk)
101120
if err then
102121
console.debug.error(err)
@@ -112,12 +131,14 @@ function ProjectDiffScreen:stage_hunk()
112131
end)
113132

114133
if has_unstaged then
115-
-- Stay on the unstaged entry for this file
116134
self:move_to(function(status, entry_type)
117135
return status.filename == filename and entry_type == 'unstaged'
118136
end)
137+
elseif next_file then
138+
self:move_to(function(status, entry_type)
139+
return status.filename == next_file and entry_type == 'unstaged'
140+
end)
119141
else
120-
-- File fully staged - jump to next unstaged file, else this file's staged
121142
local found = self:move_to(function(_, entry_type)
122143
return entry_type == 'unstaged'
123144
end)
@@ -153,6 +174,8 @@ function ProjectDiffScreen:unstage_hunk()
153174
if not hunk then return end
154175

155176
local filename = entry.status.filename
177+
local next_file = self:find_next_file(filename, 'staged')
178+
156179
local _, err = self.model:unstage_hunk(filename, hunk)
157180
if err then
158181
console.debug.error(err)
@@ -168,12 +191,14 @@ function ProjectDiffScreen:unstage_hunk()
168191
end)
169192

170193
if has_staged then
171-
-- Stay on the staged entry for this file
172194
self:move_to(function(status, entry_type)
173195
return status.filename == filename and entry_type == 'staged'
174196
end)
197+
elseif next_file then
198+
self:move_to(function(status, entry_type)
199+
return status.filename == next_file and entry_type == 'staged'
200+
end)
175201
else
176-
-- File fully unstaged - jump to next staged file, else this file's unstaged
177202
local found = self:move_to(function(_, entry_type)
178203
return entry_type == 'staged'
179204
end)
@@ -209,6 +234,8 @@ function ProjectDiffScreen:reset_hunk()
209234
if not hunk then return end
210235

211236
local filename = entry.status.filename
237+
local next_file = self:find_next_file(filename, 'unstaged')
238+
212239
loop.free_textlock()
213240
local decision = console.input('Are you sure you want to discard this hunk? (y/N) '):lower()
214241
if decision ~= 'yes' and decision ~= 'y' then return end
@@ -233,6 +260,10 @@ function ProjectDiffScreen:reset_hunk()
233260
self:move_to(function(status, entry_type)
234261
return status.filename == filename and entry_type == 'unstaged'
235262
end)
263+
elseif next_file then
264+
self:move_to(function(status, entry_type)
265+
return status.filename == next_file and entry_type == 'unstaged'
266+
end)
236267
else
237268
local found = self:move_to(function(_, entry_type)
238269
return entry_type == 'unstaged'

0 commit comments

Comments
 (0)