M src/icon.rs => src/icon.rs +45 -34
@@ 38,52 38,58 @@ pub struct Icon {
pub path: PathBuf,
/// The name of an icon theme.
pub theme: Option<String>,
- /// The base location of the `icons` directory.
- pub location: PathBuf,
}
impl Icon {
pub fn new() -> Self {
- let base = if cfg!(target_os = "linux") {
- PathBuf::from("/usr/share/icons")
- } else if cfg!(target_os = "netbsd") {
- PathBuf::from("/usr/pkg/share/icons")
- } else {
- PathBuf::new()
- };
-
Icon {
name: String::new(),
path: PathBuf::new(),
theme: None,
- location: base,
}
}
- pub fn get_available_themes(&self) -> Vec<String> {
- let mut themes = vec![];
- let mut places = vec![self.location.clone()];
+ pub fn get_icon_dirs(&self) -> Vec<PathBuf> {
+ let mut locations = vec![];
if let Ok(data) = std::env::var("XDG_DATA_HOME") {
- places.push(PathBuf::from(data).join(".icons"));
+ locations.push(PathBuf::from(data).join(".icons"));
} else if let Ok(home) = std::env::var("HOME") {
- places.push(PathBuf::from(home).join(".icons"));
+ locations.push(PathBuf::from(home).join(".icons"));
+ }
+
+ if cfg!(target_os = "linux") {
+ locations.push(PathBuf::from("/usr/share/icons"));
+ } else if cfg!(target_os = "netbsd") {
+ locations.push(PathBuf::from("/usr/pkg/share/icons"));
+ }
+
+ locations
+ }
+
+ pub fn is_valid_theme(&self, path: PathBuf) -> Option<String> {
+ if !path.join("index.theme").exists() {
+ return None;
+ }
+
+ if let Some(path) = path.file_name() {
+ if let Some(name) = path.to_str() {
+ return Some(name.to_string());
+ }
}
+ None
+ }
+
+ pub fn get_available_themes(&self) -> Vec<String> {
+ let mut themes = vec![];
+ let places = self.get_icon_dirs();
+
places.iter().for_each(|place| {
if let Ok(entries) = place.read_dir() {
for entry in entries.flatten() {
- let theme_path = entry.path();
-
- if !theme_path.join("index.theme").exists() {
- continue;
- }
-
- let theme_name = theme_path.file_name();
- if let Some(name) = theme_name {
- if let Some(str) = name.to_str() {
- themes.push(str.to_owned());
- }
+ if let Some(theme) = self.is_valid_theme(entry.path()) {
+ themes.push(theme.to_owned());
}
}
}
@@ 95,16 101,16 @@ impl Icon {
pub fn print_available_themes(&self, stream: Stream) -> Result<(), Error> {
let mut out = Vec::new();
- writeln!(out, "Available icon themes:")?;
-
let themes = self
.get_available_themes()
.into_iter()
.filter(|t| !t.eq("default"));
- for theme in themes {
- writeln!(out, "> {}", theme)?;
- }
+ write!(
+ out,
+ "Available icon themes: [{}]",
+ themes.collect::<Vec<String>>().join(", ")
+ )?;
let out = match std::str::from_utf8(&out) {
Ok(s) => s,
@@ 121,8 127,13 @@ impl Icon {
pub fn find_icon(&mut self) -> Result<PathBuf, IconError> {
if let Some(theme) = &self.theme {
- let extra_search_path = &[self.location.to_str().unwrap_or_default()];
- if let Ok(icon) = lookup_icon(&self.name).with_search_paths(extra_search_path) {
+ let search_paths = self
+ .get_icon_dirs()
+ .iter()
+ .map(|l| l.as_path().display().to_string())
+ .collect::<Vec<String>>();
+
+ if let Ok(icon) = lookup_icon(&self.name).with_search_paths(&search_paths) {
if let Some(icon) = icon.from_theme(theme).next() {
if let Ok(ico) = icon {
return Ok(ico.path);
M src/main.rs => src/main.rs +1 -1
@@ 25,7 25,7 @@ fn main() {
let opt = Options::from_args();
let config = Config::read_config().unwrap_or_default();
- if opt.icon_themes {
+ if opt.themes {
if let Err(e) = icon.print_available_themes(Stream::Stdout) {
eprintln!("Error: {}", e);
}
M src/options.rs => src/options.rs +1 -1
@@ 94,5 94,5 @@ pub struct Options {
/// Lists the available icon themes.
#[structopt(short = "L", help = "Returns a list of the available icon themes")]
- pub icon_themes: bool,
+ pub themes: bool,
}