Add 2 theme-related cli flags

async
Manos Pitsidianakis 2020-01-24 16:15:31 +02:00
parent 5230ce2d03
commit 8ec82b836a
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
3 changed files with 113 additions and 107 deletions

View File

@ -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(());
}

View File

@ -234,24 +234,24 @@ impl FileAccount {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct FileSettings {
accounts: HashMap<String, FileAccount>,
pub accounts: HashMap<String, FileAccount>,
#[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<String, Plugin>,
pub plugins: HashMap<String, Plugin>,
}
#[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<std::borrow::Cow<'static, str>, 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<Self> {
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<std::borrow::Cow<'static, str>, 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)
}
}

View File

@ -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 {