diff --git a/Cargo.lock b/Cargo.lock index a92419017..81e6a37b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2173,6 +2173,7 @@ dependencies = [ "nu-table", "nu-term-grid", "nu-test-support", + "nu-utils", "pretty_assertions", "pretty_env_logger", "rayon", @@ -2207,6 +2208,7 @@ dependencies = [ "nu-parser", "nu-path", "nu-protocol", + "nu-utils", "reedline", "thiserror", ] @@ -2267,6 +2269,7 @@ dependencies = [ "nu-table", "nu-term-grid", "nu-test-support", + "nu-utils", "num 0.4.0", "pathdiff", "polars", @@ -2448,6 +2451,13 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nu-utils" +version = "0.59.1" +dependencies = [ + "crossterm_winapi", +] + [[package]] name = "nu_plugin_example" version = "0.59.1" diff --git a/Cargo.toml b/Cargo.toml index 246369cd5..1bafce36f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ members = [ "crates/nu_plugin_gstat", "crates/nu_plugin_example", "crates/nu_plugin_query", + "crates/nu-utils", ] [dependencies] @@ -50,6 +51,7 @@ nu-protocol = { path = "./crates/nu-protocol", version = "0.59.1" } nu-system = { path = "./crates/nu-system", version = "0.59.1" } nu-table = { path = "./crates/nu-table", version = "0.59.1" } nu-term-grid = { path = "./crates/nu-term-grid", version = "0.59.1" } +nu-utils = { path = "./crates/nu-utils", version = "0.59.1" } pretty_env_logger = "0.4.0" rayon = "1.5.1" reedline = { git = "https://github.com/nushell/reedline", branch = "main" } @@ -90,7 +92,7 @@ opt-level = "s" # Optimize for size strip = "debuginfo" lto = "thin" -# build with `cargo build --profile profiling` +# build with `cargo build --profile profiling` # to analyze performance with tooling like linux perf [profile.profiling] inherits = "release" diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index 75028230f..be255fc4e 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -8,7 +8,7 @@ nu-engine = { path = "../nu-engine", version = "0.59.1" } nu-path = { path = "../nu-path", version = "0.59.1" } nu-parser = { path = "../nu-parser", version = "0.59.1" } nu-protocol = { path = "../nu-protocol", version = "0.59.1" } -# nu-ansi-term = { path = "../nu-ansi-term", version = "0.59.1" } +nu-utils = { path = "../nu-utils", version = "0.59.1" } nu-ansi-term = "0.42.0" nu-color-config = { path = "../nu-color-config" } diff --git a/crates/nu-cli/src/util.rs b/crates/nu-cli/src/util.rs index 04a81595b..f7f7afd83 100644 --- a/crates/nu-cli/src/util.rs +++ b/crates/nu-cli/src/util.rs @@ -1,16 +1,17 @@ +use crate::CliError; use log::trace; use nu_engine::eval_block; use nu_parser::{lex, parse, trim_quotes, Token, TokenContents}; -use std::io::Write; -use std::path::PathBuf; - -use crate::CliError; use nu_protocol::engine::StateWorkingSet; use nu_protocol::{ ast::Call, engine::{EngineState, Stack}, PipelineData, ShellError, Span, Value, }; +#[cfg(windows)] +use nu_utils::enable_vt_processing; +use std::io::Write; +use std::path::PathBuf; pub fn print_pipeline_data( input: PipelineData, @@ -459,29 +460,6 @@ pub fn external_exceptions(engine_state: &EngineState, stack: &Stack) -> Vec Result<(), ShellError> { - use crossterm_winapi::{ConsoleMode, Handle}; - - pub const ENABLE_PROCESSED_OUTPUT: u32 = 0x0001; - 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 - // also, instead of checking old_mode & mask, just set the mode already - - // if old_mode & mask == 0 { - console_mode - .set_mode(old_mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING)?; - // } - - Ok(()) -} - pub fn report_error( working_set: &StateWorkingSet, error: &(dyn miette::Diagnostic + Send + Sync + 'static), @@ -490,7 +468,7 @@ pub fn report_error( // reset vt processing, aka ansi because illbehaved externals can break it #[cfg(windows)] { - let _ = enable_vt_processing(); + let _ = nu_utils::enable_vt_processing(); } } diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index b46e30105..a848d800b 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -23,6 +23,7 @@ nu-system = { path = "../nu-system", version = "0.59.1" } nu-table = { path = "../nu-table", version = "0.59.1" } nu-term-grid = { path = "../nu-term-grid", version = "0.59.1" } nu-test-support = { path = "../nu-test-support", version = "0.59.1" } +nu-utils = { path = "../nu-utils", version = "0.59.1" } # Potential dependencies for extras base64 = "0.13.0" diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index f4109b76c..90d6eba40 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -63,6 +63,12 @@ impl Command for Table { 80usize }; + // reset vt processing, aka ansi because illbehaved externals can break it + #[cfg(windows)] + { + let _ = nu_utils::enable_vt_processing(); + } + match input { PipelineData::ExternalStream { .. } => Ok(input), PipelineData::Value(Value::Binary { val, .. }, ..) => { diff --git a/crates/nu-utils/.gitignore b/crates/nu-utils/.gitignore new file mode 100644 index 000000000..4c234e523 --- /dev/null +++ b/crates/nu-utils/.gitignore @@ -0,0 +1,22 @@ +/target +/scratch +**/*.rs.bk +history.txt +tests/fixtures/nuplayground +crates/*/target + +# Debian/Ubuntu +debian/.debhelper/ +debian/debhelper-build-stamp +debian/files +debian/nu.substvars +debian/nu/ + +# macOS junk +.DS_Store + +# JetBrains' IDE items +.idea/* + +# VSCode's IDE items +.vscode/* diff --git a/crates/nu-utils/Cargo.toml b/crates/nu-utils/Cargo.toml new file mode 100644 index 000000000..4ec2a0ab7 --- /dev/null +++ b/crates/nu-utils/Cargo.toml @@ -0,0 +1,17 @@ +[package] +authors = ["The Nushell Project Developers"] +description = "Nushell utility functions" +edition = "2021" +license = "MIT" +name = "nu-utils" +version = "0.59.1" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[[bin]] +name = "utils" +path = "src/main.rs" + +[dependencies] + +[target.'cfg(windows)'.dependencies] +crossterm_winapi = "0.9.0" diff --git a/crates/nu-utils/src/lib.rs b/crates/nu-utils/src/lib.rs new file mode 100644 index 000000000..c10876dab --- /dev/null +++ b/crates/nu-utils/src/lib.rs @@ -0,0 +1,3 @@ +pub mod utils; + +pub use utils::enable_vt_processing; diff --git a/crates/nu-utils/src/main.rs b/crates/nu-utils/src/main.rs new file mode 100644 index 000000000..dd86126cd --- /dev/null +++ b/crates/nu-utils/src/main.rs @@ -0,0 +1,10 @@ +#[cfg(windows)] +use nu_utils::utils::enable_vt_processing; + +fn main() { + // reset vt processing, aka ansi because illbehaved externals can break it + #[cfg(windows)] + { + let _ = enable_vt_processing(); + } +} diff --git a/crates/nu-utils/src/utils.rs b/crates/nu-utils/src/utils.rs new file mode 100644 index 000000000..9ce427c90 --- /dev/null +++ b/crates/nu-utils/src/utils.rs @@ -0,0 +1,25 @@ +use std::io::Result; + +pub fn enable_vt_processing() -> Result<()> { + #[cfg(windows)] + { + use crossterm_winapi::{ConsoleMode, Handle}; + + pub const ENABLE_PROCESSED_OUTPUT: u32 = 0x0001; + 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 + // also, instead of checking old_mode & mask, just set the mode already + + // if old_mode & mask == 0 { + console_mode + .set_mode(old_mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING)?; + // } + } + Ok(()) +}