#![allow(unused_imports)]
use std::any::Any;
use std::collections::HashMap;
use std::fmt::Debug;
#[allow(dead_code)]
use std::fmt::Display;
use std::io::Stdout;
use std::ops::RangeTo;
use std::path::Path;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use std::time::Instant;
use colored_json::prelude::*;
use colored_json::to_colored_json_auto;
use colored_json::Color;
use colored_json::ColoredFormatter;
use colored_json::CompactFormatter;
use colored_json::Style;
use colored_json::Styler;
use colored_json::ToColoredJson;
use crossterm::style::StyledContent;
use crossterm::style::Stylize;
use serde_json::Value;
use crate::colors::Printable;
use crate::colors::TimePrintable;
use crate::colors::ALL_COLORS_ANSII;
use crate::PrettyJson;
pub fn serving_on(link: &str) {
"[grey]SERVING[/] ON [green]{link}[/]".print_with(vec![link]);
}
pub fn serving(service: &str, link: &str) {
"[grey]SERVING[/] [green]{service}[/] ON [blue]{link}[/]".print_with(vec![service, link]);
}
pub fn starting(service: &str, detail: &str) {
"[yellow]╭─ run ──[/][cyan]─ {service}[/] ── [grey]{detail}[/] ──"
.print_with(vec![service, detail]);
}
pub fn update(message: &str) {
"[yellow]│[/] [grey]{message}[/]".print_with(vec![message]);
}
pub fn done(service: &str, duration: Duration) {
"[green]╰─ done ─[/][gray]─ {service}[/] ─[pink]─ {duration} ─[/]─"
.print_with(vec![service, duration.to_string_s().as_str()]);
}
pub fn stopping(service: &str) {
"[grey]STOPPING[/] [red]{service}[/]".print_with(vec![service]);
}
pub fn restarting(service: &str) {
"[grey]RESTARTING[/] [yellow]{service}[/]".print_with(vec![service]);
}
pub fn reloading(service: &str) {
"[grey]RELOADING[/] [yellow]{service}[/]".print_with(vec![service]);
}
pub fn opening(link: &str) {
"[grey]OPENING[/] [blue]{link}[/]".print_with(vec![link]);
}
pub fn opening_in(link: &str, browser: &str) {
"[grey]OPENING[/] [blue]{link}[/] IN [green]{browser}[/]".print_with(vec![link, browser]);
}
pub fn opening_in_duration(link: &str, browser: &str, duration: Duration) {
"[grey]OPENING[/] [blue]{link}[/] IN [green]{browser}[/] IN [yellow]{duration}[/]"
.print_with(vec![link, browser, duration.to_string_hms().as_str()]);
}
pub fn started(service: &str, link: &str) {
"[grey]STARTED[/] [green]{service}[/] AT [blue]{link}[/]".print_with(vec![service, link]);
}
pub fn stopped(service: &str, time: &str) {
"[grey]STOPPED[/] [red]{service}[/] ON [yellow]{}[/]".print_with(vec![service, time]);
}
pub fn restarted(service: &str, time: &str) {
"[grey]RESTARTED[/] [yellow]{service}[/] ON [yellow]{}[/]".print_with(vec![service, time]);
}
pub fn reloaded(service: &str, time: &str) {
"[grey]RELOADED[/] [yellow]{service}[/] ON [yellow]{}[/]".print_with(vec![service, time]);
}
pub fn executing(command: impl Into<String>, detail: impl Into<String>) {
"[grey]EXECUTING[/] [green]{}[/] [grey]{}[/]".print_with(vec![command.into(), detail.into()]);
}
pub fn running(path: impl Into<String> + Copy) {
let path = path.into();
let length = 40 - path.len();
let filler = "─".repeat(length);
let path = Path::new(&path);
let name = path.file_name().unwrap().to_str().unwrap();
let folder = path.parent().unwrap().to_str().unwrap();
"\n╭─[on_magenta][black] EXECUTING [/] [purple]{}[/]\n╰─ [dim_gray]from {}[/] {}─╮"
.print_with(vec![name, folder, &filler]);
}
pub fn completed_execution(command: &str, time: impl TimePrintable) {
"[grey]COMPLETED EXECUTION[/] [green]{}[/] [grey]AT[/] [cyan]{}[/]"
.print_with(vec![command, time.to_string_hms().as_str()]);
}
pub fn executed_as(command: &str, user: &str, path: &str) {
"[grey]EXECUTED[/] [green]{}[/] AS [green]{user}[/] FROM [blue]{path}[/]"
.print_with(vec![command, user, path]);
}
pub fn failed_to_execute(command: &str, reason: &str) {
"[grey]FAILED TO EXECUTE[/] [green]{}[/] BECAUSE [red]{reason}[/]"
.print_with(vec![command, reason]);
}
pub fn failed_to_execute_as(command: &str, user: &str, reason: &str) {
"[grey]FAILED TO EXECUTE[/] [green]{}[/] AS [green]{user}[/] BECAUSE [red]{reason}[/]"
.print_with(vec![command, user, reason]);
}
pub fn failed_to_open(link: &str, reason: &str) {
"[grey]FAILED TO OPEN[/] [blue]{link}[/] BECAUSE [red]{reason}[/]"
.print_with(vec![link, reason]);
}
pub fn waiting_for_service_to_start(service: &str) {
"[grey]WAITING FOR[/] [green]{service}[/] TO START".print_with(vec![service]);
}
pub fn waiting_for_service_to_stop(service: &str) {
"[grey]WAITING FOR[/] [red]{service}[/] TO STOP".print_with(vec![service]);
}
pub fn waiting_for_someone_to_something(someone: &str, something: &str) {
"[grey]WAITING FOR[/] [green]{someone}[/] TO [green]{something}[/]"
.print_with(vec![someone, something]);
}
pub fn completed_in_dur_with_result(
something: &str,
duration: Duration,
result: &str,
) {
"[grey]COMPLETED[/] [green]{something}[/] IN [yellow]{duration}[/] WITH [green]{result}[/]"
.print_with(vec![
something.to_string(),
duration.to_string_hms(),
result.to_string(),
]);
}
pub fn completed_with_results_in_duration(
something: impl Into<String>,
result: impl Into<String>,
duration: Duration,
) {
"[grey]COMPLETED[/] [green]{something}[/] WITH [green]{result}[/] IN [yellow]{duration}[/]"
.print_with(vec![
something.into(),
result.into().to_uppercase(),
duration.to_string_hms(),
]);
}
pub fn incoming(kind: impl Into<String>, payload: impl Display) {
"[yellow]INCOMING[/] [white]{kind}[/] [grey]{payload}[/]"
.print_with(vec![kind.into(), payload.to_string()]);
}
pub fn incoming_error(kind: impl Into<String>, payload: impl Display) {
"[yellow]INCOMING[/] [red]{kind}[/] [dark_red]{payload}[/]"
.print_with(vec![kind.into(), payload.to_string()]);
}
pub fn outgoing(kind: impl Into<String>, payload: impl Display) {
"[blue]OUTGOING[/] [white]{kind}[/] [grey]{payload}[/]"
.print_with(vec![kind.into(), payload.to_string()]);
}
pub fn parsed_file(file_path: &str) {
"[grey]PARSED[/] [blue]{file_path}[/]".print_with(vec![file_path.to_string()]);
}
pub fn found(arg: &str, count: usize) {
"[grey]FOUND[/] [blue]{arg}[/] [yellow]{count}[/]"
.print_with(vec![arg.to_string(), count.to_string()]);
}
pub fn error(arg: &str, file_path: &str) {
"[grey]ERROR[/] [red]{arg}[/] [blue]{file_path}[/]"
.print_with(vec![arg.to_string(), file_path.to_string()]);
}
pub fn scanning(item: &str, parent: &str) {
"[grey]SCANNING[/] [cyan]{}[/] [purple]{}[/]"
.print_with(vec![item.to_string(), parent.to_string()]);
}
pub fn pwd(pwd: &str) {
"[grey]📂[/] [blue]{}[/]".print_with(vec![pwd.to_string()]);
}
pub fn info(arg: &str) {
"[grey]INFO[/] [blue]{}[/]".print_with(vec![arg.to_string()]);
}
pub fn found_valid(arg: impl Display, arg2: impl Display, arg3: impl Display) {
"[grey]FOUND VALID[/] [blue]{}[/] [blue]{}[/] [blue]{}[/]".print_with(vec![
arg.to_string(),
arg2.to_string(),
arg3.to_string(),
]);
}
pub fn generated_code(arg: impl Display, arg2: impl Display, code: impl Display) {
"[grey]GENERATED CODE FOR[/] [blue]{}[/] [blue]{}[/] \n [green]{}[/]".print_with(vec![
arg.to_string(),
arg2.to_string(),
code.to_string(),
]);
}
pub fn reading_file(kind: &str, path: &str) {
"[grey]READ[/] [green]{}[/] [blue]{}[/]".print_with(vec![kind, path]);
}
pub fn warning(arg: impl Display, arg2: impl Display, arg3: impl Display) {
"[on_yellow] {arg} [/] [yellow]{arg2}[/] [dim_gray]\n{arg3}[/]".print_with(vec![
arg.to_string(),
arg2.to_string(),
arg3.to_string(),
]);
}
pub fn success(arg: impl Display, arg2: impl Display, arg3: impl Display) {
"[on_green] {arg} [/] [green]{arg2}[/] [dim_gray]\n{arg3}[/]".print_with(vec![
arg.to_string(),
arg2.to_string(),
arg3.to_string(),
]);
}
pub fn failed_to_read(filename: impl Display, reason: impl Display) {
"[grey]FAILED TO READ[/] [blue]{}[/] [red]{}[/]"
.print_with(vec![filename.to_string(), reason.to_string()]);
}
pub fn subtle(line: impl Display) {
"[grey]{}[/]".print_with(vec![line]);
}
pub fn message(line: impl Display) {
line.print();
}
pub fn wiped(arg: &str) {
"[grey]WIPED[/] [blue]{}[/]".print_with(vec![arg.to_string()]);
}
pub fn banner(banner: &str) {
banner.print();
}
pub fn banner_vibrant(banner: &str) {
for c in banner.chars() {
if c == ' ' {
print!(" ");
} else {
let rand = rand::random::<usize>() % ALL_COLORS_ANSII.len();
let color = ALL_COLORS_ANSII[rand];
print!("{}{}{}", color, c, "\x1b[0m");
}
}
}
pub fn loaded(arg: impl Display, arg2: impl Display) {
"[gray]LOADED[/] [blue]{arg}[/] [gray]{arg2}[/]"
.print_with(vec![arg.to_string(), arg2.to_string()]);
}
pub fn pressed(c: impl Debug) {
"[grey]PRESSED[/] [blue]{}[/]".print_with(vec![format!("{:?}", c)]);
}
pub fn preparing(arg: impl Into<String>) {
"[grey]PREPARING[/] [blue]{}[/]".print_with(vec![arg.into()]);
}
#[macro_export]
macro_rules! msg {
($($arg:expr),*) => {
{
let color_codes = ["\x1b[31m", "\x1b[32m", "\x1b[33m", "\x1b[34m"];
let mut msg = String::new();
let mut is_first = true;
let mut color_index = 0;
$(
if !is_first {
msg.push_str(", ");
}
msg.push_str(&format!("{}{}\x1b[0m", color_codes[color_index], $arg));
is_first = false;
color_index = (color_index + 1) % color_codes.len();
)*
println!("{}", msg);
}
};
}
pub fn sub_banner(sub: impl Into<String>, tail: impl Into<String>) {
let sub = sub.into();
let tail = tail.into();
let length = 60 - sub.len() - tail.len() - 4;
let filler = "─".repeat(length);
"[on_yellow][bold] {} [/][yellow] {} [/][gray] {}[/]".print_with(vec![sub, tail, filler]);
}
pub fn sub_banner_versioned(
sub: impl Into<String>,
ver: impl Into<String>,
tail: impl Into<String>,
) {
let sub = sub.into();
let ver = ver.into();
let tail = tail.into();
let length = 60 - sub.len() - ver.len() - tail.len() - 4;
let filler = "─".repeat(length);
"[on_w hite][black] {} [/][on_cyan] {} [/] {} [/][gray] {}[/]"
.print_with(vec![sub, ver, tail, filler]);
}
const CONSOLE_WIDTH: usize = 80;
pub fn banner_framed(
banner: impl Into<String>,
header: impl Into<String>,
tail: impl Into<String>,
) {
let header = header.into();
let length = (CONSOLE_WIDTH / 2) - header.len() - 4;
let filler = "─".repeat(length);
"╭─[yellow][bold] {} [/][gray]{}[/]".print_with(vec![&header, &filler]);
let banner = banner.into();
for line in banner.lines() {
if line.trim().is_empty() {
continue;
}
"│ {}".print_with(vec![&line]);
}
let tail = tail.into();
let length = (CONSOLE_WIDTH / 2) - tail.len() - 4;
let filler = "─".repeat(length);
"╰─╮─[white][bold] {} [/][gray]{}[/]".print_with(vec![&tail, &filler]);
}
pub fn headline(colors: Vec<&str>, exprs: Vec<impl Display>) {
let expressions: Vec<String> = exprs.into_iter().map(|e| e.to_string()).collect();
let mut length = CONSOLE_WIDTH - expressions.join(" ").len() - 1;
let mut colored = String::new();
for (i, expr) in expressions.iter().enumerate() {
colored.push_str(colors[i]);
if i > 0 && colored.chars().last().unwrap() != ' ' {
colored.push_str(" ");
if length > 0 {
length -= 1;
}
}
colored.push_str(expr);
colored.push_str(" \x1b[0m");
}
if let Some(color) = colors.get(expressions.len()) {
colored.push_str(color);
}
let filler = "─".repeat(length);
colored.push_str(&filler);
colored.push_str("\x1b[0m");
println!("{}", colored);
}
pub fn headline_start(colors: Vec<&str>, exprs: Vec<impl Display>) {
let expressions: Vec<String> = exprs.into_iter().map(|e| e.to_string()).collect();
let mut length = CONSOLE_WIDTH - expressions.join(" ").len() - 1 - 4;
let mut colored = String::new();
for (i, expr) in expressions.iter().enumerate() {
colored.push_str(colors[i]);
if i > 0 && colored.chars().last().unwrap() != ' ' {
colored.push_str(" ");
if length > 0 {
length -= 1;
}
}
colored.push_str(expr);
colored.push_str(" \x1b[0m");
}
if let Some(color) = colors.get(expressions.len()) {
colored.push_str(color);
}
let filler = "─".repeat(length);
colored.push_str(&filler);
colored.push_str("\x1b[0m");
colored.push_str("╮");
println!("{}", colored);
}
pub fn headline_end(colors: Vec<&str>, exprs: Vec<impl Display>) {
let expressions: Vec<String> = exprs.into_iter().map(|e| e.to_string()).collect();
let mut length = CONSOLE_WIDTH - expressions.join(" ").len() - 1 - 4;
let mut colored = String::new();
for (i, expr) in expressions.iter().enumerate() {
colored.push_str(colors[i]);
if i > 0 && colored.chars().last().unwrap() != ' ' {
colored.push_str(" ");
if length > 0 {
length -= 1;
}
}
colored.push_str(expr);
colored.push_str(" \x1b[0m");
}
if let Some(color) = colors.get(expressions.len()) {
colored.push_str(color);
}
let filler = "─".repeat(length);
colored.push_str(&filler);
colored.push_str("\x1b[0m");
colored.push_str("╯");
println!("{}", colored);
}
pub fn head(colors: Vec<&str>, exprs: Vec<impl Display>) {
let expressions: Vec<String> = exprs.into_iter().map(|e| e.to_string()).collect();
let mut colored = String::new();
for (i, expr) in expressions.iter().enumerate() {
colored.push_str(colors[i]);
if i > 0 && colored.chars().last().unwrap() != ' ' {
colored.push_str(" ");
}
colored.push_str(expr);
colored.push_str(" \x1b[0m");
}
println!("{}", colored);
}
pub fn positioned(x: i16, y: i16, text: impl Into<String>) {
let current = crossterm::cursor::position().unwrap();
let nx = match x {
x if x < 0 => current.0 - (x.abs() as u16),
x if x > 0 => current.0 + (x.abs() as u16),
_ => current.0,
};
let ny = match y {
y if y < 0 => current.1 - (y.abs() as u16),
y if y > 0 => current.1 + (y.abs() as u16),
_ => current.1,
};
crossterm::execute!(std::io::stdout(), crossterm::cursor::MoveTo(nx, ny)).unwrap();
text.into().print();
crossterm::execute!(
std::io::stdout(),
crossterm::cursor::MoveTo(current.0, current.1)
)
.unwrap();
}
pub fn divider() {
"─".repeat(CONSOLE_WIDTH).print();
}
pub fn positioned_divider(x: i16, y: i16) {
let current = crossterm::cursor::position().unwrap();
let nx = match x {
x if x < 0 => current.0 - (x.abs() as u16),
x if x > 0 => current.0 + (x.abs() as u16),
_ => current.0,
};
let ny = match y {
y if y < 0 => current.1 - (y.abs() as u16),
y if y > 0 => current.1 + (y.abs() as u16),
_ => current.1,
};
crossterm::execute!(std::io::stdout(), crossterm::cursor::MoveTo(nx, ny)).unwrap();
divider();
crossterm::execute!(
std::io::stdout(),
crossterm::cursor::MoveTo(current.0, current.1)
)
.unwrap();
}
pub fn div_text_center(text: impl Into<String>) {
let text = text.into();
let length = (CONSOLE_WIDTH / 2) - text.len() - 1;
let filler = "─".repeat(length);
format!("{} {} {}", filler, text, filler).print();
}
pub fn div_text_left(text: impl Into<String>) {
let text = text.into();
let length = CONSOLE_WIDTH - text.len() - 1;
let filler = "─".repeat(length);
format!("{} {}", text, filler).print();
}
pub fn div_text_right(text: impl Into<String>) {
let text = text.into();
let length = CONSOLE_WIDTH - text.len() - 1;
let filler = "─".repeat(length);
format!("{} {}", filler, text).print();
}
pub fn div_vibrant() {
for _ in 0..CONSOLE_WIDTH {
let rand = rand::random::<usize>() % ALL_COLORS_ANSII.len();
let color = ALL_COLORS_ANSII[rand];
print!("{}—{}", color, "\x1b[0m");
}
}
pub fn divider_positioned_vibrant(x: i16, y: i16) {
let current = crossterm::cursor::position().unwrap();
let nx = match x {
x if x < 0 => current.0 - (x.abs() as u16),
x if x > 0 => current.0 + (x.abs() as u16),
_ => current.0,
};
let ny = match y {
y if y < 0 => current.1 - (y.abs() as u16),
y if y > 0 => current.1 + (y.abs() as u16),
_ => current.1,
};
crossterm::execute!(std::io::stdout(), crossterm::cursor::MoveTo(nx, ny)).unwrap();
div_vibrant();
crossterm::execute!(
std::io::stdout(),
crossterm::cursor::MoveTo(current.0, current.1)
)
.unwrap();
}
pub fn substitute(v: impl Into<String>, u: impl Into<String>) {
let v = v.into();
let u = u.into();
"[gray]SUBSTITUTING[/] [blue]{}[/] [gray]WITH[/] [blue]{}[/]".print_with(vec![v, u]);
}
pub fn not_found(arg: &str, v: &str) {
"[red]─ ! ── [/][dim_gray]{}[/] [red]NOT FOUND ─── [/][yellow]{}[/]".print_with(vec![arg, v]);
}
pub fn sub_value(to_string: &str, value: serde_json::Value) {
"| ╰─► [yellow]SET[/][dim_gray] VALUE ─╮─► [/][magenta]{}[/]".print_with(vec![to_string]);
let msg = (&value.to_string())
.to_colored_json_with_styler(
ColorMode::default().eval(),
Styler {
key: Style::new(Color::Green).bold(),
string_value: Style::new(Color::Blue).italic(),
integer_value: Style::new(Color::Magenta).bold(),
float_value: Style::new(Color::Magenta).bold(),
object_brackets: Style::new(Color::Yellow),
array_brackets: Style::new(Color::Cyan),
..Default::default()
},
)
.unwrap_or_else(|_| "ERROR".to_string());
let mut lines: Vec<String> = msg.lines().map(|l| format!("│ │ {}", l)).collect();
lines.insert(0, "│ ╭───────────────────╯".to_string());
lines.push("│ ╰───────────────────────".to_string());
"{}".print_with(vec![lines.join("\n")]);
}
pub fn sub_key(to_string: &str) {
"│ ╰─► [pink]{}[/] ─".print_with(vec![to_string]);
}
pub fn thing(a: impl Into<String>, b: impl Into<String>, c: impl Display) {
let a = a.into();
let b = b.into();
let length = 60 - a.len() - b.len() - 4;
let filler = "─".repeat(length);
"╭───── [dim_gray]{}[/] [blue]{}[/] {}─"
.print_with(vec![a, b, filler]);
let msg = (&c.to_string())
.to_colored_json_with_styler(
ColorMode::default().eval(),
Styler {
key: Style::new(Color::Green).bold(),
string_value: Style::new(Color::Blue).italic(),
integer_value: Style::new(Color::Magenta).bold(),
float_value: Style::new(Color::Magenta).bold(),
object_brackets: Style::new(Color::Yellow),
array_brackets: Style::new(Color::Cyan),
..Default::default()
},
)
.unwrap_or_else(|_| "ERROR".to_string());
let mut lines: Vec<String> = msg.lines().map(|l| format!("│ {}", l)).collect();
lines.push("╰─────────────────────────────────".to_string());
"{}".print_with(vec![lines.join("\n")]);
}
#[macro_export]
macro_rules! anything {
($name:expr,$type:expr,$object:expr) => {
{
use termo::show::*;
use termo::colors::*;
let name = $name;
let type_ = $type;
let object = $object;
termo::show::thing(name, type_,object);
}
};
($name:expr,$object:expr) => {
{
use termo::show::*;
use termo::colors::*;
let name = $name;
let object = $object;
termo::show::thing(name, "",object);
}
};
($object:expr) => {
{
use termo::show::*;
use termo::colors::*;
let object = $object;
termo::show::thing("value","",object);
}
};
}
pub fn json(json: impl Into<Value>) {
let json = json.into();
let msg = (&json.to_string())
.to_colored_json_with_styler(
ColorMode::default().eval(),
Styler {
key: Style::new(Color::Green).bold(),
string_value: Style::new(Color::Blue).italic(),
integer_value: Style::new(Color::Magenta).bold(),
float_value: Style::new(Color::Magenta).bold(),
object_brackets: Style::new(Color::Yellow),
array_brackets: Style::new(Color::Cyan),
..Default::default()
},
)
.unwrap_or_else(|_| "ERROR".to_string());
let mut lines: Vec<String> = msg.lines().map(|l| format!("│ {}", l)).collect();
lines.insert(0, "╭─────".to_string());
lines.push("╰─────".to_string());
"{}".print_with(vec![lines.join("\n")]);
}
pub fn chop(text: impl Into<String>, max: usize) -> String {
let text = text.into();
if text.len() > max {
return format!("{}...", &text[0..max - 3]);
}
text
}
pub fn reading(type_: impl Into<String>, file: impl Into<String>) {
let type_ = type_.into();
let file = file.into();
let length = 60 - type_.len() - file.len() - 4;
let filler = "─".repeat(length);
"╭── [dim_gray]READING[/] [blue]{}[/] [yellow]{}[/] {}─"
.print_with(vec![type_, file, filler]);
}
pub fn starting_execution(scope: impl Into<String>, command: impl Into<String>) {
let start = "RUNNING".to_string();
let scope = scope.into();
let command = command.into().to_uppercase();
let length = 60 - scope.len() - command.len() - start.len() - 4;
let filler = "─".repeat(length);
"\n╭── [dim_gray]{}[/] [cyan]{}[/] [green]{}[/] {}─"
.print_with(vec![start, scope, command, filler]);
}
pub fn completed_in_dur(something: impl Into<String>, duration: Duration) {
let start = "COMPLETED".to_string();
let something = something.into().to_uppercase();
let duration = duration.to_string_ms();
let length = 60 - something.len() - duration.len() - start.len() - 4;
let filler = "─".repeat(length);
"╰── [dim_gray]{}[/] [green]{}[/] [yellow]{}[/] {}─\n"
.print_with(vec![start, something, duration, filler]);
}
pub fn action(action: impl Into<String>, command: impl Into<String>, detail: impl Into<String>) {
let detail = chop(detail, 40);
let command = chop(command, 40);
let action = chop(action, 10);
"| [dim_gray]{} ─·─► [/][cyan]{}[/] [white]{}[/]".print_with(vec![action, command, detail]);
}
pub fn sub_action(
subaction: impl Into<String>,
command: impl Into<String>,
detail: impl Into<String>,
) {
let detail = chop(detail, 40);
let command = chop(command, 40);
let subaction = chop(subaction, 10);
if detail.clone().is_empty() {
"| [dim_gray] ╰─► [/][yellow]{}[/] [white]{}[/]".print_with(vec![subaction, command]);
return;
} else {
"| [dim_gray] ╰─► [/][yellow]{}[/][dim_gray] ─► [white]{}[/] [gray]{}[/]"
.print_with(vec![subaction, command, detail]);
}
}
pub fn key(key: impl Into<String>, order: usize) {
let key = key.into();
let intend = " ".repeat(order * 2);
"| {}╰─ [pink]{}[/]".print_with(vec![intend, key]);
}
pub fn action_complete(
action: impl Into<String>,
command: impl Into<String>,
detail: impl Into<String>,
) {
let detail = chop(detail, 40);
let command = chop(command, 40);
let action = chop(action, 10);
let length = 40 - action.len() - command.len() - detail.len() - 4;
let filler = "─".repeat(length);
"╰─[green]╮[/]".print();
" [green]╰─► {} [/][yellow]{}[/][dim_gray] ──► [/]{}[dim_gray] {}[/]"
.print_with(vec![action, command, detail, filler]);
"╭─[green]╯[/]".print();
}
pub fn sub_array(r#in: &str, len: usize, intend: usize) {
let intend = " ".to_string();
"|{}╰─► [pink]{}[/] ([white]{}[/] [dim_gray]NOS[/])".print_with(vec![
intend,
r#in.to_string(),
len.to_string(),
]);
}
pub fn action_loop(arg: impl Into<String>, detail: impl Into<String>) {
let arg = arg.into();
let detail = detail.into();
"|[dim_gray] LOOP ─·─╮[/]".print();
"|[dim_gray] | [/][yellow]{}[/] | [dim_gray]{}[/] ".print_with(vec![arg, detail]);
}