From 30a4187be4bc569b4389fc1dfd0abfa2bbe0addf Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:34:29 -0500 Subject: [PATCH] a potential solution that may fix vt processing (#13961) # Description This PR is related #11950 and serves as another potential fix alongside rolling it back with https://github.com/nushell/nushell/pull/13959. The idea here is to try and properly setup the input and output console modes. I searched through a log of GitHub code to come up with this, including deno, wezterm, conpty, among others. It seems to work but it would be great if someone else would be able to test. I added comments from the consoleapi.h from windows to know what the other flags are in case we need to make other changes. # User-Facing Changes # Tests + Formatting # After Submitting --- crates/nu-utils/src/utils.rs | 74 ++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/crates/nu-utils/src/utils.rs b/crates/nu-utils/src/utils.rs index ee575b5640..ea5df308b6 100644 --- a/crates/nu-utils/src/utils.rs +++ b/crates/nu-utils/src/utils.rs @@ -1,34 +1,68 @@ +#[cfg(windows)] +use crossterm_winapi::{ConsoleMode, Handle}; use lscolors::LsColors; use std::io::{Result, Write}; pub fn enable_vt_processing() -> Result<()> { #[cfg(windows)] { - use crossterm_winapi::{ConsoleMode, Handle}; + let console_out_mode = ConsoleMode::from(Handle::current_out_handle()?); + let old_out_mode = console_out_mode.mode()?; + let console_in_mode = ConsoleMode::from(Handle::current_in_handle()?); + let old_in_mode = console_in_mode.mode()?; - pub const ENABLE_PROCESSED_OUTPUT: u32 = 0x0001; - pub const ENABLE_VIRTUAL_TERMINAL_INPUT: u32 = 0x0200; - pub const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004; - let mask = ENABLE_VIRTUAL_TERMINAL_PROCESSING; - - let console_mode = ConsoleMode::from(Handle::current_out_handle()?); - let old_mode = console_mode.mode()?; - - // researching odd ansi behavior in windows terminal repo revealed that - // enable_processed_output and enable_virtual_terminal_processing should be used - - if old_mode & mask == 0 { - console_mode.set_mode( - old_mode - | ENABLE_PROCESSED_OUTPUT - | ENABLE_VIRTUAL_TERMINAL_PROCESSING - | ENABLE_VIRTUAL_TERMINAL_INPUT, - )? - } + enable_vt_processing_input(console_in_mode, old_in_mode)?; + enable_vt_processing_output(console_out_mode, old_out_mode)?; } Ok(()) } +#[cfg(windows)] +fn enable_vt_processing_input(console_in_mode: ConsoleMode, mode: u32) -> Result<()> { + // + // Input Mode flags: + // + // #define ENABLE_PROCESSED_INPUT 0x0001 + // #define ENABLE_LINE_INPUT 0x0002 + // #define ENABLE_ECHO_INPUT 0x0004 + // #define ENABLE_WINDOW_INPUT 0x0008 + // #define ENABLE_MOUSE_INPUT 0x0010 + // #define ENABLE_INSERT_MODE 0x0020 + // #define ENABLE_QUICK_EDIT_MODE 0x0040 + // #define ENABLE_EXTENDED_FLAGS 0x0080 + // #define ENABLE_AUTO_POSITION 0x0100 + // #define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 + + const ENABLE_PROCESSED_INPUT: u32 = 0x0001; + const ENABLE_LINE_INPUT: u32 = 0x0002; + const ENABLE_ECHO_INPUT: u32 = 0x0004; + const ENABLE_VIRTUAL_TERMINAL_INPUT: u32 = 0x0200; + + console_in_mode.set_mode( + mode | ENABLE_VIRTUAL_TERMINAL_INPUT + & ENABLE_ECHO_INPUT + & ENABLE_LINE_INPUT + & ENABLE_PROCESSED_INPUT, + ) +} + +#[cfg(windows)] +fn enable_vt_processing_output(console_out_mode: ConsoleMode, mode: u32) -> Result<()> { + // + // Output Mode flags: + // + // #define ENABLE_PROCESSED_OUTPUT 0x0001 + // #define ENABLE_WRAP_AT_EOL_OUTPUT 0x0002 + // #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 + // #define DISABLE_NEWLINE_AUTO_RETURN 0x0008 + // #define ENABLE_LVB_GRID_WORLDWIDE 0x0010 + + pub const ENABLE_PROCESSED_OUTPUT: u32 = 0x0001; + pub const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004; + + console_out_mode.set_mode(mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING) +} + pub fn stdout_write_all_and_flush(output: T) -> Result<()> where T: AsRef<[u8]>,