Detailed changes
@@ -43,10 +43,6 @@ Zed's default icon theme consists of icons that are hand-designed to fit togethe
We do not accept PRs for file icons that are just an off-the-shelf SVG taken from somewhere else.
-### File icon associations
-
-We will happily accept PRs that add new file icon associations to [`file_types.json`](assets/icons/file_icons/file_types.json) to allow them to be targeted by [icon themes](https://zed.dev/docs/extensions/icon-themes).
-
### Adding new icons to the Zed icon theme
If you would like to add a new icon to the Zed icon theme, [open a Discussion](https://github.com/zed-industries/zed/discussions/new?category=ux-and-design) and we can work with you on getting an icon designed and added to Zed.
@@ -4704,11 +4704,8 @@ dependencies = [
name = "file_icons"
version = "0.1.0"
dependencies = [
- "collections",
"gpui",
"serde",
- "serde_derive",
- "serde_json",
"settings",
"theme",
"util",
@@ -16680,7 +16677,6 @@ dependencies = [
"feature_flags",
"feedback",
"file_finder",
- "file_icons",
"fs",
"futures 0.3.31",
"git",
@@ -1,260 +0,0 @@
-{
- "stems": {
- "Dockerfile": "docker",
- "Podfile": "ruby",
- "Procfile": "heroku"
- },
- "suffixes": {
- "COMMIT_EDITMSG": "vcs",
- "EDIT_DESCRIPTION": "vcs",
- "Emakefile": "erlang",
- "MERGE_MSG": "vcs",
- "NOTES_EDITMSG": "vcs",
- "R": "r",
- "TAG_EDITMSG": "vcs",
- "aac": "audio",
- "accdb": "storage",
- "app.src": "erlang",
- "astro": "astro",
- "avi": "video",
- "avif": "image",
- "bak": "backup",
- "bash": "terminal",
- "bash_aliases": "terminal",
- "bash_logout": "terminal",
- "bash_profile": "terminal",
- "bashrc": "terminal",
- "bicep": "bicep",
- "bmp": "image",
- "c": "c",
- "c++": "cpp",
- "cc": "cpp",
- "cjs": "javascript",
- "cjsx": "react",
- "coffee": "coffeescript",
- "conf": "settings",
- "cpp": "cpp",
- "cr": "crystal",
- "cs": "csharp",
- "csproj": "csproj",
- "css": "css",
- "csv": "storage",
- "cts": "typescript",
- "ctsx": "react",
- "cue": "cue",
- "cxx": "cpp",
- "dart": "dart",
- "dat": "storage",
- "db": "storage",
- "dbf": "storage",
- "diff": "diff",
- "dll": "storage",
- "doc": "document",
- "docx": "document",
- "ecr": "crystal",
- "eex": "elixir",
- "elm": "elm",
- "erl": "erlang",
- "escript": "erlang",
- "eslint.config.cjs": "eslint",
- "eslint.config.cts": "eslint",
- "eslint.config.js": "eslint",
- "eslint.config.mjs": "eslint",
- "eslint.config.mts": "eslint",
- "eslint.config.ts": "eslint",
- "eslintrc": "eslint",
- "eslintrc.js": "eslint",
- "eslintrc.json": "eslint",
- "ex": "elixir",
- "exs": "elixir",
- "fish": "terminal",
- "flac": "audio",
- "fmp": "storage",
- "fp7": "storage",
- "frm": "storage",
- "fs": "fsharp",
- "fsproj": "fsproj",
- "gdb": "storage",
- "gif": "image",
- "gitattributes": "vcs",
- "gitignore": "vcs",
- "gitkeep": "vcs",
- "gitlab-ci.yml": "gitlab",
- "gitmodules": "vcs",
- "gleam": "gleam",
- "go": "go",
- "gql": "graphql",
- "graphql": "graphql",
- "graphqls": "graphql",
- "h": "c",
- "handlebars": "code",
- "hbs": "template",
- "hcl": "hcl",
- "heex": "elixir",
- "heic": "image",
- "heif": "image",
- "hh": "cpp",
- "hpp": "cpp",
- "hrl": "erlang",
- "hs": "haskell",
- "htm": "html",
- "html": "html",
- "hxx": "cpp",
- "ib": "storage",
- "ico": "image",
- "ini": "settings",
- "inl": "cpp",
- "j2k": "image",
- "java": "java",
- "jfif": "image",
- "jl": "julia",
- "jp2": "image",
- "jpeg": "image",
- "jpg": "image",
- "js": "javascript",
- "json": "json",
- "jsonc": "storage",
- "jsx": "react",
- "jxl": "image",
- "kt": "kotlin",
- "ldf": "storage",
- "lock": "lock",
- "lockb": "bun",
- "log": "log",
- "lua": "lua",
- "luau": "luau",
- "m4a": "audio",
- "m4v": "video",
- "markdown": "markdown",
- "md": "markdown",
- "mdb": "storage",
- "mdf": "storage",
- "mdx": "document",
- "metadata": "code",
- "metal": "metal",
- "mjs": "javascript",
- "mjsx": "react",
- "mka": "audio",
- "mkv": "video",
- "ml": "ocaml",
- "mli": "ocaml",
- "mod": "go",
- "mov": "video",
- "mp3": "audio",
- "mp4": "video",
- "mts": "typescript",
- "mtsx": "react",
- "myd": "storage",
- "myi": "storage",
- "nim": "nim",
- "nix": "nix",
- "nu": "terminal",
- "odp": "document",
- "ods": "document",
- "odt": "document",
- "ogg": "audio",
- "opus": "audio",
- "otf": "font",
- "pcss": "css",
- "pdb": "storage",
- "pdf": "document",
- "php": "php",
- "plist": "template",
- "png": "image",
- "postcss": "css",
- "ppt": "document",
- "pptx": "document",
- "prettier.config.cjs": "prettier",
- "prettier.config.js": "prettier",
- "prettier.config.mjs": "prettier",
- "prettierignore": "prettier",
- "prettierrc": "prettier",
- "prettierrc.cjs": "prettier",
- "prettierrc.js": "prettier",
- "prettierrc.json": "prettier",
- "prettierrc.json5": "prettier",
- "prettierrc.mjs": "prettier",
- "prettierrc.toml": "prettier",
- "prettierrc.yaml": "prettier",
- "prettierrc.yml": "prettier",
- "prisma": "prisma",
- "profile": "terminal",
- "ps1": "terminal",
- "psd": "image",
- "py": "python",
- "qoi": "image",
- "r": "r",
- "rb": "ruby",
- "rebar.config": "erlang",
- "rkt": "code",
- "roc": "roc",
- "rs": "rust",
- "rtf": "document",
- "sass": "sass",
- "sav": "storage",
- "sc": "scala",
- "scala": "scala",
- "scm": "code",
- "scss": "sass",
- "sdf": "storage",
- "sh": "terminal",
- "sln": "vs_sln",
- "sol": "solidity",
- "sql": "storage",
- "sqlite": "storage",
- "stylelint.config.cjs": "stylelint",
- "stylelint.config.js": "stylelint",
- "stylelint.config.mjs": "stylelint",
- "stylelintignore": "stylelint",
- "stylelintrc": "stylelint",
- "stylelintrc.cjs": "stylelint",
- "stylelintrc.js": "stylelint",
- "stylelintrc.json": "stylelint",
- "stylelintrc.mjs": "stylelint",
- "stylelintrc.yaml": "stylelint",
- "stylelintrc.yml": "stylelint",
- "suo": "vs_suo",
- "svelte": "svelte",
- "svg": "image",
- "swift": "swift",
- "tcl": "tcl",
- "tf": "terraform",
- "tfvars": "terraform",
- "tiff": "image",
- "toml": "toml",
- "ts": "typescript",
- "tsv": "storage",
- "tsx": "react",
- "ttf": "font",
- "txt": "document",
- "v": "v",
- "vbproj": "vbproj",
- "vsh": "v",
- "vue": "vue",
- "vv": "v",
- "wav": "audio",
- "webm": "video",
- "webp": "image",
- "wma": "audio",
- "wmv": "video",
- "woff": "font",
- "woff2": "font",
- "work": "go",
- "wv": "audio",
- "xls": "document",
- "xlsx": "document",
- "xml": "template",
- "xrl": "erlang",
- "yaml": "settings",
- "yml": "settings",
- "yrl": "erlang",
- "zig": "zig",
- "zlogin": "terminal",
- "zsh": "terminal",
- "zsh_aliases": "terminal",
- "zsh_histfile": "terminal",
- "zsh_profile": "terminal",
- "zshenv": "terminal",
- "zshrc": "terminal"
- }
-}
@@ -13,11 +13,8 @@ path = "src/file_icons.rs"
doctest = false
[dependencies]
-collections.workspace = true
gpui.workspace = true
serde.workspace = true
-serde_derive.workspace = true
-serde_json.workspace = true
settings.workspace = true
theme.workspace = true
util.workspace = true
@@ -1,52 +1,33 @@
use std::sync::Arc;
use std::{path::Path, str};
-use collections::HashMap;
-
-use gpui::{App, AssetSource, Global, SharedString};
-use serde_derive::Deserialize;
+use gpui::{App, SharedString};
use settings::Settings;
use theme::{IconTheme, ThemeRegistry, ThemeSettings};
use util::paths::PathExt;
-#[derive(Deserialize, Debug)]
+#[derive(Debug)]
pub struct FileIcons {
- stems: HashMap<String, String>,
- suffixes: HashMap<String, String>,
-}
-
-impl Global for FileIcons {}
-
-pub const FILE_TYPES_ASSET: &str = "icons/file_icons/file_types.json";
-
-pub fn init(assets: impl AssetSource, cx: &mut App) {
- cx.set_global(FileIcons::new(assets))
+ icon_theme: Arc<IconTheme>,
}
impl FileIcons {
- pub fn get(cx: &App) -> &Self {
- cx.global::<FileIcons>()
- }
+ pub fn get(cx: &App) -> Self {
+ let theme_settings = ThemeSettings::get_global(cx);
- pub fn new(assets: impl AssetSource) -> Self {
- assets
- .load(FILE_TYPES_ASSET)
- .ok()
- .flatten()
- .and_then(|file| serde_json::from_str::<FileIcons>(str::from_utf8(&file).unwrap()).ok())
- .unwrap_or_else(|| FileIcons {
- stems: HashMap::default(),
- suffixes: HashMap::default(),
- })
+ Self {
+ icon_theme: theme_settings.active_icon_theme.clone(),
+ }
}
pub fn get_icon(path: &Path, cx: &App) -> Option<SharedString> {
- let this = cx.try_global::<Self>()?;
+ let this = Self::get(cx);
let get_icon_from_suffix = |suffix: &str| -> Option<SharedString> {
- this.stems
+ this.icon_theme
+ .file_stems
.get(suffix)
- .or_else(|| this.suffixes.get(suffix))
+ .or_else(|| this.icon_theme.file_suffixes.get(suffix))
.and_then(|typ| this.get_icon_for_type(typ, cx))
};
// TODO: Associate a type with the languages and have the file's language
@@ -28,12 +28,12 @@ use file_icons::FileIcons;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
actions, anchored, deferred, div, point, px, size, uniform_list, Action, AnyElement, App,
- AppContext as _, AssetSource, AsyncWindowContext, Bounds, ClipboardItem, Context, DismissEvent,
- Div, ElementId, Entity, EventEmitter, FocusHandle, Focusable, HighlightStyle,
- InteractiveElement, IntoElement, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior,
- MouseButton, MouseDownEvent, ParentElement, Pixels, Point, Render, ScrollStrategy,
- SharedString, Stateful, StatefulInteractiveElement as _, Styled, Subscription, Task,
- UniformListScrollHandle, WeakEntity, Window,
+ AppContext as _, AsyncWindowContext, Bounds, ClipboardItem, Context, DismissEvent, Div,
+ ElementId, Entity, EventEmitter, FocusHandle, Focusable, HighlightStyle, InteractiveElement,
+ IntoElement, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior, MouseButton,
+ MouseDownEvent, ParentElement, Pixels, Point, Render, ScrollStrategy, SharedString, Stateful,
+ StatefulInteractiveElement as _, Styled, Subscription, Task, UniformListScrollHandle,
+ WeakEntity, Window,
};
use itertools::Itertools;
use language::{BufferId, BufferSnapshot, OffsetRangeExt, OutlineItem};
@@ -664,9 +664,8 @@ pub fn init_settings(cx: &mut App) {
OutlinePanelSettings::register(cx);
}
-pub fn init(assets: impl AssetSource, cx: &mut App) {
+pub fn init(cx: &mut App) {
init_settings(cx);
- file_icons::init(assets, cx);
cx.observe_new(|workspace: &mut Workspace, _, _| {
workspace.register_action(|workspace, _: &ToggleFocus, window, cx| {
@@ -6641,7 +6640,7 @@ outline: struct OutlineEntryExcerpt
workspace::init_settings(cx);
Project::init_settings(cx);
project_search::init(cx);
- super::init((), cx);
+ super::init(cx);
});
}
@@ -18,8 +18,8 @@ use file_icons::FileIcons;
use git::status::GitSummary;
use gpui::{
actions, anchored, deferred, div, impl_actions, point, px, size, uniform_list, Action,
- AnyElement, App, AssetSource, AsyncWindowContext, Bounds, ClipboardItem, Context, DismissEvent,
- Div, DragMoveEvent, Entity, EventEmitter, ExternalPaths, FocusHandle, Focusable, Hsla,
+ AnyElement, App, AsyncWindowContext, Bounds, ClipboardItem, Context, DismissEvent, Div,
+ DragMoveEvent, Entity, EventEmitter, ExternalPaths, FocusHandle, Focusable, Hsla,
InteractiveElement, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior, MouseButton,
MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, ScrollStrategy, Stateful,
Styled, Subscription, Task, UniformListScrollHandle, WeakEntity, Window,
@@ -225,9 +225,8 @@ pub fn init_settings(cx: &mut App) {
ProjectPanelSettings::register(cx);
}
-pub fn init(assets: impl AssetSource, cx: &mut App) {
+pub fn init(cx: &mut App) {
init_settings(cx);
- file_icons::init(assets, cx);
cx.observe_new(|workspace: &mut Workspace, _, _| {
workspace.register_action(|workspace, _: &ToggleFocus, window, cx| {
@@ -9484,7 +9483,7 @@ mod tests {
theme::init(theme::LoadThemes::JustBase, cx);
language::init(cx);
editor::init_settings(cx);
- crate::init((), cx);
+ crate::init(cx);
workspace::init_settings(cx);
client::init_settings(cx);
Project::init_settings(cx);
@@ -9507,7 +9506,7 @@ mod tests {
init_settings(cx);
language::init(cx);
editor::init(cx);
- crate::init((), cx);
+ crate::init(cx);
workspace::init(app_state.clone(), cx);
Project::init_settings(cx);
@@ -455,7 +455,6 @@ mod tests {
pub(crate) fn init_test(cx: &mut TestAppContext) -> Arc<AppState> {
cx.update(|cx| {
let state = AppState::test(cx);
- file_icons::init((), cx);
language::init(cx);
crate::init(cx);
editor::init(cx);
@@ -1,3 +1,5 @@
+use std::sync::{Arc, LazyLock};
+
use collections::HashMap;
use gpui::SharedString;
@@ -28,7 +30,11 @@ pub struct IconTheme {
pub directory_icons: DirectoryIcons,
/// The icons used for chevrons.
pub chevron_icons: ChevronIcons,
- /// The mapping of file types to icon definitions.
+ /// The mapping of file stems to their associated icon keys.
+ pub file_stems: HashMap<String, String>,
+ /// The mapping of file suffixes to their associated icon keys.
+ pub file_suffixes: HashMap<String, String>,
+ /// The mapping of icon keys to icon definitions.
pub file_icons: HashMap<String, IconDefinition>,
}
@@ -57,6 +63,209 @@ pub struct IconDefinition {
pub path: SharedString,
}
+const FILE_STEMS_BY_ICON_KEY: &[(&str, &[&str])] = &[
+ ("docker", &["Dockerfile"]),
+ ("ruby", &["Podfile"]),
+ ("heroku", &["Procfile"]),
+];
+
+const FILE_SUFFIXES_BY_ICON_KEY: &[(&str, &[&str])] = &[
+ ("astro", &["astro"]),
+ (
+ "audio",
+ &[
+ "aac", "flac", "m4a", "mka", "mp3", "ogg", "opus", "wav", "wma", "wv",
+ ],
+ ),
+ ("backup", &["bak"]),
+ ("bicep", &["bicep"]),
+ ("bun", &["lockb"]),
+ ("c", &["c", "h"]),
+ ("code", &["handlebars", "metadata", "rkt", "scm"]),
+ ("coffeescript", &["coffee"]),
+ (
+ "cpp",
+ &["c++", "cc", "cpp", "cxx", "hh", "hpp", "hxx", "inl"],
+ ),
+ ("crystal", &["cr", "ecr"]),
+ ("csharp", &["cs"]),
+ ("csproj", &["csproj"]),
+ ("css", &["css", "pcss", "postcss"]),
+ ("cue", &["cue"]),
+ ("dart", &["dart"]),
+ ("diff", &["diff"]),
+ (
+ "document",
+ &[
+ "doc", "docx", "mdx", "odp", "ods", "odt", "pdf", "ppt", "pptx", "rtf", "txt", "xls",
+ "xlsx",
+ ],
+ ),
+ ("elixir", &["eex", "ex", "exs", "heex"]),
+ ("elm", &["elm"]),
+ (
+ "erlang",
+ &[
+ "Emakefile",
+ "app.src",
+ "erl",
+ "escript",
+ "hrl",
+ "rebar.config",
+ "xrl",
+ "yrl",
+ ],
+ ),
+ (
+ "eslint",
+ &[
+ "eslint.config.cjs",
+ "eslint.config.cts",
+ "eslint.config.js",
+ "eslint.config.mjs",
+ "eslint.config.mts",
+ "eslint.config.ts",
+ "eslintrc",
+ "eslintrc.js",
+ "eslintrc.json",
+ ],
+ ),
+ ("font", &["otf", "ttf", "woff", "woff2"]),
+ ("fsharp", &["fs"]),
+ ("fsproj", &["fsproj"]),
+ ("gitlab", &["gitlab-ci.yml"]),
+ ("gleam", &["gleam"]),
+ ("go", &["go", "mod", "work"]),
+ ("graphql", &["gql", "graphql", "graphqls"]),
+ ("haskell", &["hs"]),
+ ("hcl", &["hcl"]),
+ ("html", &["htm", "html"]),
+ (
+ "image",
+ &[
+ "avif", "bmp", "gif", "heic", "heif", "ico", "j2k", "jfif", "jp2", "jpeg", "jpg",
+ "jxl", "png", "psd", "qoi", "svg", "tiff", "webp",
+ ],
+ ),
+ ("java", &["java"]),
+ ("javascript", &["cjs", "js", "mjs"]),
+ ("json", &["json"]),
+ ("julia", &["jl"]),
+ ("kotlin", &["kt"]),
+ ("lock", &["lock"]),
+ ("log", &["log"]),
+ ("lua", &["lua"]),
+ ("luau", &["luau"]),
+ ("markdown", &["markdown", "md"]),
+ ("metal", &["metal"]),
+ ("nim", &["nim"]),
+ ("nix", &["nix"]),
+ ("ocaml", &["ml", "mli"]),
+ ("php", &["php"]),
+ (
+ "prettier",
+ &[
+ "prettier.config.cjs",
+ "prettier.config.js",
+ "prettier.config.mjs",
+ "prettierignore",
+ "prettierrc",
+ "prettierrc.cjs",
+ "prettierrc.js",
+ "prettierrc.json",
+ "prettierrc.json5",
+ "prettierrc.mjs",
+ "prettierrc.toml",
+ "prettierrc.yaml",
+ "prettierrc.yml",
+ ],
+ ),
+ ("prisma", &["prisma"]),
+ ("python", &["py"]),
+ ("r", &["r", "R"]),
+ ("react", &["cjsx", "ctsx", "jsx", "mjsx", "mtsx", "tsx"]),
+ ("roc", &["roc"]),
+ ("ruby", &["rb"]),
+ ("rust", &["rs"]),
+ ("sass", &["sass", "scss"]),
+ ("scala", &["scala", "sc"]),
+ ("settings", &["conf", "ini", "yaml", "yml"]),
+ ("solidity", &["sol"]),
+ (
+ "storage",
+ &[
+ "accdb", "csv", "dat", "db", "dbf", "dll", "fmp", "fp7", "frm", "gdb", "ib", "jsonc",
+ "ldf", "mdb", "mdf", "myd", "myi", "pdb", "sav", "sdf", "sql", "sqlite", "tsv",
+ ],
+ ),
+ (
+ "stylelint",
+ &[
+ "stylelint.config.cjs",
+ "stylelint.config.js",
+ "stylelint.config.mjs",
+ "stylelintignore",
+ "stylelintrc",
+ "stylelintrc.cjs",
+ "stylelintrc.js",
+ "stylelintrc.json",
+ "stylelintrc.mjs",
+ "stylelintrc.yaml",
+ "stylelintrc.yml",
+ ],
+ ),
+ ("svelte", &["svelte"]),
+ ("swift", &["swift"]),
+ ("tcl", &["tcl"]),
+ ("template", &["hbs", "plist", "xml"]),
+ (
+ "terminal",
+ &[
+ "bash",
+ "bash_aliases",
+ "bash_logout",
+ "bash_profile",
+ "bashrc",
+ "fish",
+ "nu",
+ "profile",
+ "ps1",
+ "sh",
+ "zlogin",
+ "zsh",
+ "zsh_aliases",
+ "zsh_histfile",
+ "zsh_profile",
+ "zshenv",
+ "zshrc",
+ ],
+ ),
+ ("terraform", &["tf", "tfvars"]),
+ ("toml", &["toml"]),
+ ("typescript", &["cts", "mts", "ts"]),
+ ("v", &["v", "vsh", "vv"]),
+ (
+ "vcs",
+ &[
+ "COMMIT_EDITMSG",
+ "EDIT_DESCRIPTION",
+ "MERGE_MSG",
+ "NOTES_EDITMSG",
+ "TAG_EDITMSG",
+ "gitattributes",
+ "gitignore",
+ "gitkeep",
+ "gitmodules",
+ ],
+ ),
+ ("vbproj", &["vbproj"]),
+ ("video", &["avi", "m4v", "mkv", "mov", "mp4", "webm", "wmv"]),
+ ("vs_sln", &["sln"]),
+ ("vs_suo", &["suo"]),
+ ("vue", &["vue"]),
+ ("zig", &["zig"]),
+];
+
/// A mapping of a file type identifier to its corresponding icon.
const FILE_ICONS: &[(&str, &str)] = &[
("astro", "icons/file_icons/astro.svg"),
@@ -141,12 +350,25 @@ const FILE_ICONS: &[(&str, &str)] = &[
("zig", "icons/file_icons/zig.svg"),
];
+/// Returns a mapping of file associations to icon keys.
+fn icon_keys_by_association(
+ associations_by_icon_key: &[(&str, &[&str])],
+) -> HashMap<String, String> {
+ let mut icon_keys_by_association = HashMap::default();
+ for (icon_key, associations) in associations_by_icon_key {
+ for association in *associations {
+ icon_keys_by_association.insert(association.to_string(), icon_key.to_string());
+ }
+ }
+
+ icon_keys_by_association
+}
+
/// The name of the default icon theme.
pub(crate) const DEFAULT_ICON_THEME_NAME: &str = "Zed (Default)";
-/// Returns the default icon theme.
-pub fn default_icon_theme() -> IconTheme {
- IconTheme {
+static DEFAULT_ICON_THEME: LazyLock<Arc<IconTheme>> = LazyLock::new(|| {
+ Arc::new(IconTheme {
id: "zed".into(),
name: DEFAULT_ICON_THEME_NAME.into(),
appearance: Appearance::Dark,
@@ -158,6 +380,8 @@ pub fn default_icon_theme() -> IconTheme {
collapsed: Some("icons/file_icons/chevron_right.svg".into()),
expanded: Some("icons/file_icons/chevron_down.svg".into()),
},
+ file_stems: icon_keys_by_association(FILE_STEMS_BY_ICON_KEY),
+ file_suffixes: icon_keys_by_association(FILE_SUFFIXES_BY_ICON_KEY),
file_icons: HashMap::from_iter(FILE_ICONS.into_iter().map(|(ty, path)| {
(
ty.to_string(),
@@ -166,5 +390,10 @@ pub fn default_icon_theme() -> IconTheme {
},
)
})),
- }
+ })
+});
+
+/// Returns the default icon theme.
+pub fn default_icon_theme() -> Arc<IconTheme> {
+ DEFAULT_ICON_THEME.clone()
}
@@ -23,6 +23,10 @@ pub struct IconThemeContent {
#[serde(default)]
pub chevron_icons: ChevronIconsContent,
#[serde(default)]
+ pub file_stems: HashMap<String, String>,
+ #[serde(default)]
+ pub file_suffixes: HashMap<String, String>,
+ #[serde(default)]
pub file_icons: HashMap<String, IconDefinitionContent>,
}
@@ -11,8 +11,8 @@ use parking_lot::RwLock;
use util::ResultExt;
use crate::{
- read_icon_theme, read_user_theme, refine_theme_family, Appearance, AppearanceContent,
- ChevronIcons, DirectoryIcons, IconDefinition, IconTheme, Theme, ThemeFamily,
+ default_icon_theme, read_icon_theme, read_user_theme, refine_theme_family, Appearance,
+ AppearanceContent, ChevronIcons, DirectoryIcons, IconDefinition, IconTheme, Theme, ThemeFamily,
ThemeFamilyContent, DEFAULT_ICON_THEME_NAME,
};
@@ -80,10 +80,11 @@ impl ThemeRegistry {
registry.insert_theme_families([crate::fallback_themes::zed_default_themes()]);
let default_icon_theme = crate::default_icon_theme();
- registry.state.write().icon_themes.insert(
- default_icon_theme.name.clone(),
- Arc::new(default_icon_theme),
- );
+ registry
+ .state
+ .write()
+ .icon_themes
+ .insert(default_icon_theme.name.clone(), default_icon_theme);
registry
}
@@ -263,8 +264,16 @@ impl ThemeRegistry {
.into()
};
+ let default_icon_theme = default_icon_theme();
+
let mut state = self.state.write();
for icon_theme in icon_theme_family.themes {
+ let mut file_stems = default_icon_theme.file_stems.clone();
+ file_stems.extend(icon_theme.file_stems);
+
+ let mut file_suffixes = default_icon_theme.file_suffixes.clone();
+ file_suffixes.extend(icon_theme.file_suffixes);
+
let icon_theme = IconTheme {
id: uuid::Uuid::new_v4().to_string(),
name: icon_theme.name.into(),
@@ -280,6 +289,8 @@ impl ThemeRegistry {
collapsed: icon_theme.chevron_icons.collapsed.map(resolve_icon_path),
expanded: icon_theme.chevron_icons.expanded.map(resolve_icon_path),
},
+ file_stems,
+ file_suffixes,
file_icons: icon_theme
.file_icons
.into_iter()
@@ -1,6 +1,5 @@
use std::ops::{Deref, DerefMut};
-use assets::Assets;
use editor::test::editor_lsp_test_context::EditorLspTestContext;
use gpui::{Context, Entity, SemanticVersion, UpdateGlobal};
use search::{project_search::ProjectSearchBar, BufferSearchBar};
@@ -21,7 +20,7 @@ impl VimTestContext {
cx.set_global(settings);
release_channel::init(SemanticVersion::default(), cx);
command_palette::init(cx);
- project_panel::init(Assets, cx);
+ project_panel::init(cx);
git_ui::init(cx);
crate::init(cx);
search::init(cx);
@@ -51,7 +51,6 @@ extensions_ui.workspace = true
feature_flags.workspace = true
feedback.workspace = true
file_finder.workspace = true
-file_icons.workspace = true
fs.workspace = true
futures.workspace = true
git.workspace = true
@@ -488,9 +488,9 @@ fn main() {
tab_switcher::init(cx);
outline::init(cx);
project_symbols::init(cx);
- project_panel::init(Assets, cx);
+ project_panel::init(cx);
git_ui::git_panel::init(cx);
- outline_panel::init(Assets, cx);
+ outline_panel::init(cx);
component_preview::init(cx);
tasks_ui::init(cx);
snippets_ui::init(cx);
@@ -555,7 +555,6 @@ fn main() {
load_user_themes_in_background(fs.clone(), cx);
watch_themes(fs.clone(), cx);
watch_languages(fs.clone(), app_state.languages.clone(), cx);
- watch_file_types(fs.clone(), cx);
cx.set_menus(app_menus());
initialize_workspace(app_state.clone(), prompt_builder, cx);
@@ -1158,35 +1157,3 @@ fn watch_languages(fs: Arc<dyn fs::Fs>, languages: Arc<LanguageRegistry>, cx: &m
#[cfg(not(debug_assertions))]
fn watch_languages(_fs: Arc<dyn fs::Fs>, _languages: Arc<LanguageRegistry>, _cx: &mut App) {}
-
-#[cfg(debug_assertions)]
-fn watch_file_types(fs: Arc<dyn fs::Fs>, cx: &mut App) {
- use std::time::Duration;
-
- use file_icons::FileIcons;
- use gpui::UpdateGlobal;
-
- let path = {
- let p = Path::new("assets").join(file_icons::FILE_TYPES_ASSET);
- let Ok(full_path) = p.canonicalize() else {
- return;
- };
- full_path
- };
-
- cx.spawn(|cx| async move {
- let (mut events, _) = fs.watch(path.as_path(), Duration::from_millis(100)).await;
- while (events.next().await).is_some() {
- cx.update(|cx| {
- FileIcons::update_global(cx, |file_types, _cx| {
- *file_types = file_icons::FileIcons::new(Assets);
- });
- })
- .ok();
- }
- })
- .detach()
-}
-
-#[cfg(not(debug_assertions))]
-fn watch_file_types(_fs: Arc<dyn fs::Fs>, _cx: &mut App) {}
@@ -4198,8 +4198,8 @@ mod tests {
editor::init(cx);
collab_ui::init(&app_state, cx);
git_ui::init(cx);
- project_panel::init((), cx);
- outline_panel::init((), cx);
+ project_panel::init(cx);
+ outline_panel::init(cx);
terminal_view::init(cx);
copilot::copilot_chat::init(
app_state.fs.clone(),
@@ -8,7 +8,7 @@ extend-exclude = [
".mailmap",
# File suffixes aren't typos.
- "assets/icons/file_icons/file_types.json",
+ "crates/theme/src/icon_theme.rs",
"crates/extensions_ui/src/extension_suggest.rs",
# Some countries codes are flagged as typos.