mirror of
https://github.com/danbulant/icon
synced 2026-06-05 15:41:01 +00:00
Rename some structs for clarity
This commit is contained in:
parent
b58a34b589
commit
58164cea15
3 changed files with 56 additions and 41 deletions
|
|
@ -5,7 +5,7 @@
|
||||||
//! # Quick start
|
//! # Quick start
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! let dirs = icon::SearchDirectories::default();
|
//! let dirs = icon::IconSearch::default();
|
||||||
//! // TODO.
|
//! // TODO.
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
//! While a number of directories should always be scanned for icons, the user or application is
|
//! 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.
|
//! 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*:
|
//! 2. *Parsing icon themes*:
|
||||||
//!
|
//!
|
||||||
|
|
@ -56,9 +56,8 @@
|
||||||
//! - it only supports a rust-native icon cache, which you cannot opt out of.
|
//! - 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.
|
//! - it provides only icon loading—you cannot use it to obtain information about Icon Themes.
|
||||||
|
|
||||||
|
|
||||||
mod icon;
|
mod icon;
|
||||||
mod search_dir;
|
mod search;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
|
|
||||||
pub use search_dir::*;
|
pub use search::*;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::icon::IconFile;
|
use crate::icon::IconFile;
|
||||||
use crate::theme::{Theme, ThemeDescriptor, ThemeParseError};
|
use crate::theme::{Icons, Theme, ThemeInfo, ThemeParseError};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::{OsStr, OsString};
|
use std::ffi::{OsStr, OsString};
|
||||||
use std::path::PathBuf;
|
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`.
|
/// 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.
|
/// 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
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use icon::SearchDirectories;
|
/// use icon::IconSearch;
|
||||||
///
|
///
|
||||||
/// let dirs = SearchDirectories::default();
|
/// let dirs = IconSearch::default();
|
||||||
/// // TODO
|
/// // TODO
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SearchDirectories {
|
pub struct IconSearch {
|
||||||
pub dirs: Vec<PathBuf>,
|
pub dirs: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SearchDirectories {
|
impl IconSearch {
|
||||||
|
pub const fn new_empty() -> Self {
|
||||||
|
Self {
|
||||||
|
dirs: Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn default() -> Self {
|
pub fn default() -> Self {
|
||||||
<Self as Default>::default()
|
<Self as Default>::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a list of directories to this `SearchDirectories`
|
/// Add a list of directories to this `IconSearch`
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # 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
|
where
|
||||||
I: IntoIterator<Item = P>,
|
I: IntoIterator<Item = P>,
|
||||||
P: Into<PathBuf>,
|
P: Into<PathBuf>,
|
||||||
|
|
@ -100,11 +106,20 @@ pub struct IconLocations {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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())
|
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
|
where
|
||||||
I: IntoIterator<Item = S>,
|
I: IntoIterator<Item = S>,
|
||||||
S: AsRef<OsStr>,
|
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
|
// 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.
|
// 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
|
// 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 by guaranteeing that the returned icon themes
|
// 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.
|
// have dependencies that form a direct acyclic graph without redundant paths.
|
||||||
|
|
||||||
fn collect_themes(
|
fn collect_themes(
|
||||||
name: &OsStr,
|
name: &OsStr,
|
||||||
locations: &IconLocations,
|
locations: &IconLocations,
|
||||||
themes: &mut HashMap<OsString, Option<ThemeDescriptor>>,
|
themes: &mut HashMap<OsString, Option<ThemeInfo>>,
|
||||||
) {
|
) {
|
||||||
// Skip if we already have this theme.
|
// Skip if we already have this theme.
|
||||||
if themes.contains_key(name) {
|
if themes.contains_key(name) {
|
||||||
|
|
@ -262,7 +277,7 @@ impl IconLocations {
|
||||||
|
|
||||||
let theme = Theme {
|
let theme = Theme {
|
||||||
description: theme_desc,
|
description: theme_desc,
|
||||||
parents,
|
inherits_from: parents,
|
||||||
};
|
};
|
||||||
|
|
||||||
full_themes[theme_idx] = Some(Arc::new(theme));
|
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,
|
// - all themes required by the inheritance tree of those themes, without duplicates,
|
||||||
// - and an optimal chain (inheritance tree search order) for each theme.
|
// - 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
|
where
|
||||||
S: AsRef<OsStr>,
|
S: AsRef<OsStr>,
|
||||||
{
|
{
|
||||||
|
|
@ -293,10 +312,7 @@ impl IconLocations {
|
||||||
.get(internal_name)
|
.get(internal_name)
|
||||||
.ok_or_else(|| std::io::Error::other(ThemeParseError::NotAnIconTheme))?;
|
.ok_or_else(|| std::io::Error::other(ThemeParseError::NotAnIconTheme))?;
|
||||||
|
|
||||||
ThemeDescriptor::new_from_folders(
|
ThemeInfo::new_from_folders(internal_name.to_string_lossy().into_owned(), theme.clone())
|
||||||
internal_name.to_string_lossy().into_owned(),
|
|
||||||
theme.clone(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn standalone_icon<S>(&self, icon_name: S) -> Option<&IconFile>
|
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`.
|
/// Anything that turns into an iterator of things that can become paths, can be turned into a `IconSearch`.
|
||||||
impl<I, P> From<I> for SearchDirectories
|
impl<I, P> From<I> for IconSearch
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = P>,
|
I: IntoIterator<Item = P>,
|
||||||
P: Into<PathBuf>,
|
P: Into<PathBuf>,
|
||||||
|
|
@ -320,11 +336,11 @@ where
|
||||||
fn from(value: I) -> Self {
|
fn from(value: I) -> Self {
|
||||||
let dirs = value.into_iter().map(Into::into).collect();
|
let dirs = value.into_iter().map(Into::into).collect();
|
||||||
|
|
||||||
SearchDirectories { dirs }
|
IconSearch { dirs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SearchDirectories {
|
impl Default for IconSearch {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
// "By default, apps should look in $HOME/.icons (for backwards compatibility),
|
// "By default, apps should look in $HOME/.icons (for backwards compatibility),
|
||||||
// in $XDG_DATA_DIRS/icons
|
// in $XDG_DATA_DIRS/icons
|
||||||
|
|
@ -351,13 +367,13 @@ impl Default for SearchDirectories {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod 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.
|
// these tests assume certain applications are installed on the system they are ran on.
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_standard_theme_and_icon() {
|
fn test_find_standard_theme_and_icon() {
|
||||||
let dirs = SearchDirectories::default();
|
let dirs = IconSearch::default();
|
||||||
|
|
||||||
let locations = dirs.find_icon_locations();
|
let locations = dirs.find_icon_locations();
|
||||||
|
|
||||||
|
|
@ -370,7 +386,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_2() {
|
fn test_2() {
|
||||||
let result = SearchDirectories::default()
|
let result = IconSearch::default()
|
||||||
.find_icon_locations()
|
.find_icon_locations()
|
||||||
.theme_description("breeze")
|
.theme_description("breeze")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -380,7 +396,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let _dirs = SearchDirectories::default().find_icon_locations().resolve();
|
let _dirs = IconSearch::default().find_icon_locations().resolve();
|
||||||
|
|
||||||
// it didn't panic.
|
// it didn't panic.
|
||||||
}
|
}
|
||||||
|
|
@ -12,11 +12,11 @@ pub struct Icons {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
pub description: ThemeDescriptor,
|
pub description: ThemeInfo,
|
||||||
pub parents: Vec<Arc<Theme>>,
|
pub inherits_from: Vec<Arc<Theme>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ThemeDescriptor {
|
pub struct ThemeInfo {
|
||||||
pub internal_name: String,
|
pub internal_name: String,
|
||||||
pub base_dirs: Vec<PathBuf>,
|
pub base_dirs: Vec<PathBuf>,
|
||||||
pub index_location: PathBuf,
|
pub index_location: PathBuf,
|
||||||
|
|
@ -42,7 +42,7 @@ pub enum ThemeParseError {
|
||||||
ParseError(#[from] freedesktop_entry_parser::ParseError),
|
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> {
|
pub fn new_from_folders(internal_name: String, folders: Vec<PathBuf>) -> std::io::Result<Self> {
|
||||||
let index_location = folders
|
let index_location = folders
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue