diff --git a/CHANGELOG.md b/CHANGELOG.md index ab50ac8a39..f426bc2467 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * disable blame and history popup keybinds for untracked files [[@kpbaks](https://github.com/kpbaks)] ([#2489](https://github.com/gitui-org/gitui/pull/2489)) * overwrites committer on amend of unsigned commits [[@cruessler](https://github.com/cruessler)] ([#2784](https://github.com/gitui-org/gitui/issues/2784)) * Updated project links to point to `gitui-org` instead of `extrawurst` [[@vasleymus](https://github.com/vasleymus)] ([#2538](https://github.com/gitui-org/gitui/pull/2538)) +* when staging the last file in a directory, the first item after the directory is no longer skipped [[@Tillerino](https://github.com/Tillerino)] ([#2748](https://github.com/gitui-org/gitui/issues/2748)) ## [0.27.0] - 2024-01-14 diff --git a/src/components/utils/statustree.rs b/src/components/utils/statustree.rs index 47a1e00529..3df694cebd 100644 --- a/src/components/utils/statustree.rs +++ b/src/components/utils/statustree.rs @@ -57,11 +57,8 @@ impl StatusTree { self.selection = last_selection.as_ref().map_or_else( || self.tree.items().first().map(|_| 0), |last_selection| { - self.find_last_selection( - last_selection, - last_selection_index, - ) - .or_else(|| self.tree.items().first().map(|_| 0)) + self.find_last_selection(last_selection) + .or_else(|| self.tree.items().first().map(|_| 0)) }, ); @@ -196,19 +193,18 @@ impl StatusTree { fn find_last_selection( &self, last_selection: &str, - last_index: usize, ) -> Option { if self.is_empty() { return None; } - if let Ok(i) = self.tree.items().binary_search_by(|e| { + let res = self.tree.items().binary_search_by(|e| { e.info.full_path.as_str().cmp(last_selection) - }) { - return Some(i); + }); + match res { + Ok(i) => Some(i), + Err(i) => Some(cmp::min(i, self.tree.len() - 1)), } - - Some(cmp::min(last_index, self.tree.len() - 1)) } fn selection_updown( @@ -520,7 +516,7 @@ mod tests { res.update(&string_vec_to_status(&["a", "b"])).unwrap(); res.selection = Some(1); - res.update(&string_vec_to_status(&["d", "c", "a"])).unwrap(); + res.update(&string_vec_to_status(&["a", "c", "d"])).unwrap(); assert_eq!(res.selection, Some(1)); } @@ -545,6 +541,33 @@ mod tests { assert_eq!(res.selection, Some(0)); } + #[test] + fn test_next_when_dir_disappears() { + let mut tree = StatusTree::default(); + tree.update(&string_vec_to_status(&["a/b", "c", "d"])) + .unwrap(); + tree.selection = Some(1); + assert_eq!( + tree.selected_item().unwrap().info.full_path, + "a/b" + ); + + tree.update(&string_vec_to_status(&["c", "d"])).unwrap(); + assert_eq!(tree.selected_item().unwrap().info.full_path, "c"); + } + + #[test] + fn test_next_when_last_dir_disappears() { + let mut tree = StatusTree::default(); + tree.update(&string_vec_to_status(&["a", "b", "c"])) + .unwrap(); + tree.selection = Some(2); + assert_eq!(tree.selected_item().unwrap().info.full_path, "c"); + + tree.update(&string_vec_to_status(&["a", "b"])).unwrap(); + assert_eq!(tree.selected_item().unwrap().info.full_path, "b"); + } + #[test] fn test_keep_collapsed_states() { let mut res = StatusTree::default();