mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
fix(tui/theme): suppress OSC background probe when theme is explicit
This commit is contained in:
+36
-4
@@ -14,6 +14,7 @@ use codex_core::protocol::AskForApproval;
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_core::config_types::ThemeColors;
|
||||
use codex_core::config_types::ThemeName;
|
||||
use regex_lite::Regex;
|
||||
use codex_login::AuthMode;
|
||||
use codex_login::CodexAuth;
|
||||
use codex_ollama::DEFAULT_OSS_MODEL;
|
||||
@@ -91,6 +92,21 @@ mod updates;
|
||||
|
||||
pub use cli::Cli;
|
||||
|
||||
fn theme_configured_in_config_file(codex_home: &std::path::Path) -> bool {
|
||||
let config_path = codex_home.join("config.toml");
|
||||
let Ok(contents) = std::fs::read_to_string(&config_path) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let table_pattern = Regex::new(r"(?m)^\s*\[tui\.theme\]").expect("valid regex");
|
||||
if table_pattern.is_match(&contents) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let inline_pattern = Regex::new(r"(?m)^\s*tui\.theme\s*=").expect("valid regex");
|
||||
inline_pattern.is_match(&contents)
|
||||
}
|
||||
|
||||
// (tests access modules directly within the crate)
|
||||
|
||||
pub async fn run_main(
|
||||
@@ -166,6 +182,9 @@ pub async fn run_main(
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let theme_override_in_cli = cli_kv_overrides
|
||||
.iter()
|
||||
.any(|(path, _)| path.starts_with("tui.theme"));
|
||||
|
||||
let mut config = {
|
||||
// Load configuration and support CLI overrides.
|
||||
@@ -184,7 +203,7 @@ pub async fn run_main(
|
||||
|
||||
// we load config.toml here to determine project state.
|
||||
#[allow(clippy::print_stderr)]
|
||||
let config_toml = {
|
||||
let (config_toml, theme_set_in_config_file) = {
|
||||
let codex_home = match find_codex_home() {
|
||||
Ok(codex_home) => codex_home,
|
||||
Err(err) => {
|
||||
@@ -193,8 +212,10 @@ pub async fn run_main(
|
||||
}
|
||||
};
|
||||
|
||||
let theme_set_in_config_file = theme_configured_in_config_file(&codex_home);
|
||||
|
||||
match load_config_as_toml_with_cli_overrides(&codex_home, cli_kv_overrides) {
|
||||
Ok(config_toml) => config_toml,
|
||||
Ok(config_toml) => (config_toml, theme_set_in_config_file),
|
||||
Err(err) => {
|
||||
eprintln!("Error loading config.toml: {err}");
|
||||
std::process::exit(1);
|
||||
@@ -202,6 +223,8 @@ pub async fn run_main(
|
||||
}
|
||||
};
|
||||
|
||||
let theme_configured_explicitly = theme_set_in_config_file || theme_override_in_cli;
|
||||
|
||||
let should_show_trust_screen = determine_repo_trust_state(
|
||||
&mut config,
|
||||
&config_toml,
|
||||
@@ -269,6 +292,7 @@ pub async fn run_main(
|
||||
should_show_trust_screen,
|
||||
startup_footer_notice,
|
||||
latest_upgrade_version,
|
||||
theme_configured_explicitly,
|
||||
)
|
||||
.map_err(|err| std::io::Error::other(err.to_string()))
|
||||
}
|
||||
@@ -279,6 +303,7 @@ fn run_ratatui_app(
|
||||
should_show_trust_screen: bool,
|
||||
startup_footer_notice: Option<String>,
|
||||
latest_upgrade_version: Option<String>,
|
||||
theme_configured_explicitly: bool,
|
||||
) -> color_eyre::Result<codex_core::protocol::TokenUsage> {
|
||||
color_eyre::install()?;
|
||||
|
||||
@@ -291,7 +316,7 @@ fn run_ratatui_app(
|
||||
tracing::error!("panic: {info}");
|
||||
prev_hook(info);
|
||||
}));
|
||||
maybe_apply_terminal_theme_detection(&mut config);
|
||||
maybe_apply_terminal_theme_detection(&mut config, theme_configured_explicitly);
|
||||
|
||||
let (mut terminal, terminal_info) = tui::init(&config)?;
|
||||
if config.tui.alternate_screen {
|
||||
@@ -406,7 +431,14 @@ fn cleanup_session_worktrees_and_print() {
|
||||
let _ = std::fs::remove_file(&file);
|
||||
}
|
||||
|
||||
fn maybe_apply_terminal_theme_detection(config: &mut Config) {
|
||||
fn maybe_apply_terminal_theme_detection(config: &mut Config, theme_configured_explicitly: bool) {
|
||||
if theme_configured_explicitly {
|
||||
tracing::info!(
|
||||
"Terminal theme autodetect skipped due to explicit theme configuration"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let theme = &mut config.tui.theme;
|
||||
|
||||
let autodetect_disabled = std::env::var("CODE_DISABLE_THEME_AUTODETECT")
|
||||
|
||||
@@ -221,10 +221,45 @@ fn query_osc_background_color() -> Option<(u8, u8, u8)> {
|
||||
tty_w.flush().ok()?;
|
||||
|
||||
let reply = read_osc_reply(&mut tty_r, Duration::from_millis(150))?;
|
||||
let _ = tty_w.write_all(b"\r\x1b[K");
|
||||
let _ = tty_w.flush();
|
||||
let reply_str = String::from_utf8_lossy(&reply);
|
||||
parse_osc_rgb(&reply_str)
|
||||
}
|
||||
|
||||
fn osc_background_query_supported() -> bool {
|
||||
if env::var("TMUX").is_ok() || env::var("STY").is_ok() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let term = env::var("TERM").unwrap_or_default();
|
||||
if term.is_empty() {
|
||||
return false;
|
||||
}
|
||||
let term_lower = term.to_ascii_lowercase();
|
||||
|
||||
const UNSUPPORTED_PREFIXES: [&str; 2] = ["screen", "tmux"];
|
||||
if UNSUPPORTED_PREFIXES
|
||||
.iter()
|
||||
.any(|prefix| term_lower.starts_with(prefix))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const UNSUPPORTED_TERMS: [&str; 5] = [
|
||||
"dumb",
|
||||
"linux",
|
||||
"vt100",
|
||||
"xterm-color",
|
||||
"ansi",
|
||||
];
|
||||
if UNSUPPORTED_TERMS.contains(&term_lower.as_str()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn xterm_color_to_rgb(idx: u32) -> Option<(u8, u8, u8)> {
|
||||
if idx <= 15 {
|
||||
return Some(ANSI_16_TO_RGB[idx as usize]);
|
||||
@@ -286,8 +321,10 @@ pub fn detect_dark_terminal_background() -> Option<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(rgb) = query_osc_background_color() {
|
||||
return Some(detect_dark_from_rgb(rgb));
|
||||
if osc_background_query_supported() {
|
||||
if let Some(rgb) = query_osc_background_color() {
|
||||
return Some(detect_dark_from_rgb(rgb));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(rgb) = parse_colorfgbg_env() {
|
||||
|
||||
Reference in New Issue
Block a user