~grtcdr/citron

667691b50a384c8ce9fd8967e241a8083551e979 — grtcdr 2 years ago 25c8bf9
chore: simplify Icon struct
3 files changed, 47 insertions(+), 36 deletions(-)

M src/icon.rs
M src/main.rs
M src/options.rs
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,
}