1 use crate::code::AnsiCode; 2 use crate::error::Error; 3 use std::{convert::TryInto, slice::Iter}; 4 use tui::style::{Color, Modifier, Style}; 5 6 #[derive(Debug)] 7 pub struct Stack<T> { 8 st: Vec<T>, 9 lock: bool, 10 } 11 12 impl<T> Stack<T> { new() -> Self13 pub fn new() -> Self { 14 Self { 15 st: Vec::<T>::new(), 16 lock: true, 17 } 18 } push(&mut self, value: T)19 pub fn push(&mut self, value: T) { 20 self.st.push(value); 21 } pop(&mut self) -> Option<T>22 pub fn pop(&mut self) -> Option<T> { 23 self.st.pop() 24 } first(&self) -> Option<&T>25 pub fn first(&self) -> Option<&T> { 26 self.st.first() 27 } last(&self) -> Option<&T>28 pub fn last(&self) -> Option<&T> { 29 self.st.last() 30 } iter(&mut self) -> Iter<T>31 pub fn iter(&mut self) -> Iter<T> { 32 self.st.iter() 33 } len(&mut self) -> usize34 pub fn len(&mut self) -> usize { 35 self.st.len() 36 } 37 // pub fn append(&mut self, other: &mut Vec<T>) { 38 // self.st.append(other) 39 // } clear(&mut self)40 pub fn clear(&mut self) { 41 self.st.clear(); 42 } lock(&mut self)43 pub fn lock(&mut self) { 44 self.st.clear(); 45 self.lock = true 46 } unlock(&mut self)47 pub fn unlock(&mut self) { 48 self.st.clear(); 49 self.lock = false 50 } 51 // pub fn is_locked(&self) -> bool { 52 // self.lock 53 // } is_empty(&self) -> bool54 pub fn is_empty(&self) -> bool { 55 self.st.is_empty() 56 } is_unlocked(&self) -> bool57 pub fn is_unlocked(&self) -> bool { 58 !self.lock 59 } 60 } 61 62 impl Stack<u8> { parse_usize(&mut self) -> Result<usize, Error>63 pub fn parse_usize(&mut self) -> Result<usize, Error> { 64 if self.is_empty() { 65 return Err(Error::UsizeParsingError); 66 } 67 let mut num: usize = 0; 68 for n in self.iter() { 69 // num = num * 10 + (n.saturating_sub(48_u8)) as usize 70 num = num * 10 + (n - 48_u8) as usize 71 } 72 self.clear(); 73 Ok(num) 74 } parse_color(&mut self) -> Result<Color, Error>75 pub fn parse_color(&mut self) -> Result<Color, Error> { 76 let color: Color; 77 let length = self.len(); 78 match length { 79 2 => color = Color::Indexed(self.pop().expect("Shouldn't happen len check in place")), 80 4 => { 81 let b = self.pop().expect("Shouldn't happen len check in place"); 82 let g = self.pop().expect("Shouldn't happen len check in place"); 83 let r = self.pop().expect("Shouldn't happen len check in place"); 84 color = Color::Rgb(r, g, b); 85 } 86 _ => { 87 return Err(Error::ColorParsingError); 88 } 89 } 90 self.clear(); 91 Ok(color) 92 } 93 } 94 95 #[derive(Debug, PartialEq, Clone, Copy)] 96 #[repr(u8)] 97 pub enum ColorLayer { 98 Background, 99 Foreground, 100 } 101 102 #[derive(Debug)] 103 pub struct AnsiGraphicsStack { 104 stack: Vec<usize>, 105 lock: bool, 106 } 107 108 impl AnsiGraphicsStack { new() -> Self109 pub fn new() -> Self { 110 Self { 111 stack: Vec::new(), 112 lock: true, 113 } 114 } push(&mut self, sequence: usize)115 pub fn push(&mut self, sequence: usize) { 116 self.stack.push(sequence); 117 } iter(&mut self) -> Iter<usize>118 pub fn iter(&mut self) -> Iter<usize> { 119 self.stack.iter() 120 } lock(&mut self)121 pub fn lock(&mut self) { 122 self.stack.clear(); 123 self.lock = true; 124 } unlock(&mut self)125 pub fn unlock(&mut self) { 126 self.stack.clear(); 127 self.lock = false; 128 } is_locked(&self) -> bool129 pub fn is_locked(&self) -> bool { 130 self.lock 131 } is_unlocked(&self) -> bool132 pub fn is_unlocked(&self) -> bool { 133 !self.lock 134 } 135 136 // pub fn len(&self) -> usize { 137 // self.stack.len() 138 // } 139 parse_ansi(&mut self) -> Result<Style, Error>140 pub fn parse_ansi(&mut self) -> Result<Style, Error> { 141 let mut style = Style::default(); 142 143 // let mut stack: Stack<u8> = Stack::new(); 144 let mut color_stack: Stack<u8> = Stack::new(); 145 146 let mut layer: Option<ColorLayer> = None; 147 148 for sequence in self.iter().copied() { 149 // sequence should always be an u8 150 // but since you can actually write more than u8 (incase of erroneous input) 151 // i'm using usize 152 // if input is greater than u8 simply skip the iteration and clear the color_stack. 153 154 let code; 155 let _seq: Result<u8, _> = sequence.try_into(); 156 157 let sequence: u8; 158 if let Ok(_s) = _seq { 159 sequence = _s; 160 code = AnsiCode::from(_s); 161 } else { 162 // More than a u8 163 color_stack.lock(); 164 continue; 165 } 166 167 if color_stack.is_unlocked() { 168 // don't match against other stuff 169 // on first run it will push 2/5 ie rgb or indexed color 170 if color_stack.is_empty() { 171 // sequence should be either 2 or 5 172 color_stack.push(sequence); 173 continue; 174 } 175 match color_stack.first().ok_or(Error::StackEmpty)? { 176 2 => { 177 // first number is 2 ,second, third and fourth are r, g, b 178 if color_stack.len() <= 4 { 179 color_stack.push(sequence); 180 } 181 if color_stack.len() == 4 { 182 match layer.ok_or(Error::UnknownLayer)? { 183 ColorLayer::Foreground => { 184 style = style.fg(color_stack.parse_color()?); 185 } 186 ColorLayer::Background => { 187 style = style.bg(color_stack.parse_color()?); 188 } 189 } 190 } 191 } 192 5 => { 193 if color_stack.len() <= 2 { 194 // first number is 5 second is the color index 195 color_stack.push(sequence); 196 } 197 if color_stack.len() == 2 { 198 match layer.ok_or(Error::UnknownLayer)? { 199 ColorLayer::Foreground => { 200 style = style.fg(color_stack.parse_color()?); 201 } 202 ColorLayer::Background => { 203 style = style.bg(color_stack.parse_color()?); 204 } 205 } 206 } 207 } 208 _ => { 209 color_stack.lock(); 210 } // first number is not 2 or 5 lock 211 } 212 // 213 continue; 214 } 215 match code { 216 AnsiCode::Reset => style = Style::default(), 217 AnsiCode::Bold => style = style.add_modifier(Modifier::BOLD), 218 AnsiCode::Faint => style = style.add_modifier(Modifier::DIM), 219 AnsiCode::Italic => style = style.add_modifier(Modifier::ITALIC), 220 AnsiCode::Underline => style = style.add_modifier(Modifier::UNDERLINED), 221 AnsiCode::SlowBlink => style = style.add_modifier(Modifier::SLOW_BLINK), 222 AnsiCode::RapidBlink => style = style.add_modifier(Modifier::RAPID_BLINK), 223 AnsiCode::Reverse => style = style.add_modifier(Modifier::REVERSED), 224 AnsiCode::Conceal => style = style.add_modifier(Modifier::HIDDEN), 225 AnsiCode::CrossedOut => style = style.add_modifier(Modifier::CROSSED_OUT), 226 AnsiCode::DefaultForegroundColor => style = style.fg(Color::Reset), 227 AnsiCode::DefaultBackgroundColor => style = style.bg(Color::Reset), 228 AnsiCode::SetForegroundColor => { 229 // color_layer = Some(ColorLayer::Foreground) 230 // current byte is 38 231 layer = Some(ColorLayer::Foreground); 232 color_stack.unlock(); 233 } 234 AnsiCode::SetBackgroundColor => { 235 // color_layer = Some(ColorLayer::Background) 236 // current byte is 48 237 layer = Some(ColorLayer::Background); 238 color_stack.unlock(); 239 } 240 AnsiCode::ForegroundColor(color) => style = style.fg(color), 241 AnsiCode::BackgroundColor(color) => style = style.bg(color), 242 _ => (), 243 } 244 } 245 246 Ok(style) 247 } 248 } 249