file_finder: Display file icons (#18091)

This PR adds file icons (like in tabs, the project panel and tab
switcher) to the file finder popup.

It's similar to [tab_switcher
icons](https://github.com/zed-industries/zed/pull/17115), but simpler,
because we're only dealing with actual files.

Release Notes:

- Added icons to the file finder.

Screenshot:

![image](https://github.com/user-attachments/assets/bd6a54c1-cdbd-415a-9a82-0cc7a0bb6ca2)

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
Daste 2024-09-20 20:44:13 +02:00 committed by GitHub
parent 5d12e3ce3a
commit 7dac5594cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 57 additions and 2 deletions

3
Cargo.lock generated
View file

@ -4326,6 +4326,7 @@ dependencies = [
"ctor",
"editor",
"env_logger",
"file_icons",
"futures 0.3.30",
"fuzzy",
"gpui",
@ -4333,7 +4334,9 @@ dependencies = [
"menu",
"picker",
"project",
"schemars",
"serde",
"serde_derive",
"serde_json",
"settings",
"text",

View file

@ -496,6 +496,11 @@
// Whether a preview tab gets replaced when code navigation is used to navigate away from the tab.
"enable_preview_from_code_navigation": false
},
// Settings related to the file finder.
"file_finder": {
// Whether to show file icons in the file finder.
"file_icons": true
},
// Whether or not to remove any trailing whitespace from lines of a buffer
// before saving it.
"remove_trailing_whitespace_on_save": true,

View file

@ -16,14 +16,17 @@ doctest = false
anyhow.workspace = true
collections.workspace = true
editor.workspace = true
file_icons.workspace = true
futures.workspace = true
fuzzy.workspace = true
gpui.workspace = true
menu.workspace = true
picker.workspace = true
project.workspace = true
schemars.workspace = true
settings.workspace = true
serde.workspace = true
serde_derive.workspace = true
text.workspace = true
theme.workspace = true
ui.workspace = true

View file

@ -1,11 +1,14 @@
#[cfg(test)]
mod file_finder_tests;
mod file_finder_settings;
mod new_path_prompt;
mod open_path_prompt;
use collections::HashMap;
use editor::{scroll::Autoscroll, Bias, Editor};
use file_finder_settings::FileFinderSettings;
use file_icons::FileIcons;
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
use gpui::{
actions, rems, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle,
@ -39,7 +42,12 @@ pub struct FileFinder {
init_modifiers: Option<Modifiers>,
}
pub fn init_settings(cx: &mut AppContext) {
FileFinderSettings::register(cx);
}
pub fn init(cx: &mut AppContext) {
init_settings(cx);
cx.observe_new_views(FileFinder::register).detach();
cx.observe_new_views(NewPathPrompt::register).detach();
cx.observe_new_views(OpenPathPrompt::register).detach();
@ -1041,12 +1049,14 @@ impl PickerDelegate for FileFinderDelegate {
selected: bool,
cx: &mut ViewContext<Picker<Self>>,
) -> Option<Self::ListItem> {
let settings = FileFinderSettings::get_global(cx);
let path_match = self
.matches
.get(ix)
.expect("Invalid matches state: no element for index {ix}");
let icon = match &path_match {
let history_icon = match &path_match {
Match::History { .. } => Icon::new(IconName::HistoryRerun)
.color(Color::Muted)
.size(IconSize::Small)
@ -1059,10 +1069,17 @@ impl PickerDelegate for FileFinderDelegate {
let (file_name, file_name_positions, full_path, full_path_positions) =
self.labels_for_match(path_match, cx, ix);
let file_icon = if settings.file_icons {
FileIcons::get_icon(Path::new(&file_name), cx).map(Icon::from_path)
} else {
None
};
Some(
ListItem::new(ix)
.spacing(ListItemSpacing::Sparse)
.end_slot::<AnyElement>(Some(icon))
.start_slot::<Icon>(file_icon)
.end_slot::<AnyElement>(history_icon)
.inset(true)
.selected(selected)
.child(

View file

@ -0,0 +1,27 @@
use anyhow::Result;
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
pub struct FileFinderSettings {
pub file_icons: bool,
}
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
pub struct FileFinderSettingsContent {
/// Whether to show file icons in the file finder.
///
/// Default: true
pub file_icons: Option<bool>,
}
impl Settings for FileFinderSettings {
const KEY: Option<&'static str> = Some("file_finder");
type FileContent = FileFinderSettingsContent;
fn load(sources: SettingsSources<Self::FileContent>, _: &mut gpui::AppContext) -> Result<Self> {
sources.json_merge()
}
}