From 45be8267e6cb7139b8db06aa5875b0f99563a7e4 Mon Sep 17 00:00:00 2001 From: Frederic Laing Date: Wed, 3 Dec 2025 08:43:03 +0100 Subject: [PATCH] move cli import/export functions for themes to a the appearance module --- cosmic-settings/src/main.rs | 129 +---------------- .../src/pages/desktop/appearance/commands.rs | 133 ++++++++++++++++++ .../src/pages/desktop/appearance/mod.rs | 1 + 3 files changed, 140 insertions(+), 123 deletions(-) create mode 100644 cosmic-settings/src/pages/desktop/appearance/commands.rs diff --git a/cosmic-settings/src/main.rs b/cosmic-settings/src/main.rs index 249d5f6..cb68840 100644 --- a/cosmic-settings/src/main.rs +++ b/cosmic-settings/src/main.rs @@ -196,8 +196,12 @@ pub fn main() -> color_eyre::Result<()> { if let Some(PageCommands::Appearance { command: Some(cmd) }) = &args.sub_command { return match cmd { - AppearanceCommands::Import { path } => import_theme_cli(path), - AppearanceCommands::Export { path } => export_theme_cli(path), + AppearanceCommands::Import { path } => { + pages::desktop::appearance::commands::import_theme(path) + } + AppearanceCommands::Export { path } => { + pages::desktop::appearance::commands::export_theme(path) + } }; } @@ -215,127 +219,6 @@ 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 export_theme_cli(path: &std::path::Path) -> color_eyre::Result<()> { - use cosmic::cosmic_config::CosmicConfigEntry; - use cosmic::cosmic_theme::{ThemeBuilder, ThemeMode}; - - if path.extension().is_none_or(|ext| ext != "ron") { - return Err(color_eyre::eyre::eyre!( - "Theme file must have .ron extension: {}", - path.display() - )); - } - - let mode_config = ThemeMode::config() - .map_err(|e| color_eyre::eyre::eyre!("Failed to get theme mode config: {:?}", e))?; - - let mode = ThemeMode::get_entry(&mode_config).unwrap_or_default(); - let is_dark = mode.is_dark; - let mode_str = if is_dark { "dark" } else { "light" }; - - let builder_config = if is_dark { - ThemeBuilder::dark_config() - } else { - ThemeBuilder::light_config() - } - .map_err(|e| { - color_eyre::eyre::eyre!("Failed to get {} theme builder config: {:?}", mode_str, e) - })?; - - let builder = ThemeBuilder::get_entry(&builder_config).map_err(|e| { - color_eyre::eyre::eyre!("Failed to get {} theme builder: {:?}", mode_str, e) - })?; - - let ron_string = ron::ser::to_string_pretty(&builder, Default::default()) - .map_err(|e| color_eyre::eyre::eyre!("Failed to serialize theme to RON: {}", e))?; - - std::fs::write(path, ron_string).map_err(|e| { - color_eyre::eyre::eyre!("Failed to write theme file '{}': {}", path.display(), e) - })?; - - println!( - "Successfully exported {} theme to: {}", - mode_str, - path.display() - ); - - Ok(()) -} - fn init_localizer() { let localizer = crate::localize::localizer(); let requested_languages = DesktopLanguageRequester::requested_languages(); diff --git a/cosmic-settings/src/pages/desktop/appearance/commands.rs b/cosmic-settings/src/pages/desktop/appearance/commands.rs new file mode 100644 index 0000000..074d012 --- /dev/null +++ b/cosmic-settings/src/pages/desktop/appearance/commands.rs @@ -0,0 +1,133 @@ +// Copyright 2023 System76 +// SPDX-License-Identifier: GPL-3.0-only + +//! CLI commands for theme import and export. + +use cosmic::cosmic_config::CosmicConfigEntry; +use cosmic::cosmic_theme::{Theme, ThemeBuilder, ThemeMode}; +use std::path::Path; + +/// Import a theme from a RON file and apply it. +/// +/// # Errors +/// +/// Returns an error if the theme file cannot be read, parsed, or applied. +pub fn import_theme(path: &Path) -> color_eyre::Result<()> { + 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(()) +} + +/// Export the current theme to a RON file. +/// +/// # Errors +/// +/// Returns an error if the theme cannot be read or the file cannot be written. +pub fn export_theme(path: &Path) -> color_eyre::Result<()> { + if path.extension().is_none_or(|ext| ext != "ron") { + return Err(color_eyre::eyre::eyre!( + "Theme file must have .ron extension: {}", + path.display() + )); + } + + let mode_config = ThemeMode::config() + .map_err(|e| color_eyre::eyre::eyre!("Failed to get theme mode config: {:?}", e))?; + + let mode = ThemeMode::get_entry(&mode_config).unwrap_or_default(); + let is_dark = mode.is_dark; + let mode_str = if is_dark { "dark" } else { "light" }; + + let builder_config = if is_dark { + ThemeBuilder::dark_config() + } else { + ThemeBuilder::light_config() + } + .map_err(|e| { + color_eyre::eyre::eyre!("Failed to get {} theme builder config: {:?}", mode_str, e) + })?; + + let builder = ThemeBuilder::get_entry(&builder_config).map_err(|e| { + color_eyre::eyre::eyre!("Failed to get {} theme builder: {:?}", mode_str, e) + })?; + + let ron_string = ron::ser::to_string_pretty(&builder, Default::default()) + .map_err(|e| color_eyre::eyre::eyre!("Failed to serialize theme to RON: {}", e))?; + + std::fs::write(path, ron_string).map_err(|e| { + color_eyre::eyre::eyre!("Failed to write theme file '{}': {}", path.display(), e) + })?; + + println!( + "Successfully exported {} theme to: {}", + mode_str, + path.display() + ); + + Ok(()) +} diff --git a/cosmic-settings/src/pages/desktop/appearance/mod.rs b/cosmic-settings/src/pages/desktop/appearance/mod.rs index 37aa431..8983235 100644 --- a/cosmic-settings/src/pages/desktop/appearance/mod.rs +++ b/cosmic-settings/src/pages/desktop/appearance/mod.rs @@ -1,6 +1,7 @@ // Copyright 2023 System76 // SPDX-License-Identifier: GPL-3.0-only +pub mod commands; pub mod drawer; pub mod font_config; pub mod icon_themes;