Make the version output a proper banner: ASCII wordmark, color on a tty, aligned build info
All checks were successful
CI / check (push) Successful in 5m20s

This commit is contained in:
Jean Chevronnet 2026-07-20 15:10:52 +00:00
parent 61db74875f
commit d5a89baf53
No known key found for this signature in database
2 changed files with 47 additions and 15 deletions

View file

@ -61,7 +61,8 @@ async fn main() -> Result<()> {
// `echo --version` / `-V` prints the build banner (version, git revision, build // `echo --version` / `-V` prints the build banner (version, git revision, build
// date, toolchain, target) and exits. // date, toolchain, target) and exits.
if matches!(argv.get(1).map(String::as_str), Some("--version") | Some("-V") | Some("version")) { if matches!(argv.get(1).map(String::as_str), Some("--version") | Some("-V") | Some("version")) {
println!("{}", version::banner()); use std::io::IsTerminal;
println!("{}", version::banner(std::io::stdout().is_terminal()));
return Ok(()); return Ok(());
} }
if argv.get(1).map(String::as_str) == Some("import") { if argv.get(1).map(String::as_str) == Some("import") {
@ -95,6 +96,11 @@ async fn main() -> Result<()> {
} }
let path = std::env::args().nth(1).unwrap_or_else(|| "config.toml".to_string()); let path = std::env::args().nth(1).unwrap_or_else(|| "config.toml".to_string());
// On an interactive run, greet with the full banner; under systemd (stderr is
// journald, not a tty) skip it and let the structured log line below stand.
if std::io::IsTerminal::is_terminal(&std::io::stderr()) {
eprintln!("{}", version::banner(true));
}
tracing::info!(revision = %version::revision(), built = %version::built(), rustc = version::RUSTC, "starting {}", version::short()); tracing::info!(revision = %version::revision(), built = %version::built(), rustc = version::RUSTC, "starting {}", version::short());
let cfg = config::Config::load(&path)?; let cfg = config::Config::load(&path)?;
let ts = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(); let ts = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();

View file

@ -33,22 +33,48 @@ pub fn short() -> String {
format!("echo {VERSION} ({})", revision()) format!("echo {VERSION} ({})", revision())
} }
/// The full multi-line banner for `echo --version`. // ASCII wordmark (figlet "standard", "echo").
pub fn banner() -> String { const LOGO: [&str; 5] = [
r" _ ",
r" ___ ___| |__ ___ ",
r" / _ \/ __| '_ \ / _ \ ",
r" | __/ (__| | | | (_) |",
r" \___|\___|_| |_|\___/ ",
];
/// The full banner for `echo --version` / an interactive startup. `color` emits
/// ANSI styling (only when writing to a terminal).
pub fn banner(color: bool) -> String {
let (logo, name, dim, reset) = if color {
("\x1b[38;5;44m", "\x1b[1;38;5;51m", "\x1b[2m", "\x1b[0m")
} else {
("", "", "", "")
};
let commit = if COMMIT_DATE.is_empty() { let commit = if COMMIT_DATE.is_empty() {
String::new() String::new()
} else { } else {
format!(" ({COMMIT_DATE})") format!(" {dim}({COMMIT_DATE}){reset}")
}; };
format!( // Identity text aligned against the middle rows of the logo.
"echo \u{2014} federated IRC services\n \ let side = [
version: {VERSION}\n \ String::new(),
revision: {rev}{commit}\n \ format!("{name}echo{reset} {dim}services{reset}"),
built: {built} ({profile})\n \ format!("{dim}federated IRC services{reset}"),
rustc: {RUSTC}\n \ String::new(),
target: {TARGET}", String::new(),
rev = revision(), ];
built = built(), let mut out = String::from("\n");
profile = profile(), for i in 0..LOGO.len() {
) out.push_str(&format!(" {logo}{:<24}{reset} {}\n", LOGO[i], side[i]));
}
out.push('\n');
let mut row = |label: &str, value: String| {
out.push_str(&format!(" {dim}{label:<9}{reset}{value}\n"));
};
row("version", VERSION.to_string());
row("revision", format!("{}{commit}", revision()));
row("built", format!("{} {dim}·{reset} {}", built(), profile()));
row("rustc", RUSTC.strip_prefix("rustc ").unwrap_or(RUSTC).to_string());
row("target", TARGET.to_string());
out
} }