Skip to content

Commit e80d5a9

Browse files
feat: add separator color config and config aliases
- Add separator_color option to [misc] for customizable separator colors (topgrade-rs#682) - Supports named colors (red, green, cyan, etc.) and 256-color indices - New parse_color() utility in terminal.rs - Add [general] as alias for [misc] section name (topgrade-rs#1472) - Document new config options in config.example.toml: - github_token, separator_color, distribution_override, nix_flake_dirs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8eb3375 commit e80d5a9

4 files changed

Lines changed: 77 additions & 19 deletions

File tree

config.example.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@
118118
# autodetect, nh, vanilla
119119
# nix_handler = "autodetect"
120120

121+
# GitHub token for self-update to avoid rate limiting.
122+
# Can also be set via TOPGRADE_GITHUB_TOKEN or GITHUB_TOKEN environment variables.
123+
# github_token = "ghp_..."
124+
125+
# Customize the separator line color.
126+
# Accepted values: black, red, green, yellow, blue, magenta, cyan, white
127+
# or a 256-color index (e.g., "208" for orange).
128+
# separator_color = "cyan"
129+
121130

122131
# Commands to run before anything
123132
[pre_commands]
@@ -245,6 +254,14 @@
245254
# Extra Home Manager arguments
246255
# home_manager_arguments = ["--flake", "file"]
247256

257+
# Override distribution detection for derivative distros.
258+
# Useful when your distro is not detected correctly.
259+
# Accepted values: alpine, arch, centos, debian, fedora, gentoo, nixos, opensuse, void, etc.
260+
# distribution_override = "arch"
261+
262+
# Nix flake directories to update (requires nix flake support)
263+
# nix_flake_dirs = ["~/nixos-config", "~/my-flake"]
264+
248265
# KDE Plasmoids (package IDs or exact names) to exclude from updates.
249266
# excluded_plasmoids = [""]
250267

src/config.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,8 @@ pub struct Misc {
461461
nix_handler: Option<NixHandler>,
462462

463463
github_token: Option<String>,
464+
465+
separator_color: Option<String>,
464466
}
465467

466468
#[derive(Clone, Copy, Debug, Deserialize, ValueEnum, Default)]
@@ -642,6 +644,7 @@ pub struct ConfigFile {
642644
include: Option<Include>,
643645

644646
#[merge(strategy = crate::utils::merge_strategies::inner_merge_opt)]
647+
#[serde(alias = "general")]
645648
misc: Option<Misc>,
646649

647650
#[merge(strategy = crate::utils::merge_strategies::commands_merge_opt)]
@@ -2004,6 +2007,14 @@ impl Config {
20042007
.or_else(|| std::env::var("GITHUB_TOKEN").ok())
20052008
}
20062009

2010+
/// Get the configured separator color name (e.g., "cyan", "green", "red")
2011+
pub fn separator_color(&self) -> Option<&str> {
2012+
self.config_file
2013+
.misc
2014+
.as_ref()
2015+
.and_then(|misc| misc.separator_color.as_deref())
2016+
}
2017+
20072018
pub fn enable_mandb(&self) -> bool {
20082019
self.config_file
20092020
.mandb

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ fn run() -> Result<()> {
130130
display_time(config.display_time());
131131
set_desktop_notifications(config.notify_each_step());
132132
set_show_step_ids(config.show_step_ids());
133+
set_separator_color(config.separator_color().and_then(parse_color));
133134

134135
debug!("Version: {}", crate_version!());
135136
debug!("OS: {}", env!("TARGET"));

src/terminal.rs

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::time::Duration;
88
use chrono::{Local, Timelike};
99
use color_eyre::eyre;
1010
use color_eyre::eyre::Context;
11-
use console::{Key, Term, measure_text_width, style};
11+
use console::{Color, Key, Term, measure_text_width, style};
1212
use notify_rust::{Notification, Timeout};
1313
use rust_i18n::t;
1414
use tracing::{debug, error};
@@ -44,6 +44,7 @@ struct Terminal {
4444
desktop_notification: bool,
4545
show_step_ids: bool,
4646
current_step_id: Option<String>,
47+
separator_color: Option<Color>,
4748
}
4849

4950
impl Terminal {
@@ -58,13 +59,18 @@ impl Terminal {
5859
desktop_notification: false,
5960
show_step_ids: false,
6061
current_step_id: None,
62+
separator_color: None,
6163
}
6264
}
6365

6466
fn set_show_step_ids(&mut self, show: bool) {
6567
self.show_step_ids = show;
6668
}
6769

70+
fn set_separator_color(&mut self, color: Option<Color>) {
71+
self.separator_color = color;
72+
}
73+
6874
fn set_current_step_id(&mut self, step_id: Option<String>) {
6975
self.current_step_id = step_id;
7076
}
@@ -132,24 +138,25 @@ impl Terminal {
132138

133139
match self.width {
134140
Some(width) => {
135-
self.term
136-
.write_fmt(format_args!(
137-
"{}\n",
138-
style(format_args!(
139-
"\n── {} {:─^border$}",
140-
message,
141-
"",
142-
border = max(
143-
2,
144-
min(80, width as usize)
145-
.checked_sub(4)
146-
.and_then(|e| e.checked_sub(measure_text_width(&message)))
147-
.unwrap_or(0)
148-
)
149-
))
150-
.bold()
151-
))
152-
.ok();
141+
let styled = style(format!(
142+
"\n── {} {:─^border$}",
143+
message,
144+
"",
145+
border = max(
146+
2,
147+
min(80, width as usize)
148+
.checked_sub(4)
149+
.and_then(|e| e.checked_sub(measure_text_width(&message)))
150+
.unwrap_or(0)
151+
)
152+
))
153+
.bold();
154+
let styled = if let Some(color) = self.separator_color {
155+
styled.fg(color)
156+
} else {
157+
styled
158+
};
159+
self.term.write_fmt(format_args!("{styled}\n")).ok();
153160
}
154161
None => {
155162
self.term.write_fmt(format_args!("―― {message} ――\n")).ok();
@@ -368,6 +375,28 @@ pub fn set_current_step_id(step_id: Option<String>) {
368375
TERMINAL.lock().unwrap().set_current_step_id(step_id);
369376
}
370377

378+
/// Parse a color name string into a console::Color.
379+
pub fn parse_color(name: &str) -> Option<Color> {
380+
match name.to_lowercase().as_str() {
381+
"black" => Some(Color::Black),
382+
"red" => Some(Color::Red),
383+
"green" => Some(Color::Green),
384+
"yellow" => Some(Color::Yellow),
385+
"blue" => Some(Color::Blue),
386+
"magenta" | "purple" => Some(Color::Magenta),
387+
"cyan" => Some(Color::Cyan),
388+
"white" => Some(Color::White),
389+
_ => {
390+
// Try parsing as a 256-color index (e.g., "208" for orange)
391+
name.parse::<u8>().ok().map(Color::Color256)
392+
}
393+
}
394+
}
395+
396+
pub fn set_separator_color(color: Option<Color>) {
397+
TERMINAL.lock().unwrap().set_separator_color(color);
398+
}
399+
371400
/// Print a summary of all updated components collected during the run.
372401
pub fn print_updated_components_summary(report: &[(impl AsRef<str>, StepResult)]) {
373402
let mut any_updates = false;

0 commit comments

Comments
 (0)