diff --git a/src/lib.rs b/src/lib.rs index 0868af5..971916a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ mod enums; mod parsers; +mod traits; ///This is a library for parsing ANSI escape sequences. Currently all the basic escape sequences ///are implemented: @@ -18,6 +19,4 @@ mod parsers; /// was an ANSI Sequence. pub use enums::*; -pub use parsers::{ - ParserIterator -}; +pub use traits::AnsiParser; diff --git a/src/parsers.rs b/src/parsers.rs index 1af6edf..0d665c5 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -205,7 +205,7 @@ named!( ); named!( - parse_escape<&str, Output>, + pub parse_escape<&str, Output>, do_parse!( tag_s!("\u{1b}[") >> seq: combined >> @@ -213,62 +213,3 @@ named!( ) ); -pub struct ParserIterator<'a> { - dat: &'a str, -} - -impl<'a> Iterator for ParserIterator<'a> { - type Item = Output<'a>; - - fn next(&mut self) -> Option { - if self.dat == "" { - return None; - } - - let pos = self.dat.find('\u{1b}'); - if let Some(loc) = pos { - if loc == 0 { - let res = parse_escape(&self.dat[loc..]); - - if let Ok(ret) = res { - self.dat = &ret.0; - Some(ret.1) - }else{ - let pos = self.dat[(loc+1)..].find('\u{1b}'); - if let Some(loc) = pos { - //Added to because it's based one character ahead - let loc = loc+1; - - let temp = &self.dat[..loc]; - self.dat = &self.dat[loc..]; - - Some(Output::TextBlock(temp)) - }else{ - let temp = self.dat; - self.dat = ""; - - Some(Output::TextBlock(temp)) - } - } - - }else { - let temp = &self.dat[..loc]; - self.dat = &self.dat[loc..]; - - Some(Output::TextBlock(&temp)) - } - }else{ - let temp = self.dat; - self.dat = ""; - Some(Output::TextBlock(temp)) - } - } -} - -impl<'a> ParserIterator<'a> { - pub fn new(string: &'a str) -> ParserIterator<'a> { - ParserIterator { - dat: string, - } - } -} diff --git a/src/parsers/tests.rs b/src/parsers/tests.rs index b98f3d1..0e0ec7e 100644 --- a/src/parsers/tests.rs +++ b/src/parsers/tests.rs @@ -1,4 +1,6 @@ use super::*; +use crate::*; + use std::fmt::Write; macro_rules! test_parser { @@ -8,7 +10,6 @@ macro_rules! test_parser { let mut buff = String::new(); let ret = parse_escape($string); - println!("{:#?}", ret); assert!(ret.is_ok()); let ret = ret.unwrap().1; @@ -20,17 +21,54 @@ macro_rules! test_parser { } } -test_parser!(set_video_mode_a, "\u{1b}[4;31;42m"); -test_parser!(set_video_mode_b, "\u{1b}[4m"); +test_parser!(cursor_pos, "\u{1b}[10;5H"); +test_parser!(cursor_up, "\u{1b}[5A"); +test_parser!(cursor_down, "\u{1b}[5B"); +test_parser!(cursor_forward, "\u{1b}[5C"); +test_parser!(cursor_backward,"\u{1b}[5D"); +test_parser!(cursor_save, "\u{1b}[s"); +test_parser!(cursor_restore, "\u{1b}[u"); + +test_parser!(erase_display, "\u{1b}[2J"); +test_parser!(erase_line, "\u{1b}[K"); + +test_parser!(set_video_mode_a, "\u{1b}[4m"); +test_parser!(set_video_mode_b, "\u{1b}[4;42m"); +test_parser!(set_video_mode_c, "\u{1b}[4;31;42m"); test_parser!(reset_mode, "\u{1b}[=13l"); test_parser!(set_mode, "\u{1b}[=7h"); +test_parser!(show_cursor, "\u{1b}[?25h"); +test_parser!(hide_cursor, "\u{1b}[?25l"); +test_parser!(cursor_to_app, "\u{1b}[?1h"); + +test_parser!(set_newline_mode, "\u{1b}[20h"); +test_parser!(set_column_132, "\u{1b}[?3h"); +test_parser!(set_smooth_scroll, "\u{1b}[?4h"); +test_parser!(set_reverse_video, "\u{1b}[?5h"); +test_parser!(set_origin_rel, "\u{1b}[?6h"); +test_parser!(set_auto_wrap, "\u{1b}[?7h"); +test_parser!(set_auto_repeat, "\u{1b}[?8h"); +test_parser!(set_interlacing, "\u{1b}[?9h"); + +test_parser!(set_cursor_key_to_cursor, "\u{1b}[?1l"); + +test_parser!(set_linefeed, "\u{1b}[20l"); +test_parser!(set_vt52, "\u{1b}[?2l"); +test_parser!(set_col80, "\u{1b}[?3l"); +test_parser!(set_jump_scroll, "\u{1b}[?4l"); +test_parser!(set_normal_video, "\u{1b}[?5l"); +test_parser!(set_origin_abs, "\u{1b}[?6l"); +test_parser!(reset_auto_wrap, "\u{1b}[?7l"); +test_parser!(reset_auto_repeat, "\u{1b}[?8l"); +test_parser!(reset_interlacing, "\u{1b}[?9l"); + + #[test] fn test_parser_iterator() { - let parse_str = "\x1b[=25l\x1b[=7l\x1b[0m\x1b[36m\x1b[1m-`"; - - let strings: Vec = ParserIterator::new(parse_str) + let strings: Vec<_> = "\x1b[=25l\x1b[=7l\x1b[0m\x1b[36m\x1b[1m-`" + .ansi_parse() .collect(); assert_eq!(strings.len(), 6); @@ -38,8 +76,8 @@ fn test_parser_iterator() { #[test] fn test_parser_iterator_failure() { - let parse_str = "\x1b[=25l\x1b[=7l\x1b[0m\x1b[36;1;15;2m\x1b[1m-`"; - let strings: Vec = ParserIterator::new(parse_str) + let strings: Vec<_> = "\x1b[=25l\x1b[=7l\x1b[0m\x1b[36;1;15;2m\x1b[1m-`" + .ansi_parse() .collect(); assert_eq!(strings.len(), 6); diff --git a/src/traits.rs b/src/traits.rs new file mode 100644 index 0000000..ec0352f --- /dev/null +++ b/src/traits.rs @@ -0,0 +1,74 @@ +use crate::enums::{Output}; +use crate::parsers::parse_escape; + +pub trait AnsiParser { + fn ansi_parse<'a>(&'a self) -> AnsiParseIterator<'a>; +} + +impl AnsiParser for str { + fn ansi_parse<'a>(&'a self) -> AnsiParseIterator<'a> { + AnsiParseIterator { + dat: self + } + } +} + +impl AnsiParser for String { + fn ansi_parse<'a>(&'a self) -> AnsiParseIterator<'a> { + AnsiParseIterator { + dat: self + } + } +} + +pub struct AnsiParseIterator<'a> { + dat: &'a str, +} + +impl<'a> Iterator for AnsiParseIterator<'a> { + type Item = Output<'a>; + + fn next(&mut self) -> Option { + if self.dat == "" { + return None; + } + + let pos = self.dat.find('\u{1b}'); + if let Some(loc) = pos { + if loc == 0 { + let res = parse_escape(&self.dat[loc..]); + + if let Ok(ret) = res { + self.dat = &ret.0; + Some(ret.1) + }else{ + let pos = self.dat[(loc+1)..].find('\u{1b}'); + if let Some(loc) = pos { + //Added to because it's based one character ahead + let loc = loc+1; + + let temp = &self.dat[..loc]; + self.dat = &self.dat[loc..]; + + Some(Output::TextBlock(temp)) + }else{ + let temp = self.dat; + self.dat = ""; + + Some(Output::TextBlock(temp)) + } + } + + }else { + let temp = &self.dat[..loc]; + self.dat = &self.dat[loc..]; + + Some(Output::TextBlock(&temp)) + } + }else{ + let temp = self.dat; + self.dat = ""; + Some(Output::TextBlock(temp)) + } + } +}