diff --git a/Cargo.lock b/Cargo.lock
index 10cfb997adf925df617bbc01d56c9951ee3265e5..3ce94d08b918309552c69950671af25c266cd9be 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5360,6 +5360,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"client",
+ "collections",
"context_menu",
"db",
"drag_and_drop",
diff --git a/assets/icons/file_icons/archive.svg b/assets/icons/file_icons/archive.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f11115cdcee09d1b40317c525cd3d256ea6be557
--- /dev/null
+++ b/assets/icons/file_icons/archive.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/file_icons/book.svg b/assets/icons/file_icons/book.svg
new file mode 100644
index 0000000000000000000000000000000000000000..890b8988a30c703d87a9b27e408ab6730c215fdf
--- /dev/null
+++ b/assets/icons/file_icons/book.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/file_icons/camera.svg b/assets/icons/file_icons/camera.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d8b9cf459c512343d135a5bfe5c8928874cd0862
--- /dev/null
+++ b/assets/icons/file_icons/camera.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/file_icons/code.svg b/assets/icons/file_icons/code.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2733e4b535af74fbf795b51fe8090343396bc953
--- /dev/null
+++ b/assets/icons/file_icons/code.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/file_icons/database.svg b/assets/icons/file_icons/database.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9072e091b5da2feb5d728450a2022d72bf674081
--- /dev/null
+++ b/assets/icons/file_icons/database.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/file_icons/eslint.svg b/assets/icons/file_icons/eslint.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ec5051d4474957e33034d32e79e646124adbe222
--- /dev/null
+++ b/assets/icons/file_icons/eslint.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/file_icons/file.svg b/assets/icons/file_icons/file.svg
new file mode 100644
index 0000000000000000000000000000000000000000..cc422734e77e3e226b2c2452f006163f4de12ea6
--- /dev/null
+++ b/assets/icons/file_icons/file.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/file_icons/file_types.json b/assets/icons/file_icons/file_types.json
new file mode 100644
index 0000000000000000000000000000000000000000..4f3f8160d7e722b23c63c01db387527dd0eb8448
--- /dev/null
+++ b/assets/icons/file_icons/file_types.json
@@ -0,0 +1,149 @@
+{
+ "suffixes": {
+ "aac": "audio",
+ "bash": "terminal",
+ "bmp": "image",
+ "c": "code",
+ "conf": "settings",
+ "cpp": "code",
+ "cc": "code",
+ "css": "code",
+ "doc": "document",
+ "docx": "document",
+ "eslintrc": "eslint",
+ "eslintrc.js": "eslint",
+ "eslintrc.json": "eslint",
+ "flac": "audio",
+ "fish": "terminal",
+ "gitattributes": "vcs",
+ "gitignore": "vcs",
+ "gif": "image",
+ "go": "code",
+ "h": "code",
+ "handlebars": "code",
+ "hbs": "template",
+ "htm": "template",
+ "html": "template",
+ "svelte": "template",
+ "hpp": "code",
+ "ico": "image",
+ "ini": "settings",
+ "java": "code",
+ "jpeg": "image",
+ "jpg": "image",
+ "js": "code",
+ "json": "storage",
+ "lock": "lock",
+ "log": "log",
+ "md": "document",
+ "mdx": "document",
+ "mp3": "audio",
+ "mp4": "video",
+ "ods": "document",
+ "odp": "document",
+ "odt": "document",
+ "ogg": "video",
+ "pdf": "document",
+ "php": "code",
+ "png": "image",
+ "ppt": "document",
+ "pptx": "document",
+ "prettierrc": "prettier",
+ "prettierignore": "prettier",
+ "ps1": "terminal",
+ "psd": "image",
+ "py": "code",
+ "rb": "code",
+ "rkt": "code",
+ "rs": "rust",
+ "rtf": "document",
+ "scm": "code",
+ "sh": "terminal",
+ "bashrc": "terminal",
+ "bash_profile": "terminal",
+ "bash_aliases": "terminal",
+ "bash_logout": "terminal",
+ "profile": "terminal",
+ "zshrc": "terminal",
+ "zshenv": "terminal",
+ "zsh_profile": "terminal",
+ "zsh_aliases": "terminal",
+ "zsh_histfile": "terminal",
+ "zlogin": "terminal",
+ "sql": "code",
+ "svg": "image",
+ "swift": "code",
+ "tiff": "image",
+ "toml": "settings",
+ "ts": "typescript",
+ "tsx": "code",
+ "txt": "document",
+ "wav": "audio",
+ "webm": "video",
+ "xls": "document",
+ "xlsx": "document",
+ "xml": "template",
+ "yaml": "settings",
+ "yml": "settings",
+ "zsh": "terminal"
+ },
+ "types": {
+ "audio": {
+ "icon": "icons/file_icons/file.svg"
+ },
+ "code": {
+ "icon": "icons/file_icons/code.svg"
+ },
+ "default": {
+ "icon": "icons/file_icons/file.svg"
+ },
+ "directory": {
+ "icon": "icons/file_icons/folder.svg"
+ },
+ "document": {
+ "icon": "icons/file_icons/book.svg"
+ },
+ "eslint": {
+ "icon": "icons/file_icons/eslint.svg"
+ },
+ "expanded_directory": {
+ "icon": "icons/file_icons/folder-open.svg"
+ },
+ "image": {
+ "icon": "icons/file_icons/image.svg"
+ },
+ "lock": {
+ "icon": "icons/file_icons/lock.svg"
+ },
+ "log": {
+ "icon": "icons/file_icons/info.svg"
+ },
+ "prettier": {
+ "icon": "icons/file_icons/prettier.svg"
+ },
+ "rust": {
+ "icon": "icons/file_icons/rust.svg"
+ },
+ "settings": {
+ "icon": "icons/file_icons/settings.svg"
+ },
+ "storage": {
+ "icon": "icons/file_icons/database.svg"
+ },
+ "template": {
+ "icon": "icons/file_icons/html.svg"
+ },
+ "terminal": {
+ "icon": "icons/file_icons/terminal.svg"
+ },
+ "typescript": {
+ "icon": "icons/file_icons/typescript.svg"
+ },
+ "vcs": {
+ "icon": "icons/file_icons/git.svg"
+ },
+ "video": {
+ "icon": "icons/file_icons/file.svg"
+ }
+ }
+}
diff --git a/assets/icons/file_icons/folder-open.svg b/assets/icons/file_icons/folder-open.svg
new file mode 100644
index 0000000000000000000000000000000000000000..65c5744049b9c3271fc494fc290ec6a88b9519bf
--- /dev/null
+++ b/assets/icons/file_icons/folder-open.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/file_icons/folder.svg b/assets/icons/file_icons/folder.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5157bae839ef47be384f3d33aa4472f2e5609f6f
--- /dev/null
+++ b/assets/icons/file_icons/folder.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/file_icons/git.svg b/assets/icons/file_icons/git.svg
new file mode 100644
index 0000000000000000000000000000000000000000..82d8c8f57c014e7c2bf679b34dcdf4da0c668049
--- /dev/null
+++ b/assets/icons/file_icons/git.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/file_icons/hash.svg b/assets/icons/file_icons/hash.svg
new file mode 100644
index 0000000000000000000000000000000000000000..edd04626782e52bc2f3c1a73a08f2de166828c33
--- /dev/null
+++ b/assets/icons/file_icons/hash.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/file_icons/html.svg b/assets/icons/file_icons/html.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ba9ec142995d5abb1ce0a66edcd1bc8467773202
--- /dev/null
+++ b/assets/icons/file_icons/html.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/file_icons/image.svg b/assets/icons/file_icons/image.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ee5e49f2d480d0f6f25ecc95b49aff1a5dbf5871
--- /dev/null
+++ b/assets/icons/file_icons/image.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/file_icons/info.svg b/assets/icons/file_icons/info.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e84ae7c6282fc21eb627563aa3512f111bfddac9
--- /dev/null
+++ b/assets/icons/file_icons/info.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/file_icons/lock.svg b/assets/icons/file_icons/lock.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3051bbf801d4fe4f6dd14bc71d924fc9c87a32f6
--- /dev/null
+++ b/assets/icons/file_icons/lock.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/file_icons/notebook.svg b/assets/icons/file_icons/notebook.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6eaec16d0a34ec83aec053f6387049c2fc7a6f0e
--- /dev/null
+++ b/assets/icons/file_icons/notebook.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/file_icons/package.svg b/assets/icons/file_icons/package.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2a692ba4b4d1f89bfce502ce9a7354dde7c90459
--- /dev/null
+++ b/assets/icons/file_icons/package.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/file_icons/prettier.svg b/assets/icons/file_icons/prettier.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2d2c6ee7193e5d6c6a281f777b13fa4ed55c6bf2
--- /dev/null
+++ b/assets/icons/file_icons/prettier.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/icons/file_icons/rust.svg b/assets/icons/file_icons/rust.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1802f0e190d86041be658afda706b5bc36db1644
--- /dev/null
+++ b/assets/icons/file_icons/rust.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/file_icons/settings.svg b/assets/icons/file_icons/settings.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e827055d1972ffd657fcc6129775a66be37d8e5f
--- /dev/null
+++ b/assets/icons/file_icons/settings.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/file_icons/terminal.svg b/assets/icons/file_icons/terminal.svg
new file mode 100644
index 0000000000000000000000000000000000000000..939587c53ecc97042821439590ab49ff2f980853
--- /dev/null
+++ b/assets/icons/file_icons/terminal.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/file_icons/typescript.svg b/assets/icons/file_icons/typescript.svg
new file mode 100644
index 0000000000000000000000000000000000000000..179b3d85724edb25889a62b80d1bd46d510fde5e
--- /dev/null
+++ b/assets/icons/file_icons/typescript.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/settings/default.json b/assets/settings/default.json
index 5cf5f59f76239cbe22738e9471606a883cd5b98e..e1f2d932705003342ed75ddbd125d0b3c3436ef3 100644
--- a/assets/settings/default.json
+++ b/assets/settings/default.json
@@ -99,6 +99,8 @@
"project_panel": {
// Whether to show the git status in the project panel.
"git_status": true,
+ // Whether to show file icons in the project panel.
+ "file_icons": true,
// Where to dock project panel. Can be 'left' or 'right'.
"dock": "left",
// Default width of the project panel.
diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml
index 33606fccc41854e3ae767fc691cd0edf15f047e2..4fe5372a519ab9e67803c7b5eda89d273f257202 100644
--- a/crates/project_panel/Cargo.toml
+++ b/crates/project_panel/Cargo.toml
@@ -10,6 +10,7 @@ doctest = false
[dependencies]
context_menu = { path = "../context_menu" }
+collections = { path = "../collections" }
db = { path = "../db" }
drag_and_drop = { path = "../drag_and_drop" }
editor = { path = "../editor" }
diff --git a/crates/project_panel/src/file_associations.rs b/crates/project_panel/src/file_associations.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6e2e373d766b02c04fb4ecd9cf4a4ba2cc0d3a0c
--- /dev/null
+++ b/crates/project_panel/src/file_associations.rs
@@ -0,0 +1,84 @@
+use std::{path::Path, str, sync::Arc};
+
+use collections::HashMap;
+
+use gpui::{AppContext, AssetSource};
+use serde_derive::Deserialize;
+use util::iife;
+
+#[derive(Deserialize, Debug)]
+struct TypeConfig {
+ icon: Arc,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct FileAssociations {
+ suffixes: HashMap,
+ types: HashMap,
+}
+
+const DIRECTORY_TYPE: &'static str = "directory";
+const EXPANDED_DIRECTORY_TYPE: &'static str = "expanded_directory";
+pub const FILE_TYPES_ASSET: &'static str = "icons/file_icons/file_types.json";
+
+pub fn init(assets: impl AssetSource, cx: &mut AppContext) {
+ cx.set_global(FileAssociations::new(assets))
+}
+
+impl FileAssociations {
+ pub fn new(assets: impl AssetSource) -> Self {
+ assets
+ .load("icons/file_icons/file_types.json")
+ .and_then(|file| {
+ serde_json::from_str::(str::from_utf8(&file).unwrap())
+ .map_err(Into::into)
+ })
+ .unwrap_or_else(|_| FileAssociations {
+ suffixes: HashMap::default(),
+ types: HashMap::default(),
+ })
+ }
+
+ pub fn get_icon(path: &Path, cx: &AppContext) -> Arc {
+ iife!({
+ let this = cx.has_global::().then(|| cx.global::())?;
+
+ // FIXME: Associate a type with the languages and have the file's langauge
+ // override these associations
+ iife!({
+ let suffix = path
+ .file_name()
+ .and_then(|os_str| os_str.to_str())
+ .and_then(|file_name| {
+ file_name
+ .find('.')
+ .and_then(|dot_index| file_name.get(dot_index + 1..))
+ })?;
+
+ this.suffixes
+ .get(suffix)
+ .and_then(|type_str| this.types.get(type_str))
+ .map(|type_config| type_config.icon.clone())
+ })
+ .or_else(|| this.types.get("default").map(|config| config.icon.clone()))
+ })
+ .unwrap_or_else(|| Arc::from("".to_string()))
+ }
+
+ pub fn get_folder_icon(expanded: bool, cx: &AppContext) -> Arc {
+ iife!({
+ let this = cx.has_global::().then(|| cx.global::())?;
+
+ let key = if expanded {
+ EXPANDED_DIRECTORY_TYPE
+ } else {
+ DIRECTORY_TYPE
+ };
+
+ this.types
+ .get(key)
+ .map(|type_config| type_config.icon.clone())
+ })
+ .unwrap_or_else(|| Arc::from("".to_string()))
+ }
+}
diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs
index 5442a8be7456f08cb3d5f494ca0bcba9ffbaa1c7..d97c47a339dfde546550fc9b70ebc75659f416a6 100644
--- a/crates/project_panel/src/project_panel.rs
+++ b/crates/project_panel/src/project_panel.rs
@@ -1,9 +1,12 @@
+pub mod file_associations;
mod project_panel_settings;
use context_menu::{ContextMenu, ContextMenuItem};
use db::kvp::KEY_VALUE_STORE;
use drag_and_drop::{DragAndDrop, Draggable};
use editor::{Cancel, Editor};
+use file_associations::FileAssociations;
+
use futures::stream::StreamExt;
use gpui::{
actions,
@@ -15,8 +18,8 @@ use gpui::{
geometry::vector::Vector2F,
keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton, PromptLevel},
- Action, AnyElement, AppContext, AsyncAppContext, ClipboardItem, Element, Entity, ModelHandle,
- Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
+ Action, AnyElement, AppContext, AssetSource, AsyncAppContext, ClipboardItem, Element, Entity,
+ ModelHandle, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
};
use menu::{Confirm, SelectNext, SelectPrev};
use project::{
@@ -94,6 +97,7 @@ pub enum ClipboardEntry {
#[derive(Debug, PartialEq, Eq)]
pub struct EntryDetails {
filename: String,
+ icon: Option>,
path: Arc,
depth: usize,
kind: EntryKind,
@@ -129,8 +133,9 @@ pub fn init_settings(cx: &mut AppContext) {
settings::register::(cx);
}
-pub fn init(cx: &mut AppContext) {
+pub fn init(assets: impl AssetSource, cx: &mut AppContext) {
init_settings(cx);
+ file_associations::init(assets, cx);
cx.add_action(ProjectPanel::expand_selected_entry);
cx.add_action(ProjectPanel::collapse_selected_entry);
cx.add_action(ProjectPanel::select_prev);
@@ -230,6 +235,11 @@ impl ProjectPanel {
})
.detach();
+ cx.observe_global::(|_, cx| {
+ cx.notify();
+ })
+ .detach();
+
let view_id = cx.view_id();
let mut this = Self {
project: project.clone(),
@@ -1166,7 +1176,10 @@ impl ProjectPanel {
}
let end_ix = range.end.min(ix + visible_worktree_entries.len());
- let git_status_setting = settings::get::(cx).git_status;
+ let (git_status_setting, show_file_icons) = {
+ let settings = settings::get::(cx);
+ (settings.git_status, settings.file_icons)
+ };
if let Some(worktree) = self.project.read(cx).worktree_for_id(*worktree_id, cx) {
let snapshot = worktree.read(cx).snapshot();
let root_name = OsStr::new(snapshot.root_name());
@@ -1179,6 +1192,11 @@ impl ProjectPanel {
let entry_range = range.start.saturating_sub(ix)..end_ix - ix;
for entry in visible_worktree_entries[entry_range].iter() {
let status = git_status_setting.then(|| entry.git_status).flatten();
+ let is_expanded = expanded_entry_ids.binary_search(&entry.id).is_ok();
+ let icon = show_file_icons.then(|| match entry.kind {
+ EntryKind::File(_) => FileAssociations::get_icon(&entry.path, cx),
+ _ => FileAssociations::get_folder_icon(is_expanded, cx),
+ });
let mut details = EntryDetails {
filename: entry
@@ -1187,11 +1205,12 @@ impl ProjectPanel {
.unwrap_or(root_name)
.to_string_lossy()
.to_string(),
+ icon,
path: entry.path.clone(),
depth: entry.path.components().count(),
kind: entry.kind,
is_ignored: entry.is_ignored,
- is_expanded: expanded_entry_ids.binary_search(&entry.id).is_ok(),
+ is_expanded,
is_selected: self.selection.map_or(false, |e| {
e.worktree_id == snapshot.id() && e.entry_id == entry.id
}),
@@ -1254,23 +1273,36 @@ impl ProjectPanel {
.unwrap_or(style.text.color);
Flex::row()
- .with_child(
- if kind.is_dir() {
- if details.is_expanded {
- Svg::new("icons/chevron_down_8.svg").with_color(style.icon_color)
- } else {
- Svg::new("icons/chevron_right_8.svg").with_color(style.icon_color)
- }
+ .with_child(if let Some(icon) = &details.icon {
+ Svg::new(icon.to_string())
+ .with_color(style.icon_color)
+ .constrained()
+ .with_max_width(style.icon_size)
+ .with_max_height(style.icon_size)
+ .aligned()
.constrained()
+ .with_width(style.icon_size)
+ } else if kind.is_dir() {
+ if details.is_expanded {
+ Svg::new("icons/chevron_down_8.svg").with_color(style.chevron_color)
} else {
- Empty::new().constrained()
+ Svg::new("icons/chevron_right_8.svg").with_color(style.chevron_color)
}
- .with_max_width(style.icon_size)
- .with_max_height(style.icon_size)
+ .constrained()
+ .with_max_width(style.chevron_size)
+ .with_max_height(style.chevron_size)
.aligned()
.constrained()
- .with_width(style.icon_size),
- )
+ .with_width(style.chevron_size)
+ } else {
+ Empty::new()
+ .constrained()
+ .with_max_width(style.chevron_size)
+ .with_max_height(style.chevron_size)
+ .aligned()
+ .constrained()
+ .with_width(style.chevron_size)
+ })
.with_child(if show_editor && editor.is_some() {
ChildView::new(editor.as_ref().unwrap(), cx)
.contained()
@@ -2581,7 +2613,7 @@ mod tests {
theme::init((), cx);
language::init(cx);
editor::init_settings(cx);
- crate::init(cx);
+ crate::init((), cx);
workspace::init_settings(cx);
Project::init_settings(cx);
});
@@ -2596,7 +2628,7 @@ mod tests {
language::init(cx);
editor::init(cx);
pane::init(cx);
- crate::init(cx);
+ crate::init((), cx);
workspace::init(app_state.clone(), cx);
Project::init_settings(cx);
});
diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs
index 1d6c590710b5b783b6acbfe27e89903de5ad3f69..f0d60d7f4fc0505103c524c2a59022e17772a59d 100644
--- a/crates/project_panel/src/project_panel_settings.rs
+++ b/crates/project_panel/src/project_panel_settings.rs
@@ -13,6 +13,7 @@ pub enum ProjectPanelDockPosition {
#[derive(Deserialize, Debug)]
pub struct ProjectPanelSettings {
pub git_status: bool,
+ pub file_icons: bool,
pub dock: ProjectPanelDockPosition,
pub default_width: f32,
}
@@ -20,6 +21,7 @@ pub struct ProjectPanelSettings {
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
pub struct ProjectPanelSettingsContent {
pub git_status: Option,
+ pub file_icons: Option,
pub dock: Option,
pub default_width: Option,
}
diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs
index b7a7408bef1f0ad6c5afe9748f1f6033f72e5f6d..29c0d9ce8ebbd515a85dfd149504ed22d2fd7691 100644
--- a/crates/theme/src/theme.rs
+++ b/crates/theme/src/theme.rs
@@ -480,8 +480,10 @@ pub struct ProjectPanelEntry {
#[serde(flatten)]
pub container: ContainerStyle,
pub text: TextStyle,
- pub icon_color: Color,
pub icon_size: f32,
+ pub icon_color: Color,
+ pub chevron_color: Color,
+ pub chevron_size: f32,
pub icon_spacing: f32,
pub status: EntryStatus,
}
diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs
index 8f528771c9ed95cb95ce7d25ce4e8a2762cac1ea..ea019a0fdd6361557d0b53c50f3215e0e8a9f895 100644
--- a/crates/zed/src/main.rs
+++ b/crates/zed/src/main.rs
@@ -154,7 +154,7 @@ fn main() {
file_finder::init(cx);
outline::init(cx);
project_symbols::init(cx);
- project_panel::init(cx);
+ project_panel::init(Assets, cx);
diagnostics::init(cx);
search::init(cx);
vector_store::init(fs.clone(), http.clone(), languages.clone(), cx);
@@ -166,6 +166,7 @@ fn main() {
cx.spawn(|cx| watch_themes(fs.clone(), cx)).detach();
cx.spawn(|_| watch_languages(fs.clone(), languages.clone()))
.detach();
+ watch_file_types(fs.clone(), cx);
languages.set_theme(theme::current(cx).clone());
cx.observe_global::({
@@ -685,6 +686,26 @@ async fn watch_languages(fs: Arc, languages: Arc) -> O
Some(())
}
+#[cfg(debug_assertions)]
+fn watch_file_types(fs: Arc, cx: &mut AppContext) {
+ cx.spawn(|mut cx| async move {
+ let mut events = fs
+ .watch(
+ "assets/icons/file_icons/file_types.json".as_ref(),
+ Duration::from_millis(100),
+ )
+ .await;
+ while (events.next().await).is_some() {
+ cx.update(|cx| {
+ cx.update_global(|file_types, _| {
+ *file_types = project_panel::file_associations::FileAssociations::new(Assets);
+ });
+ })
+ }
+ })
+ .detach()
+}
+
#[cfg(not(debug_assertions))]
async fn watch_themes(_fs: Arc, _cx: AsyncAppContext) -> Option<()> {
None
@@ -695,6 +716,11 @@ async fn watch_languages(_: Arc, _: Arc) -> Option<()>
None
}
+#[cfg(not(debug_assertions))]
+fn watch_file_types(fs: Arc, cx: &mut AppContext) {
+ None
+}
+
fn connect_to_cli(
server_name: &str,
) -> Result<(mpsc::Receiver, IpcSender)> {
diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs
index 9dffc644ae7fd63a5a722db94fd4bdb25a979a99..6bbba0bd02b7da005c9711d00591952baf2594ae 100644
--- a/crates/zed/src/zed.rs
+++ b/crates/zed/src/zed.rs
@@ -2334,7 +2334,7 @@ mod tests {
editor::init(cx);
project_panel::init_settings(cx);
pane::init(cx);
- project_panel::init(cx);
+ project_panel::init((), cx);
terminal_view::init(cx);
ai::init(cx);
app_state
diff --git a/script/generate-licenses b/script/generate-licenses
index 14c9d4c79f1646d4889da82d9ee24c7975003532..9a2fe8921a8fe06e4716b98bcec9b2b28af4a994 100755
--- a/script/generate-licenses
+++ b/script/generate-licenses
@@ -26,4 +26,4 @@ sed -i '' 's/'/'\''/g' $OUTPUT_FILE # The ` '\'' ` thing ends the string, a
sed -i '' 's/=/=/g' $OUTPUT_FILE
sed -i '' 's/`/`/g' $OUTPUT_FILE
sed -i '' 's/<//g' $OUTPUT_FILE
\ No newline at end of file
+sed -i '' 's/>/>/g' $OUTPUT_FILE
diff --git a/styles/src/style_tree/project_panel.ts b/styles/src/style_tree/project_panel.ts
index af997d0a6e8099a0b8449bf0685df1dd4a0a4eda..e239f9a84023088d988f74e709c6485ade8a9510 100644
--- a/styles/src/style_tree/project_panel.ts
+++ b/styles/src/style_tree/project_panel.ts
@@ -46,9 +46,11 @@ export default function project_panel(): any {
const base_properties = {
height: 22,
background: background(theme.middle),
- icon_color: foreground(theme.middle, "variant"),
- icon_size: 7,
- icon_spacing: 5,
+ chevron_color: foreground(theme.middle, "variant"),
+ icon_color: with_opacity(foreground(theme.middle, "active"), 0.3),
+ chevron_size: 7,
+ icon_size: 14,
+ icon_spacing: 6,
text: text(theme.middle, "sans", "variant", { size: "sm" }),
status: {
...git_status,
@@ -62,17 +64,17 @@ export default function project_panel(): any {
const unselected_default_style = merge(
base_properties,
unselected?.default ?? {},
- {}
+ {},
)
const unselected_hovered_style = merge(
base_properties,
{ background: background(theme.middle, "hovered") },
- unselected?.hovered ?? {}
+ unselected?.hovered ?? {},
)
const unselected_clicked_style = merge(
base_properties,
{ background: background(theme.middle, "pressed") },
- unselected?.clicked ?? {}
+ unselected?.clicked ?? {},
)
const selected_default_style = merge(
base_properties,
@@ -80,7 +82,7 @@ export default function project_panel(): any {
background: background(theme.lowest),
text: text(theme.lowest, "sans", { size: "sm" }),
},
- selected_style?.default ?? {}
+ selected_style?.default ?? {},
)
const selected_hovered_style = merge(
base_properties,
@@ -88,7 +90,7 @@ export default function project_panel(): any {
background: background(theme.lowest, "hovered"),
text: text(theme.lowest, "sans", { size: "sm" }),
},
- selected_style?.hovered ?? {}
+ selected_style?.hovered ?? {},
)
const selected_clicked_style = merge(
base_properties,
@@ -96,7 +98,7 @@ export default function project_panel(): any {
background: background(theme.lowest, "pressed"),
text: text(theme.lowest, "sans", { size: "sm" }),
},
- selected_style?.clicked ?? {}
+ selected_style?.clicked ?? {},
)
return toggleable({
@@ -155,7 +157,7 @@ export default function project_panel(): any {
}),
background: background(theme.middle),
padding: { left: 6, right: 6, top: 0, bottom: 6 },
- indent_width: 12,
+ indent_width: 20,
entry: default_entry,
dragged_entry: {
...default_entry.inactive.default,
@@ -173,7 +175,7 @@ export default function project_panel(): any {
default: {
icon_color: foreground(theme.middle, "variant"),
},
- }
+ },
),
cut_entry: entry(
{
@@ -188,7 +190,7 @@ export default function project_panel(): any {
size: "sm",
}),
},
- }
+ },
),
filename_editor: {
background: background(theme.middle, "on"),