diff --git a/src/matcher.rs b/src/matcher.rs index 2e65ac3..3efd207 100644 --- a/src/matcher.rs +++ b/src/matcher.rs @@ -9,7 +9,9 @@ use onig::{ EncodedBytes, Regex, RegexOptions, Region, SearchOptions, Syntax, SyntaxBehavior, SyntaxOperator, }; -use onig_sys::{OnigEncCtype_ONIGENC_CTYPE_WORD, OnigEncodingUTF8}; +use onig_sys::{ + ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS, OnigEncCtype_ONIGENC_CTYPE_WORD, OnigEncodingUTF8, +}; use uucore::error::{UResult, USimpleError}; use uucore::show_warning; @@ -311,7 +313,14 @@ impl CompiledPattern { fn compile_with(pattern: &str, syntax: &Syntax, options: RegexOptions) -> UResult { Regex::with_options_and_encoding(pattern, options, syntax).map_err(|err| { - USimpleError::new(2, format!("invalid pattern \"{pattern}\": {err}")) + // A reversed range like `[b-a]` is ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS. + // GNU grep reports it simply as "Invalid range end" (no pattern + // echoed), so translate this code to match its diagnostic. + let message = match err.code() { + ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS => "Invalid range end".to_string(), + _ => format!("invalid pattern \"{pattern}\": {err}"), + }; + USimpleError::new(2, message) }) } diff --git a/tests/test_grep.rs b/tests/test_grep.rs index d612a40..5016993 100644 --- a/tests/test_grep.rs +++ b/tests/test_grep.rs @@ -141,6 +141,18 @@ fn ere_invalid_pattern_is_error() { .stderr_contains("invalid pattern"); } +#[test] +fn reversed_range_endpoints_match_gnu_message() { + // A reversed bracket range like `[b-a]` must fail with exit 2 and GNU's + // diagnostic "Invalid range end", in both basic and extended modes. + for args in [&["[b-a]"][..], &["-E", "[b-a]"][..]] { + let (_s, mut c) = ucmd(); + c.args(args) + .fails_with_code(2) + .stderr_contains("Invalid range end"); + } +} + #[test] fn quiet_match_overrides_file_error() { // With -q, a match makes grep exit 0 even if an earlier file could not be