@@ -6,61 +6,111 @@ 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+ struct EscAction {
10+ consume_next : bool ,
11+ end : bool ,
12+ }
1513
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- }
14+ trait EscSequence {
15+ const START_CHAR : char ;
16+ fn on_char ( c : char ) -> EscAction ;
17+ fn on_escape ( next : Option < char > ) -> EscAction ;
18+ }
19+
20+ #[ derive( Clone , Copy , Debug ) ]
21+ struct OscSequence ;
22+
23+ impl EscSequence for OscSequence {
24+ const START_CHAR : char = ']' ;
25+
26+ fn on_char ( c : char ) -> EscAction {
27+ EscAction {
28+ consume_next : false ,
29+ end : c == '\u{07}' ,
30+ }
31+ }
32+
33+ fn on_escape ( next : Option < char > ) -> EscAction {
34+ if matches ! ( next, Some ( '\\' ) ) {
35+ EscAction {
36+ consume_next : true ,
37+ end : true ,
38+ }
39+ } else {
40+ EscAction {
41+ consume_next : false ,
42+ end : false ,
2643 }
27- _ => { }
2844 }
2945 }
46+ }
3047
31- end
48+ #[ derive( Clone , Copy , Debug ) ]
49+ struct DcsSequence ;
50+
51+ impl EscSequence for DcsSequence {
52+ const START_CHAR : char = 'P' ;
53+
54+ fn on_char ( _c : char ) -> EscAction {
55+ EscAction {
56+ consume_next : false ,
57+ end : false ,
58+ }
59+ }
60+
61+ fn on_escape ( next : Option < char > ) -> EscAction {
62+ match next {
63+ Some ( '\\' ) => EscAction {
64+ consume_next : true ,
65+ end : true ,
66+ } ,
67+ None => EscAction {
68+ consume_next : false ,
69+ end : true ,
70+ } ,
71+ Some ( '\u{1b}' ) => EscAction {
72+ consume_next : true ,
73+ end : false ,
74+ } ,
75+ _ => EscAction {
76+ consume_next : false ,
77+ end : false ,
78+ } ,
79+ }
80+ }
3281}
3382
34- fn consume_dcs_end_exclusive ( it : & mut Peekable < CharIndices < ' _ > > , start : usize ) -> usize {
83+ fn consume_exclusive < S : EscSequence > ( it : & mut Peekable < CharIndices < ' _ > > , start : usize ) -> usize {
3584 let mut end = start + 1 ;
36- let Some ( ( idx, 'P' ) ) = it. next ( ) else {
85+ let Some ( ( idx, start_char ) ) = it. next ( ) else {
3786 return end;
3887 } ;
88+ if start_char != S :: START_CHAR {
89+ return end;
90+ }
3991 end = idx + 1 ;
4092
4193 while let Some ( ( idx, c) ) = it. next ( ) {
4294 end = idx + c. len_utf8 ( ) ;
4395 match c {
4496 '\u{9c}' => return end,
4597 '\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- '\\' => {
98+ let action = S :: on_escape ( it. peek ( ) . map ( |( _, next) | * next) ) ;
99+ if action. consume_next {
100+ if let Some ( ( next_idx, _) ) = it. peek ( ) {
55101 end = * next_idx + 1 ;
56102 it. next ( ) ;
57- return end;
58103 }
59- _ => { }
104+ }
105+ if action. end {
106+ return end;
60107 }
61108 }
62109 _ => { }
63110 }
111+ if S :: on_char ( c) . end {
112+ return end;
113+ }
64114 }
65115
66116 end
@@ -231,8 +281,12 @@ fn find_ansi_code_exclusive(it: &mut Peekable<CharIndices>) -> Option<(usize, us
231281 '\u{1b}' => {
232282 it. next ( ) ;
233283 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) ) ) ,
284+ Some ( ( _, ']' ) ) => {
285+ return Some ( ( start, consume_exclusive :: < OscSequence > ( it, start) ) )
286+ }
287+ Some ( ( _, 'P' ) ) => {
288+ return Some ( ( start, consume_exclusive :: < DcsSequence > ( it, start) ) )
289+ }
236290 _ => {
237291 if let Some ( end) = find_dfa_end_exclusive_after_entry ( it) {
238292 return Some ( ( start, end) ) ;
0 commit comments