feat(spaceshd): GetConfig/SetConfig handlers with live ConfigChanged broadcast

This commit is contained in:
2026-06-14 09:24:51 +07:00
parent c4746f9864
commit ad29665352
2 changed files with 74 additions and 4 deletions
+34
View File
@@ -35,6 +35,27 @@ pub struct Config {
}
impl Config {
/// Resolve to a client-facing view, applying defaults and the shell resolver.
pub fn to_view(&self) -> spacesh_proto::config_view::ConfigView {
spacesh_proto::config_view::ConfigView {
default_shell: self.resolved_shell(),
font_family: self.terminal.font_family.clone().unwrap_or_else(|| "JetBrains Mono".into()),
font_size: self.terminal.font_size.unwrap_or(13).clamp(10, 20),
theme: self.appearance.theme.clone().unwrap_or_else(|| "dark".into()),
accent: self.appearance.accent.clone().unwrap_or_else(|| "blue".into()),
}
}
/// Shell for a plain panel using THIS in-memory config
/// (env -> config -> passwd -> $SHELL -> /bin/sh).
pub fn resolved_shell(&self) -> String {
if let Ok(s) = std::env::var("SPACESH_SHELL") { if !s.is_empty() { return s; } }
if let Some(s) = &self.default_shell { if !s.is_empty() { return s.clone(); } }
if let Some(s) = login_shell() { return s; }
if let Ok(s) = std::env::var("SHELL") { if !s.is_empty() { return s; } }
"/bin/sh".into()
}
/// Load `~/.spacesh/config.toml`. Any error (missing file, bad TOML) yields defaults.
pub fn load() -> Self {
let Ok(dir) = crate::lifecycle::spacesh_dir() else { return Self::default() };
@@ -71,6 +92,8 @@ impl Config {
/// Order: `SPACESH_SHELL` env → `config.toml` `default_shell` → login shell
/// from the passwd DB → `$SHELL` → `/bin/sh`. The passwd lookup matters under
/// launchd, where `$SHELL` is typically absent (so a bash fallback would win).
// retained for the env-override test and potential startup use
#[allow(dead_code)]
pub fn default_shell() -> String {
if let Ok(s) = std::env::var("SPACESH_SHELL") {
if !s.is_empty() { return s; }
@@ -158,6 +181,17 @@ mod tests {
assert!(c.appearance.theme.is_none());
}
#[test]
fn to_view_applies_defaults_and_clamp() {
let mut c = Config::default();
c.terminal.font_size = Some(99);
let v = c.to_view();
assert_eq!(v.font_size, 20);
assert_eq!(v.theme, "dark");
assert_eq!(v.accent, "blue");
assert!(!v.font_family.is_empty());
}
#[test]
fn save_then_reload_round_trips() {
let dir = std::env::temp_dir().join(format!("spacesh-cfg-save-{}", std::process::id()));