| Crates.io | rustyhues |
| lib.rs | rustyhues |
| version | 1.0.0 |
| created_at | 2026-01-17 22:01:11.445355+00 |
| updated_at | 2026-01-17 22:01:11.445355+00 |
| description | Lightweight, zero-macro ANSI color styling for Rust CLIs, with smart terminal detection, RGB/hex support, conditional styling, and configurable semantic styles. |
| homepage | |
| repository | https://github.com/avaideas/rustyhues |
| max_upload_size | |
| id | 2051265 |
| size | 92,686 |
Lightweight, zero-macro ANSI color styling for Rust CLIs, with smart terminal detection, RGB/hex support, conditional styling, and configurable semantic styles like success(), warning(), and error().
use rustyhues::Stylize;
fn main() {
println!("{}", "Hello, RustyHues!".blue().bold());
}
"text".blue().bold() via a blanket Stylize trait.rgb(255, 0, 128) and hex("ff0080") or hex("f08").NO_COLOR, CLICOLOR, CLICOLOR_FORCE, TERM=dumb, and TTY detection.success(), warning(), error(), info(), and debug() with configurable palettes..is() / .not().Add RustyHues to your project:
cargo add rustyhues
Or manually in Cargo.toml:
[dependencies]
rustyhues = "1.0"
use rustyhues::Stylize;
fn main() {
println!("{}", "Success".green().bold());
println!("{}", "Warning".yellow());
eprintln!("{}", "Error on stderr".red().paint_err());
}
Under the hood:
&str, String, etc.Paint<T> wrapper that implements Display, so it fits into println!, format!, logs, etc.Named ANSI colors:
use rustyhues::Stylize;
// Standard ANSI colors
println!("{}", "Black".black());
println!("{}", "Red".red());
println!("{}", "Green".green());
println!("{}", "Yellow".yellow());
println!("{}", "Blue".blue());
println!("{}", "Magenta".magenta());
println!("{}", "Cyan".cyan());
println!("{}", "White".white());
// Bright variants
println!("{}", "Bright Red".bright_red());
println!("{}", "Bright Blue".bright_blue());
Background colors:
use rustyhues::Stylize;
println!("{}", "On red".bg_red());
println!("{}", "Bright on white".blue().bg_bright_white());
Text decorations:
use rustyhues::Stylize;
println!("{}", "Bold".bold());
println!("{}", "Dim".dim());
println!("{}", "Italic".italic());
println!("{}", "Underline".underline());
println!("{}", "Inverted".invert());
You can chain as many styles as you like:
use rustyhues::Stylize;
println!("{}", "Fancy".cyan().bg_bright_black().bold().underline());
RustyHues supports full 24-bit color (when the terminal does) and gracefully falls back to the nearest ANSI color if not.
use rustyhues::Stylize;
println!("{}", "Custom RGB".rgb(255, 128, 64));
println!("{}", "RGB background".bg_rgb(10, 20, 30));
use rustyhues::Stylize;
println!("{}", "Hex color".hex("ff8844"));
println!("{}", "Hex background".bg_hex("#333333"));
println!("{}", "Short hex".hex("F84"));
println!("{}", "Short bg hex".bg_hex("#333"));
Invalid hex values simply don't apply any extra style (they don't panic):
use rustyhues::Stylize;
let painted = format!("{}", "X".blue().hex("ZZZZZZ"));
assert!(painted.starts_with("\x1b[34m")); // blue is still applied
For log-style output, RustyHues comes with predefined styles:
use rustyhues::Stylize;
println!("{}", "All good".success());
println!("{}", "Heads up".warning());
println!("{}", "Something broke".error());
println!("{}", "FYI".info());
println!("{}", "Debug details".debug());
By default:
You can customize these globally via rustyhues::env:
use rustyhues::Stylize;
use rustyhues::{env, Color, Decoration};
fn main() {
// Change success style to cyan text on white background, underlined
env::set_success_style(
Some(Color::Cyan),
Some(Color::White),
Some(Decoration::Underline),
);
println!("{}", "Success?".success());
// Reset all predefined styles back to defaults
env::reset_all_predefined_styles();
}
Or target a specific style:
use rustyhues::{env, Color, Decoration};
// Change warning style to bright yellow text, bold
env::set_warning_style(
Some(Color::BrightYellow),
None,
Some(Decoration::Bold),
);
You can also use the generic setter:
use rustyhues::{env, Color, Decoration};
env::set_predefined_style(
env::PredefinedStyleType::Error,
Some(Color::BrightRed),
None,
Some(Decoration::Bold),
);
is / not)A unique RustyHues feature is conditional styling based on runtime expressions. This lets you write logic like:
"Only apply this style if this condition is true."
Simple case:
use rustyhues::Stylize;
fn main() {
let debug_mode = true;
println!(
"{}",
"Debug details".is(Some(debug_mode)).magenta()
);
}
debug_mode == true, the text is magenta.debug_mode == false, no styles are applied.is, not, e_is, e_not, n_is, n_notA few helper methods are supplied so that Some() and None don't have to be typed. These are:
e_is - Expression ise_not - Expression is notn_is - None isn_not - None is notYou can get quite expressive:
use rustyhues::Stylize;
let is_ok = true;
// Equivalent ways to say “if is_ok then style, otherwise don't”:
println!("{}", "OK".is(Some(is_ok)).green());
println!("{}", "OK".e_is(is_ok).green());
// Invert the condition:
println!("{}", "Not OK".not(Some(is_ok)).red());
println!("{}", "Not OK".e_not(is_ok).red());
// Toggle style with no explicit expression:
println!("{}", "Maybe styled".n_is().blue()); // toggles on/off
println!("{}", "Maybe not".n_not().red()); // toggles on/off
// Use as if / else
println!("{}", "Maybe Ok".e_is(is_ok).green().n_not().red());
You can chain comparisons in complex expressions. RustyHues internally tracks whether styles should be applied as it walks the items you've built up.
By default, styling assumes stdout. If you want a Paint explicitly targeting stderr, use paint_err():
use rustyhues::Stylize;
eprintln!("{}", "This goes to stderr".paint_err().red().bold());
Both stdout and stderr obey the same environment/TTY detection rules.
By default, RustyHues writes a reset \x1b[0m at the end of your string so that styles don't continue to subsequent output.
Sometimes you want them to continue, for example when you're building custom prompts:
use rustyhues::Stylize;
print!("{}", ">>> ".green().no_reset());
// terminal remains green after this
println!("still green");
You can also be explicit:
use rustyhues::Stylize;
println!("{}", "No reset".blue().should_reset(false));
println!("{}", "No reset".blue().should_reset(true));
The env module controls global behavior.
use rustyhues::env::{self, ColorChoice};
env::set_color_choice(ColorChoice::Always); // always style
env::set_color_choice(ColorChoice::Never); // never style
env::set_color_choice(ColorChoice::Auto); // (default) auto-detect
You can read the current value with:
let current = env::color_choice();
use rustyhues::env;
// Let RustyHues decide (based on COLORTERM, etc.)
env::set_true_color_allowed(None);
// Force allow truecolor
env::set_true_color_allowed(Some(true));
// Force disable truecolor (always fall back to nearest ANSI color)
env::set_true_color_allowed(Some(false));
Internally, when truecolor is disabled, RustyHues finds the nearest ANSI color using Euclidean distance in RGB space.
When ColorChoice::Auto is active (the default), RustyHues follows common conventions:
NO_COLOR set - disables colors.TERM=dumb - disables colors.CLICOLOR=0 - disables colors.CLICOLOR_FORCE=1 - force enables colors.On Unix, TTY detection uses libc::isatty.
On Windows, RustyHues uses the Windows API to:
ENABLE_VIRTUAL_TERMINAL_PROCESSING) so ANSI escape codes are supported in modern terminals.RustyHues uses some global mutable state in env (color choice, truecolor, predefined styles). This is great for configuring an app, but just be aware in tests:
Recommended patterns:
use rustyhues::env::{self, ColorChoice};
fn setup_colors_for_tests() {
env::set_color_choice(ColorChoice::Always);
env::set_true_color_allowed(Some(false)); // stable ANSI output
env::reset_all_predefined_styles();
}
You can call this at the start of relevant tests. If you see flaky tests due to ordering, consider:
cargo test -- --test-threads=1, orPublicly exported types and modules you'll commonly use:
paint(), paint_err()rgb, bg_rgb, hex, bg_hexred, bg_red, bright_red, bg_bright_red, etc...bold, dim, italic, underline, invertis(), not(), e_is(), e_not(), n_is(), n_not()success(), warning(), error(), info(), debug()should_reset(), no_reset()Paint<T> - styling wrapper that implements Display.Color - ANSI color enum.Decoration - ANSI text decoration enum.RGB - RGB struct with helpers (including closest_color()).Comparison - Is / Not for conditional styling.env::ColorChoice - Auto, Always, Never.env::set_color_choice, env::color_choiceenv::set_true_color_allowed, env::true_color_allowedenv::PredefinedStyleTypeenv::predefined_styleenv::set_predefined_styleenv::set_success_style, env::set_warning_style, env::set_error_style, env::set_info_style, env::set_debug_styleenv::reset_predefined_styleenv::reset_all_predefined_stylesRustyHues is dual-licensed under:
You may choose either license.
Enjoy painting your terminal with RustyHues