From 207be3c771d281baae6e5fa0fb74be9a056e97a2 Mon Sep 17 00:00:00 2001 From: Can Celik Date: Tue, 1 Sep 2026 15:48:22 +0300 Subject: refactor: render the shell in the client (#3487) * feat: add opt-in client-rendered shell * feat: add client-owned shell mouse controls * feat: complete client-owned shell chrome * feat: add client-owned shell settings and notifications * feat: run client shell custom commands * feat: render popup terminals in client shell * feat: add client-owned scrollback and copy mode * fix: preserve client worktree trust defaults * feat: render startup diagnostics in client shell * feat: render onboarding in client shell * feat: render product announcements in client shell * feat: render release notes in client shell * feat: render mobile switcher in client shell * feat: render kitty graphics in client shell * fix: preserve client shell lifecycle coherence * refactor: route client shell commands through endpoint connections * refactor: make the client-rendered shell the default * refactor: remove monolithic launch mode * refactor: complete client-rendered shell cutover * perf: retain client pane surface updates * perf: scale retained pane surface updates * perf: remove remote pane input latency * test: make client shell checks platform-independent * fix: prevent client timer starvation * test: fix client shell platform gates * test: accept retained surfaces in cross-area checks * test: make client mode assertions platform-neutral * fix: badge only outdated integrations --- src/config.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 9 deletions(-) (limited to 'src/config.rs') diff --git a/src/config.rs b/src/config.rs index 02ad2fbc..117374ee 100644 --- a/src/config.rs +++ b/src/config.rs @@ -8,6 +8,7 @@ mod sound; mod tab_bar; mod theme; mod window_title; +mod write; pub use self::{ io::{ @@ -38,6 +39,7 @@ pub use self::{ }; pub(crate) use self::keybinds::parse_key_combo; +pub(crate) use self::write::{update_file_at, write_edit, ConfigEdit}; pub(crate) use self::{ io::upsert_top_level_bool, tab_bar::{ @@ -49,7 +51,28 @@ pub(crate) use self::{ window_title::{sanitize_window_title_text, window_title_diagnostics}, }; +pub(crate) use self::{keybinds::CommandKeybindType, model::KeysConfig}; + pub const CONFIG_PATH_ENV_VAR: &str = "HERDR_CONFIG_PATH"; + +pub(crate) fn is_keybinding_config_diagnostic(diagnostic: &str) -> bool { + if diagnostic.starts_with("config parse error:") || diagnostic.starts_with("config read error:") + { + return false; + } + diagnostic.contains("keybinding") || diagnostic.contains("keys.") +} + +pub(crate) fn config_diagnostic_summary_without_keybindings( + diagnostics: &[String], +) -> Option { + let diagnostics = diagnostics + .iter() + .filter(|diagnostic| !is_keybinding_config_diagnostic(diagnostic)) + .cloned() + .collect::>(); + config_diagnostic_summary(&diagnostics) +} pub const DEFAULT_SCROLLBACK_LIMIT_BYTES: usize = 10_000_000; pub const DEFAULT_MOUSE_SCROLL_LINES: usize = 3; pub const DEFAULT_MOBILE_WIDTH_THRESHOLD: u16 = 64; @@ -134,12 +157,6 @@ impl Config { }) } - #[cfg(test)] - pub fn live_keybinds(&self) -> Result> { - self.live_keybinds_with_diagnostics() - .map(|(live, _diagnostics)| live) - } - pub(crate) fn live_keybinds_with_diagnostics( &self, ) -> Result<(LiveKeybindConfig, Vec), Vec> { @@ -157,12 +174,21 @@ impl Config { keys: model::KeysConfigOverlay, } - toml::to_string_pretty(&KeysProfile { - keys: self.keys.local_profile(&self.keybinds()), - }) + let mut keys = self.keys.local_profile(&self.keybinds()); + keys.set_prefix(format_key_combo(self.prefix_key())); + toml::to_string_pretty(&KeysProfile { keys }) } } +pub(crate) fn keybindings_from_profile_toml(profile: &str) -> Result { + let config = toml::from_str::(profile) + .map_err(|err| format!("invalid keybinding profile: {err}"))?; + config + .live_keybinds_with_diagnostics() + .map(|(keybinds, _diagnostics)| keybinds) + .map_err(|diagnostics| diagnostics.join("; ")) +} + #[cfg(test)] mod tests { use super::*; @@ -192,6 +218,23 @@ command = "lazygit" assert!(!profile.contains("[[keys.command]]")); } + #[test] + fn local_keybindings_profile_publishes_the_effective_prefix_fallback() { + let config: Config = toml::from_str( + r#" +[keys] +prefix = "ctrl+" +"#, + ) + .unwrap(); + + let profile = config.local_keybindings_profile_toml().unwrap(); + let keybinds = keybindings_from_profile_toml(&profile).unwrap(); + + assert!(profile.contains("prefix = \"ctrl+b\"")); + assert_eq!(keybinds.prefix, config.prefix_key()); + } + #[test] fn local_keybindings_profile_preserves_user_default_provenance() { let config: Config = toml::from_str( -- cgit v1.2.3