From c0991528100d72fa05e9f37196e280fef3995da6 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 2 Aug 2026 09:12:57 +0200 Subject: [PATCH] sed: underline the offending script character at a terminal When stderr is a terminal (or UUTILS_DIAG=always), quote the offending script line and underline the faulty character, in the layout uucore's diagnostics use. Pipes and the test suite still get the single-line message. Both error constructors handle this, so no call site changes. ScriptLocation now carries the line text, captured only when diagnostics are on and shared between commands from the same line, so semantic errors raised after compilation can still be drawn. Anything that cannot be drawn (non-UTF-8 script, empty line, no line recorded) leaves the message unchanged. --- Cargo.lock | 12 +++ Cargo.toml | 4 +- docs/src/extensions.md | 11 +++ src/sed/error_handling.rs | 158 +++++++++++++++++++++++++++++-- src/sed/script_char_provider.rs | 18 ++++ tests/by-util/test_sed.rs | 160 ++++++++++++++++++++++++++++++++ 6 files changed, 355 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53506ad1..d0f92a88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,6 +85,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ariadne" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8454c8a44ce2cb9cc7e7fae67fc6128465b343b92c6631e94beca3c8d1524ea5" +dependencies = [ + "unicode-width", + "yansi", +] + [[package]] name = "assert_fs" version = "1.1.4" @@ -1129,6 +1139,7 @@ dependencies = [ "tempfile", "terminal_size", "textwrap", + "unicode-width", "uucore", "uutests", "xattr", @@ -1453,6 +1464,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f24a5910ebbf2c0baf486a9125705f8e026a8f7741a3ea8cf5eca3c9257c9bdf" dependencies = [ + "ariadne", "clap", "dns-lookup", "fluent", diff --git a/Cargo.toml b/Cargo.toml index 52a7ab02..cb7e28f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,8 @@ sha2 = { version = "0.11.0", default-features = false, features = ["alloc"] } tempfile = "3.10.1" terminal_size = "0.4.2" textwrap = { version = "0.16.1", features = ["terminal_size"] } -uucore = { version = "0.12.0", features = ["libc"] } +unicode-width = "0.2.2" +uucore = { version = "0.12.0", features = ["diagnostics", "libc"] } rustix = "1.1.4" xattr = "1.3.1" @@ -81,6 +82,7 @@ regex = { workspace = true } tempfile = { workspace = true } terminal_size = { workspace = true } textwrap = { workspace = true } +unicode-width = { workspace = true } uucore = { workspace = true } rustix = { workspace = true } diff --git a/docs/src/extensions.md b/docs/src/extensions.md index c81b4b53..3b2a1adf 100644 --- a/docs/src/extensions.md +++ b/docs/src/extensions.md @@ -39,6 +39,17 @@ Below is a list of these extensions and incompatibilities. ## New extensions * Unicode characters can be specified in regular expression pattern, replacement and transliteration sequences using `\uXXXX` or `\UXXXXXXXX` sequences. +* On a terminal, script errors also quote the script line and underline the + character at fault (`UUTILS_DIAG=always` or `never` overrides this): + ``` + $ sed 's/a/b/q' + sed: