1use std::error::Error;
2use std::io::{self, BufRead};
3use rargsxd::*;
4
5const OFF: &'static str = "\x1b[m";
6
7pub trait StyledString {
9 fn get_str(&self) -> String;
11
12 fn do_off(&self) -> &str {
13 if self.get_str().ends_with(OFF) {""}
14 else {OFF}
15 }
16
17 fn remove_off(&self) -> String {
18 let mut cur = self.get_str();
19 while let Some(new) = cur.strip_suffix(OFF) {
20 cur = new.to_string();
21 }
22 cur
23 }
24
25 fn fgblack(&self) -> String {format!("\x1b[30m{}{}", self.get_str(), self.do_off())}
26 fn fgred(&self) -> String {format!("\x1b[31m{}{}", self.get_str(), self.do_off())}
27 fn fggreen(&self) -> String {format!("\x1b[32m{}{}", self.get_str(), self.do_off())}
28 fn fgyellow(&self) -> String {format!("\x1b[33m{}{}", self.get_str(), self.do_off())}
29 fn fgblue(&self) -> String {format!("\x1b[34m{}{}", self.get_str(), self.do_off())}
30 fn fgmagenta(&self) -> String {format!("\x1b[35m{}{}", self.get_str(), self.do_off())}
31 fn fgcyan(&self) -> String {format!("\x1b[36m{}{}", self.get_str(), self.do_off())}
32 fn fgwhite(&self) -> String {format!("\x1b[37m{}{}", self.get_str(), self.do_off())}
33
34 fn bgblack(&self) -> String {format!("\x1b[40m{}{}", self.get_str(), self.do_off())}
35 fn bgred(&self) -> String {format!("\x1b[41m{}{}", self.get_str(), self.do_off())}
36 fn bggreen(&self) -> String {format!("\x1b[42m{}{}", self.get_str(), self.do_off())}
37 fn bgyellow(&self) -> String {format!("\x1b[43m{}{}", self.get_str(), self.do_off())}
38 fn bgblue(&self) -> String {format!("\x1b[44m{}{}", self.get_str(), self.do_off())}
39 fn bgmagenta(&self) -> String {format!("\x1b[45m{}{}", self.get_str(), self.do_off())}
40 fn bgcyan(&self) -> String {format!("\x1b[46m{}{}", self.get_str(), self.do_off())}
41 fn bgwhite(&self) -> String {format!("\x1b[47m{}{}", self.get_str(), self.do_off())}
42
43 fn rgb(&self, rgb: &str) -> String {format!("\x1b[38;2;{}m{}{}", rgb, self.get_str(), self.do_off())}
44
45 fn bold(&self) -> String {format!("\x1b[1m{}{}", self.get_str(), self.do_off())}
46 fn italics(&self) -> String {format!("\x1b[3m{}{}", self.get_str(), self.do_off())}
47 fn underline(&self) -> String {format!("\x1b[4m{}{}", self.get_str(), self.do_off())}
48 fn strike(&self) -> String {format!("\x1b[9m{}{}", self.get_str(), self.do_off())}
49}
50
51impl StyledString for String {
52 fn get_str(&self) -> String {
53 self.clone()
54 }
55}
56
57impl StyledString for &str {
58 fn get_str(&self) -> String {
59 self.to_string()
60 }
61}
62
63pub fn strip_styles(input: String) -> String {
64 let mut output = String::new();
65 let mut skip = false;
66 for ch in input.chars() {
67 if ch == '\x1b' {
68 skip = true;
69 continue;
70 } else if ch == 'm' && skip {
71 skip = false;
72 continue;
73 } else if skip {
74 continue;
75 } else {
76 output.push(ch);
77 }
78 }
79 output
80}
81
82pub fn run(args: ArgParser) -> Result<(), Box<dyn Error>> {
83 let mut modifier = String::new();
84
85 if args.get_bool("bold") {modifier = modifier.bold()}
86 if args.get_bool("italics") {modifier = modifier.italics()}
87 if args.get_bool("underline") {modifier = modifier.underline()}
88 if args.get_bool("strike") {modifier = modifier.strike()}
89
90 if args.get_str("fg") != "" {
91 modifier = match args.get_str("fg").as_str() {
92 "black" => modifier.fgblack(),
93 "red" => modifier.fgred(),
94 "green" => modifier.fggreen(),
95 "yellow" => modifier.fgyellow(),
96 "blue" => modifier.fgblue(),
97 "magenta" => modifier.fgmagenta(),
98 "cyan" => modifier.fgcyan(),
99 "white" => modifier.fgwhite(),
100 _ => "".to_string(),
101 }
102 }
103
104 if args.get_str("bg") != "" {
105 modifier = match args.get_str("bg").as_str() {
106 "black" => modifier.bgblack(),
107 "red" => modifier.bgred(),
108 "green" => modifier.bggreen(),
109 "yellow" => modifier.bgyellow(),
110 "blue" => modifier.bgblue(),
111 "magenta" => modifier.bgmagenta(),
112 "cyan" => modifier.bgcyan(),
113 "white" => modifier.bgwhite(),
114 _ => "".to_string(),
115 }
116 }
117
118 if args.get_str("rgb") != "" {modifier = modifier.rgb(&args.get_str("rgb"))}
119
120 modifier = modifier.remove_off();
121 if args.extra.len() > 0 {
122 let string = args.extra.join(" ");
123 println!("{}{}", modifier, string);
124 } else {
125 let stdin = io::stdin();
126 for line in stdin.lock().lines() {
128 let mut string = line? + "\n";
129 if !args.get_bool("dontforce") {
130 string = strip_styles(string);
131 }
132 print!("{}{}", modifier, string);
133 }
134 }
135 Ok(())
136}