#[cfg(test)] mod tests; use crate::AnsiSequence; use core::convert::TryInto; use heapless::Vec; use nom::*; macro_rules! tag_parser { ($sig:ident, $tag:expr, $ret:expr) => { named!( $sig<&str, AnsiSequence>, do_parse!( tag!($tag) >> ($ret) ) ); } } named!( parse_int<&str, u32>, map_res!( nom::digit, |s: &str| s.parse::() ) ); // TODO kind of ugly, would prefer to pass in the default so we could use it for // all escapes with defaults (not just those that default to 1). named!( parse_def_cursor_int<&str, u32>, map!( nom::digit0, |s: &str| s.parse::().unwrap_or(1) ) ); named!( cursor_pos<&str, AnsiSequence>, do_parse!( tag!("[") >> x: parse_def_cursor_int >> opt!(tag!(";")) >> y: parse_def_cursor_int >> alt!( tag!("H") | tag!("f") ) >> (AnsiSequence::CursorPos(x, y)) ) ); named!( cursor_up<&str, AnsiSequence>, do_parse!( tag!("[") >> am: parse_def_cursor_int >> tag!("A") >> (AnsiSequence::CursorUp(am)) ) ); named!( cursor_down<&str, AnsiSequence>, do_parse!( tag!("[") >> am: parse_def_cursor_int >> tag!("B") >> (AnsiSequence::CursorDown(am)) ) ); named!( cursor_forward<&str, AnsiSequence>, do_parse!( tag!("[") >> am: parse_def_cursor_int >> tag!("C") >> (AnsiSequence::CursorForward(am)) ) ); named!( cursor_backward<&str, AnsiSequence>, do_parse!( tag!("[") >> am: parse_def_cursor_int >> tag!("D") >> (AnsiSequence::CursorBackward(am)) ) ); named!( graphics_mode1<&str, AnsiSequence>, do_parse!( tag!("[") >> val: parse_int >> tag!("m") >> val: expr_res!(val.try_into()) >> conv: expr_res!(Vec::from_slice(&[val])) >> (AnsiSequence::SetGraphicsMode(conv)) ) ); named!( graphics_mode2<&str, AnsiSequence>, do_parse!( tag!("[") >> val1: parse_int >> tag!(";") >> val2: parse_int >> tag!("m") >> val1: expr_res!(val1.try_into()) >> val2: expr_res!(val2.try_into()) >> conv: expr_res!(Vec::from_slice(&[ val1, val2, ])) >> (AnsiSequence::SetGraphicsMode(conv)) ) ); named!( graphics_mode3<&str, AnsiSequence>, do_parse!( tag!("[") >> val1: parse_int >> tag!(";") >> val2: parse_int >> tag!(";") >> val3: parse_int >> tag!("m") >> val1: expr_res!(val1.try_into()) >> val2: expr_res!(val2.try_into()) >> val3: expr_res!(val3.try_into()) >> conv: expr_res!(Vec::from_slice(&[ val1, val2, val3, ])) >> (AnsiSequence::SetGraphicsMode(conv)) ) ); named!( graphics_mode4<&str, AnsiSequence>, do_parse!( tag!("[m") >> (AnsiSequence::SetGraphicsMode(Vec::new())) ) ); named!( graphics_mode5<&str, AnsiSequence>, do_parse!( tag!("[") >> val1: parse_int >> tag!(";") >> val2: parse_int >> tag!(";") >> val3: parse_int >> tag!(";") >> val4: parse_int >> tag!(";") >> val5: parse_int >> tag!("m") >> val1: expr_res!(val1.try_into()) >> val2: expr_res!(val2.try_into()) >> val3: expr_res!(val3.try_into()) >> val4: expr_res!(val4.try_into()) >> val5: expr_res!(val5.try_into()) >> conv: expr_res!(Vec::from_slice(&[ val1, val2, val3, val4, val5, ])) >> (AnsiSequence::SetGraphicsMode(conv)) ) ); named!( graphics_mode<&str, AnsiSequence>, alt!( graphics_mode1 | graphics_mode2 | graphics_mode3 | graphics_mode4 | graphics_mode5 ) ); named!( set_mode<&str, AnsiSequence>, do_parse!( tag!("[=") >> mode: parse_int >> conv: expr_res!(mode.try_into()) >> tag!("h") >> (AnsiSequence::SetMode(conv)) ) ); named!( reset_mode<&str, AnsiSequence>, do_parse!( tag!("[=") >> mode: parse_int >> conv: expr_res!(mode.try_into()) >> tag!("l") >> (AnsiSequence::ResetMode(conv)) ) ); named!( set_top_and_bottom<&str, AnsiSequence>, do_parse!( tag!("[") >> x: parse_int >> tag!(";") >> y: parse_int >> tag!("r") >> (AnsiSequence::SetTopAndBottom(x, y)) ) ); tag_parser!(cursor_save, "[s", AnsiSequence::CursorSave); tag_parser!(cursor_restore, "[u", AnsiSequence::CursorRestore); tag_parser!(erase_display, "[2J", AnsiSequence::EraseDisplay); tag_parser!(erase_line, "[K", AnsiSequence::EraseLine); tag_parser!(hide_cursor, "[?25l", AnsiSequence::HideCursor); tag_parser!(show_cursor, "[?25h", AnsiSequence::ShowCursor); tag_parser!(cursor_to_app, "[?1h", AnsiSequence::CursorToApp); tag_parser!(set_new_line_mode, "[20h", AnsiSequence::SetNewLineMode); tag_parser!(set_col_132, "[?3h", AnsiSequence::SetCol132); tag_parser!(set_smooth_scroll, "[?4h", AnsiSequence::SetSmoothScroll); tag_parser!(set_reverse_video, "[?5h", AnsiSequence::SetReverseVideo); tag_parser!(set_origin_rel, "[?6h", AnsiSequence::SetOriginRelative); tag_parser!(set_auto_wrap, "[?7h", AnsiSequence::SetAutoWrap); tag_parser!(set_auto_repeat, "[?8h", AnsiSequence::SetAutoRepeat); tag_parser!(set_interlacing, "[?9h", AnsiSequence::SetInterlacing); tag_parser!(set_linefeed, "[20l", AnsiSequence::SetLineFeedMode); tag_parser!(set_cursorkey, "[?1l", AnsiSequence::SetCursorKeyToCursor); tag_parser!(set_vt52, "[?2l", AnsiSequence::SetVT52); tag_parser!(set_col80, "[?3l", AnsiSequence::SetCol80); tag_parser!(set_jump_scroll, "[?4l", AnsiSequence::SetJumpScrolling); tag_parser!(set_normal_video, "[?5l", AnsiSequence::SetNormalVideo); tag_parser!(set_origin_abs, "[?6l", AnsiSequence::SetOriginAbsolute); tag_parser!(reset_auto_wrap, "[?7l", AnsiSequence::ResetAutoWrap); tag_parser!(reset_auto_repeat, "[?8l", AnsiSequence::ResetAutoRepeat); tag_parser!(reset_interlacing, "[?9l", AnsiSequence::ResetInterlacing); tag_parser!(set_alternate_keypad, "=", AnsiSequence::SetAlternateKeypad); tag_parser!(set_numeric_keypad, ">", AnsiSequence::SetNumericKeypad); tag_parser!(set_uk_g0, "(A", AnsiSequence::SetUKG0); tag_parser!(set_uk_g1, ")A", AnsiSequence::SetUKG1); tag_parser!(set_us_g0, "(B", AnsiSequence::SetUSG0); tag_parser!(set_us_g1, ")B", AnsiSequence::SetUSG1); tag_parser!(set_g0_special, "(0", AnsiSequence::SetG0SpecialChars); tag_parser!(set_g1_special, ")0", AnsiSequence::SetG1SpecialChars); tag_parser!(set_g0_alternate, "(1", AnsiSequence::SetG0AlternateChar); tag_parser!(set_g1_alternate, ")1", AnsiSequence::SetG1AlternateChar); tag_parser!(set_g0_graph, "(2", AnsiSequence::SetG0AltAndSpecialGraph); tag_parser!(set_g1_graph, ")2", AnsiSequence::SetG1AltAndSpecialGraph); tag_parser!(set_single_shift2, "N", AnsiSequence::SetSingleShift2); tag_parser!(set_single_shift3, "O", AnsiSequence::SetSingleShift3); named!( combined<&str, AnsiSequence>, alt!( cursor_pos | cursor_up | cursor_down | cursor_forward | cursor_backward | cursor_save | cursor_restore | erase_display | erase_line | graphics_mode | set_mode | reset_mode | hide_cursor | show_cursor | cursor_to_app | set_new_line_mode | set_col_132 | set_smooth_scroll | set_reverse_video | set_origin_rel | set_auto_wrap | set_auto_repeat | set_interlacing | set_linefeed | set_cursorkey | set_vt52 | set_col80 | set_jump_scroll | set_normal_video | set_origin_abs | reset_auto_wrap | reset_auto_repeat | reset_interlacing | set_top_and_bottom | set_alternate_keypad | set_numeric_keypad | set_uk_g0 | set_uk_g1 | set_us_g0 | set_us_g1 | set_g0_special | set_g1_special | set_g0_alternate | set_g1_alternate | set_g0_graph | set_g1_graph | set_single_shift2 | set_single_shift3 ) ); named!( pub parse_escape<&str, AnsiSequence>, do_parse!( tag!("\u{1b}") >> seq: combined >> (seq) ) );