use anyhow::Result;
#[cfg(target_os = "windows")]
pub fn configure_console() -> Result<()> {
configure_utf8_codepage();
enable_virtual_terminal_processing();
Ok(())
}
#[cfg(target_os = "windows")]
fn configure_utf8_codepage() {
use windows_sys::Win32::System::Console::{SetConsoleCP, SetConsoleOutputCP};
const CP_UTF8: u32 = 65001;
let ok_output = unsafe { SetConsoleOutputCP(CP_UTF8) };
let ok_input = unsafe { SetConsoleCP(CP_UTF8) };
if ok_output == 0 {
tracing::warn!("failed to configure SetConsoleOutputCP(65001)");
}
if ok_input == 0 {
tracing::warn!("failed to configure SetConsoleCP(65001)");
}
}
#[cfg(target_os = "windows")]
fn enable_virtual_terminal_processing() {
use windows_sys::Win32::System::Console::{
GetConsoleMode, GetStdHandle, SetConsoleMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING,
STD_ERROR_HANDLE, STD_OUTPUT_HANDLE,
};
use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE};
for (handle_id, label) in [
(STD_OUTPUT_HANDLE, "stdout"),
(STD_ERROR_HANDLE, "stderr"),
] {
let handle: HANDLE = unsafe { GetStdHandle(handle_id) };
if handle == 0 || handle == INVALID_HANDLE_VALUE {
tracing::debug!(handle = label, "console handle unavailable for VT mode");
continue;
}
let mut mode: u32 = 0;
let got = unsafe { GetConsoleMode(handle, &mut mode) };
if got == 0 {
tracing::debug!(handle = label, "GetConsoleMode failed (non-console handle)");
continue;
}
let new_mode = mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if new_mode == mode {
continue;
}
let set = unsafe { SetConsoleMode(handle, new_mode) };
if set == 0 {
tracing::warn!(
handle = label,
"failed to enable ENABLE_VIRTUAL_TERMINAL_PROCESSING"
);
} else {
tracing::debug!(handle = label, "virtual terminal processing enabled");
}
}
}
#[cfg(not(target_os = "windows"))]
#[allow(dead_code)]
pub fn configure_console() -> Result<()> {
Ok(())
}