added ansi_parse trait so things are more ergonomic
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
mod enums;
|
mod enums;
|
||||||
mod parsers;
|
mod parsers;
|
||||||
|
mod traits;
|
||||||
|
|
||||||
///This is a library for parsing ANSI escape sequences. Currently all the basic escape sequences
|
///This is a library for parsing ANSI escape sequences. Currently all the basic escape sequences
|
||||||
///are implemented:
|
///are implemented:
|
||||||
@@ -18,6 +19,4 @@ mod parsers;
|
|||||||
/// was an ANSI Sequence.
|
/// was an ANSI Sequence.
|
||||||
|
|
||||||
pub use enums::*;
|
pub use enums::*;
|
||||||
pub use parsers::{
|
pub use traits::AnsiParser;
|
||||||
ParserIterator
|
|
||||||
};
|
|
||||||
|
@@ -205,7 +205,7 @@ named!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
named!(
|
named!(
|
||||||
parse_escape<&str, Output>,
|
pub parse_escape<&str, Output>,
|
||||||
do_parse!(
|
do_parse!(
|
||||||
tag_s!("\u{1b}[") >>
|
tag_s!("\u{1b}[") >>
|
||||||
seq: combined >>
|
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<Self::Item> {
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
macro_rules! test_parser {
|
macro_rules! test_parser {
|
||||||
@@ -8,7 +10,6 @@ macro_rules! test_parser {
|
|||||||
let mut buff = String::new();
|
let mut buff = String::new();
|
||||||
let ret = parse_escape($string);
|
let ret = parse_escape($string);
|
||||||
|
|
||||||
println!("{:#?}", ret);
|
|
||||||
assert!(ret.is_ok());
|
assert!(ret.is_ok());
|
||||||
let ret = ret.unwrap().1;
|
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!(cursor_pos, "\u{1b}[10;5H");
|
||||||
test_parser!(set_video_mode_b, "\u{1b}[4m");
|
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!(reset_mode, "\u{1b}[=13l");
|
||||||
test_parser!(set_mode, "\u{1b}[=7h");
|
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]
|
#[test]
|
||||||
fn test_parser_iterator() {
|
fn test_parser_iterator() {
|
||||||
let parse_str = "\x1b[=25l\x1b[=7l\x1b[0m\x1b[36m\x1b[1m-`";
|
let strings: Vec<_> = "\x1b[=25l\x1b[=7l\x1b[0m\x1b[36m\x1b[1m-`"
|
||||||
|
.ansi_parse()
|
||||||
let strings: Vec<Output> = ParserIterator::new(parse_str)
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
assert_eq!(strings.len(), 6);
|
assert_eq!(strings.len(), 6);
|
||||||
@@ -38,8 +76,8 @@ fn test_parser_iterator() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parser_iterator_failure() {
|
fn test_parser_iterator_failure() {
|
||||||
let parse_str = "\x1b[=25l\x1b[=7l\x1b[0m\x1b[36;1;15;2m\x1b[1m-`";
|
let strings: Vec<_> = "\x1b[=25l\x1b[=7l\x1b[0m\x1b[36;1;15;2m\x1b[1m-`"
|
||||||
let strings: Vec<Output> = ParserIterator::new(parse_str)
|
.ansi_parse()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
assert_eq!(strings.len(), 6);
|
assert_eq!(strings.len(), 6);
|
||||||
|
74
src/traits.rs
Normal file
74
src/traits.rs
Normal file
@@ -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<Self::Item> {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user