@@ -6,61 +6,89 @@ use core::{
66 str:: CharIndices ,
77} ;
88
9- fn consume_osc_end_exclusive ( it : & mut Peekable < CharIndices < ' _ > > , start : usize ) -> usize {
10- let mut end = start + 1 ;
11- let Some ( ( idx, ']' ) ) = it. next ( ) else {
12- return end;
13- } ;
14- end = idx + 1 ;
9+ enum EscStep {
10+ Continue ,
11+ End ,
12+ ConsumeNext ,
13+ }
1514
16- while let Some ( ( idx, c) ) = it. next ( ) {
17- end = idx + c. len_utf8 ( ) ;
18- match c {
19- '\u{07}' | '\u{9c}' => return end,
20- '\u{1b}' => {
21- if let Some ( ( next_idx, '\\' ) ) = it. peek ( ) {
22- end = * next_idx + 1 ;
23- it. next ( ) ;
24- return end;
25- }
26- }
27- _ => { }
15+ trait EscSequence {
16+ const START_CHAR : char ;
17+ fn on_char ( c : char ) -> EscStep ;
18+ fn on_escape ( next : Option < char > ) -> EscStep ;
19+ }
20+
21+ #[ derive( Clone , Copy , Debug ) ]
22+ struct OscSequence ;
23+
24+ impl EscSequence for OscSequence {
25+ const START_CHAR : char = ']' ;
26+
27+ fn on_char ( c : char ) -> EscStep {
28+ if c == '\u{07}' {
29+ EscStep :: End
30+ } else {
31+ EscStep :: Continue
2832 }
2933 }
3034
31- end
35+ fn on_escape ( next : Option < char > ) -> EscStep {
36+ if matches ! ( next, Some ( '\\' ) ) {
37+ EscStep :: End
38+ } else {
39+ EscStep :: Continue
40+ }
41+ }
42+ }
43+
44+ #[ derive( Clone , Copy , Debug ) ]
45+ struct DcsSequence ;
46+
47+ impl EscSequence for DcsSequence {
48+ const START_CHAR : char = 'P' ;
49+
50+ fn on_char ( _c : char ) -> EscStep {
51+ EscStep :: Continue
52+ }
53+
54+ fn on_escape ( next : Option < char > ) -> EscStep {
55+ match next {
56+ Some ( '\\' ) | None => EscStep :: End ,
57+ Some ( '\u{1b}' ) => EscStep :: ConsumeNext ,
58+ _ => EscStep :: Continue ,
59+ }
60+ }
3261}
3362
34- fn consume_dcs_end_exclusive ( it : & mut Peekable < CharIndices < ' _ > > , start : usize ) -> usize {
63+ fn consume_exclusive < S : EscSequence > ( it : & mut Peekable < CharIndices < ' _ > > , start : usize ) -> usize {
3564 let mut end = start + 1 ;
36- let Some ( ( idx, 'P' ) ) = it. next ( ) else {
65+ let Some ( ( idx, start_char ) ) = it. next ( ) else {
3766 return end;
3867 } ;
68+ if start_char != S :: START_CHAR {
69+ return end;
70+ }
3971 end = idx + 1 ;
4072
4173 while let Some ( ( idx, c) ) = it. next ( ) {
4274 end = idx + c. len_utf8 ( ) ;
4375 match c {
4476 '\u{9c}' => return end,
45- '\u{1b}' => {
46- let Some ( ( next_idx, next) ) = it. peek ( ) else {
47- return end;
48- } ;
49- match next {
50- '\u{1b}' => {
51- end = * next_idx + 1 ;
52- it. next ( ) ;
53- }
54- '\\' => {
77+ '\u{1b}' => match S :: on_escape ( it. peek ( ) . map ( |( _, next) | * next) ) {
78+ EscStep :: End => return end,
79+ EscStep :: ConsumeNext => {
80+ if let Some ( ( next_idx, _) ) = it. peek ( ) {
5581 end = * next_idx + 1 ;
5682 it. next ( ) ;
57- return end;
5883 }
59- _ => { }
6084 }
61- }
85+ EscStep :: Continue => { }
86+ } ,
6287 _ => { }
6388 }
89+ if matches ! ( S :: on_char( c) , EscStep :: End ) {
90+ return end;
91+ }
6492 }
6593
6694 end
@@ -231,8 +259,18 @@ fn find_ansi_code_exclusive(it: &mut Peekable<CharIndices>) -> Option<(usize, us
231259 '\u{1b}' => {
232260 it. next ( ) ;
233261 match it. peek ( ) {
234- Some ( ( _, ']' ) ) => return Some ( ( start, consume_osc_end_exclusive ( it, start) ) ) ,
235- Some ( ( _, 'P' ) ) => return Some ( ( start, consume_dcs_end_exclusive ( it, start) ) ) ,
262+ Some ( ( _, ']' ) ) => {
263+ return Some ( (
264+ start,
265+ consume_exclusive :: < OscSequence > ( it, start) ,
266+ ) )
267+ }
268+ Some ( ( _, 'P' ) ) => {
269+ return Some ( (
270+ start,
271+ consume_exclusive :: < DcsSequence > ( it, start) ,
272+ ) )
273+ }
236274 _ => {
237275 if let Some ( end) = find_dfa_end_exclusive_after_entry ( it) {
238276 return Some ( ( start, end) ) ;
0 commit comments