setup_console/
lib.rs

1#[derive(Debug, Clone)]
2pub enum SetupConsoleErrorType {
3    InvalidOutputHandle,
4    GetConsoleModeFailed,
5    SetConsoleModeFailed,
6}
7
8#[derive(Debug, Clone)]
9pub struct SetupConsoleError(SetupConsoleErrorType);
10
11impl std::fmt::Display for SetupConsoleError {
12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13        write!(
14            f,
15            "{}",
16            match self.0 {
17                SetupConsoleErrorType::InvalidOutputHandle => "stdout is invalid",
18                SetupConsoleErrorType::GetConsoleModeFailed => "failed to get console mode",
19                SetupConsoleErrorType::SetConsoleModeFailed => "failed to set console mode",
20            }
21        )
22    }
23}
24
25#[cfg(target_os = "windows")]
26pub fn try_init() -> Result<(), SetupConsoleError> {
27    use windows_sys::Win32::{
28        Foundation::INVALID_HANDLE_VALUE,
29        System::Console::{
30            GetConsoleMode, GetStdHandle, SetConsoleMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING,
31            STD_OUTPUT_HANDLE,
32        },
33    };
34    unsafe {
35        let std_output = GetStdHandle(STD_OUTPUT_HANDLE);
36        if std_output == INVALID_HANDLE_VALUE {
37            return Err(SetupConsoleError(
38                SetupConsoleErrorType::InvalidOutputHandle,
39            ));
40        }
41        let mut console_mode = 0;
42        if GetConsoleMode(std_output, &mut console_mode) == 0 {
43            return Err(SetupConsoleError(
44                SetupConsoleErrorType::GetConsoleModeFailed,
45            ));
46        }
47        console_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
48        if SetConsoleMode(std_output, console_mode) == 0 {
49            return Err(SetupConsoleError(
50                SetupConsoleErrorType::SetConsoleModeFailed,
51            ));
52        }
53    }
54    Ok(())
55}
56
57#[cfg(not(target_os = "windows"))]
58pub fn try_init() -> Result<(), SetupConsoleError> {
59    Ok(())
60}
61
62#[cfg(target_os = "windows")]
63pub fn init() {
64    use windows_sys::Win32::{Foundation::GetLastError, System::Threading::ExitProcess};
65    if let Err(error) = try_init() {
66        eprintln!("Error: {}", error);
67        unsafe {
68            ExitProcess(GetLastError());
69        };
70    }
71}
72
73#[cfg(not(target_os = "windows"))]
74pub fn init() {}