Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add coloring to repo names and version diff #1292

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 141 additions & 24 deletions src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,11 @@ pub fn color_repo(enabled: bool, name: &str) -> String {
return name.to_string();
}

let mut col: u32 = 5;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a small hash function. Meaning colours should be different for similar strings. As there's only 6 possibilities we're bound to get conflicts.

Maybe we can adjust it to avoid this known conflict but just using the length would be a big no.


for &b in name.as_bytes() {
col = (b as u32).wrapping_add((col << 4).wrapping_add(col));
}

col = (col % 6) + 9;
let col = Style::from(Color::Fixed(col as u8)).bold();
col.paint(name).to_string()
let color = 9 + (name.len() % 6) as u8;
Style::from(Color::Fixed(color))
.bold()
.paint(name)
.to_string()
}

pub fn print_target(targ: &str, quiet: bool) {
Expand Down Expand Up @@ -443,13 +439,38 @@ pub fn print_install_verbose(config: &Config, actions: &Actions, devel: &HashSet
});

for pkg in &install {
println!(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if println is going to overpad by the amount of characters we added by colouring. Can't we just do package_len -= pkg_str.len() - pkg.pkg.db().unwrap().name().len() - pkg.pkg.name().len() - 1 to calculate the difference like you have but keep using the {:<package_len$} and similar formatters instead of repeating strings.

"{:<package_len$} {:<old_len$} {:<new_len$} {}",
format!("{}/{}", pkg.pkg.db().unwrap().name(), pkg.pkg.name()),
let repo_name = pkg.pkg.db().unwrap().name();
let colored_repo = color_repo(config.color.enabled, repo_name);
let pkg_str = format!("{}/{}", colored_repo, pkg.pkg.name());
let visible_width = repo_name.len() + 1 + pkg.pkg.name().len(); // Calculate visible width without ANSI codes
let padding = " ".repeat(package_len.saturating_sub(visible_width));

let (old_colored, new_colored) = colorize_version_diff(
db.pkg(pkg.pkg.name())
.map(|pkg| pkg.version().as_str())
.unwrap_or(""),
pkg.pkg.version().as_str(),
);

// Calculate visible width of the colored versions
let old_visible_width = db
.pkg(pkg.pkg.name())
.map(|pkg| pkg.version().as_str().len())
.unwrap_or(0);
let new_visible_width = pkg.pkg.version().as_str().len();

// Add padding to maintain alignment
let old_padding = " ".repeat(old_len.saturating_sub(old_visible_width));
let new_padding = " ".repeat(new_len.saturating_sub(new_visible_width));

println!(
"{}{} {}{} {}{} {}",
pkg_str,
padding,
old_colored,
old_padding,
new_colored,
new_padding,
if pkg.make { &yes } else { &no }
);
}
Expand All @@ -475,37 +496,83 @@ pub fn print_install_verbose(config: &Config, actions: &Actions, devel: &HashSet
match pkg {
Base::Aur(base) => {
for pkg in &base.pkgs {
let repo_name = repo(config, &pkg.pkg.name);
let colored_repo = color_repo(config.color.enabled, &repo_name);
let pkg_str = format!("{}/{}", colored_repo, pkg.pkg.name);
let visible_width = repo_name.len() + 1 + pkg.pkg.name.len();
let padding = " ".repeat(package_len.saturating_sub(visible_width));

let ver = if devel.contains(&pkg.pkg.name) {
"latest-commit"
} else {
&pkg.pkg.version
};

let old_version = old_ver(config, &pkg.pkg.name)
.map(|v| v.as_str())
.unwrap_or_default();

// Colorize the versions
let (old_colored, new_colored) = colorize_version_diff(old_version, ver);

// Calculate visible width of the colored versions
let old_visible_width = old_version.len();
let new_visible_width = ver.len();

// Add padding to maintain alignment
let old_padding = " ".repeat(old_len.saturating_sub(old_visible_width));
let new_padding = " ".repeat(new_len.saturating_sub(new_visible_width));

println!(
"{:<package_len$} {:<old_len$} {:<new_len$} {}",
format!("{}/{}", repo(config, &pkg.pkg.name), pkg.pkg.name),
old_ver(config, &pkg.pkg.name)
.map(|v| v.as_str())
.unwrap_or_default(),
ver,
"{}{} {}{} {}{} {}",
pkg_str,
padding,
old_colored,
old_padding,
new_colored,
new_padding,
if pkg.make { &yes } else { &no }
);
}
}
Base::Pkgbuild(base) => {
for pkg in &base.pkgs {
let repo_name = &base.repo;
let colored_repo = color_repo(config.color.enabled, repo_name);
let pkg_str = format!("{}/{}", colored_repo, pkg.pkg.pkgname);
let visible_width = repo_name.len() + 1 + pkg.pkg.pkgname.len();
let padding = " ".repeat(package_len.saturating_sub(visible_width));

let ver = base.srcinfo.version();
let ver = if devel.contains(&pkg.pkg.pkgname) {
"latest-commit"
} else {
&ver
};

let old_version = old_ver(config, &pkg.pkg.pkgname)
.map(|v| v.as_str())
.unwrap_or_default();

// Colorize the versions
let (old_colored, new_colored) = colorize_version_diff(old_version, ver);

// Calculate visible width of the colored versions
let old_visible_width = old_version.len();
let new_visible_width = ver.len();

// Add padding to maintain alignment
let old_padding = " ".repeat(old_len.saturating_sub(old_visible_width));
let new_padding = " ".repeat(new_len.saturating_sub(new_visible_width));

println!(
"{:<package_len$} {:<old_len$} {:<new_len$} {}",
format!("{}/{}", base.repo, pkg.pkg.pkgname),
old_ver(config, &pkg.pkg.pkgname)
.map(|v| v.as_str())
.unwrap_or_default(),
ver,
"{}{} {}{} {}{} {}",
pkg_str,
padding,
old_colored,
old_padding,
new_colored,
new_padding,
if pkg.make { &yes } else { &no }
);
}
Expand All @@ -516,3 +583,53 @@ pub fn print_install_verbose(config: &Config, actions: &Actions, devel: &HashSet

println!();
}

fn colorize_version_diff(old_ver: &str, new_ver: &str) -> (String, String) {
if old_ver.is_empty() {
return (
String::new(),
Style::new().fg(Color::Green).paint(new_ver).to_string(), // all green for new version
);
}

let mut old_colored = String::new();
let mut new_colored = String::new();

// Split versions into characters
let old_chars: Vec<char> = old_ver.chars().collect();
let new_chars: Vec<char> = new_ver.chars().collect();

// Find common prefix
let mut common_len = 0;
for (a, b) in old_chars.iter().zip(new_chars.iter()) {
if a == b {
common_len += 1;
} else {
break;
}
}

// Color the old version (red for different parts)
old_colored.push_str(&old_ver[..common_len]);
if common_len < old_ver.len() {
old_colored.push_str(
&Style::new()
.fg(Color::Red)
.paint(&old_ver[common_len..])
.to_string(),
);
}

// Color the new version (green for different parts)
new_colored.push_str(&new_ver[..common_len]);
if common_len < new_ver.len() {
new_colored.push_str(
&Style::new()
.fg(Color::Green)
.paint(&new_ver[common_len..])
.to_string(),
);
}

(old_colored, new_colored)
}