util: Fix edge case when parsing paths (#36025)

Searching for files broke a couple releases ago. It used to be possible
to start typing part of a file name, then select a file (not confirm it
yet) and then type in `:` and a line number to navigate directly to that
line.
The current behavior can be seen in the following screenshots. When the
`:` is typed, the selection is lost, since no files match any more.
<img width="552" height="370" alt="Screenshot From 2025-08-12 10-36-08"
src="https://github.com/user-attachments/assets/e4b4b613-7f0c-40d7-94c9-04d8ab541656"
/>
<img width="553" height="124" alt="Screenshot From 2025-08-12 10-36-25"
src="https://github.com/user-attachments/assets/843e9ecf-9e08-4fa6-9340-0388a957cbb2"
/>
<img width="549" height="370" alt="Screenshot From 2025-08-12 10-36-47"
src="https://github.com/user-attachments/assets/4a1bbbd8-268a-4ea8-999f-6cef1eb34a45"
/>

---

With this PR, the previous behavior is restored and can be seen in these
screenshots:

<img width="552" height="370" alt="Screenshot From 2025-08-12 10-36-08"
src="https://github.com/user-attachments/assets/466e1906-4735-47ae-a699-117bdd6490ca"
/>
<img width="549" height="370" alt="Screenshot From 2025-08-12 10-47-07"
src="https://github.com/user-attachments/assets/17f3acda-662d-4962-9eb8-4b494f211d26"
/>
<img width="549" height="370" alt="Screenshot From 2025-08-12 10-47-21"
src="https://github.com/user-attachments/assets/d98447fe-7377-4f4f-b3da-f690cd44c141"
/>

---

Release Notes:

- Adjusted the file finder to show matching file paths when adding the
`:row:column` to the query
This commit is contained in:
Hendrik Müller 2025-08-25 11:28:33 +02:00 committed by GitHub
parent 11545c669e
commit c48197b280
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 54 additions and 3 deletions

View file

@ -1401,13 +1401,16 @@ impl PickerDelegate for FileFinderDelegate {
#[cfg(windows)]
let raw_query = raw_query.trim().to_owned().replace("/", "\\");
#[cfg(not(windows))]
let raw_query = raw_query.trim().to_owned();
let raw_query = raw_query.trim();
let file_query_end = if path_position.path.to_str().unwrap_or(&raw_query) == raw_query {
let raw_query = raw_query.trim_end_matches(':').to_owned();
let path = path_position.path.to_str();
let path_trimmed = path.unwrap_or(&raw_query).trim_end_matches(':');
let file_query_end = if path_trimmed == raw_query {
None
} else {
// Safe to unwrap as we won't get here when the unwrap in if fails
Some(path_position.path.to_str().unwrap().len())
Some(path.unwrap().len())
};
let query = FileSearchQuery {

View file

@ -218,6 +218,7 @@ async fn test_matching_paths(cx: &mut TestAppContext) {
" ndan ",
" band ",
"a bandana",
"bandana:",
] {
picker
.update_in(cx, |picker, window, cx| {
@ -252,6 +253,53 @@ async fn test_matching_paths(cx: &mut TestAppContext) {
}
}
#[gpui::test]
async fn test_matching_paths_with_colon(cx: &mut TestAppContext) {
let app_state = init_test(cx);
app_state
.fs
.as_fake()
.insert_tree(
path!("/root"),
json!({
"a": {
"foo:bar.rs": "",
"foo.rs": "",
}
}),
)
.await;
let project = Project::test(app_state.fs.clone(), [path!("/root").as_ref()], cx).await;
let (picker, _, cx) = build_find_picker(project, cx);
// 'foo:' matches both files
cx.simulate_input("foo:");
picker.update(cx, |picker, _| {
assert_eq!(picker.delegate.matches.len(), 3);
assert_match_at_position(picker, 0, "foo.rs");
assert_match_at_position(picker, 1, "foo:bar.rs");
});
// 'foo:b' matches one of the files
cx.simulate_input("b");
picker.update(cx, |picker, _| {
assert_eq!(picker.delegate.matches.len(), 2);
assert_match_at_position(picker, 0, "foo:bar.rs");
});
cx.dispatch_action(editor::actions::Backspace);
// 'foo:1' matches both files, specifying which row to jump to
cx.simulate_input("1");
picker.update(cx, |picker, _| {
assert_eq!(picker.delegate.matches.len(), 3);
assert_match_at_position(picker, 0, "foo.rs");
assert_match_at_position(picker, 1, "foo:bar.rs");
});
}
#[gpui::test]
async fn test_unicode_paths(cx: &mut TestAppContext) {
let app_state = init_test(cx);