branch picker: Always show HEAD first (#11552)

Thorsten Ball created

I think this is a lot less confusing than another branch being selected
by default when there's no query.



Release Notes:

- Changed the branch picker to always show the current branch as the
default selected entry.



https://github.com/zed-industries/zed/assets/1185253/18b50656-f6ac-4138-b4e0-9024072e1555

Change summary

crates/git/src/repository.rs |  3 +++
crates/vcs_menu/src/lib.rs   | 20 +++++++++++++-------
2 files changed, 16 insertions(+), 7 deletions(-)

Detailed changes

crates/git/src/repository.rs 🔗

@@ -19,6 +19,7 @@ pub use git2::Repository as LibGitRepository;
 
 #[derive(Clone, Debug, Hash, PartialEq)]
 pub struct Branch {
+    pub is_head: bool,
     pub name: Box<str>,
     /// Timestamp of most recent commit, normalized to Unix Epoch format.
     pub unix_timestamp: Option<i64>,
@@ -202,6 +203,7 @@ impl GitRepository for RealGitRepository {
         let valid_branches = local_branches
             .filter_map(|branch| {
                 branch.ok().and_then(|(branch, _)| {
+                    let is_head = branch.is_head();
                     let name = branch.name().ok().flatten().map(Box::from)?;
                     let timestamp = branch.get().peel_to_commit().ok()?.time();
                     let unix_timestamp = timestamp.seconds();
@@ -211,6 +213,7 @@ impl GitRepository for RealGitRepository {
                     let unix_timestamp =
                         time::OffsetDateTime::from_unix_timestamp(unix_timestamp).ok()?;
                     Some(Branch {
+                        is_head,
                         name,
                         unix_timestamp: Some(unix_timestamp.to_offset(utc_offset).unix_timestamp()),
                     })

crates/vcs_menu/src/lib.rs 🔗

@@ -159,14 +159,20 @@ impl PickerDelegate for BranchListDelegate {
             let candidates = picker.update(&mut cx, |view, _| {
                 const RECENT_BRANCHES_COUNT: usize = 10;
                 let mut branches = view.delegate.all_branches.clone();
-                if query.is_empty() && branches.len() > RECENT_BRANCHES_COUNT {
-                    // Truncate list of recent branches
-                    // Do a partial sort to show recent-ish branches first.
-                    branches.select_nth_unstable_by(RECENT_BRANCHES_COUNT - 1, |lhs, rhs| {
-                        rhs.unix_timestamp.cmp(&lhs.unix_timestamp)
+                if query.is_empty() {
+                    if branches.len() > RECENT_BRANCHES_COUNT {
+                        // Truncate list of recent branches
+                        // Do a partial sort to show recent-ish branches first.
+                        branches.select_nth_unstable_by(RECENT_BRANCHES_COUNT - 1, |lhs, rhs| {
+                            rhs.is_head
+                                .cmp(&lhs.is_head)
+                                .then(rhs.unix_timestamp.cmp(&lhs.unix_timestamp))
+                        });
+                        branches.truncate(RECENT_BRANCHES_COUNT);
+                    }
+                    branches.sort_unstable_by(|lhs, rhs| {
+                        rhs.is_head.cmp(&lhs.is_head).then(lhs.name.cmp(&rhs.name))
                     });
-                    branches.truncate(RECENT_BRANCHES_COUNT);
-                    branches.sort_unstable_by(|lhs, rhs| lhs.name.cmp(&rhs.name));
                 }
                 branches
                     .into_iter()