4949//! [Op(name), [Param(value)]]
5050//!
5151
52- use alloc:: { borrow:: ToOwned , string:: String , vec:: Vec } ;
52+ use alloc:: {
53+ borrow:: ToOwned ,
54+ string:: { String , ToString } ,
55+ vec,
56+ vec:: Vec ,
57+ } ;
5358use core:: { fmt:: Debug , str:: FromStr } ;
5459use nom:: { IResult , Parser } ;
5560
@@ -406,21 +411,21 @@ fn set_text_mode_atom(input: &str) -> TextOpResult {
406411 } ) ( input)
407412}
408413
409- /// ESC [ ? <anything > h
414+ /// ESC [ ? <numbers > h
410415fn set_private_sequence ( input : & str ) -> OpResult {
411416 nom:: sequence:: tuple ( (
412417 nom:: character:: streaming:: char ( '?' ) ,
413- nom:: bytes :: streaming:: take_till ( |c| c == 'h' ) ,
418+ nom:: character :: streaming:: digit0 ,
414419 nom:: character:: streaming:: char ( 'h' ) ,
415420 ) ) ( input)
416421 . map ( |( rest, ( _, b, _) ) | ( rest, Op :: DecPrivateSet ( b. to_owned ( ) ) ) )
417422}
418423
419- /// ESC [ ? <anything > l
424+ /// ESC [ ? <numbers > l
420425fn reset_private_sequence ( input : & str ) -> OpResult {
421426 nom:: sequence:: tuple ( (
422427 nom:: character:: streaming:: char ( '?' ) ,
423- nom:: bytes :: streaming:: take_till ( |c| c == 'l' ) ,
428+ nom:: character :: streaming:: digit0 ,
424429 nom:: character:: streaming:: char ( 'l' ) ,
425430 ) ) ( input)
426431 . map ( |( rest, ( _, b, _) ) | ( rest, Op :: DecPrivateReset ( b. to_owned ( ) ) ) )
@@ -477,10 +482,29 @@ pub enum OpChar {
477482 Op ( Op ) ,
478483}
479484
485+ #[ derive( Debug ) ]
480486pub enum OpStr {
481487 Str ( String ) ,
482488 Op ( Op ) ,
483- InSequence ,
489+ }
490+
491+ #[ derive( Debug ) ]
492+ pub struct ParseRes < ' a > {
493+ pub rest : & ' a str ,
494+ pub opstr : Vec < OpStr > ,
495+ }
496+
497+ impl < ' a > ParseRes < ' a > {
498+ fn from_ops ( ops : Vec < OpStr > ) -> ParseRes < ' a > {
499+ ParseRes {
500+ rest : "" ,
501+ opstr : ops,
502+ }
503+ }
504+
505+ fn new ( ops : Vec < OpStr > , rest : & ' a str ) -> ParseRes < ' a > {
506+ ParseRes { rest, opstr : ops }
507+ }
484508}
485509
486510impl From < char > for OpChar {
@@ -489,58 +513,51 @@ impl From<char> for OpChar {
489513 }
490514}
491515
492- pub struct TerminalEsc {
493- buffer : String ,
516+ pub fn parse_esc_str ( s : & str ) -> ParseRes {
517+ parse_esc_str_tail ( s , vec ! [ ] )
494518}
495519
496520///
497- /// Future buffered version
521+ /// buffered version
498522/// "hello" -> "hello" (nom returns Error)
499523/// "ESC[","garbage" -> `InSequence`, "arbage" (nom returns Failure)
500- /// "ESC[Ablah", "garbage" -> [Foo(Op), Foo("blah")], [Foo("garbage")],
524+ /// "ESC[Ablah", "garbage" -> [Foo(Op(A)), Foo("blah")], [Foo("garbage")],
525+ /// "garbageESC[Ablah" -> ["garbage", Op(A), "blah"]
526+ /// "garbageESC[Xblah" -> ["garbage", "blah"]
501527///
502- impl TerminalEsc {
503- pub fn new ( ) -> TerminalEsc {
504- TerminalEsc {
505- buffer : String :: new ( ) ,
506- }
528+ pub fn parse_esc_str_tail ( s : & str , mut current : Vec < OpStr > ) -> ParseRes {
529+ if s. is_empty ( ) {
530+ return ParseRes :: from_ops ( current) ;
507531 }
508-
509- pub fn push ( & mut self , c : char ) -> Option < OpChar > {
510- self . buffer . push ( c) ;
511-
512- let seq = self . buffer . as_str ( ) ;
513- match parse ( seq) {
514- Err ( nom:: Err :: Incomplete ( _) ) => {
515- // If we are incomplete, then do nothing
516- // print!("{}", c.escape_default());
517- None
518- }
519- Err ( nom:: Err :: Error ( _) ) => {
520- // If we got an error, then we didn't recognize an esc seq at all
521- // So pop the char back off the buffer
522- self . buffer . pop ( ) . map ( OpChar :: from)
523- // h e l l o
524- }
525- Err ( nom:: Err :: Failure ( _) ) => {
526- // And clear the buffer
527- // ESC [ 6 * ESC [ 6 * ESC [ 6 * h e l l o literally the word loop and then some returns
528-
529- // If failure, then we were in a sequence but bombed out, and consume all the chars
530- self . buffer . clear ( ) ;
531- None
532- }
533- Ok ( ( _, op) ) => {
534- // If we parsed an escape sequence, then clear the buffer and return the Op
535- self . buffer . clear ( ) ;
536- Some ( OpChar :: Op ( op) )
537- }
532+ match parse ( s) {
533+ Err ( nom:: Err :: Incomplete ( _) ) => {
534+ // If we are incomplete, then do nothing
535+ // print!("{}", c.escape_default());
536+ ParseRes :: new ( current, s)
538537 }
539- }
540- }
538+ Err ( nom:: Err :: Error ( _) ) => {
539+ // If we got an error, then we didn't recognize an esc seq at all
540+ // So pop the char back off the buffer
541+ let ( rest, esc) = s. find ( ESC ) . map_or ( ( s, "" ) , |i| s. split_at ( i) ) ;
542+ // abcde,ESC[
543+ current. push ( OpStr :: Str ( rest. to_string ( ) ) ) ;
544+ parse_esc_str_tail ( esc, current)
545+ // h e l l o
546+ }
547+ Err ( nom:: Err :: Failure ( e) ) => {
548+ // And clear the buffer
549+ // ESC [ 6 * ESC [ 6 * ESC [ 6 * h e l l o literally the word loop and then some returns
550+
551+ // If failure, then we were in a sequence but bombed out, and consume all the chars
552+ // ESC [ XYZ
553+ let skip_index = e. input . ceil_char_boundary ( 1 ) ;
554+ parse_esc_str_tail ( & e. input [ skip_index..] , current)
555+ }
556+ Ok ( ( rest, op) ) => {
557+ // If we parsed an escape sequence, then clear the buffer and return the Op
541558
542- impl Default for TerminalEsc {
543- fn default ( ) -> Self {
544- TerminalEsc :: new ( )
559+ current . push ( OpStr :: Op ( op ) ) ;
560+ parse_esc_str_tail ( rest , current )
561+ }
545562 }
546563}
0 commit comments