file_finder: Fix open path prompt creating wrong highlight indices (#40488)

Fixes ZED-28R

Release Notes:

- Fixed open path prompt panicking on certain inputs
This commit is contained in:
Lukas Wirth
2025-10-17 12:41:09 +00:00
committed by GitHub
parent b59a3bbd49
commit b7112320bb
3 changed files with 39 additions and 33 deletions
+30 -31
View File
@@ -669,7 +669,7 @@ impl PickerDelegate for OpenPathDelegate {
) -> Option<Self::ListItem> {
let settings = FileFinderSettings::get_global(cx);
let candidate = self.get_entry(ix)?;
let match_positions = match &self.directory_state {
let mut match_positions = match &self.directory_state {
DirectoryState::List { .. } => self.string_matches.get(ix)?.positions.clone(),
DirectoryState::Create { user_input, .. } => {
if let Some(user_input) = user_input {
@@ -710,29 +710,38 @@ impl PickerDelegate for OpenPathDelegate {
});
match &self.directory_state {
DirectoryState::List { parent_path, .. } => Some(
ListItem::new(ix)
.spacing(ListItemSpacing::Sparse)
.start_slot::<Icon>(file_icon)
.inset(true)
.toggle_state(selected)
.child(HighlightedLabel::new(
if parent_path == &self.prompt_root {
format!("{}{}", self.prompt_root, candidate.path.string)
} else if is_current_dir_candidate {
"open this directory".to_string()
} else {
candidate.path.string
},
DirectoryState::List { parent_path, .. } => {
let (label, indices) = if *parent_path == self.prompt_root {
match_positions.iter_mut().for_each(|position| {
*position += self.prompt_root.len();
});
(
format!("{}{}", self.prompt_root, candidate.path.string),
match_positions,
)),
),
)
} else if is_current_dir_candidate {
("open this directory".to_string(), vec![])
} else {
(candidate.path.string, match_positions)
};
Some(
ListItem::new(ix)
.spacing(ListItemSpacing::Sparse)
.start_slot::<Icon>(file_icon)
.inset(true)
.toggle_state(selected)
.child(HighlightedLabel::new(label, indices)),
)
}
DirectoryState::Create {
parent_path,
user_input,
..
} => {
let (label, delta) = if parent_path == &self.prompt_root {
let (label, delta) = if *parent_path == self.prompt_root {
match_positions.iter_mut().for_each(|position| {
*position += self.prompt_root.len();
});
(
format!("{}{}", self.prompt_root, candidate.path.string),
self.prompt_root.len(),
@@ -740,10 +749,10 @@ impl PickerDelegate for OpenPathDelegate {
} else {
(candidate.path.string.clone(), 0)
};
let label_len = label.len();
let label_with_highlights = match user_input {
Some(user_input) => {
let label_len = label.len();
if user_input.file.string == candidate.path.string {
if user_input.exists {
let label = if user_input.is_dir {
@@ -772,20 +781,10 @@ impl PickerDelegate for OpenPathDelegate {
.into_any_element()
}
} else {
let mut highlight_positions = match_positions;
highlight_positions.iter_mut().for_each(|position| {
*position += delta;
});
HighlightedLabel::new(label, highlight_positions).into_any_element()
HighlightedLabel::new(label, match_positions).into_any_element()
}
}
None => {
let mut highlight_positions = match_positions;
highlight_positions.iter_mut().for_each(|position| {
*position += delta;
});
HighlightedLabel::new(label, highlight_positions).into_any_element()
}
None => HighlightedLabel::new(label, match_positions).into_any_element(),
};
Some(
+1 -1
View File
@@ -228,7 +228,7 @@ impl PickerDelegate for PickerPromptDelegate {
let highlights: Vec<_> = hit
.positions
.iter()
.filter(|index| index < &&self.max_match_length)
.filter(|&&index| index < self.max_match_length)
.copied()
.collect();
@@ -15,9 +15,16 @@ impl HighlightedLabel {
/// Constructs a label with the given characters highlighted.
/// Characters are identified by UTF-8 byte position.
pub fn new(label: impl Into<SharedString>, highlight_indices: Vec<usize>) -> Self {
let label = label.into();
for &run in &highlight_indices {
assert!(
label.is_char_boundary(run),
"highlight index {run} is not a valid UTF-8 boundary"
);
}
Self {
base: LabelLike::new(),
label: label.into(),
label,
highlight_indices,
}
}