From 92f759fd09751a59f5f12c9e9c1f3b4ac3b6808f Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Mon, 9 Jan 2023 23:54:07 +0100 Subject: [PATCH] fix: merge themes from multiple locations --- src/lib.rs | 27 ++++++++++++++++++++------- src/theme/mod.rs | 29 +++++++++++++++++++---------- src/theme/parse.rs | 15 +++++++++++---- src/theme/paths.rs | 2 +- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0ba8555..33ea9f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,15 +75,18 @@ mod theme; /// ]) /// # } pub fn list_themes() -> Vec<&'static str> { - THEMES + let mut themes = THEMES .values() + .flatten() .map(|path| &path.index) .filter_map(|index| { index .section(Some("Icon Theme")) .and_then(|section| section.get("Name")) }) - .collect() + .collect::>(); + themes.dedup(); + themes } /// The lookup builder struct, holding all the lookup query parameters. @@ -232,14 +235,24 @@ impl<'a> LookupBuilder<'a> { } // Then lookup in the given theme - THEMES.get(self.theme).and_then(|icon_theme| { - let icon = icon_theme - .try_get_icon(self.name, self.size, self.scale, self.force_svg) + THEMES.get(self.theme).and_then(|icon_themes| { + let icon = icon_themes + .iter() + .find_map(|theme| { + theme.try_get_icon(self.name, self.size, self.scale, self.force_svg) + }) .or_else(|| { // Fallback to the parent themes recursively - icon_theme.inherits().into_iter().find_map(|parent| { + let mut parents = icon_themes + .iter() + .flat_map(|t| t.inherits()) + .collect::>(); + parents.dedup(); + parents.into_iter().find_map(|parent| { THEMES.get(parent).and_then(|parent| { - parent.try_get_icon(self.name, self.size, self.scale, self.force_svg) + parent.iter().find_map(|t| { + t.try_get_icon(self.name, self.size, self.scale, self.force_svg) + }) }) }) }) diff --git a/src/theme/mod.rs b/src/theme/mod.rs index cd0a940..c8373ab 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -14,7 +14,7 @@ mod paths; type Result = std::result::Result; -pub static THEMES: Lazy> = +pub static THEMES: Lazy>> = Lazy::new(|| get_all_themes().expect("Failed to get theme paths")); pub struct Theme { @@ -140,14 +140,14 @@ fn try_build_xmp>(name: &str, path: P) -> Option { } // Iter through the base paths and get all theme directories -pub(super) fn get_all_themes() -> Result> { - let mut icon_themes = BTreeMap::new(); +pub(super) fn get_all_themes() -> Result>> { + let mut icon_themes = BTreeMap::<_, Vec<_>>::new(); for theme_base_dir in BASE_PATHS.iter() { for entry in theme_base_dir.read_dir()? { let entry = entry?; if let Some(theme) = Theme::from_path(entry.path()) { let name = entry.file_name().to_string_lossy().to_string(); - icon_themes.insert(name, theme); + icon_themes.entry(name).or_default().push(theme); } } } @@ -190,17 +190,24 @@ mod test { #[test] fn get_one_icon() { - let theme = THEMES.get("Adwaita").unwrap(); + let themes = THEMES.get("Adwaita").unwrap(); println!( "{:?}", - theme.try_get_icon_exact_size("edit-delete-symbolic", 24, 1, false) + themes.iter().find_map(|t| t.try_get_icon_exact_size( + "edit-delete-symbolic", + 24, + 1, + false + )) ); } #[test] fn should_get_png_first() { - let theme = THEMES.get("hicolor").unwrap(); - let icon = theme.try_get_icon_exact_size("blueman", 24, 1, true); + let themes = THEMES.get("hicolor").unwrap(); + let icon = themes + .iter() + .find_map(|t| t.try_get_icon_exact_size("blueman", 24, 1, true)); assert_that!(icon).is_some().is_equal_to(PathBuf::from( "/usr/share/icons/hicolor/scalable/apps/blueman.svg", )); @@ -208,8 +215,10 @@ mod test { #[test] fn should_get_svg_first() { - let theme = THEMES.get("hicolor").unwrap(); - let icon = theme.try_get_icon_exact_size("blueman", 24, 1, false); + let themes = THEMES.get("hicolor").unwrap(); + let icon = themes + .iter() + .find_map(|t| t.try_get_icon_exact_size("blueman", 24, 1, false)); assert_that!(icon).is_some().is_equal_to(PathBuf::from( "/usr/share/icons/hicolor/22x22/apps/blueman.png", )); diff --git a/src/theme/parse.rs b/src/theme/parse.rs index feaa44b..2beb98c 100644 --- a/src/theme/parse.rs +++ b/src/theme/parse.rs @@ -88,11 +88,18 @@ mod test { #[test] fn should_get_theme_parents() { - let theme = THEMES.get("Arc").unwrap(); - let parents = theme.inherits(); + for theme in THEMES.get("Arc").unwrap() { + let parents = theme.inherits(); - assert_that!(parents).does_not_contain("hicolor"); + assert_that!(parents).does_not_contain("hicolor"); - assert_that!(parents).is_equal_to(vec!["Moka", "Faba", "elementary", "Adwaita", "gnome"]); + assert_that!(parents).is_equal_to(vec![ + "Moka", + "Faba", + "elementary", + "Adwaita", + "gnome", + ]); + } } } diff --git a/src/theme/paths.rs b/src/theme/paths.rs index b0c42c1..d520228 100644 --- a/src/theme/paths.rs +++ b/src/theme/paths.rs @@ -61,7 +61,7 @@ mod test { #[test] fn should_read_theme_index() -> Result<()> { let themes = get_all_themes()?; - let themes: Vec<&Theme> = themes.values().collect(); + let themes: Vec<&Theme> = themes.values().flatten().collect(); assert_that!(themes).is_not_empty(); Ok(()) }