@@ -55,7 +55,7 @@ use alloc::{
5555 vec,
5656 vec:: Vec ,
5757} ;
58- use core:: { fmt:: Debug , marker :: PhantomData , num:: ParseIntError , str:: FromStr } ;
58+ use core:: { fmt:: Debug , num:: ParseIntError , str:: FromStr } ;
5959use nom:: { IResult , Parser } ;
6060
6161const ESC : char = '\u{1B}' ;
@@ -546,11 +546,17 @@ fn parse4<'a>(input: &'a str) -> OpResult {
546546 nom:: sequence:: terminated ( nom:: combinator:: map_res ( P :: recognize, P :: map) , tail)
547547 }
548548
549- fn opt_param < ' a , P : Params < ' a > , Any > (
549+ fn opt_param < ' a , P : Params < ' a > + Copy , Any > (
550550 tail : impl StrParser < ' a , Any > ,
551551 default : P ,
552552 ) -> impl StrParser < ' a , P > {
553- move |input| todo ! ( )
553+ nom:: sequence:: terminated (
554+ nom:: combinator:: map_res ( nom:: combinator:: opt ( P :: recognize) , move |opt| match opt {
555+ None => Ok ( default) ,
556+ Some ( o) => P :: map ( o) ,
557+ } ) ,
558+ tail,
559+ )
554560 }
555561
556562 use nom:: branch:: alt;
@@ -690,7 +696,7 @@ pub fn parse6(input: &str) -> Result<Op, String> {
690696 nom:: combinator:: success ( "" ) ,
691697 ) ) ;
692698 let fin = nom:: combinator:: recognize ( nom:: character:: streaming:: satisfy ( |ch| {
693- '\x40' < ch && ch < '\x7e'
699+ ( '\x40' ..= '\x7e' ) . contains ( & ch )
694700 } ) ) ;
695701
696702 let ( rest, ( ( params, intermediate) , fin) ) =
@@ -765,38 +771,110 @@ pub fn parse6(input: &str) -> Result<Op, String> {
765771}
766772
767773fn parse3 ( input : & str ) -> OpResult {
768- use self :: start_with_esc as esc;
769774 use nom:: branch:: alt;
770775 use nom:: character:: streaming:: char as ch;
771- use nom:: combinator:: map;
776+ use nom:: combinator:: { cut, fail} ;
777+ use nom:: sequence:: terminated as term;
778+
779+ // can't use trait aliases in the return type, see: https://github.com/rust-lang/rust-analyzer/issues/13410
780+ fn esc < ' a , P : StrParser < ' a , O > , O > (
781+ parser : P ,
782+ ) -> impl nom:: Parser < & ' a str , O , nom:: error:: Error < & ' a str > > {
783+ nom:: sequence:: preceded ( ch ( '\x1b' ) , parser)
784+ }
785+
786+ // can't use trait aliases in the return type, see: https://github.com/rust-lang/rust-analyzer/issues/13410
787+ fn csi < ' a , P : StrParser < ' a , O > , O > (
788+ parser : P ,
789+ ) -> impl nom:: Parser < & ' a str , O , nom:: error:: Error < & ' a str > > {
790+ nom:: sequence:: preceded (
791+ alt ( (
792+ nom:: combinator:: recognize ( ch ( '\u{9b}' ) ) ,
793+ nom:: combinator:: recognize ( nom:: bytes:: streaming:: tag ( "\x1b [" ) ) ,
794+ ) ) ,
795+ parser,
796+ )
797+ }
798+
799+ trait Params < ' a > : Sized {
800+ type O ;
801+ type Err ;
802+ fn recognize ( input : & ' a str ) -> IResult < & ' a str , Self :: O > ;
803+ fn map ( o : Self :: O ) -> Result < Self , Self :: Err > ;
804+ }
805+ impl < ' a > Params < ' a > for ( usize , usize ) {
806+ type O = ( & ' a str , & ' a str ) ;
807+ type Err = ParseIntError ;
808+
809+ fn recognize ( input : & ' a str ) -> IResult < & ' a str , ( & ' a str , & ' a str ) > {
810+ nom:: sequence:: separated_pair (
811+ nom:: character:: streaming:: digit1,
812+ nom:: character:: streaming:: char ( ';' ) ,
813+ nom:: character:: streaming:: digit1,
814+ ) ( input)
815+ }
816+
817+ fn map ( ( a, b) : ( & ' a str , & ' a str ) ) -> Result < Self , ParseIntError > {
818+ Ok ( ( usize:: from_str ( a) ?, usize:: from_str ( b) ?) )
819+ }
820+ }
821+
822+ fn param < ' a , P : Params < ' a > > ( ) -> impl StrParser < ' a , P > {
823+ nom:: combinator:: map_res ( P :: recognize, P :: map)
824+ }
825+
826+ fn final_char < I , E : nom:: error:: ParseError < I > > ( i : I ) -> IResult < I , char , E >
827+ where
828+ I : nom:: Slice < nom:: lib:: std:: ops:: RangeFrom < usize > > + nom:: InputIter ,
829+ <I as nom:: InputIter >:: Item : nom:: AsChar ,
830+ {
831+ nom:: character:: streaming:: satisfy ( |ch| ( '\x40' ..='\x7e' ) . contains ( & ch) ) . parse ( i)
832+ }
833+
834+ fn non_final < I , E : nom:: error:: ParseError < I > > ( i : I ) -> IResult < I , I , E >
835+ where
836+ I : nom:: Slice < nom:: lib:: std:: ops:: RangeFrom < usize > >
837+ + nom:: Slice < nom:: lib:: std:: ops:: RangeTo < usize > >
838+ + nom:: InputIter
839+ + Clone
840+ + nom:: Offset
841+ + nom:: InputLength ,
842+ <I as nom:: InputIter >:: Item : nom:: AsChar ,
843+ {
844+ nom:: combinator:: recognize ( nom:: multi:: many0_count ( nom:: character:: streaming:: satisfy (
845+ |ch| !( '\x40' ..='\x7e' ) . contains ( & ch) ,
846+ ) ) )
847+ . parse ( i)
848+ }
849+
850+ fn bail < I , O , E : nom:: error:: ParseError < I > > ( i : I ) -> IResult < I , O , E > {
851+ cut ( fail) ( i)
852+ }
772853
773854 alt ( (
774855 alt ( (
775- esc ( map ( ch ( '7' ) , |_| Op :: SaveCursorPos ) ) ,
776- esc ( map ( ch ( '8' ) , |_| Op :: RestoreCursorPos ) ) ,
777- ) ) ,
778- esc ( nom:: sequence:: preceded (
779- ch ( '[' ) ,
780- map ( ch ( 'H' ) , |_| Op :: MoveCursorAbs { x : 0 , y : 0 } ) ,
781- ) ) ,
782- esc ( nom:: sequence:: preceded (
783- ch ( '[' ) ,
784- map ( dual_int_parameter_sequence :: < usize > ( 'H' ) , |( a, b) | {
785- Op :: MoveCursorAbs {
786- x : b. saturating_sub ( 1 ) ,
787- y : a. saturating_sub ( 1 ) ,
788- }
789- } ) ,
856+ esc ( ch ( '7' ) ) . map ( |_| Op :: SaveCursorPos ) ,
857+ esc ( ch ( '8' ) ) . map ( |_| Op :: RestoreCursorPos ) ,
790858 ) ) ,
791- esc ( nom :: sequence :: preceded (
792- ch ( '[' ) ,
793- map ( dual_int_parameter_sequence :: < usize > ( 'f ') , |( a, b) | {
859+ csi ( alt ( ( alt ( (
860+ alt ( ( ch ( 'H' ) , ch ( 'f' ) ) ) . map ( |_| Op :: MoveCursorAbs { x : 0 , y : 0 } ) ,
861+ term ( param :: < ( usize , usize ) > ( ) , alt ( ( ch ( 'H ') , ch ( 'f' ) ) ) ) . map ( |( a, b) | {
794862 Op :: MoveCursorAbs {
795863 x : b. saturating_sub ( 1 ) ,
796864 y : a. saturating_sub ( 1 ) ,
797865 }
798866 } ) ,
799- ) ) ,
867+ term ( non_final, alt ( ( ch ( 'H' ) , ch ( 'f' ) ) ) ) . and_then ( bail) ,
868+ ) ) , ) ) ) ,
869+ // unknown sequence
870+ nom:: combinator:: recognize ( nom:: sequence:: preceded (
871+ alt ( (
872+ esc ( nom:: combinator:: success ( ( ) ) ) ,
873+ csi ( nom:: combinator:: success ( ( ) ) ) ,
874+ ) ) ,
875+ term ( non_final, final_char) ,
876+ ) )
877+ . and_then ( bail) ,
800878 ) ) ( input)
801879}
802880
0 commit comments