1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
#[cfg(test)]
mod tests;

///The following are the implemented ANSI escape sequences. More to be added.
#[derive(Debug, PartialEq)]
pub enum AnsiSequence {
    CursorPos(u32, u32),
    CursorUp(u32),
    CursorDown(u32),
    CursorForward(u32),
    CursorBackward(u32),
    CursorSave,
    CursorRestore,
    EraseDisplay,
    EraseLine,
    SetGraphicsMode(Vec<u32>),
    SetMode(u8),
    ResetMode(u8),
    HideCursor,
    ShowCursor,
    CursorToApp,
    SetNewLineMode,
    SetCol132,
    SetSmoothScroll,
    SetReverseVideo,
    SetOriginRelative,
    SetAutoWrap,
    SetAutoRepeat,
    SetInterlacing,
    SetLineFeedMode,
    SetCursorKeyToCursor,
}

use std::fmt::Display;
impl Display for AnsiSequence {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(formatter, "\u{1b}[")?;
        
        use AnsiSequence::*;
        match self {
            CursorPos(line, col) 
                => write!(formatter, "{};{}H", line, col),
            CursorUp(amt)
                => write!(formatter, "{}A", amt),
            CursorDown(amt)
                => write!(formatter, "{}B", amt),
            CursorForward(amt)
                => write!(formatter, "{}C", amt),
            CursorBackward(amt)
                => write!(formatter, "{}D", amt),
            CursorSave
                => write!(formatter, "s"),
            CursorRestore
                => write!(formatter, "u"),
            EraseDisplay
                => write!(formatter, "2J"),
            EraseLine
                => write!(formatter, "K"),
            SetGraphicsMode(vec)
                => {
                    match vec.len() {
                        1 => write!(formatter, "{}m", vec[0]),
                        2 => write!(formatter, "{};{}m", vec[0], vec[1]),
                        3 => write!(formatter, "{};{};{}m", vec[0], vec[1], vec[2]),
                        _ => unreachable!()
                    }
                },
            SetMode(mode)
                => write!(formatter, "={}h", mode),
            ResetMode(mode)
                => write!(formatter, "={}l", mode),
            ShowCursor
                => write!(formatter, "?25h"),
            HideCursor
                => write!(formatter, "?25l"),
            CursorToApp
                => write!(formatter, "?1h"),
            SetNewLineMode
                => write!(formatter, "20h"),
            SetCol132
                => write!(formatter, "?3h"),
            SetSmoothScroll
                => write!(formatter, "?4h"),
            SetReverseVideo
                => write!(formatter, "?5h"),
            SetOriginRelative
                => write!(formatter, "?6h"),
            SetAutoWrap
                => write!(formatter, "?7h"),
            SetAutoRepeat
                => write!(formatter, "?8h"),
            SetInterlacing
                => write!(formatter, "?9h"),
            SetLineFeedMode
                => write!(formatter, "20l"),
            SetCursorKeyToCursor
                => write!(formatter, "?1l")
        }
    }
}

///This is what is outputted by the parsing iterator.
///Each block contains either straight-up text, or simply
///an ANSI escape sequence.
#[derive(Debug, PartialEq)]
pub enum Output<'a> {
    TextBlock(&'a str),
    Escape(AnsiSequence)
}