this repo has no description
at main 5.0 kB view raw
1use nu_ansi_term::Color::{self, Green, Red, Yellow}; 2use std::collections::BTreeMap; 3use terminal_light::luma; 4 5use super::{ 6 package::{DiffType, Package, SizeDelta}, 7 parser::DiffRoot, 8}; 9 10#[derive(Debug)] 11pub struct PackageExtra { 12 name: String, 13 base_package: Package, 14} 15 16#[derive(Debug)] 17pub struct PackageListDiff { 18 all: Vec<PackageExtra>, 19 added: BTreeMap<String, Package>, 20 removed: BTreeMap<String, Package>, 21 changed: BTreeMap<String, Package>, 22 size_delta: SizeDelta, 23 longest_name: usize, 24 25 // Whether to sort by size difference when displaying 26 pub by_size: bool, 27} 28 29impl PackageListDiff { 30 pub fn new() -> Self { 31 PackageListDiff { 32 all: Vec::new(), 33 added: BTreeMap::new(), 34 removed: BTreeMap::new(), 35 changed: BTreeMap::new(), 36 size_delta: SizeDelta(0), 37 longest_name: 0, 38 by_size: false, 39 } 40 } 41} 42 43impl std::fmt::Display for PackageListDiff { 44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 45 if self.by_size { 46 self.display_by_size(f)?; 47 } else { 48 if self.added.is_empty() && self.removed.is_empty() && self.changed.is_empty() { 49 return write!(f, "No differences found."); 50 } 51 52 self.display_by_category(f)?; 53 } 54 55 { 56 let delta = &self.size_delta; 57 writeln!(f, "size diff: {delta}")?; 58 } 59 60 Ok(()) 61 } 62} 63 64impl PackageListDiff { 65 fn display_by_size(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 66 let all = { 67 let mut v: Vec<_> = self.all.iter().collect(); 68 v.sort_by_key(|pkg| -pkg.base_package.size_delta.0); 69 v 70 }; 71 72 let name_width = self.longest_name + 2; 73 let package_width = (all 74 .iter() 75 .map(|pkg| strip_ansi_escapes::strip(format!("{}", pkg.base_package)).len()) 76 .max() 77 .expect("At least one package exists")) 78 .min(120); 79 80 for package in &all { 81 let name = &package.name; 82 let package = &package.base_package; 83 let delta = &package.size_delta; 84 let versions = format!("{package}"); 85 let visual_len = strip_ansi_escapes::strip(&versions).len(); 86 let padding = " ".repeat(package_width.saturating_sub(visual_len)); 87 writeln!(f, "{name:name_width$}{versions}{padding} {delta}")?; 88 } 89 90 writeln!(f)?; 91 92 Ok(()) 93 } 94 95 fn display_by_category(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 96 let text_color = if luma().is_ok_and(|luma| luma > 0.6) { 97 Color::DarkGray 98 } else { 99 Color::LightGray 100 }; 101 let title_style = nu_ansi_term::Style::new().underline().bold().fg(text_color); 102 103 let name_width = self.longest_name + 2; 104 105 if !self.changed.is_empty() { 106 writeln!(f, "{}", &title_style.paint("Changed"))?; 107 for (name, package) in &self.changed { 108 writeln!(f, "[{}] {name:name_width$}{package}", Yellow.paint("C"))?; 109 } 110 writeln!(f)?; 111 } 112 113 if !self.added.is_empty() { 114 writeln!(f, "{}", &title_style.paint("Added"))?; 115 for (name, package) in &self.added { 116 write!(f, "[{}] {name:name_width$}{package}", Green.paint("A"))?; 117 writeln!(f)?; 118 } 119 writeln!(f)?; 120 } 121 122 if !self.removed.is_empty() { 123 writeln!(f, "{}", &title_style.paint("Removed"))?; 124 for (name, package) in &self.removed { 125 writeln!(f, "[{}] {name:name_width$}{package}", Red.paint("R"))?; 126 } 127 writeln!(f)?; 128 } 129 130 Ok(()) 131 } 132 133 #[allow(clippy::wrong_self_convention)] 134 pub fn from_diff_root(&mut self, diff_root: DiffRoot) { 135 for (name, diff_package) in diff_root.packages { 136 let package = Package::from(diff_package); 137 138 self.size_delta.0 += package.size_delta.0; 139 self.longest_name = self.longest_name.max(name.len()); 140 141 if self.by_size { 142 self.all.push(PackageExtra { 143 name, 144 base_package: package, 145 }); 146 147 continue; 148 } 149 150 match package.diff_type { 151 DiffType::Added => { 152 self.added.insert(name, package); 153 } 154 DiffType::Removed => { 155 self.removed.insert(name, package); 156 } 157 DiffType::Changed => { 158 self.changed.insert(name, package); 159 } 160 DiffType::Unknown => { 161 // This should never happen, but just in case 162 eprintln!("Unknown diff type for package: {name}"); 163 } 164 } 165 } 166 } 167}