From d5ce98a4c61a5bf2b849ab4158cf88209d652b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Wed, 27 Nov 2024 02:29:22 +0100 Subject: [PATCH 1/3] fix(task): strip ansi codes when printing tasks --- cli/tools/task.rs | 6 +++++- tests/integration/task_tests.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/cli/tools/task.rs b/cli/tools/task.rs index 1b83422ba93193..aac3201de024b3 100644 --- a/cli/tools/task.rs +++ b/cli/tools/task.rs @@ -725,7 +725,11 @@ fn print_available_tasks( writeln!(writer, " {slash_slash} {}", colors::italic_gray(line))?; } } - writeln!(writer, " {}", desc.task.command)?; + writeln!( + writer, + " {}", + console_static_text::ansi::strip_ansi_codes(&desc.task.command) + )?; if !desc.task.dependencies.is_empty() { writeln!( writer, diff --git a/tests/integration/task_tests.rs b/tests/integration/task_tests.rs index 56bab2970d051b..ca5d3b26e3cd0e 100644 --- a/tests/integration/task_tests.rs +++ b/tests/integration/task_tests.rs @@ -3,6 +3,9 @@ // Most of the tests for this are in deno_task_shell. // These tests are intended to only test integration. +use test_util as util; +use util::TestContextBuilder; + // use test_util::env_vars_for_npm_tests; // use test_util::itest; // use test_util::TestContext; @@ -28,3 +31,27 @@ // exit_code: 1, // http_server: true, // }); + +#[test] +fn deno_task_ansi_escape_codes() { + let context = TestContextBuilder::default().use_temp_cwd().build(); + let temp_dir = context.temp_dir(); + temp_dir.write("deno.json", r#"{ + "tasks": { + "dev": "echo 'BOOO!!!'", + "next": "\u001b[3F\u001b[0G- dev\u001b[1E\u001b[2K echo 'I am your friend.'" + } +} +"#); + + context + .new_command() + .args_vec(["task"]) + .with_pty(|mut console| { + console.expect("Available tasks:"); + console.expect("- dev"); + console.expect(" echo 'BOOO!!!'"); + console.expect("- next"); + console.expect(" - dev echo 'I am your friend.'") + }); +} From d0e9fea17a96395d51901c8d19dd126faffbf1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Wed, 27 Nov 2024 02:32:22 +0100 Subject: [PATCH 2/3] fix --- cli/tools/task.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/cli/tools/task.rs b/cli/tools/task.rs index aac3201de024b3..093455b55bef46 100644 --- a/cli/tools/task.rs +++ b/cli/tools/task.rs @@ -722,7 +722,13 @@ fn print_available_tasks( if let Some(description) = &desc.task.description { let slash_slash = colors::italic_gray("//"); for line in description.lines() { - writeln!(writer, " {slash_slash} {}", colors::italic_gray(line))?; + writeln!( + writer, + " {slash_slash} {}", + colors::italic_gray(console_static_text::ansi::strip_ansi_codes( + line + )) + )?; } } writeln!( @@ -731,11 +737,18 @@ fn print_available_tasks( console_static_text::ansi::strip_ansi_codes(&desc.task.command) )?; if !desc.task.dependencies.is_empty() { + let dependencies = desc + .task + .dependencies + .into_iter() + .map(|d| console_static_text::ansi::strip_ansi_codes(&d).to_string()) + .collect::>() + .join(", "); writeln!( writer, " {} {}", colors::gray("depends on:"), - colors::cyan(desc.task.dependencies.join(", ")) + colors::cyan(dependencies) )?; } } From e7255bbd30b3751ae55c7fb8d39b3ed798827576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Wed, 27 Nov 2024 03:14:36 +0100 Subject: [PATCH 3/3] control chars --- cli/tools/task.rs | 22 ++++++++++++++++----- tests/integration/task_tests.rs | 34 ++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/cli/tools/task.rs b/cli/tools/task.rs index 093455b55bef46..4752738c527a8c 100644 --- a/cli/tools/task.rs +++ b/cli/tools/task.rs @@ -8,6 +8,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; +use console_static_text::ansi::strip_ansi_codes; use deno_config::workspace::FolderConfigs; use deno_config::workspace::TaskDefinition; use deno_config::workspace::TaskOrScript; @@ -725,23 +726,21 @@ fn print_available_tasks( writeln!( writer, " {slash_slash} {}", - colors::italic_gray(console_static_text::ansi::strip_ansi_codes( - line - )) + colors::italic_gray(strip_ansi_codes_and_escape_control_chars(line)) )?; } } writeln!( writer, " {}", - console_static_text::ansi::strip_ansi_codes(&desc.task.command) + strip_ansi_codes_and_escape_control_chars(&desc.task.command) )?; if !desc.task.dependencies.is_empty() { let dependencies = desc .task .dependencies .into_iter() - .map(|d| console_static_text::ansi::strip_ansi_codes(&d).to_string()) + .map(|d| strip_ansi_codes_and_escape_control_chars(&d)) .collect::>() .join(", "); writeln!( @@ -755,3 +754,16 @@ fn print_available_tasks( Ok(()) } + +fn strip_ansi_codes_and_escape_control_chars(s: &str) -> String { + strip_ansi_codes(s) + .chars() + .map(|c| match c { + '\n' => "\\n".to_string(), + '\r' => "\\r".to_string(), + '\t' => "\\t".to_string(), + c if c.is_control() => format!("\\x{:02x}", c as u8), + c => c.to_string(), + }) + .collect() +} diff --git a/tests/integration/task_tests.rs b/tests/integration/task_tests.rs index ca5d3b26e3cd0e..f2e901228abd1c 100644 --- a/tests/integration/task_tests.rs +++ b/tests/integration/task_tests.rs @@ -52,6 +52,38 @@ fn deno_task_ansi_escape_codes() { console.expect("- dev"); console.expect(" echo 'BOOO!!!'"); console.expect("- next"); - console.expect(" - dev echo 'I am your friend.'") + console.expect(" - dev echo 'I am your friend.'"); + }); +} + +#[test] +fn deno_task_control_chars() { + let context = TestContextBuilder::default().use_temp_cwd().build(); + let temp_dir = context.temp_dir(); + temp_dir.write( + "deno.json", + r#"{ + "tasks": { + "dev": "echo 'BOOO!!!' && \r echo hi there is my command", + "serve": { + "description": "this is a\tm\rangled description", + "command": "echo hello" + } + } +} +"#, + ); + + context + .new_command() + .args_vec(["task"]) + .with_pty(|mut console| { + console.expect("Available tasks:"); + console.expect("- dev"); + console + .expect(" echo 'BOOO!!!' && \\r echo hi there is my command"); + console.expect("- serve"); + console.expect(" // this is a\\tm\\rangled description"); + console.expect(" echo hello"); }); }