Skip to content

Commit

Permalink
Initial Commit.
Browse files Browse the repository at this point in the history
This is most probably terrible code !
  • Loading branch information
uttarayan21 committed Apr 25, 2021
0 parents commit 4cd9c8f
Show file tree
Hide file tree
Showing 13 changed files with 527 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "ansitui"
version = "0.1.0"
edition = "2018"

[dependencies]
tui = { version = "0.14.0", default-features = false }
13 changes: 13 additions & 0 deletions ansi.py
Original file line number Diff line number Diff line change
@@ -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))
15 changes: 15 additions & 0 deletions archlinux.ascii
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
              ..              
              cl              
             :ooc             
            ;oooo:            
           .looooo:           
          ;c;:looooc          
         :ooooooooooc         
        :ooooooooooool        
       coooool;;loooool.      
     .looooo'    .oooooo.     
    .ooooooc      ;oooocl'    
   'ooooooo:      'ooooo:,    
  ,oool:,..        ..,:looo;  
 :c,.                    .,c: 
..                          .'
209 changes: 209 additions & 0 deletions src/ansi.rs
Original file line number Diff line number Diff line change
@@ -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<u8> {
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<Color, Error> {
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<usize>,
}

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<usize> {
self.stack.iter()
}
pub fn parse_ansi(&mut self) -> Style {
let mut style = Style::default();
let mut color_stack: Stack<u8> = Stack::new();
let mut color_parse: bool = false;
let mut color_parse_mode: Option<AnsiColorMode> = None;
let mut last_sequence: usize = 0;
let mut color_layer: Option<AnsiColorLayer> = 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<Text<'t>, Error> {
let mut reader = bytes.as_ref().iter();
let mut buffer: Vec<Spans> = Vec::new();
let mut style: Option<Style> = None;
let mut ansi_stack: AnsiGraphicsStack = AnsiGraphicsStack::new();
let mut num_stack: Stack<u8> = Stack::new();
let mut graphics_start: bool = false;
let mut line_buffer = String::new();
// let mut last_byte: &u8 = reader.next().expect("Zero size bytes buffer");
let mut last_byte: &u8 = &0_u8;
for byte in reader {
match (last_byte, byte) {
(&b'\x1b', &b'[') => {
if style.is_some() {
buffer.push(Spans::from(Span::styled(
line_buffer.clone(),
style.unwrap(),
)));
}
graphics_start = true;
}
(_, code) => {
if graphics_start {
if code == &b'm' {
ansi_stack.push(num_stack.parse_usize());
style = Some(ansi_stack.parse_ansi());
graphics_start = false;
} else if code == &b';' {
ansi_stack.push(num_stack.parse_usize());
} else {
num_stack.push(*code);
}
} else if code != &b'\x1b' {
line_buffer.push(*code as char)
}
last_byte = code;
}
}
}
println!("{:?}", buffer);

Ok(buffer.into())
}
Loading

0 comments on commit 4cd9c8f

Please sign in to comment.