@@ -55,8 +55,7 @@ static KEYWORD_RE: LazyLock<Regex> =
5555 LazyLock :: new ( || Regex :: new ( r"(?i)\b(?:true|false|null|nil|none|undefined|NaN)\b" ) . unwrap ( ) ) ;
5656
5757// 12. Version numbers (dotted: 2.4.1, 10.15.7 — exactly 3 segments)
58- static VERSION_RE : LazyLock < Regex > =
59- LazyLock :: new ( || Regex :: new ( r"\bv?\d+\.\d+\.\d+\b" ) . unwrap ( ) ) ;
58+ static VERSION_RE : LazyLock < Regex > = LazyLock :: new ( || Regex :: new ( r"\bv?\d+\.\d+\.\d+\b" ) . unwrap ( ) ) ;
6059
6160// 13. Numbers (2+ digits, or decimal, or with unit suffix — skip tiny standalone digits)
6261static NUMBER_RE : LazyLock < Regex > = LazyLock :: new ( || {
@@ -225,17 +224,17 @@ fn collect_all_regions(text: &str) -> Vec<MatchRegion> {
225224
226225 // 4. IPv4 addresses (validate octets)
227226 for caps in IPV4_RE . captures_iter ( text) {
228- if let Some ( m) = caps. get ( 0 ) {
229- if is_valid_ipv4 ( & caps) {
230- let region = MatchRegion {
231- start : m . start ( ) ,
232- end : m. end ( ) ,
233- style : ip_style ( ) ,
234- kind : TokenKind :: Ip ,
235- } ;
236- if ! overlaps ( & regions , & region ) {
237- regions . push ( region) ;
238- }
227+ if let Some ( m) = caps. get ( 0 )
228+ && is_valid_ipv4 ( & caps)
229+ {
230+ let region = MatchRegion {
231+ start : m. start ( ) ,
232+ end : m . end ( ) ,
233+ style : ip_style ( ) ,
234+ kind : TokenKind :: Ip ,
235+ } ;
236+ if ! overlaps ( & regions , & region) {
237+ regions . push ( region ) ;
239238 }
240239 }
241240 }
@@ -479,34 +478,34 @@ fn timestamp_style() -> Style {
479478fn highlight_plain_line ( parsed : & ParsedLine ) -> Line < ' _ > {
480479 let style = level_style ( parsed. level ) ;
481480
482- if let Some ( ref ts) = parsed. timestamp {
483- if let Some ( pos) = parsed. raw . find ( ts. as_str ( ) ) {
484- let ts_end = pos + ts. len ( ) ;
485- let ( ts_part, rest) = parsed. raw . split_at ( ts_end) ;
486- let mut spans = vec ! [ Span :: styled( ts_part. to_string( ) , timestamp_style( ) ) ] ;
487-
488- // Extract level keyword as a bold badge if present
489- if parsed. level . is_some ( ) {
490- if let Some ( level_match) = HIGHLIGHT_LEVEL_RE . find ( rest) {
491- let before_level = & rest[ ..level_match. start ( ) ] ;
492- let level_text = level_match. as_str ( ) ;
493- let after_level = & rest[ level_match. end ( ) ..] ;
494-
495- if !before_level. is_empty ( ) {
496- spans. push ( Span :: styled ( before_level. to_string ( ) , style) ) ;
497- }
498- spans. push ( Span :: styled (
499- level_text. to_string ( ) ,
500- style. add_modifier ( Modifier :: BOLD ) ,
501- ) ) ;
502- spans. extend ( tokenize_with_patterns ( after_level, style) ) ;
503- return Line :: from ( spans) ;
504- }
481+ if let Some ( ref ts) = parsed. timestamp
482+ && let Some ( pos) = parsed. raw . find ( ts. as_str ( ) )
483+ {
484+ let ts_end = pos + ts. len ( ) ;
485+ let ( ts_part, rest) = parsed. raw . split_at ( ts_end) ;
486+ let mut spans = vec ! [ Span :: styled( ts_part. to_string( ) , timestamp_style( ) ) ] ;
487+
488+ // Extract level keyword as a bold badge if present
489+ if parsed. level . is_some ( )
490+ && let Some ( level_match) = HIGHLIGHT_LEVEL_RE . find ( rest)
491+ {
492+ let before_level = & rest[ ..level_match. start ( ) ] ;
493+ let level_text = level_match. as_str ( ) ;
494+ let after_level = & rest[ level_match. end ( ) ..] ;
495+
496+ if !before_level. is_empty ( ) {
497+ spans. push ( Span :: styled ( before_level. to_string ( ) , style) ) ;
505498 }
506-
507- spans. extend ( tokenize_with_patterns ( rest, style) ) ;
499+ spans. push ( Span :: styled (
500+ level_text. to_string ( ) ,
501+ style. add_modifier ( Modifier :: BOLD ) ,
502+ ) ) ;
503+ spans. extend ( tokenize_with_patterns ( after_level, style) ) ;
508504 return Line :: from ( spans) ;
509505 }
506+
507+ spans. extend ( tokenize_with_patterns ( rest, style) ) ;
508+ return Line :: from ( spans) ;
510509 }
511510 Line :: from ( tokenize_with_patterns ( & parsed. raw , style) )
512511}
@@ -558,14 +557,14 @@ fn highlight_json_line(parsed: &ParsedLine) -> Line<'_> {
558557fn highlight_syslog_line ( parsed : & ParsedLine ) -> Line < ' _ > {
559558 let style = level_style ( parsed. level ) ;
560559
561- if let Some ( ref ts) = parsed. timestamp {
562- if let Some ( pos) = parsed. raw . find ( ts. as_str ( ) ) {
563- let ts_end = pos + ts . len ( ) ;
564- let ( ts_part , rest ) = parsed . raw . split_at ( ts_end ) ;
565- let mut spans = vec ! [ Span :: styled ( ts_part . to_string ( ) , timestamp_style ( ) ) ] ;
566- spans . extend ( tokenize_with_patterns ( rest , style ) ) ;
567- return Line :: from ( spans) ;
568- }
560+ if let Some ( ref ts) = parsed. timestamp
561+ && let Some ( pos) = parsed. raw . find ( ts. as_str ( ) )
562+ {
563+ let ts_end = pos + ts . len ( ) ;
564+ let ( ts_part , rest ) = parsed . raw . split_at ( ts_end ) ;
565+ let mut spans = vec ! [ Span :: styled ( ts_part . to_string ( ) , timestamp_style ( ) ) ] ;
566+ spans. extend ( tokenize_with_patterns ( rest , style ) ) ;
567+ return Line :: from ( spans ) ;
569568 }
570569 Line :: from ( tokenize_with_patterns ( & parsed. raw , style) )
571570}
@@ -672,32 +671,33 @@ pub fn apply_search_highlight(line: Line<'_>, pattern: &str) -> Line<'static> {
672671/// In pretty mode for JSON, returns the expanded multi-line JSON.
673672/// For everything else (or when pretty=false), returns a single line.
674673pub fn highlight_line_expanded ( parsed : & ParsedLine , pretty : bool ) -> Vec < Line < ' _ > > {
675- if pretty && parsed. format == LogFormat :: Json {
676- if let Some ( ref pretty_json) = parsed. pretty_json {
677- let style = level_style ( parsed. level ) ;
678- let level_str = match parsed. level {
679- Some ( LogLevel :: Fatal ) => "FTL" ,
680- Some ( LogLevel :: Error ) => "ERR" ,
681- Some ( LogLevel :: Warn ) => "WRN" ,
682- Some ( LogLevel :: Info ) => "INF" ,
683- Some ( LogLevel :: Debug ) => "DBG" ,
684- Some ( LogLevel :: Trace ) => "TRC" ,
685- None => "???" ,
686- } ;
674+ if pretty
675+ && parsed. format == LogFormat :: Json
676+ && let Some ( ref pretty_json) = parsed. pretty_json
677+ {
678+ let style = level_style ( parsed. level ) ;
679+ let level_str = match parsed. level {
680+ Some ( LogLevel :: Fatal ) => "FTL" ,
681+ Some ( LogLevel :: Error ) => "ERR" ,
682+ Some ( LogLevel :: Warn ) => "WRN" ,
683+ Some ( LogLevel :: Info ) => "INF" ,
684+ Some ( LogLevel :: Debug ) => "DBG" ,
685+ Some ( LogLevel :: Trace ) => "TRC" ,
686+ None => "???" ,
687+ } ;
687688
688- let mut lines = Vec :: new ( ) ;
689- // First line: level badge + separator
690- lines. push ( Line :: from ( vec ! [
691- Span :: styled( "--- " . to_string( ) , style. add_modifier( Modifier :: BOLD ) ) ,
692- Span :: styled( format!( "[{}]" , level_str) , level_badge_style( parsed. level) ) ,
693- Span :: styled( " " . to_string( ) , Style :: default ( ) ) ,
694- ] ) ) ;
695- // Pretty-printed JSON lines
696- for json_line in pretty_json. lines ( ) {
697- lines. push ( Line :: from ( Span :: styled ( format ! ( " {}" , json_line) , style) ) ) ;
698- }
699- return lines;
689+ let mut lines = Vec :: new ( ) ;
690+ // First line: level badge + separator
691+ lines. push ( Line :: from ( vec ! [
692+ Span :: styled( "--- " . to_string( ) , style. add_modifier( Modifier :: BOLD ) ) ,
693+ Span :: styled( format!( "[{}]" , level_str) , level_badge_style( parsed. level) ) ,
694+ Span :: styled( " " . to_string( ) , Style :: default ( ) ) ,
695+ ] ) ) ;
696+ // Pretty-printed JSON lines
697+ for json_line in pretty_json. lines ( ) {
698+ lines. push ( Line :: from ( Span :: styled ( format ! ( " {}" , json_line) , style) ) ) ;
700699 }
700+ return lines;
701701 }
702702 vec ! [ highlight_line( parsed) ]
703703}
0 commit comments