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:  --------- Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
parent
5d12e3ce3a
commit
7dac5594cd
5 changed files with 57 additions and 2 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -4326,6 +4326,7 @@ dependencies = [
|
||||||
"ctor",
|
"ctor",
|
||||||
"editor",
|
"editor",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"file_icons",
|
||||||
"futures 0.3.30",
|
"futures 0.3.30",
|
||||||
"fuzzy",
|
"fuzzy",
|
||||||
"gpui",
|
"gpui",
|
||||||
|
@ -4333,7 +4334,9 @@ dependencies = [
|
||||||
"menu",
|
"menu",
|
||||||
"picker",
|
"picker",
|
||||||
"project",
|
"project",
|
||||||
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"settings",
|
"settings",
|
||||||
"text",
|
"text",
|
||||||
|
|
|
@ -496,6 +496,11 @@
|
||||||
// Whether a preview tab gets replaced when code navigation is used to navigate away from the tab.
|
// Whether a preview tab gets replaced when code navigation is used to navigate away from the tab.
|
||||||
"enable_preview_from_code_navigation": false
|
"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
|
// Whether or not to remove any trailing whitespace from lines of a buffer
|
||||||
// before saving it.
|
// before saving it.
|
||||||
"remove_trailing_whitespace_on_save": true,
|
"remove_trailing_whitespace_on_save": true,
|
||||||
|
|
|
@ -16,14 +16,17 @@ doctest = false
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
collections.workspace = true
|
collections.workspace = true
|
||||||
editor.workspace = true
|
editor.workspace = true
|
||||||
|
file_icons.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
fuzzy.workspace = true
|
fuzzy.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
menu.workspace = true
|
menu.workspace = true
|
||||||
picker.workspace = true
|
picker.workspace = true
|
||||||
project.workspace = true
|
project.workspace = true
|
||||||
|
schemars.workspace = true
|
||||||
settings.workspace = true
|
settings.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
serde_derive.workspace = true
|
||||||
text.workspace = true
|
text.workspace = true
|
||||||
theme.workspace = true
|
theme.workspace = true
|
||||||
ui.workspace = true
|
ui.workspace = true
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod file_finder_tests;
|
mod file_finder_tests;
|
||||||
|
|
||||||
|
mod file_finder_settings;
|
||||||
mod new_path_prompt;
|
mod new_path_prompt;
|
||||||
mod open_path_prompt;
|
mod open_path_prompt;
|
||||||
|
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use editor::{scroll::Autoscroll, Bias, Editor};
|
use editor::{scroll::Autoscroll, Bias, Editor};
|
||||||
|
use file_finder_settings::FileFinderSettings;
|
||||||
|
use file_icons::FileIcons;
|
||||||
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
|
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, rems, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle,
|
actions, rems, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle,
|
||||||
|
@ -39,7 +42,12 @@ pub struct FileFinder {
|
||||||
init_modifiers: Option<Modifiers>,
|
init_modifiers: Option<Modifiers>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn init_settings(cx: &mut AppContext) {
|
||||||
|
FileFinderSettings::register(cx);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
|
init_settings(cx);
|
||||||
cx.observe_new_views(FileFinder::register).detach();
|
cx.observe_new_views(FileFinder::register).detach();
|
||||||
cx.observe_new_views(NewPathPrompt::register).detach();
|
cx.observe_new_views(NewPathPrompt::register).detach();
|
||||||
cx.observe_new_views(OpenPathPrompt::register).detach();
|
cx.observe_new_views(OpenPathPrompt::register).detach();
|
||||||
|
@ -1041,12 +1049,14 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &mut ViewContext<Picker<Self>>,
|
cx: &mut ViewContext<Picker<Self>>,
|
||||||
) -> Option<Self::ListItem> {
|
) -> Option<Self::ListItem> {
|
||||||
|
let settings = FileFinderSettings::get_global(cx);
|
||||||
|
|
||||||
let path_match = self
|
let path_match = self
|
||||||
.matches
|
.matches
|
||||||
.get(ix)
|
.get(ix)
|
||||||
.expect("Invalid matches state: no element for index {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)
|
Match::History { .. } => Icon::new(IconName::HistoryRerun)
|
||||||
.color(Color::Muted)
|
.color(Color::Muted)
|
||||||
.size(IconSize::Small)
|
.size(IconSize::Small)
|
||||||
|
@ -1059,10 +1069,17 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
let (file_name, file_name_positions, full_path, full_path_positions) =
|
let (file_name, file_name_positions, full_path, full_path_positions) =
|
||||||
self.labels_for_match(path_match, cx, ix);
|
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(
|
Some(
|
||||||
ListItem::new(ix)
|
ListItem::new(ix)
|
||||||
.spacing(ListItemSpacing::Sparse)
|
.spacing(ListItemSpacing::Sparse)
|
||||||
.end_slot::<AnyElement>(Some(icon))
|
.start_slot::<Icon>(file_icon)
|
||||||
|
.end_slot::<AnyElement>(history_icon)
|
||||||
.inset(true)
|
.inset(true)
|
||||||
.selected(selected)
|
.selected(selected)
|
||||||
.child(
|
.child(
|
||||||
|
|
27
crates/file_finder/src/file_finder_settings.rs
Normal file
27
crates/file_finder/src/file_finder_settings.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue