@@ -87,6 +87,23 @@ function ProjectDiffScreen:move_to(query_fn)
8787 return self .status_list_view :move_to (query_fn )
8888end
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+
90107function 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