From 8ad14220eb2d9243f53cd6e9188ebfeab5bf37fc Mon Sep 17 00:00:00 2001 From: liwenkai <2020583117@qq.com> Date: Mon, 29 Jun 2026 19:58:33 +0800 Subject: [PATCH] =?UTF-8?q?fix(tui):=20Windows=20=E4=B9=9F=E6=8A=8A=20stde?= =?UTF-8?q?rr=20=E9=87=8D=E5=AE=9A=E5=90=91=E5=88=B0=E6=97=A5=E5=BF=97(Set?= =?UTF-8?q?StdHandle),=E9=81=BF=E5=85=8D=20LSP/=E9=94=99=E8=AF=AF=E8=BE=93?= =?UTF-8?q?=E5=87=BA=E7=B3=8A=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 1 + crates/deep-code-tui/Cargo.toml | 8 ++++++++ crates/deep-code-tui/src/ui.rs | 36 ++++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 3e9639c..c617da0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -950,6 +950,7 @@ dependencies = [ "tokio-util", "unicode-segmentation", "unicode-width 0.2.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/crates/deep-code-tui/Cargo.toml b/crates/deep-code-tui/Cargo.toml index 25b256a..e99ab4c 100644 --- a/crates/deep-code-tui/Cargo.toml +++ b/crates/deep-code-tui/Cargo.toml @@ -26,5 +26,13 @@ unicode-width = "0.2" tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync", "time"] } tokio-util = { version = "0.7", features = ["rt"] } +# Redirect stderr to the log file on Windows (SetStdHandle), mirroring the +# unix `dup2` path so stray writes can't paint over the alternate-screen TUI. +[target.'cfg(windows)'.dependencies] +windows-sys = { version = "0.59", features = [ + "Win32_Foundation", + "Win32_System_Console", +] } + [dev-dependencies] tempfile = "3" diff --git a/crates/deep-code-tui/src/ui.rs b/crates/deep-code-tui/src/ui.rs index 52489a6..b38794c 100644 --- a/crates/deep-code-tui/src/ui.rs +++ b/crates/deep-code-tui/src/ui.rs @@ -108,7 +108,41 @@ fn redirect_stderr_to_log() { } } -#[cfg(not(unix))] +/// Windows equivalent of the unix path: point the process's `STD_ERROR_HANDLE` +/// at the log file via `SetStdHandle`, so LSP/persistence `eprintln!`s land in +/// the log instead of corrupting the alternate-screen TUI. +#[cfg(windows)] +fn redirect_stderr_to_log() { + use std::os::windows::io::AsRawHandle; + + use windows_sys::Win32::Foundation::HANDLE; + use windows_sys::Win32::System::Console::{STD_ERROR_HANDLE, SetStdHandle}; + + let path = crate::cli::workspace_root() + .join(".deep-code") + .join("deep-code.log"); + if let Some(parent) = path.parent() { + let _ = std::fs::create_dir_all(parent); + } + let Ok(file) = std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(&path) + else { + return; + }; + let handle: HANDLE = file.as_raw_handle(); + // SAFETY: `handle` is a valid, writable file handle. SetStdHandle just + // records it as the process's stderr; `forget` keeps it open for the + // process lifetime (the alternate-screen TUI runs until exit), mirroring how + // the unix `dup2` fd outlives the dropped `File`. + unsafe { + SetStdHandle(STD_ERROR_HANDLE, handle); + } + std::mem::forget(file); +} + +#[cfg(not(any(unix, windows)))] fn redirect_stderr_to_log() {} fn run_loop(terminal: &mut AppTerminal, app: &mut App) -> Result<()> {