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() {}