From 8ec82b836a8bd8cb7130e584ec89dd62ee78fc3f Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Fri, 24 Jan 2020 16:15:31 +0200 Subject: [PATCH] Add 2 theme-related cli flags --- src/bin.rs | 20 +++++- ui/src/conf.rs | 150 +++++++++++++----------------------------- ui/src/conf/themes.rs | 50 ++++++++++++++ 3 files changed, 113 insertions(+), 107 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 50cc96c11..ef3b74005 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -151,6 +151,18 @@ fn run_app() -> Result<()> { "--version" | "-v" => { args.version = true; } + "--print-loaded-themes" => { + let s = ui::conf::FileSettings::new()?; + print!("{}", s.terminal.themes.to_string()); + return Ok(()); + } + "--print-default-theme" => { + print!( + "{}", + ui::conf::Theme::default().key_to_string("dark", false) + ); + return Ok(()); + } e => match prev { None => error_and_exit!("error: value without command {}", e), Some(CreateConfig) if args.create_config.is_none() => { @@ -179,11 +191,13 @@ fn run_app() -> Result<()> { println!(""); println!("\t--help, -h\t\tshow this message and exit"); println!("\t--version, -v\t\tprint version and exit"); - println!("\t--create-config[ PATH]\tCreate a sample configuration file with available configuration options. If PATH is not specified, meli will try to create it in $XDG_CONFIG_HOME/meli/config"); + println!("\t--create-config[ PATH]\tcreate a sample configuration file with available configuration options. If PATH is not specified, meli will try to create it in $XDG_CONFIG_HOME/meli/config"); println!( - "\t--test-config PATH\tTest a configuration file for syntax issues or missing options." + "\t--test-config PATH\ttest a configuration file for syntax issues or missing options." ); - println!("\t--config PATH, -c PATH\tUse specified configuration file"); + println!("\t--config PATH, -c PATH\tuse specified configuration file"); + println!("\t--print-loaded-themes\tprint loaded themes in full to stdout and exit."); + println!("\t--print-default-theme\tprint default theme in full to stdout and exit."); return Ok(()); } diff --git a/ui/src/conf.rs b/ui/src/conf.rs index d8ae0cdd0..975d16842 100644 --- a/ui/src/conf.rs +++ b/ui/src/conf.rs @@ -234,24 +234,24 @@ impl FileAccount { #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct FileSettings { - accounts: HashMap, + pub accounts: HashMap, #[serde(default)] - pager: PagerSettings, + pub pager: PagerSettings, #[serde(default)] - listing: ListingSettings, + pub listing: ListingSettings, #[serde(default)] - notifications: NotificationsSettings, + pub notifications: NotificationsSettings, #[serde(default)] - shortcuts: Shortcuts, - composing: ComposingSettings, + pub shortcuts: Shortcuts, + pub composing: ComposingSettings, #[serde(default)] - tags: TagsSettings, + pub tags: TagsSettings, #[serde(default)] - pgp: PGPSettings, + pub pgp: PGPSettings, #[serde(default)] - terminal: TerminalSettings, + pub terminal: TerminalSettings, #[serde(default)] - plugins: HashMap, + pub plugins: HashMap, } #[derive(Debug, Clone, Default)] @@ -336,70 +336,10 @@ impl FileSettings { let path = config_path .to_str() .expect("Configuration file path was not valid UTF-8"); - FileSettings::validate(path)?; - let mut s: FileSettings = toml::from_str(&pp::pp(path)?).map_err(|err| err.to_string())?; - let Theme { - light: default_light, - dark: default_dark, - .. - } = Theme::default(); - for (k, v) in default_light.into_iter() { - if !s.terminal.themes.light.contains_key(&k) { - s.terminal.themes.light.insert(k, v); - } - } - for theme in s.terminal.themes.other_themes.values_mut() { - for (k, v) in default_dark.clone().into_iter() { - if !theme.contains_key(&k) { - theme.insert(k, v); - } - } - } - if let Ok(xdg_dirs) = xdg_dirs { - for theme_folder in xdg_dirs.find_config_files("themes") { - let read_dir = std::fs::read_dir(theme_folder)?; - for theme in read_dir { - let theme = theme?; - if theme.path().is_file() { - use std::os::unix::ffi::OsStrExt; - let theme_name = if let Some(n) = theme - .path() - .file_stem() - .map(|f| String::from_utf8_lossy(f.as_bytes()).into_owned()) - { - n - } else { - continue; - }; - let mut t: HashMap, ThemeAttributeInner> = - toml::from_str(&pp::pp(theme.path())?).map_err(|err| { - format!( - "Could not parse theme in `{}`: {}", - theme.path().display(), - err.to_string() - ) - })?; - for (k, v) in default_dark.clone().into_iter() { - if !t.contains_key(&k) { - t.insert(k, v); - } - } - s.terminal.themes.other_themes.insert(theme_name, t); - } - } - } - } - for (k, v) in default_dark.into_iter() { - if !s.terminal.themes.dark.contains_key(&k) { - s.terminal.themes.dark.insert(k, v); - } - } - s.terminal.themes.validate()?; - - Ok(s) + FileSettings::validate(path) } - pub fn validate(path: &str) -> Result<()> { + pub fn validate(path: &str) -> Result { let s = pp::pp(path)?; let mut s: FileSettings = toml::from_str(&s).map_err(|e| { MeliError::new(format!( @@ -420,35 +360,28 @@ impl FileSettings { } } - if let Ok(xdg_dirs) = xdg::BaseDirectories::with_prefix("meli") { - for theme_folder in xdg_dirs.find_config_files("themes") { - let read_dir = std::fs::read_dir(theme_folder)?; - for theme in read_dir { - let theme = theme?; - if theme.path().is_file() { - use std::os::unix::ffi::OsStrExt; - let theme_name = if let Some(n) = theme - .path() - .file_stem() - .map(|f| String::from_utf8_lossy(f.as_bytes()).into_owned()) - { - n - } else { - continue; - }; - let t: HashMap, ThemeAttributeInner> = - toml::from_str(&pp::pp(theme.path())?).map_err(|err| { - format!( - "Could not parse theme in `{}`: {}", - theme.path().display(), - err.to_string() - ) - })?; - s.terminal.themes.other_themes.insert(theme_name, t); - } + let Theme { + light: default_light, + dark: default_dark, + .. + } = Theme::default(); + for (k, v) in default_light.into_iter() { + if !s.terminal.themes.light.contains_key(&k) { + s.terminal.themes.light.insert(k, v); + } + } + for theme in s.terminal.themes.other_themes.values_mut() { + for (k, v) in default_dark.clone().into_iter() { + if !theme.contains_key(&k) { + theme.insert(k, v); } } } + for (k, v) in default_dark.into_iter() { + if !s.terminal.themes.dark.contains_key(&k) { + s.terminal.themes.dark.insert(k, v); + } + } match s.terminal.theme.as_str() { "dark" | "light" => {} t if s.terminal.themes.other_themes.contains_key(t) => {} @@ -457,7 +390,8 @@ impl FileSettings { } } - for (name, acc) in s.accounts { + s.terminal.themes.validate()?; + for (name, acc) in &s.accounts { let FileAccount { root_folder, format, @@ -471,11 +405,11 @@ impl FileSettings { refresh_command: _, index_style: _, cache_type: _, - } = acc; + } = acc.clone(); let lowercase_format = format.to_lowercase(); let s = AccountSettings { - name, + name: name.to_string(), root_folder, format: format.clone(), identity, @@ -492,7 +426,7 @@ impl FileSettings { backends.validate_config(&lowercase_format, &s)?; } - Ok(()) + Ok(s) } } @@ -832,8 +766,16 @@ mod pp { path.as_ref().to_path_buf() }; - let ret = pp_helper(&p_buf, 0); + let mut ret = pp_helper(&p_buf, 0)?; drop(p_buf); - ret + if let Ok(xdg_dirs) = xdg::BaseDirectories::with_prefix("meli") { + for theme_folder in xdg_dirs.find_config_files("themes") { + let read_dir = std::fs::read_dir(theme_folder)?; + for theme in read_dir { + ret.extend(pp_helper(&theme?.path(), 0)?.chars()); + } + } + } + Ok(ret) } } diff --git a/ui/src/conf/themes.rs b/ui/src/conf/themes.rs index 8d2a37548..cbfd51ed5 100644 --- a/ui/src/conf/themes.rs +++ b/ui/src/conf/themes.rs @@ -325,6 +325,56 @@ impl Theme { Err(format!("Unrecognized theme keywords: {}", keys.join(", ")).into()) } } + + pub fn key_to_string(&self, key: &str, unlink: bool) -> String { + let theme = match key { + "light" => &self.light, + "dark" => &self.dark, + t => self.other_themes.get(t).unwrap_or(&self.dark), + }; + let mut ret = String::new(); + ret.extend(format!("[terminal.themes.{}]\n", key).chars()); + if unlink { + for k in theme.keys() { + ret.extend( + format!( + "\"{}\" = {{ fg = {}, bg = {}, attrs = {} }}\n", + k, + toml::to_string(&unlink_fg(&theme, k)).unwrap(), + toml::to_string(&unlink_bg(&theme, k)).unwrap(), + toml::to_string(&unlink_attrs(&theme, k)).unwrap(), + ) + .chars(), + ); + } + } else { + for k in theme.keys() { + ret.extend( + format!( + "\"{}\" = {{ fg = {}, bg = {}, attrs = {} }}\n", + k, + toml::to_string(&theme[k].fg).unwrap(), + toml::to_string(&theme[k].bg).unwrap(), + toml::to_string(&theme[k].attrs).unwrap(), + ) + .chars(), + ); + } + } + ret + } + pub fn to_string(&self) -> String { + let mut ret = String::new(); + ret.extend(self.key_to_string("dark", true).chars()); + + ret.push_str("\n\n"); + ret.extend(self.key_to_string("light", true).chars()); + for name in self.other_themes.keys() { + ret.push_str("\n\n"); + ret.extend(self.key_to_string(name, true).chars()); + } + ret + } } impl Default for Theme {