mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 05:51:14 +00:00
Fix open path prompt not showing hidden files (#46965)
Closes #39036 The open path prompt will now show hidden files when "." is entered. Also fixes an issue with "open this directory" showing twice when used by the "toolchain: add toolchain" prompt. With a tree of ``` zed-industries ├── .hidden ├── .hidden-file ├── zed ├── zed-working ├── zeta └── zeta-dataset ``` **Before:** <img width="656" height="174" alt="image" src="https://github.com/user-attachments/assets/abf30ce3-b1c2-4a14-a45d-c17b6c3aef6f" /> **After (current directory view without inputting "."):** <img width="648" height="261" alt="image" src="https://github.com/user-attachments/assets/00c65546-32c1-4c85-a05c-53152ab2f942" /> **After (when inputting "." to see hidden entries):** <img width="618" height="156" alt="image" src="https://github.com/user-attachments/assets/8453ae89-b1a7-44d4-9f7d-ed89e55a7020" /> Release Notes: - Made Zed's built in file picker to show all hidden files by default
This commit is contained in:
parent
03663b966d
commit
795eb34098
2 changed files with 87 additions and 38 deletions
|
|
@ -225,7 +225,8 @@ impl OpenPathPrompt {
|
|||
cx: &mut Context<Workspace>,
|
||||
) {
|
||||
workspace.toggle_modal(window, cx, |window, cx| {
|
||||
let delegate = OpenPathDelegate::new(tx, lister.clone(), creating_path, cx);
|
||||
let delegate =
|
||||
OpenPathDelegate::new(tx, lister.clone(), creating_path, cx).show_hidden();
|
||||
let picker = Picker::uniform_list(delegate, window, cx).width(rems(34.));
|
||||
let mut query = lister.default_query(cx);
|
||||
if let Some(suggested_name) = suggested_name {
|
||||
|
|
@ -402,14 +403,15 @@ impl PickerDelegate for OpenPathDelegate {
|
|||
return;
|
||||
};
|
||||
|
||||
if !hidden_entries {
|
||||
new_entries.retain(|entry| !entry.path.string.starts_with('.'));
|
||||
}
|
||||
|
||||
let max_id = new_entries
|
||||
.iter()
|
||||
.map(|entry| entry.path.id)
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
if !suffix.starts_with('.') && !hidden_entries {
|
||||
new_entries.retain(|entry| !entry.path.string.starts_with('.'));
|
||||
}
|
||||
|
||||
if suffix.is_empty() {
|
||||
let should_prepend_with_current_dir = this
|
||||
|
|
@ -489,6 +491,8 @@ impl PickerDelegate for OpenPathDelegate {
|
|||
if is_create_state && !entry.is_dir && Some(&suffix) == Some(&entry.path.string)
|
||||
{
|
||||
None
|
||||
} else if !suffix.is_empty() && entry.path.string == current_dir {
|
||||
None
|
||||
} else {
|
||||
Some(&entry.path)
|
||||
}
|
||||
|
|
@ -892,33 +896,6 @@ fn path_candidates(
|
|||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn get_dir_and_suffix(query: String, path_style: PathStyle) -> (String, String) {
|
||||
let last_item = Path::new(&query)
|
||||
.file_name()
|
||||
.unwrap_or_default()
|
||||
.to_string_lossy();
|
||||
let (mut dir, suffix) = if let Some(dir) = query.strip_suffix(last_item.as_ref()) {
|
||||
(dir.to_string(), last_item.into_owned())
|
||||
} else {
|
||||
(query.to_string(), String::new())
|
||||
};
|
||||
match path_style {
|
||||
PathStyle::Posix => {
|
||||
if dir.is_empty() {
|
||||
dir = "/".to_string();
|
||||
}
|
||||
}
|
||||
PathStyle::Windows => {
|
||||
if dir.len() < 3 {
|
||||
dir = "C:\\".to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
(dir, suffix)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn get_dir_and_suffix(query: String, path_style: PathStyle) -> (String, String) {
|
||||
match path_style {
|
||||
PathStyle::Posix => {
|
||||
|
|
@ -933,17 +910,18 @@ fn get_dir_and_suffix(query: String, path_style: PathStyle) -> (String, String)
|
|||
(dir, suffix)
|
||||
}
|
||||
PathStyle::Windows => {
|
||||
let (mut dir, suffix) = if let Some(index) = query.rfind('\\') {
|
||||
(query[..index].to_string(), query[index + 1..].to_string())
|
||||
let last_sep = query.rfind('\\').into_iter().chain(query.rfind('/')).max();
|
||||
let (mut dir, suffix) = if let Some(index) = last_sep {
|
||||
(
|
||||
query[..index + 1].to_string(),
|
||||
query[index + 1..].to_string(),
|
||||
)
|
||||
} else {
|
||||
(query, String::new())
|
||||
};
|
||||
if dir.len() < 3 {
|
||||
dir = "C:\\".to_string();
|
||||
}
|
||||
if !dir.ends_with('\\') {
|
||||
dir.push('\\');
|
||||
}
|
||||
(dir, suffix)
|
||||
}
|
||||
}
|
||||
|
|
@ -987,6 +965,34 @@ mod tests {
|
|||
get_dir_and_suffix("C:\\Users\\Junkui\\Documents\\".into(), PathStyle::Windows);
|
||||
assert_eq!(dir, "C:\\Users\\Junkui\\Documents\\");
|
||||
assert_eq!(suffix, "");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("C:\\root\\.".into(), PathStyle::Windows);
|
||||
assert_eq!(dir, "C:\\root\\");
|
||||
assert_eq!(suffix, ".");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("C:\\root\\..".into(), PathStyle::Windows);
|
||||
assert_eq!(dir, "C:\\root\\");
|
||||
assert_eq!(suffix, "..");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("C:\\root\\.hidden".into(), PathStyle::Windows);
|
||||
assert_eq!(dir, "C:\\root\\");
|
||||
assert_eq!(suffix, ".hidden");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("C:/root/".into(), PathStyle::Windows);
|
||||
assert_eq!(dir, "C:/root/");
|
||||
assert_eq!(suffix, "");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("C:/root/Use".into(), PathStyle::Windows);
|
||||
assert_eq!(dir, "C:/root/");
|
||||
assert_eq!(suffix, "Use");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("C:\\root/Use".into(), PathStyle::Windows);
|
||||
assert_eq!(dir, "C:\\root/");
|
||||
assert_eq!(suffix, "Use");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("C:/root\\.hidden".into(), PathStyle::Windows);
|
||||
assert_eq!(dir, "C:/root\\");
|
||||
assert_eq!(suffix, ".hidden");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1014,5 +1020,17 @@ mod tests {
|
|||
let (dir, suffix) = get_dir_and_suffix("/Users/Junkui/Documents/".into(), PathStyle::Posix);
|
||||
assert_eq!(dir, "/Users/Junkui/Documents/");
|
||||
assert_eq!(suffix, "");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("/root/.".into(), PathStyle::Posix);
|
||||
assert_eq!(dir, "/root/");
|
||||
assert_eq!(suffix, ".");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("/root/..".into(), PathStyle::Posix);
|
||||
assert_eq!(dir, "/root/");
|
||||
assert_eq!(suffix, "..");
|
||||
|
||||
let (dir, suffix) = get_dir_and_suffix("/root/.hidden".into(), PathStyle::Posix);
|
||||
assert_eq!(dir, "/root/");
|
||||
assert_eq!(suffix, ".hidden");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ async fn test_open_path_prompt(cx: &mut TestAppContext) {
|
|||
.insert_tree(
|
||||
path!("/root"),
|
||||
json!({
|
||||
".a1": ".A1",
|
||||
".b1": ".B1",
|
||||
"a1": "A1",
|
||||
"a2": "A2",
|
||||
"a3": "A3",
|
||||
|
|
@ -51,7 +53,7 @@ async fn test_open_path_prompt(cx: &mut TestAppContext) {
|
|||
#[cfg(windows)]
|
||||
let expected_separator = ".\\";
|
||||
|
||||
// If the query ends with a slash, the picker should show the contents of the directory.
|
||||
// If the query ends with a slash, the picker should show the contents of the directory and not show any of the hidden entries.
|
||||
let query = path!("/root/");
|
||||
insert_query(query, &picker, cx).await;
|
||||
assert_eq!(
|
||||
|
|
@ -94,6 +96,33 @@ async fn test_open_path_prompt(cx: &mut TestAppContext) {
|
|||
let query = path!("/root/dir2/di");
|
||||
insert_query(query, &picker, cx).await;
|
||||
assert_eq!(collect_match_candidates(&picker, cx), vec!["dir3", "dir4"]);
|
||||
|
||||
// Don't show candidates for the query ".".
|
||||
let query = path!("/root/.");
|
||||
insert_query(query, &picker, cx).await;
|
||||
assert_eq!(collect_match_candidates(&picker, cx), Vec::<String>::new());
|
||||
|
||||
// Don't show any candidates for the query ".a".
|
||||
let query = path!("/root/.a");
|
||||
insert_query(query, &picker, cx).await;
|
||||
assert_eq!(collect_match_candidates(&picker, cx), Vec::<String>::new());
|
||||
|
||||
// Show candidates for the query "./".
|
||||
// Should show current directory and contents.
|
||||
let query = path!("/root/./");
|
||||
insert_query(query, &picker, cx).await;
|
||||
assert_eq!(
|
||||
collect_match_candidates(&picker, cx),
|
||||
vec![expected_separator, "a1", "a2", "a3", "dir1", "dir2"]
|
||||
);
|
||||
|
||||
// Show candidates for the query "../". Show parent contents.
|
||||
let query = path!("/root/dir1/../");
|
||||
insert_query(query, &picker, cx).await;
|
||||
assert_eq!(
|
||||
collect_match_candidates(&picker, cx),
|
||||
vec![expected_separator, "a1", "a2", "a3", "dir1", "dir2"]
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
|
@ -369,11 +398,13 @@ async fn test_open_path_prompt_with_show_hidden(cx: &mut TestAppContext) {
|
|||
let expected_separator = ".\\";
|
||||
|
||||
insert_query(path!("/root/"), &picker, cx).await;
|
||||
|
||||
assert_eq!(
|
||||
collect_match_candidates(&picker, cx),
|
||||
vec![expected_separator, ".hidden", "directory_1", "directory_2"]
|
||||
);
|
||||
|
||||
insert_query(path!("/root/."), &picker, cx).await;
|
||||
assert_eq!(collect_match_candidates(&picker, cx), vec![".hidden"]);
|
||||
}
|
||||
|
||||
fn init_test(cx: &mut TestAppContext) -> Arc<AppState> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue