use crate::commands::ShellCommand;
use crate::shared_functions::tokenize;
use std::fmt::{Formatter, Display};
#[derive(Debug, Copy, Clone)]
pub enum BgColor {
Black = 40,
Red = 41,
Green = 42,
Yellow = 43,
Blue = 44,
Magenta = 45,
Cyan = 46,
White = 47,
}
#[derive(Debug, Copy, Clone)]
pub enum FgColor {
Black = 30,
Red = 31,
Green = 32,
Yellow = 33,
Blue = 34,
Magenta = 35,
Cyan = 36,
White = 37,
}
#[derive(Debug, Copy, Clone)]
pub enum Color {
Bg(BgColor),
Fg(FgColor),
}
impl Display for BgColor {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "\x1b[{}m", &self.to_u8())
}
}
impl Display for FgColor {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "\x1b[{}m", &self.to_u8())
}
}
impl BgColor {
pub fn to_u8(self) -> u8 {
match self {
BgColor::Black => 40,
BgColor::Red => 41,
BgColor::Green => 42,
BgColor::Yellow => 43,
BgColor::Blue => 44,
BgColor::Magenta => 45,
BgColor::Cyan => 46,
BgColor::White => 47,
}
}
}
impl FgColor {
pub fn to_u8(self) -> u8 {
match self {
FgColor::Black => 30,
FgColor::Red => 31,
FgColor::Green => 32,
FgColor::Yellow => 33,
FgColor::Blue => 34,
FgColor::Magenta => 35,
FgColor::Cyan => 36,
FgColor::White => 37,
}
}
}
pub enum FontEffects {
ResetBackground = 49,
ResetEverything = 0,
ResetForeground = 39,
Bold = 1,
Italics = 3,
Underline = 4,
}
impl Display for FontEffects {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "\x1b[{}m", &self.to_u8())
}
}
impl FontEffects {
pub fn to_u8(self: &FontEffects) -> u8 {
match self {
FontEffects::ResetBackground => 49,
FontEffects::ResetEverything => 0,
FontEffects::ResetForeground => 39,
FontEffects::Bold => 1,
FontEffects::Italics => 3,
FontEffects::Underline => 4,
}
}
}
#[derive(Debug, Clone)]
pub struct EscapeSequence {
escape_sequence: String,
}
impl Display for EscapeSequence {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.escape_sequence)
}
}
impl EscapeSequence {
pub fn builder() -> EsBuilder {
EsBuilder::default()
}
}
#[derive(Clone, Debug)]
pub struct EsBuilder {
escape_sequence: String,
}
impl Default for EsBuilder {
fn default() -> EsBuilder {
EsBuilder {
escape_sequence: String::from("\x1b["),
}
}
}
impl EsBuilder {
pub fn new() -> EsBuilder {
EsBuilder {
escape_sequence: String::from("\x1b["),
}
}
pub fn append(&mut self, argument: u8) {
self.escape_sequence.push_str(&argument.to_string());
self.escape_sequence.push(';');
}
pub fn build(&mut self) -> EscapeSequence {
self.escape_sequence.pop();
self.escape_sequence.push('m');
EscapeSequence {
escape_sequence: self.escape_sequence.clone(),
}
}
}
pub fn get_files_from_input(input: &str) -> Vec<String> {
let tokenized_vec = tokenize(input);
let mut tmp_vec: String = String::new();
let mut file_vec: Vec<String> = Vec::new();
let mut file = false;
let mut file_end = false;
let mut tok_iter = tokenized_vec.iter().peekable();
while tok_iter.peek() != None {
let tok_iter_char = tok_iter.next().unwrap().as_str();
if file_end {
file_vec.push(tmp_vec.to_string());
tmp_vec.clear();
file = false;
file_end = false;
continue;
}
if tok_iter_char == "%" && tok_iter.peek().unwrap().as_str() == "[" {
file = true;
} else if file {
if tok_iter_char == "[" {
continue;
} else if tok_iter_char != "]" {
tmp_vec.push_str(tok_iter_char);
} else if tok_iter_char == "]" {
file_end = true;
continue;
}
}
} {
if file_end {
file_vec.push(tmp_vec.to_string());
file_vec.clear();
}
}
file_vec
}
pub fn get_commands_from_input(input: &str) -> Vec<ShellCommand> {
let tokenized_vec = tokenize(input);
let mut tmp_vec: String = String::new();
let mut command_vec: Vec<ShellCommand> = Vec::new();
let mut command = false;
let mut command_end = false;
let mut tok_iter = tokenized_vec.iter().peekable();
while tok_iter.peek() != None {
let tok_iter_char = tok_iter.next().unwrap().as_str();
if command_end {
command_vec.push(ShellCommand::new(tmp_vec.as_str()));
tmp_vec.clear();
command = false;
command_end = false;
continue;
}
if tok_iter_char == "%" && tok_iter.peek().unwrap().as_str() == "(" {
command = true;
} else if command {
if tok_iter_char == "(" {
continue;
} else if tok_iter_char != ")" {
tmp_vec.push_str(tok_iter_char);
} else if tok_iter_char == ")" {
command_end = true;
continue;
}
}
} {
if command_end {
command_vec.push(ShellCommand::new(tmp_vec.as_str()));
tmp_vec.clear();
}
}
command_vec
}
pub fn parse_prompt_effects(input: &str) -> String {
let tokenized_vec = tokenize(input);
let mut tok_iter = tokenized_vec.iter().peekable();
let mut es_builder = EscapeSequence::builder();
let mut es_seqs: Vec<(String, String)> = Vec::new();
let mut fin_prompt = String::new();
let mut tmp_string = String::new();
let mut pos_option = false;
let mut pos_bgcol = false;
let mut bgcol = false;
let mut fgcol = false;
let mut pos_fgcol = false;
let mut option = false;
let mut option_fin = false;
let mut es_fin = false;
let mut not_pos_option;
while tok_iter.peek() != None {
let cur_char = tok_iter.next().unwrap().as_str();
match cur_char {
"%" => {
not_pos_option = false;
if !option_fin {
option_fin = false;
}
pos_option = true;
}
"B" => {
not_pos_option = false;
option_fin = false;
pos_bgcol = true;
pos_fgcol = false;
}
"F" => {
not_pos_option = false;
option_fin = false;
pos_bgcol = false;
pos_fgcol = true;
}
_ => {
not_pos_option = true;
if option_fin {
es_fin = true;
}
}
}
if es_fin {
for (ty, seq) in &es_seqs {
let mut arg = 0;
match ty.as_str() {
"O" => {
arg = match seq.as_str() {
"b" => FontEffects::Bold.to_u8(),
"i" => FontEffects::Italics.to_u8(),
"rb" => FontEffects::ResetBackground.to_u8(),
"re" => FontEffects::ResetEverything.to_u8(),
"rf" => FontEffects::ResetForeground.to_u8(),
"u" => FontEffects::Underline.to_u8(),
_ => 0,
};
}
"B" => {
let tmp_arg = match seq.as_str() {
"BLACK" => Color::Bg(BgColor::Black),
"RED" => Color::Bg(BgColor::Red),
"GREEN" => Color::Bg(BgColor::Green),
"YELLOW" => Color::Bg(BgColor::Yellow),
"BLUE" => Color::Bg(BgColor::Blue),
"MAGENTA" => Color::Bg(BgColor::Magenta),
"CYAN" => Color::Bg(BgColor::Cyan),
_ => Color::Bg(BgColor::White),
};
arg = match tmp_arg {
Color::Fg(fg) => {
fg.to_u8()
},
Color::Bg(bg) => {
bg.to_u8()
}
};
}
"F" => {
let tmp_arg = match seq.as_str() {
"BLACK" => Color::Fg(FgColor::Black),
"RED" => Color::Fg(FgColor::Red),
"GREEN" => Color::Fg(FgColor::Green),
"YELLOW" => Color::Fg(FgColor::Yellow),
"BLUE" => Color::Fg(FgColor::Blue),
"MAGENTA" => Color::Fg(FgColor::Magenta),
"CYAN" => Color::Fg(FgColor::Cyan),
_ => Color::Fg(FgColor::White),
};
arg = match tmp_arg {
Color::Fg(fg) => {
fg.to_u8()
},
Color::Bg(bg) => {
bg.to_u8()
}
};
}
_ => (),
}
es_builder.append(arg);
}
fin_prompt.push_str(es_builder.build().escape_sequence.as_str());
es_builder = EsBuilder::new();
es_seqs.clear();
option_fin = false;
es_fin = false;
}
if pos_option && cur_char == "{" {
option = true;
option_fin = false;
pos_option = false;
continue;
} else if pos_bgcol && cur_char == "<" {
bgcol = true;
option_fin = false;
pos_bgcol= false;
continue;
} else if pos_fgcol && cur_char == "<" {
fgcol = true;
option_fin = false;
pos_fgcol = false;
continue;
}
if option {
if cur_char != "}" {
tmp_string.push_str(cur_char);
} else if cur_char == "}" {
option_fin = true;
match tmp_string.as_str() {
"b" | "i" | "rb" | "re" | "rf" | "u" => es_seqs.push(("O".to_string(), tmp_string.clone())),
_ => fin_prompt.push_str(format!("%{{{}}}", tmp_string).as_str()),
}
tmp_string.clear();
option = false;
}
continue;
} else if bgcol {
if cur_char != ">" {
tmp_string.push_str(cur_char);
} else if cur_char == ">" {
option_fin = true;
es_seqs.push(("B".to_string(), tmp_string.clone()));
tmp_string.clear();
bgcol = false;
}
continue;
} else if fgcol {
if cur_char != ">" {
tmp_string.push_str(cur_char);
} else if cur_char == ">" {
option_fin = true;
es_seqs.push(("F".to_string(), tmp_string.clone()));
tmp_string.clear();
fgcol = false;
}
continue;
}
if not_pos_option && (!option || !bgcol || !fgcol) {
fin_prompt.push_str(cur_char);
}
};
fin_prompt
}