diff --git a/Cargo.lock b/Cargo.lock index 62665b1..872812e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -435,6 +435,7 @@ dependencies = [ "tempfile", "term_grid", "terminal_size", + "thiserror", "unicode-width", "url", "users", diff --git a/Cargo.toml b/Cargo.toml index 0f6807e..3e4421a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ libc = "0.2.*" human-sort = "0.2.2" term_grid = "0.1.*" terminal_size = "0.1.*" +thiserror = "1.0" chrono = "0.4.*" chrono-humanize = "0.1.*" unicode-width = "0.1.*" diff --git a/src/app.rs b/src/app.rs index 9a65fac..971d013 100644 --- a/src/app.rs +++ b/src/app.rs @@ -54,6 +54,8 @@ pub fn build() -> App<'static> { Arg::with_name("icon-theme") .long("icon-theme") .default_value("fancy") + .possible_value("fancy") + .possible_value("unicode") .multiple_occurrences(true) .takes_value(true) .number_of_values(1) diff --git a/src/flags/icons.rs b/src/flags/icons.rs index 638c92e..fec9aac 100644 --- a/src/flags/icons.rs +++ b/src/flags/icons.rs @@ -96,7 +96,6 @@ pub enum IconTheme { Unicode, #[default] Fancy, - Custom(String), } impl IconTheme { diff --git a/src/icon.rs b/src/icon.rs index cb8b4f9..a23e9b6 100644 --- a/src/icon.rs +++ b/src/icon.rs @@ -4,7 +4,6 @@ use crate::theme::{icon::IconTheme, Theme}; pub struct Icons { icon_separator: String, - theme: Option, } @@ -16,11 +15,14 @@ impl Icons { pub fn new(tty: bool, when: IconOption, theme: FlagTheme, icon_separator: String) -> Self { let icon_theme = match (tty, when, theme) { (_, IconOption::Never, _) | (false, IconOption::Auto, _) => None, - (_, _, FlagTheme::Fancy) => Some(IconTheme::default()), + (_, _, FlagTheme::Fancy) => { + if let Ok(t) = Theme::from_path::("icons") { + Some(t) + } else { + Some(IconTheme::default()) + } + }, (_, _, FlagTheme::Unicode) => Some(IconTheme::unicode()), - (_, _, FlagTheme::Custom(ref file)) => { - Some(Theme::from_path::(file).unwrap_or_default()) - } }; Self { diff --git a/src/theme.rs b/src/theme.rs index c284193..ae0cdcc 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -1,9 +1,11 @@ pub mod color; pub mod icon; -use serde::{de::DeserializeOwned, Deserialize}; -use std::fs; use std::path::Path; +use std::{fs, io}; + +use serde::{de::DeserializeOwned, Deserialize}; +use thiserror::Error; use crate::config_file; use crate::print_error; @@ -20,49 +22,53 @@ pub struct Theme { pub icon: IconTheme, } +#[derive(Error, Debug)] +pub enum Error { + #[error("Theme file not existed")] + NotExisted(#[from] io::Error), + #[error("Theme file format invalid")] + InvalidFormat(#[from] serde_yaml::Error), + #[error("Theme file path invalid {0}")] + InvalidPath(String), + #[error("Unknown Theme error")] + Unknown(), +} + impl Theme { /// This read theme from file, /// use the file path if it is absolute /// prefix the config_file dir to it if it is not - pub fn from_path(file: &str) -> Option { + pub fn from_path(file: &str) -> Result { let real = if let Some(path) = config_file::Config::expand_home(file) { path } else { print_error!("Not a valid theme file path: {}.", &file); - return None; + return Err(Error::InvalidPath(file.to_string())); }; let path = if Path::new(&real).is_absolute() { real } else { - config_file::Config::config_file_path()? - .join("themes") - .join(real) + match config_file::Config::config_file_path() { + Some(p) => p.join("themes").join(real), + None => return Err(Error::InvalidPath("config home not existed".into())), + } }; - match fs::read(&path.with_extension("yaml")) { - Ok(f) => match Self::with_yaml(&String::from_utf8_lossy(&f)) { - Ok(t) => Some(t), - Err(e) => { - print_error!("Theme file {} format error: {}.", &file, e); - None - } - }, - Err(_) => { - // try `yml` if `yaml` extension file not found - match fs::read(&path.with_extension("yml")) { - Ok(f) => match Self::with_yaml(&String::from_utf8_lossy(&f)) { - Ok(t) => Some(t), - Err(e) => { - print_error!("Theme file {} format error: {}.", &file, e); - None - } - }, + + // try `yml` if `yaml` extension file not found or error + let mut err: Error = Error::Unknown(); + for ext in ["yaml", "yml"] { + match fs::read(&path.with_extension(ext)) { + Ok(f) => match Self::with_yaml(&String::from_utf8_lossy(&f)) { + Ok(t) => return Ok(t), Err(e) => { - print_error!("Not a valid theme: {}, {}.", path.to_string_lossy(), e); - None + err = Error::from(e); } - } + }, + Err(e) => err = Error::from(e), } } + + Err(err) } /// This constructs a Theme struct with a passed [Yaml] str.