use std::io::stdout;
use chrono::{Datelike, Utc};
use crossterm::{execute, terminal::SetTitle};
fn box_line(length: usize, is_top: bool) -> String {
if length < 2 {
return String::new();
}
if is_top {
format!("{}{}{}", "┌", "─".repeat(length - 2), "┐")
} else {
format!("{}{}{}", "└", "─".repeat(length - 2), "┘")
}
}
fn box_separator(length: usize) -> String {
if length < 2 {
return String::new();
}
format!("{}{}{}", "├", "─".repeat(length - 2), "┤")
}
fn box_data(data: String, target_length: usize) -> String {
let padding = if ((target_length - 2) / 2) > (data.chars().count() / 2) {
((target_length - 2) / 2) - (data.chars().count() / 2)
} else {
0
};
let mut s = format!("{}{}{}{}", " ".repeat(padding), data, " ".repeat(padding), "│");
while s.chars().count() < target_length - 1 {
s = format!("{}{}", " ", s);
}
format!("{}{}", "│", s)
}
fn box_tabular_data_rows(
data: Vec<Vec<String>>,
sizes: Vec<usize>,
target_length: usize,
spacing: usize,
) -> Vec<String> {
let max_cell_length = sizes.iter().max().unwrap();
let mut result = Vec::new();
for items in data {
let mut s = " ".repeat(spacing);
for string in items {
if &string.chars().count() < max_cell_length {
let padding = (max_cell_length / 2) - (&string.chars().count() / 2);
s = format!(
"{}{}{}{}{}",
s,
" ".repeat(padding),
string,
" ".repeat(padding),
" ".repeat(spacing)
);
} else {
s = format!("{}{}{}", s, string, " ".repeat(spacing));
}
}
result.push(box_data(s, target_length));
}
result
}
fn multiline_find_display_length(lines: &str) -> usize {
let mut result = 0;
if let Some(line) = lines.lines().max_by(|x, y| x.chars().count().cmp(&y.chars().count())) {
result = line.len();
result /= 2;
result -= result / 10;
}
result
}
pub fn print_banner(commands: Vec<String>, chunk_size: usize) {
let terminal_title = format!("Minotari Base Node - Version {}", env!("CARGO_PKG_VERSION"));
if let Err(e) = execute!(stdout(), SetTitle(terminal_title.as_str())) {
println!("Error setting terminal title. {e}")
}
let chunks: Vec<Vec<String>> = commands.chunks(chunk_size).map(|x| x.to_vec()).collect();
let mut cell_sizes = Vec::new();
let mut row_cell_count: usize = 0;
let mut command_data: Vec<Vec<String>> = Vec::new();
for chunk in chunks {
let mut cells: Vec<String> = Vec::new();
for item in chunk {
cells.push(item.clone());
cell_sizes.push(item.chars().count());
row_cell_count += 1;
}
if row_cell_count < chunk_size {
while row_cell_count < chunk_size {
cells.push(" ".to_string());
cell_sizes.push(1);
row_cell_count += 1;
}
} else {
row_cell_count = 0;
}
command_data.push(cells);
}
let row_cell_sizes: Vec<Vec<usize>> = cell_sizes.chunks(chunk_size).map(|x| x.to_vec()).collect();
let mut row_cell_size = Vec::new();
let mut max_cell_size: usize = 0;
for sizes in row_cell_sizes {
for size in sizes {
if size > max_cell_size {
max_cell_size = size;
}
}
row_cell_size.push(max_cell_size);
max_cell_size = 0;
}
let banner = include!("../../assets/tari_banner.rs");
let target_line_length = multiline_find_display_length(banner);
for line in banner.lines() {
println!("{line}");
}
println!("\n{}", box_line(target_line_length, true));
let logo = include!("../../assets/tari_logo.rs");
for line in logo.lines() {
println!("{}", box_data(line.to_string(), target_line_length));
}
println!("{}", box_data(" ".to_string(), target_line_length));
println!("{}", box_data("Minotari Base Node".to_string(), target_line_length));
println!("{}", box_data("~~~~~~~~~~~~~~".to_string(), target_line_length));
println!(
"{}",
box_data(
format!("Copyright 2019-{}. {}", Utc::now().year(), "The Tari Project"),
target_line_length
)
);
println!(
"{}",
box_data(format!("Version {}", env!("CARGO_PKG_VERSION")), target_line_length)
);
println!("{}", box_separator(target_line_length));
println!("{}", box_data("Commands".to_string(), target_line_length));
println!("{}", box_data("~~~~~~~~".to_string(), target_line_length));
println!("{}", box_separator(target_line_length));
let rows = box_tabular_data_rows(command_data, row_cell_size, target_line_length, 10);
for row in rows {
println!("{row}");
}
println!("{}", box_line(target_line_length, false));
}