Rename some structs for clarity

This commit is contained in:
Ridan Vandenbergh 2025-06-20 20:48:44 +02:00
parent b58a34b589
commit 58164cea15
No known key found for this signature in database
3 changed files with 56 additions and 41 deletions

View file

@ -5,7 +5,7 @@
//! # Quick start
//!
//! ```
//! let dirs = icon::SearchDirectories::default();
//! let dirs = icon::IconSearch::default();
//! // TODO.
//! ```
//!
@ -24,7 +24,7 @@
//! While a number of directories should always be scanned for icons, the user or application is
//! allowed to search additional directories as it sees fit.
//!
//! [SearchDirectories] handles this part, and is also the main entrypoint for `icon`.
//! [IconSearch] handles this part, and is also the main entrypoint for `icon`.
//!
//! 2. *Parsing icon themes*:
//!
@ -56,9 +56,8 @@
//! - it only supports a rust-native icon cache, which you cannot opt out of.
//! - it provides only icon loading—you cannot use it to obtain information about Icon Themes.
mod icon;
mod search_dir;
mod search;
pub mod theme;
pub use search_dir::*;
pub use search::*;

View file

@ -1,5 +1,5 @@
use crate::icon::IconFile;
use crate::theme::{Theme, ThemeDescriptor, ThemeParseError};
use crate::theme::{Icons, Theme, ThemeInfo, ThemeParseError};
use std::collections::HashMap;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;
@ -9,40 +9,46 @@ use std::sync::Arc;
///
/// By default, that is `$HOME/.icons`, `$XDG_DATA_DIRS/icons` and `/usr/share/pixmaps`.
/// Applications may further add their own icon directories to this list, and users may extend or change the list.
/// The default list may be obtained using the `Default` implementation on `SearchDirectories` or its `default` method.
/// The default list may be obtained using the `Default` implementation on `IconSearch` or its `default` method.
///
/// To add directories to the instance, use [SearchDirectories::append].
/// To add directories to the instance, use [IconSearch::add_directories].
///
/// To construct a new `SearchDirectories` from a list, use the `From` implementation or construct it by hand.
/// To construct a new `IconSearch` from a list, use the `From` implementation or construct it by hand.
///
/// # Example
///
/// ```
/// use icon::SearchDirectories;
/// use icon::IconSearch;
///
/// let dirs = SearchDirectories::default();
/// let dirs = IconSearch::default();
/// // TODO
/// ```
#[derive(Debug, Clone)]
pub struct SearchDirectories {
pub struct IconSearch {
pub dirs: Vec<PathBuf>,
}
impl SearchDirectories {
impl IconSearch {
pub const fn new_empty() -> Self {
Self {
dirs: Vec::new()
}
}
pub fn default() -> Self {
<Self as Default>::default()
}
/// Add a list of directories to this `SearchDirectories`
/// Add a list of directories to this `IconSearch`
///
/// # Example
///
/// ```
/// use icon::SearchDirectories;
/// use icon::IconSearch;
///
/// let dirs = SearchDirectories::default().append(["/home/root/.icons"]);
/// let dirs = IconSearch::default().add_directories(["/home/root/.icons"]);
/// ```
pub fn append<I, P>(mut self, directories: I) -> Self
pub fn add_directories<I, P>(mut self, directories: I) -> Self
where
I: IntoIterator<Item = P>,
P: Into<PathBuf>,
@ -100,11 +106,20 @@ pub struct IconLocations {
}
impl IconLocations {
pub fn resolve(&self) -> Vec<Arc<Theme>> {
pub fn icons(self) -> Icons {
let themes = self.resolve();
Icons {
standalone_icons: self.standalone_icons,
themes,
}
}
pub fn resolve(&self) -> HashMap<OsString, Arc<Theme>> {
self.resolve_only(self.themes_directories.keys())
}
pub fn resolve_only<I, S>(&self, theme_names: I) -> Vec<Arc<Theme>>
pub fn resolve_only<I, S>(&self, theme_names: I) -> HashMap<OsString, Arc<Theme>>
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
@ -115,14 +130,14 @@ impl IconLocations {
// To accommodate this, either one has to keep a list of visited icon themes every time they
// perform a lookup, or avoid the issue altogether by removing redundant parents up-front.
// That second option is what this function does, paying a (rather small) one-time cost to
// make the rest of the API cleaner and smaller by guaranteeing that the returned icon themes
// That second option is what this function does, being to pay a (rather small) one-time cost to
// make the rest of the API cleaner and smaller. It guarantees that the returned icon themes
// have dependencies that form a direct acyclic graph without redundant paths.
fn collect_themes(
name: &OsStr,
locations: &IconLocations,
themes: &mut HashMap<OsString, Option<ThemeDescriptor>>,
themes: &mut HashMap<OsString, Option<ThemeInfo>>,
) {
// Skip if we already have this theme.
if themes.contains_key(name) {
@ -262,7 +277,7 @@ impl IconLocations {
let theme = Theme {
description: theme_desc,
parents,
inherits_from: parents,
};
full_themes[theme_idx] = Some(Arc::new(theme));
@ -279,10 +294,14 @@ impl IconLocations {
// - all themes required by the inheritance tree of those themes, without duplicates,
// - and an optimal chain (inheritance tree search order) for each theme.
full_themes
// and to wrap things up, let's zip the themes back up with their names
theme_names
.into_iter()
.zip(full_themes)
.collect::<HashMap<_, _>>()
}
pub fn theme_description<S>(&self, internal_name: S) -> std::io::Result<ThemeDescriptor>
pub fn theme_description<S>(&self, internal_name: S) -> std::io::Result<ThemeInfo>
where
S: AsRef<OsStr>,
{
@ -293,10 +312,7 @@ impl IconLocations {
.get(internal_name)
.ok_or_else(|| std::io::Error::other(ThemeParseError::NotAnIconTheme))?;
ThemeDescriptor::new_from_folders(
internal_name.to_string_lossy().into_owned(),
theme.clone(),
)
ThemeInfo::new_from_folders(internal_name.to_string_lossy().into_owned(), theme.clone())
}
pub fn standalone_icon<S>(&self, icon_name: S) -> Option<&IconFile>
@ -311,8 +327,8 @@ impl IconLocations {
}
}
/// Anything that turns into an iterator of things that can become paths, can be turned into a `SearchDirectories`.
impl<I, P> From<I> for SearchDirectories
/// Anything that turns into an iterator of things that can become paths, can be turned into a `IconSearch`.
impl<I, P> From<I> for IconSearch
where
I: IntoIterator<Item = P>,
P: Into<PathBuf>,
@ -320,11 +336,11 @@ where
fn from(value: I) -> Self {
let dirs = value.into_iter().map(Into::into).collect();
SearchDirectories { dirs }
IconSearch { dirs }
}
}
impl Default for SearchDirectories {
impl Default for IconSearch {
fn default() -> Self {
// "By default, apps should look in $HOME/.icons (for backwards compatibility),
// in $XDG_DATA_DIRS/icons
@ -351,13 +367,13 @@ impl Default for SearchDirectories {
#[cfg(test)]
mod test {
use crate::search_dir::SearchDirectories;
use crate::search::IconSearch;
// these tests assume certain applications are installed on the system they are ran on.
#[test]
fn test_find_standard_theme_and_icon() {
let dirs = SearchDirectories::default();
let dirs = IconSearch::default();
let locations = dirs.find_icon_locations();
@ -370,7 +386,7 @@ mod test {
#[test]
fn test_2() {
let result = SearchDirectories::default()
let result = IconSearch::default()
.find_icon_locations()
.theme_description("breeze")
.unwrap();
@ -380,7 +396,7 @@ mod test {
#[test]
fn test() {
let _dirs = SearchDirectories::default().find_icon_locations().resolve();
let _dirs = IconSearch::default().find_icon_locations().resolve();
// it didn't panic.
}

View file

@ -12,11 +12,11 @@ pub struct Icons {
}
pub struct Theme {
pub description: ThemeDescriptor,
pub parents: Vec<Arc<Theme>>,
pub description: ThemeInfo,
pub inherits_from: Vec<Arc<Theme>>,
}
pub struct ThemeDescriptor {
pub struct ThemeInfo {
pub internal_name: String,
pub base_dirs: Vec<PathBuf>,
pub index_location: PathBuf,
@ -42,7 +42,7 @@ pub enum ThemeParseError {
ParseError(#[from] freedesktop_entry_parser::ParseError),
}
impl ThemeDescriptor {
impl ThemeInfo {
pub fn new_from_folders(internal_name: String, folders: Vec<PathBuf>) -> std::io::Result<Self> {
let index_location = folders
.iter()