diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ac5285a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ansitui" +version = "0.1.0" +edition = "2018" + +[dependencies] +tui = { version = "0.14.0", default-features = false } diff --git a/ansi.py b/ansi.py new file mode 100755 index 0000000..5bd301f --- /dev/null +++ b/ansi.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +# for code in range(107): +# print(f"\x1b[{code}mTHIS IS TEXT\x1b[0m") + +# for z in range(255): +# print( +# f"\x1b[{38};{5};{z};{1};{7};{3};{5};{4}mTEXT \\x1b[{38};{5};{z}m\\1xb[0m\x1b[0m") + +llist = [27, 49, 49, 49, 51, 49, 109, 49, 50, 51, 52, 27, 48, 109, ] + +for l in llist: + print(chr(l)) diff --git a/archlinux.ascii b/archlinux.ascii new file mode 100644 index 0000000..5355dd1 --- /dev/null +++ b/archlinux.ascii @@ -0,0 +1,15 @@ +              ..               +              cl               +             :ooc              +            ;oooo:             +           .looooo:            +          ;c;:looooc           +         :ooooooooooc          +        :ooooooooooool         +       coooool;;loooool.       +     .looooo'    .oooooo.      +    .ooooooc      ;oooocl'     +   'ooooooo:      'ooooo:,     +  ,oool:,..        ..,:looo;   + :c,.                    .,c:  +..                          .' diff --git a/src/ansi.rs b/src/ansi.rs new file mode 100644 index 0000000..275637c --- /dev/null +++ b/src/ansi.rs @@ -0,0 +1,209 @@ +#![allow(dead_code, unused_mut, unused_imports)] +use crate::code::AnsiCode; +use crate::color::AnsiColor; +use crate::error::Error; +use crate::stack::Stack; +use std::slice::Iter; +use tui::{ + style::{Color, Modifier, Style}, + text::{Span, Spans, Text}, +}; + +impl Stack { + pub fn parse_usize(&mut self) -> usize { + let mut num: usize = 0 as usize; + for n in self.iter() { + // num = num * 10 + (n.saturating_sub(48_u8)) as usize + num = num * 10 + (n - 48_u8) as usize + } + self.clear(); + num + } + pub fn parse_color(&mut self) -> Result { + let mut color: Color; + let length = self.len(); + if length == 1 { + color = Color::Indexed(self.pop().expect("Shouldn't happen len check in place")) + } else if length == 3 { + let b = self.pop().unwrap(); + let g = self.pop().unwrap(); + let r = self.pop().unwrap(); + color = Color::Rgb(r, g, b); + } else { + return Err(Error::TempError); + } + self.clear(); + Ok(color) + } +} + +#[derive(Debug, PartialEq, Clone, Copy)] +#[repr(u8)] +pub enum AnsiColorMode { + RGB = 2, + Indexed = 5, +} + +#[derive(Debug, PartialEq, Clone, Copy)] +#[repr(u8)] +pub enum AnsiColorLayer { + Background, + Foreground, +} + +#[derive(Debug)] +pub struct AnsiGraphicsStack { + stack: Stack, +} + +impl AnsiGraphicsStack { + pub fn new() -> Self { + Self { + stack: Stack::new(), + } + } + pub fn push(&mut self, sequence: usize) { + self.stack.push(sequence); + } + pub fn iter(&mut self) -> Iter { + self.stack.iter() + } + pub fn parse_ansi(&mut self) -> Style { + let mut style = Style::default(); + let mut color_stack: Stack = Stack::new(); + let mut color_parse: bool = false; + let mut color_parse_mode: Option = None; + let mut last_sequence: usize = 0; + let mut color_layer: Option = None; + // println!("{:?}", self); + for sequence in self.iter().cloned() { + if color_parse { + if sequence < 255 { + if AnsiCode::from(last_sequence as u8) == AnsiCode::ForegroundColorIndex + || AnsiCode::from(last_sequence as u8) == AnsiCode::BackgroundColorIndex + || sequence == AnsiColorMode::RGB as usize + { + color_parse_mode = Some(AnsiColorMode::RGB) + } else if AnsiCode::from(last_sequence as u8) == AnsiCode::ForegroundColorIndex + || AnsiCode::from(last_sequence as u8) == AnsiCode::BackgroundColorIndex + || sequence == AnsiColorMode::Indexed as usize + { + color_parse_mode = Some(AnsiColorMode::Indexed) + } else if color_parse_mode.is_some() { + let mode = color_parse_mode.unwrap(); + match mode { + AnsiColorMode::Indexed => { + color_stack.push(sequence as u8); + match color_layer.unwrap() { + AnsiColorLayer::Foreground => { + style = style.fg(color_stack.parse_color().unwrap()) + } + AnsiColorLayer::Background => { + style = style.bg(color_stack.parse_color().unwrap()) + } + } + } + AnsiColorMode::RGB => { + color_stack.push(sequence as u8); + if color_stack.len() == 3 { + match color_layer.unwrap() { + AnsiColorLayer::Foreground => { + style = style.fg(color_stack.parse_color().unwrap()) + } + AnsiColorLayer::Background => { + style = style.bg(color_stack.parse_color().unwrap()) + } + } + } + } + } + } else { + color_parse = false; + } + } else { + // println!("stop color index"); + color_parse = false; + } + last_sequence = sequence; + continue; + } + let code = AnsiCode::from(sequence as u8); + match code { + AnsiCode::Reset => style = Style::default(), + AnsiCode::Bold => style = style.add_modifier(Modifier::BOLD), + AnsiCode::Faint => style = style.add_modifier(Modifier::DIM), + AnsiCode::Italic => style = style.add_modifier(Modifier::ITALIC), + AnsiCode::Underline => style = style.add_modifier(Modifier::UNDERLINED), + AnsiCode::SlowBlink => style = style.add_modifier(Modifier::SLOW_BLINK), + AnsiCode::RapidBlink => style = style.add_modifier(Modifier::RAPID_BLINK), + AnsiCode::Reverse => style = style.add_modifier(Modifier::REVERSED), + AnsiCode::Conceal => style = style.add_modifier(Modifier::HIDDEN), + AnsiCode::CrossedOut => style = style.add_modifier(Modifier::CROSSED_OUT), + AnsiCode::DefaultForegroundColor => style = style.fg(Color::Reset), + AnsiCode::DefaultBackgroundColor => style = style.bg(Color::Reset), + AnsiCode::ForegroundColorIndex => { + // println!("foreground color index"); + color_parse = true; + color_layer = Some(AnsiColorLayer::Foreground) + } + AnsiCode::BackgroundColorIndex => { + // println!("background color index"); + color_parse = true; + color_layer = Some(AnsiColorLayer::Background) + } + AnsiCode::ForegroundColor(color) => style = style.fg(Color::from(color)), + AnsiCode::BackgroundColor(color) => style = style.bg(Color::from(color)), + _ => (), + } + last_sequence = sequence; + } + self.stack.clear(); + println!("style {:?}", style); + // println!("-----------------------------"); + style + } +} + +pub fn ansi_to_text<'t, B: AsRef<[u8]>>(bytes: B) -> Result, Error> { + let mut reader = bytes.as_ref().iter(); + let mut buffer: Vec = Vec::new(); + let mut style: Option