@@ -32,7 +32,6 @@ pub struct OutputWidget {
3232 error_pane_placement : ErrorPanePlacement ,
3333 visible_range_x : Range < usize > ,
3434 visible_range_y : Range < usize > ,
35- highlight : String ,
3635 highlight_positions : Vec < ( usize , Range < usize > ) > ,
3736 highlight_index : usize ,
3837 pub error_display_mode : ErrorDisplayMode ,
@@ -55,7 +54,6 @@ impl OutputWidget {
5554 error_display_mode,
5655 output_height : 0u16 ,
5756 error_pane_placement,
58- highlight : String :: new ( ) ,
5957 highlight_positions : vec ! [ ] ,
6058 visible_range_x : 0 ..0 ,
6159 visible_range_y : 0 ..0 ,
@@ -94,57 +92,66 @@ impl OutputWidget {
9492 }
9593 }
9694
97- pub fn highlight ( & mut self , search_str : & str , case_sensitive : bool ) {
98- self . highlight = search_str. to_string ( ) ;
99- if !search_str. is_empty ( ) {
100- let pattern = if case_sensitive {
101- Regex :: new ( & regex:: escape ( & search_str) ) . unwrap ( )
95+ pub fn highlight ( & mut self , search_str : & str , case_sensitive : bool , regex : bool ) {
96+ if search_str. is_empty ( ) {
97+ self . highlight_positions = vec ! [ ] ;
98+ } else {
99+ let mut search_str = String :: from ( search_str) ;
100+
101+ if !case_sensitive {
102+ search_str = search_str. to_lowercase ( ) ;
103+ }
104+
105+ let pattern_res = if regex {
106+ Regex :: new ( & search_str)
102107 } else {
103- Regex :: new ( & regex:: escape ( & search_str. to_lowercase ( ) ) ) . unwrap ( )
108+ Regex :: new ( & regex:: escape ( & search_str) )
104109 } ;
105110
106- let positions = self
107- . output
108- . lines
109- . iter ( )
110- . enumerate ( )
111- . filter_map ( |( i, line) | {
112- let line_to_match = if case_sensitive {
113- line
114- } else {
115- & line. to_lowercase ( )
116- } ;
117- let matches = pattern
118- . find_iter ( line_to_match)
119- . map ( |m| ( i, m. start ( ) ..m. start ( ) + search_str. len ( ) ) )
120- . collect_vec ( ) ;
121- if !matches. is_empty ( ) {
122- Some ( matches)
123- } else {
124- None
125- }
126- } )
127- . flatten ( )
128- . collect :: < Vec < ( usize , Range < usize > ) > > ( ) ;
129-
130- // find the first match in the visible range otherwise start from the beginning
131- match positions
132- . iter ( )
133- . find_position ( |( line, _range) | line >= & self . visible_range_y . start )
134- {
135- Some ( ( z, _) ) => self . highlight_index = z,
136- None => self . highlight_index = 0 ,
137- }
111+ if let Ok ( pattern) = pattern_res {
112+ let positions = self
113+ . output
114+ . lines
115+ . iter ( )
116+ . enumerate ( )
117+ . filter_map ( |( i, line) | {
118+ let line_to_match = if case_sensitive {
119+ line
120+ } else {
121+ & line. to_lowercase ( )
122+ } ;
123+ let matches = pattern
124+ . find_iter ( line_to_match)
125+ . map ( |m| ( i, m. start ( ) ..m. end ( ) ) )
126+ . collect_vec ( ) ;
127+ if !matches. is_empty ( ) {
128+ Some ( matches)
129+ } else {
130+ None
131+ }
132+ } )
133+ . flatten ( )
134+ . collect :: < Vec < ( usize , Range < usize > ) > > ( ) ;
135+
136+ // find the first match in the visible range otherwise start from the beginning
137+ match positions
138+ . iter ( )
139+ . find_position ( |( line, _range) | line >= & self . visible_range_y . start )
140+ {
141+ Some ( ( z, _) ) => self . highlight_index = z,
142+ None => self . highlight_index = 0 ,
143+ }
138144
139- self . highlight_positions = positions;
145+ self . highlight_positions = positions;
140146
141- // focus on the first match
142- if !self . highlight_positions . is_empty ( ) {
143- let ( line, range) = self . highlight_positions [ self . highlight_index ] . clone ( ) ;
144- self . adjust_viewport_for_highlight ( line, range) ;
147+ // focus on the first match
148+ if !self . highlight_positions . is_empty ( ) {
149+ let ( line, range) = self . highlight_positions [ self . highlight_index ] . clone ( ) ;
150+ self . adjust_viewport_for_highlight ( line, range) ;
151+ }
152+ } else {
153+ self . highlight_positions = vec ! [ ] ;
145154 }
146- } else {
147- self . highlight_positions = vec ! [ ] ;
148155 }
149156 }
150157
@@ -155,7 +162,7 @@ impl OutputWidget {
155162
156163 if !self . visible_range_x . contains ( & range. start ) {
157164 if range. start < self . visible_range_x . len ( ) {
158- // scroll fully to the left if highligh is in the first "horizontal " page"
165+ // scroll fully to the left if highlight is in the first "horizontal page"
159166 self . offset . x = 0 ;
160167 } else {
161168 self . offset . x = range. start . saturating_sub ( self . visible_range_x . len ( ) / 4 ) ;
@@ -181,7 +188,6 @@ impl OutputWidget {
181188
182189 self . highlight_index = 0 ;
183190 self . highlight_positions = vec ! [ ] ;
184- self . highlight = String :: new ( ) ;
185191 }
186192
187193 pub fn handle_event ( & mut self , event : & Event ) {
@@ -593,7 +599,7 @@ mod tests {
593599 . unwrap ( ) ;
594600 assert_snapshot ! ( "highlight base" , terminal. backend( ) ) ;
595601
596- widget. highlight ( "line2" , false ) ;
602+ widget. highlight ( "line2" , false , false ) ;
597603 terminal
598604 . draw ( |frame| widget. render ( frame. area ( ) , frame. buffer_mut ( ) ) )
599605 . unwrap ( ) ;
@@ -624,7 +630,7 @@ mod tests {
624630 . unwrap ( ) ;
625631 assert_snapshot ! ( "highlight prev 4x" , terminal. backend( ) ) ;
626632
627- widget. highlight ( "line50" , false ) ;
633+ widget. highlight ( "line50" , false , false ) ;
628634 terminal
629635 . draw ( |frame| widget. render ( frame. area ( ) , frame. buffer_mut ( ) ) )
630636 . unwrap ( ) ;
@@ -649,7 +655,7 @@ mod tests {
649655 . unwrap ( ) ;
650656 assert_snapshot ! ( "highlight horizontal base" , terminal. backend( ) ) ;
651657
652- widget. highlight ( "hl" , false ) ;
658+ widget. highlight ( "hl" , false , false ) ;
653659 for i in 1 ..6 {
654660 widget. highlight_next ( ) ;
655661 terminal
0 commit comments