composition_cli/display/
mod.rs1use colored::Colorize;
2
3use crate::{context::AppContext, core::CompositionEntry};
4
5pub mod spinner;
6
7pub fn display_composition(
8 app_context: &AppContext,
9 composition_entries: &mut Vec<CompositionEntry>,
10) {
11 composition_entries.sort_by_key(|e| std::cmp::Reverse(e.line_count));
13
14 let total_lines: usize = composition_entries.iter().map(|e| e.line_count).sum();
15 composition_entries.iter_mut().for_each(|e| {
16 let percentage = (e.line_count as f32 / total_lines as f32) * 100.0;
17 e.percentage = percentage;
18 });
19
20 let max_display_width = composition_entries
21 .iter()
22 .map(|e| e.tracked.display.len())
23 .max()
24 .unwrap_or(20);
25
26 let max_lines_width = composition_entries
27 .iter()
28 .map(|e| e.line_count.ilog10() + 1)
29 .max()
30 .unwrap_or(10) as usize;
31
32 for entry in composition_entries {
33 if entry.line_count == 0 {
34 continue;
35 }
36
37 let bar_width = (entry.percentage * app_context.scale_bar / 2.0).round() as usize;
40 let bar = "█".repeat(bar_width);
41 let bar = match (app_context.config.use_color, &entry.tracked.color) {
42 (true, Some(hex)) => {
43 if let Some((r, g, b)) = hex_to_rgb(hex) {
44 bar.truecolor(r, g, b)
45 } else {
46 bar.normal()
47 }
48 }
49 (true, None) | (false, _) => bar.normal(),
50 };
51
52 println!(
53 "{:>width_display$} | {:>width_lines$} lines | {:>5.2}% | {}",
54 entry.tracked.display,
55 entry.line_count,
56 entry.percentage,
57 bar,
58 width_display = max_display_width + 1,
59 width_lines = max_lines_width,
60 );
61 }
62}
63
64fn hex_to_rgb(hex: &str) -> Option<(u8, u8, u8)> {
65 let hex = hex.trim_start_matches('#');
66 if hex.len() != 6 {
67 return None;
68 }
69
70 let r = u8::from_str_radix(&hex[0..2], 16).ok()?;
71 let g = u8::from_str_radix(&hex[2..4], 16).ok()?;
72 let b = u8::from_str_radix(&hex[4..6], 16).ok()?;
73
74 Some((r, g, b))
75}