use std::fs::{self, OpenOptions};
use std::path::PathBuf;
use crate::config::Config as ThconConfig;
use crate::operation::Operation;
use crate::themeable::{ConfigState, Themeable};
use crate::AppConfig;
use crate::Disableable;
use anyhow::Result;
use log::{debug, warn};
use serde::{Deserialize, Serialize};
use serde_json::ser::{PrettyFormatter, Serializer};
use serde_json::Value as JsonValue;
#[derive(Debug, Deserialize, Disableable, AppConfig)]
pub struct _Config {
light: ConfigSection,
dark: ConfigSection,
#[serde(rename = "preferences")]
preferences_file: Option<String>,
#[serde(default = "is_disabled")]
disabled: bool,
}
fn is_disabled() -> bool {
true
}
#[derive(Debug, Deserialize)]
pub struct ConfigSection {
color_scheme: Option<String>,
theme: Option<String>,
}
impl Default for _Config {
fn default() -> Self {
Self {
light: ConfigSection {
color_scheme: Some(
"Packages/Color Scheme - Default/Celeste.sublime-color-scheme".to_string(),
),
theme: Some("Adaptive.sublime-theme".to_string()),
},
dark: ConfigSection {
color_scheme: Some(
"Packages/Color Scheme - Default/Monokai.sublime-color-scheme".to_string(),
),
theme: Some("Default.sublime-theme".to_string()),
},
preferences_file: None,
disabled: true,
}
}
}
fn preferences_path() -> PathBuf {
[
dirs::config_dir().unwrap().to_str().unwrap(),
#[cfg(mac)]
"Sublime Text 3",
#[cfg(not(mac))]
"sublime-text-3",
"Packages",
"User",
"Preferences.sublime-settings",
]
.iter()
.collect()
}
pub struct SublimeText;
impl Themeable for SublimeText {
fn config_state(&self, config: &ThconConfig) -> ConfigState {
let config_state = ConfigState::with_default_config(
config.sublime_text.as_ref().map(|c| c.inner.as_ref()),
);
if config_state == ConfigState::Default {
return ConfigState::Disabled;
}
config_state
}
fn switch(&self, config: &ThconConfig, operation: &Operation) -> Result<()> {
let config = match self.config_state(config) {
ConfigState::NoDefault => unreachable!(),
ConfigState::Disabled => return Ok(()),
ConfigState::Default => unreachable!(),
ConfigState::Enabled => config.sublime_text.as_ref().unwrap().unwrap_inner_left(),
};
let section = match operation {
Operation::Darken => &config.dark,
Operation::Lighten => &config.light,
};
let settings_path = match &config.preferences_file {
Some(pathstr) => PathBuf::from(pathstr),
None => preferences_path(),
};
debug!(
"Reading/writing Preferences.sublime-settings at {}",
&settings_path.display()
);
let settings = fs::read_to_string(&settings_path).unwrap_or_default();
let mut settings: JsonValue = serde_json::from_str(&settings).unwrap_or_default();
if let Some(color_scheme) = §ion.color_scheme {
settings["color_scheme"] = JsonValue::String(color_scheme.to_string());
}
if let Some(theme) = §ion.theme {
settings["theme"] = JsonValue::String(theme.to_string());
}
let maybe_settings_file = OpenOptions::new()
.read(true)
.write(true)
.truncate(true)
.open(&settings_path);
if let Ok(file) = maybe_settings_file {
let formatter = PrettyFormatter::with_indent(b" ");
let mut serializer = Serializer::with_formatter(file, formatter);
settings.serialize(&mut serializer).unwrap();
} else {
warn!(
"Could not find Preferences.sublime-settings at {}",
&settings_path.display()
);
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::SublimeText;
use crate::themeable::Themeable;
use crate::{Config as ThconConfig, ConfigState};
#[test]
fn disabled_by_default() {
let st = SublimeText {};
let config: ThconConfig = serde_json::from_str("{}").unwrap();
assert_eq!(st.config_state(&config), ConfigState::Disabled);
}
}