theme: Return structured errors when a theme is not found (#25090)
This PR updates the `ThemeRegistry` to return structured errors from the `get` and `get_icon_theme` methods (which are used to retrieve themes and icon themes, respectively). We want to be able to carry the name of the theme that was not found as state on the error, which is why we use a `Result` and not an `Option`. However, we also want to be able to accurately identify when the error case is "not found" so we can take appropriate action, based on the circumstances. By using a custom error type instead of an `anyhow::Error`, we get both. There isn't any functional change in this PR. This just sets us up for future improvements in this error. Release Notes: - N/A
This commit is contained in:
parent
76f501af71
commit
8e7cad7848
4 changed files with 43 additions and 15 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -13481,6 +13481,7 @@ dependencies = [
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"settings",
|
"settings",
|
||||||
"strum",
|
"strum",
|
||||||
|
"thiserror 1.0.69",
|
||||||
"util",
|
"util",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
|
@ -36,6 +36,7 @@ serde_json_lenient.workspace = true
|
||||||
serde_repr.workspace = true
|
serde_repr.workspace = true
|
||||||
settings.workspace = true
|
settings.workspace = true
|
||||||
strum.workspace = true
|
strum.workspace = true
|
||||||
|
thiserror.workspace = true
|
||||||
util.workspace = true
|
util.workspace = true
|
||||||
uuid.workspace = true
|
uuid.workspace = true
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{fmt::Debug, path::Path};
|
use std::{fmt::Debug, path::Path};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
use fs::Fs;
|
use fs::Fs;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use gpui::{App, AssetSource, Global, SharedString};
|
use gpui::{App, AssetSource, Global, SharedString};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
use thiserror::Error;
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -25,6 +26,16 @@ pub struct ThemeMeta {
|
||||||
pub appearance: Appearance,
|
pub appearance: Appearance,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An error indicating that the theme with the given name was not found.
|
||||||
|
#[derive(Debug, Error, Clone)]
|
||||||
|
#[error("theme not found: {0}")]
|
||||||
|
pub struct ThemeNotFoundError(pub SharedString);
|
||||||
|
|
||||||
|
/// An error indicating that the icon theme with the given name was not found.
|
||||||
|
#[derive(Debug, Error, Clone)]
|
||||||
|
#[error("icon theme not found: {0}")]
|
||||||
|
pub struct IconThemeNotFoundError(pub SharedString);
|
||||||
|
|
||||||
/// The global [`ThemeRegistry`].
|
/// The global [`ThemeRegistry`].
|
||||||
///
|
///
|
||||||
/// This newtype exists for obtaining a unique [`TypeId`](std::any::TypeId) when
|
/// This newtype exists for obtaining a unique [`TypeId`](std::any::TypeId) when
|
||||||
|
@ -145,12 +156,12 @@ impl ThemeRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the theme with the given name.
|
/// Returns the theme with the given name.
|
||||||
pub fn get(&self, name: &str) -> Result<Arc<Theme>> {
|
pub fn get(&self, name: &str) -> Result<Arc<Theme>, ThemeNotFoundError> {
|
||||||
self.state
|
self.state
|
||||||
.read()
|
.read()
|
||||||
.themes
|
.themes
|
||||||
.get(name)
|
.get(name)
|
||||||
.ok_or_else(|| anyhow!("theme not found: {}", name))
|
.ok_or_else(|| ThemeNotFoundError(name.to_string().into()))
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +220,7 @@ impl ThemeRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the default icon theme.
|
/// Returns the default icon theme.
|
||||||
pub fn default_icon_theme(&self) -> Result<Arc<IconTheme>> {
|
pub fn default_icon_theme(&self) -> Result<Arc<IconTheme>, IconThemeNotFoundError> {
|
||||||
self.get_icon_theme(DEFAULT_ICON_THEME_NAME)
|
self.get_icon_theme(DEFAULT_ICON_THEME_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,12 +238,12 @@ impl ThemeRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the icon theme with the specified name.
|
/// Returns the icon theme with the specified name.
|
||||||
pub fn get_icon_theme(&self, name: &str) -> Result<Arc<IconTheme>> {
|
pub fn get_icon_theme(&self, name: &str) -> Result<Arc<IconTheme>, IconThemeNotFoundError> {
|
||||||
self.state
|
self.state
|
||||||
.read()
|
.read()
|
||||||
.icon_themes
|
.icon_themes
|
||||||
.get(name)
|
.get(name)
|
||||||
.ok_or_else(|| anyhow!("icon theme not found: {name}"))
|
.ok_or_else(|| IconThemeNotFoundError(name.to_string().into()))
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::fallback_themes::zed_default_dark;
|
use crate::fallback_themes::zed_default_dark;
|
||||||
use crate::{
|
use crate::{
|
||||||
Appearance, IconTheme, SyntaxTheme, Theme, ThemeRegistry, ThemeStyleContent,
|
Appearance, IconTheme, IconThemeNotFoundError, SyntaxTheme, Theme, ThemeNotFoundError,
|
||||||
DEFAULT_ICON_THEME_NAME,
|
ThemeRegistry, ThemeStyleContent, DEFAULT_ICON_THEME_NAME,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
|
@ -578,10 +578,15 @@ impl ThemeSettings {
|
||||||
|
|
||||||
let mut new_theme = None;
|
let mut new_theme = None;
|
||||||
|
|
||||||
if let Some(theme) = themes.get(theme).log_err() {
|
match themes.get(theme) {
|
||||||
|
Ok(theme) => {
|
||||||
self.active_theme = theme.clone();
|
self.active_theme = theme.clone();
|
||||||
new_theme = Some(theme);
|
new_theme = Some(theme);
|
||||||
}
|
}
|
||||||
|
Err(err @ ThemeNotFoundError(_)) => {
|
||||||
|
log::error!("{err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.apply_theme_overrides();
|
self.apply_theme_overrides();
|
||||||
|
|
||||||
|
@ -838,9 +843,14 @@ impl settings::Settings for ThemeSettings {
|
||||||
|
|
||||||
let theme_name = value.theme(*system_appearance);
|
let theme_name = value.theme(*system_appearance);
|
||||||
|
|
||||||
if let Some(theme) = themes.get(theme_name).log_err() {
|
match themes.get(theme_name) {
|
||||||
|
Ok(theme) => {
|
||||||
this.active_theme = theme;
|
this.active_theme = theme;
|
||||||
}
|
}
|
||||||
|
Err(err @ ThemeNotFoundError(_)) => {
|
||||||
|
log::error!("{err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.theme_overrides.clone_from(&value.theme_overrides);
|
this.theme_overrides.clone_from(&value.theme_overrides);
|
||||||
|
@ -851,9 +861,14 @@ impl settings::Settings for ThemeSettings {
|
||||||
|
|
||||||
let icon_theme_name = value.icon_theme(*system_appearance);
|
let icon_theme_name = value.icon_theme(*system_appearance);
|
||||||
|
|
||||||
if let Some(icon_theme) = themes.get_icon_theme(icon_theme_name).log_err() {
|
match themes.get_icon_theme(icon_theme_name) {
|
||||||
|
Ok(icon_theme) => {
|
||||||
this.active_icon_theme = icon_theme;
|
this.active_icon_theme = icon_theme;
|
||||||
}
|
}
|
||||||
|
Err(err @ IconThemeNotFoundError(_)) => {
|
||||||
|
log::error!("{err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
merge(&mut this.ui_font_size, value.ui_font_size.map(Into::into));
|
merge(&mut this.ui_font_size, value.ui_font_size.map(Into::into));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue