workspace::Open: Highlight fuzzy matches (#26320)

Partial: https://github.com/zed-industries/zed/issues/15398

Changes:
Adds highlighting to the matches when using `"use_system_path_prompts":
false`

| before | after |
|---|---|

|![image](https://github.com/user-attachments/assets/60a385a0-abb0-49c5-935c-e71149161562)|![image](https://github.com/user-attachments/assets/d66ce980-cea9-4c22-8e6a-9720344be39a)|

Release Notes:

- N/A
This commit is contained in:
brian tan 2025-03-12 16:54:38 -04:00 committed by GitHub
parent 9be7934f12
commit edeed7b619
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,5 +1,5 @@
use futures::channel::oneshot; use futures::channel::oneshot;
use fuzzy::StringMatchCandidate; use fuzzy::{StringMatch, StringMatchCandidate};
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use project::DirectoryLister; use project::DirectoryLister;
use std::{ use std::{
@ -9,7 +9,7 @@ use std::{
Arc, Arc,
}, },
}; };
use ui::{prelude::*, LabelLike, ListItemSpacing}; use ui::{prelude::*, HighlightedLabel, ListItemSpacing};
use ui::{Context, ListItem, Window}; use ui::{Context, ListItem, Window};
use util::{maybe, paths::compare_paths}; use util::{maybe, paths::compare_paths};
use workspace::Workspace; use workspace::Workspace;
@ -22,6 +22,7 @@ pub struct OpenPathDelegate {
selected_index: usize, selected_index: usize,
directory_state: Option<DirectoryState>, directory_state: Option<DirectoryState>,
matches: Vec<usize>, matches: Vec<usize>,
string_matches: Vec<StringMatch>,
cancel_flag: Arc<AtomicBool>, cancel_flag: Arc<AtomicBool>,
should_dismiss: bool, should_dismiss: bool,
} }
@ -34,6 +35,7 @@ impl OpenPathDelegate {
selected_index: 0, selected_index: 0,
directory_state: None, directory_state: None,
matches: Vec::new(), matches: Vec::new(),
string_matches: Vec::new(),
cancel_flag: Arc::new(AtomicBool::new(false)), cancel_flag: Arc::new(AtomicBool::new(false)),
should_dismiss: true, should_dismiss: true,
} }
@ -223,6 +225,7 @@ impl PickerDelegate for OpenPathDelegate {
if suffix == "" { if suffix == "" {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.delegate.matches.clear(); this.delegate.matches.clear();
this.delegate.string_matches.clear();
this.delegate this.delegate
.matches .matches
.extend(match_candidates.iter().map(|m| m.path.id)); .extend(match_candidates.iter().map(|m| m.path.id));
@ -249,6 +252,7 @@ impl PickerDelegate for OpenPathDelegate {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.delegate.matches.clear(); this.delegate.matches.clear();
this.delegate.string_matches = matches.clone();
this.delegate this.delegate
.matches .matches
.extend(matches.into_iter().map(|m| m.candidate_id)); .extend(matches.into_iter().map(|m| m.candidate_id));
@ -337,13 +341,22 @@ impl PickerDelegate for OpenPathDelegate {
let m = self.matches.get(ix)?; let m = self.matches.get(ix)?;
let directory_state = self.directory_state.as_ref()?; let directory_state = self.directory_state.as_ref()?;
let candidate = directory_state.match_candidates.get(*m)?; let candidate = directory_state.match_candidates.get(*m)?;
let highlight_positions = self
.string_matches
.iter()
.find(|string_match| string_match.candidate_id == *m)
.map(|string_match| string_match.positions.clone())
.unwrap_or_default();
Some( Some(
ListItem::new(ix) ListItem::new(ix)
.spacing(ListItemSpacing::Sparse) .spacing(ListItemSpacing::Sparse)
.inset(true) .inset(true)
.toggle_state(selected) .toggle_state(selected)
.child(LabelLike::new().child(candidate.path.string.clone())), .child(HighlightedLabel::new(
candidate.path.string.clone(),
highlight_positions,
)),
) )
} }