diff --git a/cosmic-settings/src/main.rs b/cosmic-settings/src/main.rs index 274537c..a02d302 100644 --- a/cosmic-settings/src/main.rs +++ b/cosmic-settings/src/main.rs @@ -21,6 +21,8 @@ pub mod theme; pub mod utils; pub mod widget; +use std::path::PathBuf; + use clap::{Parser, Subcommand}; use cosmic::{app::CosmicFlags, iced::Limits}; use i18n_embed::DesktopLanguageRequester; @@ -34,6 +36,11 @@ use tracing_subscriber::prelude::*; pub struct Args { #[command(subcommand)] sub_command: Option, + + /// Import a theme from a RON file and exit without starting the GUI + #[arg(long, value_name = "FILE")] + #[serde(skip)] + import_theme: Option, } #[derive(Subcommand, Debug, Serialize, Deserialize, Clone)] @@ -175,6 +182,10 @@ pub fn main() -> color_eyre::Result<()> { let args = Args::parse(); + if let Some(theme_path) = &args.import_theme { + return import_theme_cli(theme_path); + } + let settings = cosmic::app::Settings::default() .size_limits(Limits::NONE.min_width(360.0).min_height(300.0)); @@ -189,6 +200,80 @@ pub fn main() -> color_eyre::Result<()> { Ok(()) } +fn import_theme_cli(path: &std::path::Path) -> color_eyre::Result<()> { + use cosmic::cosmic_config::CosmicConfigEntry; + use cosmic::cosmic_theme::{Theme, ThemeBuilder, ThemeMode}; + + if !path.exists() { + return Err(color_eyre::eyre::eyre!( + "Theme file not found: {}", + path.display() + )); + } + + if path.extension().is_none_or(|ext| ext != "ron") { + return Err(color_eyre::eyre::eyre!( + "Theme file must have .ron extension: {}", + path.display() + )); + } + + let content = std::fs::read_to_string(path).map_err(|e| { + color_eyre::eyre::eyre!("Failed to read theme file '{}': {}", path.display(), e) + })?; + + let builder: ThemeBuilder = ron::de::from_str(&content).map_err(|e| { + color_eyre::eyre::eyre!("Failed to parse theme file '{}': {}", path.display(), e) + })?; + + let is_dark = builder.palette.is_dark(); + let mode_str = if is_dark { "dark" } else { "light" }; + + if let Ok(mode_config) = ThemeMode::config() { + let mut mode = ThemeMode::get_entry(&mode_config).unwrap_or_default(); + if mode.is_dark != is_dark { + let _ = mode.set_is_dark(&mode_config, is_dark); + } + } + + let (theme_config, builder_config) = if is_dark { + (Theme::dark_config(), ThemeBuilder::dark_config()) + } else { + (Theme::light_config(), ThemeBuilder::light_config()) + }; + + if let Ok(config) = builder_config { + builder.write_entry(&config).map_err(|e| { + color_eyre::eyre::eyre!("Failed to write theme builder config: {:?}", e) + })?; + } else { + return Err(color_eyre::eyre::eyre!( + "Failed to get {} theme builder config", + mode_str + )); + } + + let theme = builder.build(); + if let Ok(config) = theme_config { + theme + .write_entry(&config) + .map_err(|e| color_eyre::eyre::eyre!("Failed to write theme config: {:?}", e))?; + } else { + return Err(color_eyre::eyre::eyre!( + "Failed to get {} theme config", + mode_str + )); + } + + println!( + "Successfully imported {} theme from: {}", + mode_str, + path.display() + ); + + Ok(()) +} + fn init_localizer() { let localizer = crate::localize::localizer(); let requested_languages = DesktopLanguageRequester::requested_languages();