nu_ansi_term/windows.rs
1/// Enables ANSI code support on Windows 10.
2///
3/// This uses Windows API calls to alter the properties of the console that
4/// the program is running in.
5///
6/// https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx
7///
8/// Returns a `Result` with the Windows error code if unsuccessful.
9#[cfg(windows)]
10pub fn enable_ansi_support() -> Result<(), u32> {
11 // ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76%
12 use windows::w;
13 use windows::Win32::Foundation::GetLastError;
14 use windows::Win32::Foundation::INVALID_HANDLE_VALUE;
15 use windows::Win32::Storage::FileSystem::{CreateFileW, OPEN_EXISTING};
16 use windows::Win32::Storage::FileSystem::{
17 FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_SHARE_WRITE,
18 };
19 use windows::Win32::System::Console::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
20 use windows::Win32::System::Console::{GetConsoleMode, SetConsoleMode};
21
22 unsafe {
23 // ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
24 // Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected
25 let console_handle = CreateFileW(
26 w!("CONOUT$"),
27 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
28 FILE_SHARE_WRITE,
29 std::ptr::null_mut(), // SECURITY_ATTRIBUTES
30 OPEN_EXISTING,
31 0, // FILE_FLAGS_AND_ATTRIBUTES
32 0, // hTemplateFile: HANDLE
33 );
34 if console_handle == INVALID_HANDLE_VALUE {
35 return Err(GetLastError());
36 }
37
38 // ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode
39 let mut console_mode = 0;
40 if 0 == GetConsoleMode(console_handle, &mut console_mode) {
41 return Err(GetLastError());
42 }
43
44 // VT processing not already enabled?
45 if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 {
46 // https://docs.microsoft.com/en-us/windows/console/setconsolemode
47 if 0 == SetConsoleMode(
48 console_handle,
49 console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING,
50 ) {
51 return Err(GetLastError());
52 }
53 }
54
55 Ok(())
56 }
57}