app
Adom Chip Thumbnailer
Public Made by Adomby adom
The chip-icon factory: from a STEP file it renders the complete family of chip icons, shaded 3D orientations, transparent icons, name-lasered variants, and 11 vector outline styles, in a live web app
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
//! ANSI-colored output helpers, mirroring the ok!/err!/hint!/note! pattern
//! used by step2glb and chip-fetcher so log scraping is consistent across
//! the Adom CLI ecosystem. is_terminal()-gated per gallia/skills/
//! adom-cli-design/SKILL.md — never leak raw ANSI to pipes / log files.
#![allow(dead_code)]
use std::io::IsTerminal;
use std::sync::OnceLock;
pub const GREEN: &str = "\x1b[32m";
pub const RED: &str = "\x1b[31m";
pub const YELLOW: &str = "\x1b[33m";
pub const CYAN: &str = "\x1b[36m";
pub const BOLD: &str = "\x1b[1m";
pub const DIM: &str = "\x1b[2m";
pub const RESET: &str = "\x1b[0m";
static STDOUT_IS_TTY: OnceLock<bool> = OnceLock::new();
static STDERR_IS_TTY: OnceLock<bool> = OnceLock::new();
pub fn stdout_is_tty() -> bool {
*STDOUT_IS_TTY.get_or_init(|| std::io::stdout().is_terminal())
}
pub fn stderr_is_tty() -> bool {
*STDERR_IS_TTY.get_or_init(|| std::io::stderr().is_terminal())
}
/// Strip CSI sequences like `\x1b[36m`, `\x1b[0m`, `\x1b[1;32m` etc.
/// Used when stdout/stderr isn't a TTY so log files don't get raw escape
/// codes leaked into them.
pub fn strip_ansi(s: &str) -> String {
let mut out = String::with_capacity(s.len());
let mut chars = s.chars().peekable();
while let Some(c) = chars.next() {
if c == '\x1b' && chars.peek() == Some(&'[') {
chars.next();
for c2 in chars.by_ref() {
if c2.is_ascii_alphabetic() {
break;
}
}
continue;
}
out.push(c);
}
out
}
pub fn ok<S: AsRef<str>>(msg: S) {
let s = msg.as_ref();
if stdout_is_tty() {
println!("{GREEN}{BOLD}OK:{RESET} {s}");
} else {
println!("OK: {}", strip_ansi(s));
}
}
pub fn err<S: AsRef<str>>(msg: S) {
let s = msg.as_ref();
if stderr_is_tty() {
eprintln!("{RED}{BOLD}ERROR:{RESET} {s}");
} else {
eprintln!("ERROR: {}", strip_ansi(s));
}
}
pub fn warn<S: AsRef<str>>(msg: S) {
let s = msg.as_ref();
if stderr_is_tty() {
eprintln!("{YELLOW}{BOLD}WARN:{RESET} {s}");
} else {
eprintln!("WARN: {}", strip_ansi(s));
}
}
pub fn hint<S: AsRef<str>>(msg: S) {
let s = msg.as_ref();
if stderr_is_tty() {
eprintln!("{DIM}Hint:{RESET} {s}");
} else {
eprintln!("Hint: {}", strip_ansi(s));
}
}
#[macro_export]
macro_rules! note {
($($arg:tt)*) => {{
let __s = format!($($arg)*);
if $crate::ui::stdout_is_tty() {
println!("{}", __s);
} else {
println!("{}", $crate::ui::strip_ansi(&__s));
}
}};
}