use crate::cli::Cli;
use crate::config::load_config;
use crate::config::save_config;
use crate::size;
use crate::structure::ArtType;
use crate::structure::Package;
use anyhow::Result;
use clap::Parser;
use owo_colors::colors::CustomColor;
use owo_colors::OwoColorize;
pub fn handler(package: &Package, cargo_version: &str) -> Result<()> {
let cli = Cli::parse();
let mut cfg = load_config().unwrap_or_default();
cfg.enable_art = !cli.disable_art;
if let Some(art_type) = cli.art_type {
cfg.art_type = art_type;
}
save_config(&cfg)?;
let size = size::get_size();
let info = format_package_info(PackageInfo {
cargo_version,
package,
size,
git_commits: get_commits()?,
});
print_art(&info, cfg.enable_art, cfg.art_type);
Ok(())
}
fn get_commits() -> Result<usize> {
use std::process::Command;
let output = Command::new("git")
.args(["rev-list", "--count", "HEAD"])
.output()?;
if output.status.success() {
let count_str = String::from_utf8_lossy(&output.stdout);
let count = count_str.trim().parse::<usize>()?;
Ok(count)
} else {
Err(anyhow::anyhow!(
"Failed to get commit count: {}",
String::from_utf8_lossy(&output.stderr)
))
}
}
pub struct PackageInfo<'a> {
pub(crate) cargo_version: &'a str,
pub(crate) package: &'a Package,
pub(crate) size: size::Size,
pub(crate) git_commits: usize,
}
pub fn format_with_art(info: PackageInfo, art_type: ArtType) -> Vec<String> {
let info_lines = format_package_info(info);
let ascii_art = art_gen(art_type, true);
let ascii_lines: Vec<&str> = ascii_art.trim_matches('\n').lines().collect();
ascii_lines
.iter()
.zip(
info_lines
.iter()
.map(|s| s.as_str())
.chain(std::iter::repeat("")),
)
.map(|(art_line, side_text)| {
format!(
"{:<40} {}",
art_line.fg::<CustomColor<247, 76, 0>>(),
side_text
)
})
.collect()
}
pub fn format_package_info(info: PackageInfo) -> Vec<String> {
let authors = info.package.authors.join(", ");
let dependencies = info.package.dependencies.len().to_string();
let lines = info.size.lines().to_string();
let file_size = format!(
"{}kB ({}files)",
info.size.filesize(),
info.size.number_of_files()
);
let commits = info.git_commits.to_string();
let fields = [
("Cargo Version:", info.cargo_version),
("Package:", info.package.name.as_str()),
("Version:", info.package.version.as_str()),
(
"Description:",
info.package.description.as_deref().unwrap_or("none"),
),
("Authors:", authors.as_str()),
("Dependencies:", dependencies.as_str()),
("Lines of Code:", lines.as_str()),
("File Size:", file_size.as_str()),
(
"Repo:",
info.package.repository.as_deref().unwrap_or("none"),
),
(
"Documentation:",
info.package.documentation.as_deref().unwrap_or("none"),
),
(
"License:",
info.package.license.as_deref().unwrap_or("none"),
),
("Edition:", info.package.edition.as_str()),
("Git Commits:", commits.as_str()),
];
fields
.iter()
.map(|(label, value)| format!("{} {:>1}", label.fg::<CustomColor<247, 76, 0>>(), value))
.collect()
}
fn print_art(info: &[String], enable_art: bool, art_type: ArtType) {
if !enable_art {
for line in info {
println!("{line}");
}
return;
}
let ascii_art = art_gen(art_type, enable_art);
let ascii_lines: Vec<&str> = ascii_art.trim_matches('\n').lines().collect();
for (art_line, side_text) in ascii_lines
.iter()
.zip(info.iter().chain(std::iter::repeat(&"".to_string())))
{
println!(
"{:<40} {}",
art_line.fg::<CustomColor<247, 76, 0>>(),
side_text
);
}
}
fn art_gen(art_type: ArtType, enable_art: bool) -> String {
if !enable_art {
return String::new();
}
match art_type {
ArtType::Crab => crab_art(),
ArtType::Rust => rust_art(),
}
}
fn crab_art() -> String {
r#"
R RR RR
R RRRRRRRR R R
R RR R RRRRRRRRRRRRR R RR
rR RRR R RRRRRRRRRRRRRRRRR R RRR R
RRR RR RRRRRRRRRRRRRRRRRRRRRRR RRRRR
RRRRR RRRRRRRRRRRRRRRRRRRRRRRR RRRR
RRR RRRRRRRRRRRRRRRRRRRRRRRRRRRR RR
R RRRRRRRRRR= RR = RRRRRRRRRRR
RRRRRRRRRRRR= RR = RRRRRRRRRR
RRRRRRRRRRR RR RRRRRRRRRR
RR==RRRRRRRRRRRRRRRRRRRRRR===RR
RR = ==RRRRRRR RRRRRR== = RR
RR = =========== = RR
RR R
R R
R
"#
.to_string()
}
fn rust_art() -> String {
r#"
` :y.`yy`.y: `
-``MNsNMMNNNNMMNsNM``-
` -MMNMMMMNNm``NNNMMMMNMM- `
`NNNMMMdo:` `+md/ `:odMMMNNN`
-ssNMMNo. .oNMMNss-
`mMMMMNmmmmmmmmmmmmmmmdy+` `sMMMm`
`mMMMMMMMMMMMMMMMMMMMMMMMMMN/ hMMMMm`
-oMN-:Ny:mMMMMMm oNMMMMMm oN::MMo-
.yMMMhhh+ dMMMMMd:::::+mMMMMN/ odyhMMMy.
-sNMMy dMMMMMMMMMMMMMMMMs` `yMMNs-
-sNMMy dMMMMMNyyyydMMMMMMy .odMMNs-
.yMMMm dMMMMMh +MMMMMM+ sMMMMMy.
-oMMMMMMMMMMMMMMMMM+ mMMMMMMMMMMMMMo-
`mMMMMMMMMMMMMMMMMM+ :NMMMMMMMMMMMMm`
`mMMMm `-:o+:/mMMMm`
-ssNMMMyomo smohMMMNss-
`NNNMs+mN/-` `-/Nd/yMNNN`
` -MMNMMMMMNmmmmNMMMMMNMM- `
-``MNsNMMNMMNMMNsNM``-
` :y.`yy`.y: `
"#
.to_string()
}