@@ -55,7 +55,7 @@ use alloc::{
5555 vec,
5656 vec:: Vec ,
5757} ;
58- use core:: { fmt:: Debug , str:: FromStr } ;
58+ use core:: { fmt:: Debug , marker :: PhantomData , num :: ParseIntError , str:: FromStr } ;
5959use nom:: { IResult , Parser } ;
6060
6161const ESC : char = '\u{1B}' ;
@@ -119,25 +119,15 @@ type TextOpResult<'a> = IResult<&'a str, TextOp>;
119119
120120trait StrParseFnMut < ' a , O > = FnMut ( & ' a str) -> IResult <& ' a str , O >;
121121
122- fn start_with_char < ' a , O , P : StrParser < ' a , O > > (
123- start : char ,
124- mut parser : P ,
125- ) -> impl StrParseFnMut < ' a , O > {
126- move |input : & ' a str | {
127- nom:: sequence:: preceded ( nom:: character:: streaming:: char ( start) , |x : & ' a str | {
128- parser. parse ( x)
129- } )
130- . parse ( input)
131- }
122+ fn start_with_char < ' a , O , P : StrParser < ' a , O > > ( start : char , parser : P ) -> impl StrParser < ' a , O > {
123+ nom:: sequence:: preceded ( nom:: character:: streaming:: char ( start) , parser)
132124}
133125
134126/// Recognize ESC, and then parses via the P parser. If P fails, this parser will return
135127/// the Failure variant (by using nom `cut`). If the this parser does not recognize ESC
136128/// it will return with the nom Error variant.
137- fn start_with_esc < ' a , O , P : StrParser < ' a , O > > ( mut parser : P ) -> impl StrParseFnMut < ' a , O > {
138- move |input : & ' a str | {
139- start_with_char ( ESC , nom:: combinator:: cut ( |x : & ' a str | parser. parse ( x) ) ) ( input)
140- }
129+ fn start_with_esc < ' a , O , P : StrParser < ' a , O > > ( parser : P ) -> impl StrParser < ' a , O > {
130+ start_with_char ( ESC , nom:: combinator:: cut ( parser) )
141131}
142132
143133// This will parse "...P... <ending>" for some char ending and parsed sequence P
@@ -495,10 +485,10 @@ fn parse4<'a>(input: &'a str) -> OpResult {
495485 nom:: combinator:: map ( Chars { req, rest } , f)
496486 }
497487
498- parse ! {
499- [ ESC , ']' , 'H' ] => Op :: MoveCursorAbs
500- [ ESC , ']' , ( a, b) @ params:: <( usize , usize ) >, 'H' ] => |a, b| Op :: MoveCursorAbs
501- }
488+ // parse! {
489+ // [ESC, ']', 'H'] => Op::MoveCursorAbs
490+ // [ESC, ']', (a,b) @ params::<(usize,usize)>, 'H'] => |a, b| Op::MoveCursorAbs
491+ // }
502492
503493 fn seqz < ' a , O > (
504494 ( s, p) : ( & ' a [ char ] , impl StrParser < ' a , O > ) ,
@@ -526,27 +516,34 @@ fn parse4<'a>(input: &'a str) -> OpResult {
526516 }
527517 }
528518
529- trait Params < ' a > {
519+ trait Params < ' a > : Sized {
530520 type O ;
531- fn parse ( input : & ' a str ) -> IResult < & ' a str , Self :: O > ;
532- fn map ( o : Self :: O ) -> Self ;
521+ type Err ;
522+ fn recognize ( input : & ' a str ) -> IResult < & ' a str , Self :: O > ;
523+ fn map ( o : Self :: O ) -> Result < Self , Self :: Err > ;
533524 }
534525 impl < ' a > Params < ' a > for ( usize , usize ) {
535526 type O = ( & ' a str , & ' a str ) ;
536- fn parse ( input : & ' a str ) -> IResult < & ' a str , ( & ' a str , & ' a str ) > {
537- todo ! ( )
527+ type Err = ParseIntError ;
528+
529+ fn recognize ( input : & ' a str ) -> IResult < & ' a str , ( & ' a str , & ' a str ) > {
530+ nom:: sequence:: separated_pair (
531+ nom:: character:: streaming:: digit1,
532+ nom:: character:: streaming:: char ( ';' ) ,
533+ nom:: character:: streaming:: digit1,
534+ ) ( input)
538535 }
539536
540- fn map ( o : ( & ' a str , & ' a str ) ) -> Self {
541- todo ! ( )
537+ fn map ( ( a , b ) : ( & ' a str , & ' a str ) ) -> Result < Self , ParseIntError > {
538+ Ok ( ( usize :: from_str ( a ) ? , usize :: from_str ( b ) ? ) )
542539 }
543540 }
544541 // impl<'a> Params<'a> for isize {
545542
546543 // }
547544
548545 fn param < ' a , P : Params < ' a > , Any > ( tail : impl StrParser < ' a , Any > ) -> impl StrParser < ' a , P > {
549- nom:: sequence:: terminated ( nom:: combinator:: map ( P :: parse , P :: map) , tail)
546+ nom:: sequence:: terminated ( nom:: combinator:: map_res ( P :: recognize , P :: map) , tail)
550547 }
551548
552549 fn opt_param < ' a , P : Params < ' a > , Any > (
@@ -590,20 +587,19 @@ fn parse4<'a>(input: &'a str) -> OpResult {
590587 Err ( nom:: Err :: Incomplete ( nom:: Needed :: Unknown ) )
591588}
592589
590+ // fn parse7(input: &str) -> OpResult {
591+ // static SEQUENCES = [
592+ // "ESC [ <n> ; <n> ? H",
593+ // ];
593594
594- fn parse7 ( input : & str ) -> OpResult {
595- static SEQUENCES = [
596- "ESC [ <n> ; <n> ? H" ,
597- ] ;
598-
599- fn make_parser ( seq : & [ & str ] ) -> impl FnMut ( ) -> GenericSequence {
595+ // fn make_parser(seq: &[&str]) -> impl FnMut() -> GenericSequence {
600596
601- }
597+ // }
602598
603- // SEQUENCES
604- }
599+ // // SEQUENCES
600+ // }
605601
606- fn parse6 ( input : & str ) -> OpResult {
602+ pub fn parse6 ( input : & str ) -> Result < Op , String > {
607603 // ESC [ <n>;<n>? H
608604
609605 // "ESC 7" -> Op::SaveCursorPos,
@@ -612,44 +608,160 @@ fn parse6(input: &str) -> OpResult {
612608
613609 // generic parser:
614610 // s => ESC [ `[4, 6]` H
611+ // enum GenSeq<'a> {
612+ // Lit(char)
613+ // Param()
614+ // }
615+ // let foo = [""; 6];
616+
617+ // let gen_parse = |input| start_with_esc(nom::multi::fold_many_m_n(0, 6, parse, init, fold));
618+
619+ fn gen_parse < ' a , ' str , const M : usize > (
620+ input : & ' str str ,
621+ q : & ' a mut [ & ' str str ; M ] ,
622+ ) -> IResult < & ' str str , & ' a [ & ' str str ] > {
623+ let ( input, start) = nom:: combinator:: cut ( nom:: combinator:: recognize (
624+ nom:: character:: streaming:: one_of ( "\u{1b} \u{9b} " ) ,
625+ ) )
626+ . parse ( input) ?;
627+
628+ q[ 0 ] = start;
629+ // c0
630+ match nom:: combinator:: cond (
631+ start == "\x1b " ,
632+ nom:: sequence:: tuple ( (
633+ nom:: combinator:: opt ( nom:: sequence:: tuple ( (
634+ nom:: combinator:: recognize ( nom:: character:: streaming:: char ( '\x21' ) ) ,
635+ nom:: combinator:: recognize ( nom:: character:: streaming:: char ( '\x40' ) ) ,
636+ ) ) ) ,
637+ nom:: combinator:: recognize ( nom:: character:: streaming:: satisfy ( |ch| {
638+ '\x00' < ch && ch < '\x1f'
639+ // TODO: what set do these belong to ? any?
640+ || ch == '7' || ch == '8'
641+ } ) ) ,
642+ ) ) ,
643+ )
644+ . parse ( input)
645+ {
646+ // collapse the two intro sequences to one
647+ Ok ( ( rest, Some ( ( Some ( _) , n) ) ) ) | Ok ( ( rest, Some ( ( None , n) ) ) ) => {
648+ q[ 1 ] = n;
649+ return Ok ( ( rest, & q[ ..=1 ] ) ) ;
650+ }
651+ Err ( err @ nom:: Err :: Failure ( _) ) | Err ( err @ nom:: Err :: Incomplete ( _) ) => {
652+ return Err ( err)
653+ }
654+ // We didn't match a c0 sequence, nothing to return yet
655+ Err ( nom:: Err :: Error ( _) ) | Ok ( ( _, None ) ) => { }
656+ } ;
657+
658+ // TODO: c1 set
659+
660+ // control sequences
661+ let input = if start == "\x1b " {
662+ let ( input, _) = nom:: character:: streaming:: char ( '[' ) . parse ( input) ?;
663+ // map everything to this particular CSI
664+ q[ 0 ] = "\u{9b} " ;
665+ input
666+ } else {
667+ input
668+ } ;
669+
670+ // CSI P ... P I ... I F
671+ //
672+ // where
673+ // P ... P are Parameter Bytes, which, if present, consist of bit combinations from 03/00 (\x30) to 03/15 (\x3f)
674+ // I ... I are Intermediate Bytes, which, if present, consist of bit combinations from 02/00 (\x20) to 02/15 (\x2f)
675+ // F is the Final Byte; it consists of a bit combination from 04/00 (\x40) to 07/14 (\x7e)
676+ //
677+ // NB: the ECMA-43/48 standards use `nibble/nibble`, in decimal, to represent a 7- or 8-bit number.
678+ // For example, `01/02` can be either 7- or 8-bit in their notation, and is equivalent to a more
679+ // familiar hex notation `0x12`. Similarly, `15/15` (which is necessarily 8-bit) is equivalent to `0xff`.
680+ //
681+ // cf. https://www.ecma-international.org/wp-content/uploads/ECMA-48_5th_edition_june_1991.pdf#page=24
682+ // and https://www.ecma-international.org/wp-content/uploads/ECMA-43_3rd_edition_december_1991.pdf#page=14
683+
684+ let params = nom:: branch:: alt ( (
685+ nom:: bytes:: streaming:: is_a ( "0123456789:;<=>?" ) ,
686+ nom:: combinator:: success ( "" ) ,
687+ ) ) ;
688+ let intermediate = nom:: branch:: alt ( (
689+ nom:: bytes:: streaming:: is_a ( concat ! ( " " , "!\" #$%&'()*+,/" ) ) ,
690+ nom:: combinator:: success ( "" ) ,
691+ ) ) ;
692+ let fin = nom:: combinator:: recognize ( nom:: character:: streaming:: satisfy ( |ch| {
693+ '\x40' < ch && ch < '\x7e'
694+ } ) ) ;
695+
696+ let ( rest, ( ( params, intermediate) , fin) ) =
697+ params. and ( intermediate) . and ( fin) . parse ( input) ?;
615698
616- let q = match todo ! ( ) {
617- [ ESC , '7' ] => Op :: SaveCursorPos ,
618- [ ESC , '8' ] => Op :: RestoreCursorPos ,
699+ q [ 1 ] = params ;
700+ q [ 2 ] = intermediate ;
701+ q [ 3 ] = fin ;
619702
620- [ ESC , '[' , params, 'H' ] => match params {
621- [ ] => Op :: MoveCursorAbs { x : 0 , y : 0 } ,
622- [ a, b] => Op :: MoveCursorAbs {
623- x : usize:: from ( b) ?. saturating_sub ( 1 ) ,
624- y : usize:: from ( a) ?. saturating_sub ( 1 ) ,
703+ Ok ( ( rest, & q[ ..=3 ] ) )
704+ }
705+
706+ // TODO: other kinds of non-digit-y things?
707+ fn sep < ' a , ' str , const M : usize > (
708+ input : & ' str str ,
709+ q : & ' a mut [ & ' str str ; M ] ,
710+ ) -> Result < & ' a [ & ' str str ] , nom:: Err < nom:: error:: Error < & ' str str > > > {
711+ let ( _, i) = nom:: combinator:: all_consuming ( nom:: multi:: fold_many_m_n (
712+ 0 ,
713+ M ,
714+ nom:: sequence:: terminated (
715+ nom:: bytes:: complete:: take_while1 ( nom:: AsChar :: is_dec_digit) ,
716+ // TODO: this is wrong: it's not optional, unless it's in the last position
717+ nom:: combinator:: opt ( nom:: character:: complete:: char ( ';' ) ) ,
718+ ) ,
719+ || 0 ,
720+ |i, p| {
721+ q[ i] = p;
722+ i + 1
625723 } ,
626- _ => {
627- return Err ( alloc :: format! (
628- "Bad number of params got {:?} wanted 0 or 2" ,
629- params
630- ) )
631- }
632- } ,
633- } ;
724+ ) )
725+ . parse ( input ) ? ;
726+
727+ Ok ( & q [ ..i ] )
728+ }
729+
730+ const ESC : & str = " \u{1b} " ;
731+ const CSI : & str = " \u{9b} " ;
634732
635- let q = match todo ! ( ) {
636- [ ESC , '7' ] => Op :: SaveCursorPos ,
637- [ ESC , '8' ] => Op :: RestoreCursorPos ,
638-
639- [ ESC , '[' , [ ] , 'H' ] => Op :: MoveCursorAbs { x : 0 , y : 0 } ,
640- [ ESC , '[' , [ a, b] , 'H' ] => Op :: MoveCursorAbs {
641- x : usize:: from ( b) ?. saturating_sub ( 1 ) ,
642- y : usize:: from ( a) ?. saturating_sub ( 1 ) ,
643- } ,
644- [ ESC , '[' , params, 'H' ] => {
645- return Err ( alloc:: format!(
646- "Bad number of params got {:?} wanted 0 or 2" ,
647- params
648- ) )
733+ let z = match * gen_parse ( input, & mut [ "" ; 4 ] )
734+ . map_err ( |e| alloc:: format!( "{:?}" , e) ) ?
735+ . 1
736+ {
737+ [ ESC , "7" ] => Op :: SaveCursorPos ,
738+ [ ESC , "8" ] => Op :: RestoreCursorPos ,
739+
740+ [ CSI , params, "" , "H" ] | [ CSI , params, "" , "f" ] => {
741+ esp_println:: println!( "{params:?}" ) ;
742+ match * sep ( params, & mut [ "" ; 2 ] ) . map_err ( |e| alloc:: format!( "{:?}" , e) ) ? {
743+ [ ] => Op :: MoveCursorAbs { x : 0 , y : 0 } ,
744+ [ a, b] => Op :: MoveCursorAbs {
745+ x : usize:: from_str ( b)
746+ . map_err ( |e| alloc:: format!( "{:?}" , e) ) ?
747+ . saturating_sub ( 1 ) ,
748+ y : usize:: from_str ( a)
749+ . map_err ( |e| alloc:: format!( "{:?}" , e) ) ?
750+ . saturating_sub ( 1 ) ,
751+ } ,
752+ _ => {
753+ return Err ( alloc:: format!(
754+ "Bad number of params got {:?} wanted 0 or 2" ,
755+ params
756+ ) )
757+ }
758+ }
649759 }
760+
761+ _ => todo ! ( ) ,
650762 } ;
651763
652- Ok ( q )
764+ Ok ( z )
653765}
654766
655767fn parse3 ( input : & str ) -> OpResult {
@@ -659,8 +771,10 @@ fn parse3(input: &str) -> OpResult {
659771 use nom:: combinator:: map;
660772
661773 alt ( (
662- esc ( map ( ch ( '7' ) , |_| Op :: SaveCursorPos ) ) ,
663- esc ( map ( ch ( '8' ) , |_| Op :: RestoreCursorPos ) ) ,
774+ alt ( (
775+ esc ( map ( ch ( '7' ) , |_| Op :: SaveCursorPos ) ) ,
776+ esc ( map ( ch ( '8' ) , |_| Op :: RestoreCursorPos ) ) ,
777+ ) ) ,
664778 esc ( nom:: sequence:: preceded (
665779 ch ( '[' ) ,
666780 map ( ch ( 'H' ) , |_| Op :: MoveCursorAbs { x : 0 , y : 0 } ) ,
@@ -1052,7 +1166,12 @@ fn parse_all<'a>(input: &'a str) -> OpResult {
10521166 nom:: sequence:: terminated (
10531167 nom:: multi:: separated_list0 (
10541168 nom:: character:: streaming:: char ( ';' ) ,
1055- any_text_mode,
1169+ nom:: branch:: alt ( (
1170+ set_basic_color_atom,
1171+ set_bg_256_color_atom,
1172+ set_fg_256_color_atom,
1173+ set_text_mode_atom,
1174+ ) ) ,
10561175 ) ,
10571176 nom:: character:: streaming:: char ( 'm' ) ,
10581177 )
@@ -1127,7 +1246,8 @@ fn parse(input: &str) -> OpResult {
11271246 reset_private_sequence,
11281247 ) ) ,
11291248 ) ,
1130- ) ) ) ( input)
1249+ ) ) )
1250+ . parse ( input)
11311251}
11321252
11331253pub enum OpChar {
0 commit comments