diff options
author | Matt Mastracci <matthew@mastracci.com> | 2024-02-18 21:51:06 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-19 04:51:06 +0000 |
commit | 7e6b94231290020b55f1d08fb03ea8132781abc5 (patch) | |
tree | 3767f12db7180b13175c5a7f33c731b192f891a5 /runtime/permissions/prompter.rs | |
parent | 9a43a2b4959be288034ef0c43f638542de2028b8 (diff) |
feat(core): highlight unprintable chars in permission prompts (#22468)
If we strip out unprintable chars, we don't see the full filename being
requested by permission prompts. Instead, we highlight and escape them
to make them visible.
Diffstat (limited to 'runtime/permissions/prompter.rs')
-rw-r--r-- | runtime/permissions/prompter.rs | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/runtime/permissions/prompter.rs b/runtime/permissions/prompter.rs index f054b31f3..da5979f0a 100644 --- a/runtime/permissions/prompter.rs +++ b/runtime/permissions/prompter.rs @@ -11,12 +11,24 @@ use std::io::StderrLock; use std::io::StdinLock; use std::io::Write as IoWrite; -/// Helper function to strip ansi codes and ASCII control characters. -fn strip_ansi_codes_and_ascii_control(s: &str) -> std::borrow::Cow<str> { - console_static_text::ansi::strip_ansi_codes(s) - .chars() - .filter(|c| !c.is_ascii_control()) - .collect() +/// Helper function to make control characters visible so users can see the underlying filename. +fn escape_control_characters(s: &str) -> std::borrow::Cow<str> { + if !s.contains(|c: char| c.is_ascii_control() || c.is_control()) { + return std::borrow::Cow::Borrowed(s); + } + let mut output = String::with_capacity(s.len() * 2); + for c in s.chars() { + match c { + c if c.is_ascii_control() => output.push_str( + &colors::white_bold_on_red(c.escape_debug().to_string()).to_string(), + ), + c if c.is_control() => output.push_str( + &colors::white_bold_on_red(c.escape_debug().to_string()).to_string(), + ), + c => output.push(c), + } + } + output.into() } pub const PERMISSION_EMOJI: &str = "⚠️"; @@ -249,9 +261,9 @@ impl PermissionPrompter for TtyPrompter { return PromptResponse::Deny; // don't grant permission if this fails } - let message = strip_ansi_codes_and_ascii_control(message); - let name = strip_ansi_codes_and_ascii_control(name); - let api_name = api_name.map(strip_ansi_codes_and_ascii_control); + let message = escape_control_characters(message); + let name = escape_control_characters(name); + let api_name = api_name.map(escape_control_characters); // print to stderr so that if stdout is piped this is still displayed. let opts: String = if is_unary { |