summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMikihiro SUDA <s@sudame.net>2023-04-22 23:14:49 +0900
committerGitHub <noreply@github.com>2023-04-22 22:14:49 +0800
commitff3e48e20b53583e880a9b8e4893ff0b503a9abe (patch)
tree935dc406f18dd1bb5f67c929f11e26f9184be81e /src
parent5ecb868c19b82b635381d13c8601687d33d57d0d (diff)
Icon theme with overrides from config (#792)
Diffstat (limited to 'src')
-rw-r--r--src/theme/icon.rs68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/theme/icon.rs b/src/theme/icon.rs
index e955db3..ebd6a93 100644
--- a/src/theme/icon.rs
+++ b/src/theme/icon.rs
@@ -1,12 +1,48 @@
use serde::Deserialize;
use std::collections::HashMap;
+enum ByFilename {
+ Name,
+ Extension,
+}
+
+fn deserialize_by_filename<'de, D>(
+ deserializer: D,
+ by: ByFilename,
+) -> Result<HashMap<String, String>, D::Error>
+where
+ D: serde::de::Deserializer<'de>,
+{
+ let default = match by {
+ ByFilename::Name => IconTheme::get_default_icons_by_name(),
+ ByFilename::Extension => IconTheme::get_default_icons_by_extension(),
+ };
+ HashMap::<_, _>::deserialize(deserializer)
+ .map(|input| default.into_iter().chain(input.into_iter()).collect())
+}
+
+fn deserialize_by_name<'de, D>(deserializer: D) -> Result<HashMap<String, String>, D::Error>
+where
+ D: serde::de::Deserializer<'de>,
+{
+ deserialize_by_filename(deserializer, ByFilename::Name)
+}
+
+fn deserialize_by_extension<'de, D>(deserializer: D) -> Result<HashMap<String, String>, D::Error>
+where
+ D: serde::de::Deserializer<'de>,
+{
+ deserialize_by_filename(deserializer, ByFilename::Extension)
+}
+
#[derive(Debug, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
#[serde(deny_unknown_fields)]
#[serde(default)]
pub struct IconTheme {
+ #[serde(deserialize_with = "deserialize_by_name")]
pub name: HashMap<String, String>,
+ #[serde(deserialize_with = "deserialize_by_extension")]
pub extension: HashMap<String, String>,
pub filetype: ByType,
}
@@ -656,4 +692,36 @@ filetype:
let empty: IconTheme = Theme::with_yaml("filetype:\n dir: ").unwrap();
assert_eq!(empty.filetype.dir, "");
}
+
+ #[test]
+ fn test_custom_icon_by_name() {
+ // When a user sets to use 📦-icon for a cargo.toml file,
+ let theme: IconTheme = Theme::with_yaml("name:\n cargo.toml: 📦").unwrap();
+ // 📦-icon should be used for a cargo.toml file.
+ assert_eq!(theme.name.get("cargo.toml").unwrap(), "📦");
+ }
+
+ #[test]
+ fn test_default_icon_by_name_with_custom_entry() {
+ // When a user sets to use 📦-icon for a cargo.toml file,
+ let theme: IconTheme = Theme::with_yaml("name:\n cargo.toml: 📦").unwrap();
+ // the default icon  should be used for a cargo.lock file.
+ assert_eq!(theme.name.get("cargo.lock").unwrap(), "\u{e7a8}");
+ }
+
+ #[test]
+ fn test_custom_icon_by_extension() {
+ // When a user sets to use 🦀-icon for *.rs files,
+ let theme: IconTheme = Theme::with_yaml("extension:\n rs: 🦀").unwrap();
+ // 🦀-icon should be used for *.rs files.
+ assert_eq!(theme.extension.get("rs").unwrap(), "🦀");
+ }
+
+ #[test]
+ fn test_default_icon_by_extension_with_custom_entry() {
+ // When a user sets to use 🦀-icon for *.rs files,
+ let theme: IconTheme = Theme::with_yaml("extension:\n rs: 🦀").unwrap();
+ // the default icon  should be used for *.go files.
+ assert_eq!(theme.extension.get("go").unwrap(), "\u{e627}");
+ }
}