diff options
author | Mikihiro SUDA <s@sudame.net> | 2023-04-22 23:14:49 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-22 22:14:49 +0800 |
commit | ff3e48e20b53583e880a9b8e4893ff0b503a9abe (patch) | |
tree | 935dc406f18dd1bb5f67c929f11e26f9184be81e /src | |
parent | 5ecb868c19b82b635381d13c8601687d33d57d0d (diff) |
Icon theme with overrides from config (#792)
Diffstat (limited to 'src')
-rw-r--r-- | src/theme/icon.rs | 68 |
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}"); + } } |