ANSI escape codes in Rust
Rust string literals support \x1b directly — println!("\x1b[31mred\x1b[0m") works with no dependencies. For ergonomic colour APIs reach for owo-colors (zero-allocation, compile-time) or colored (more dynamic). For NO_COLOR / isatty handling without writing the env-check yourself, termcolor mirrors the Go pattern. For full TUI work — windows, cursor, raw mode, mouse — use crossterm; for higher-level layouts, ratatui (formerly tui-rs) sits on top of it.
Recommended libraries
- owo-colors
Zero-allocation colour extension on every string-like type —
"error".red().bold()produces no heap traffic. Compile-time style colors via const generics. ANSI only; no terminfo lookup. - colored
The original
"text".red().bold()API — more flexible than owo-colors (runtime palette, custom colours) at the cost of allocation. HonoursNO_COLORandCLICOLOR_FORCEout of the box. - termcolor
ripgrep's colour layer — a
WriteColortrait over stdout/stderr that handles ANSI on POSIX and the Windows console API on Windows.ColorChoice::Autodoes NO_COLOR + isatty for you. - crossterm
Full cross-platform terminal toolkit — cursor, colour, raw mode, alternate screen, mouse / focus / paste events, keyboard input. The foundation under
ratatui. Use directly for CLIs; layer ratatui for full-screen TUIs.
Idiomatic patterns
fn main() {
println!("\x1b[1;31merror:\x1b[0m permission denied");
}use owo_colors::OwoColorize;
fn main() {
println!("{} permission denied", "error:".red().bold());
}use std::io::Write;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
fn main() -> std::io::Result<()> {
// Auto downgrades to plain text under NO_COLOR= or non-tty stdout.
let mut out = StandardStream::stdout(ColorChoice::Auto);
out.set_color(ColorSpec::new().set_fg(Some(Color::Red)).set_bold(true))?;
write!(out, "error:")?;
out.reset()?;
writeln!(out, " permission denied")?;
Ok(())
}use std::io::{stdout, Write};
use crossterm::{
cursor::{Hide, Show},
execute,
terminal::{disable_raw_mode, enable_raw_mode},
};
fn main() -> std::io::Result<()> {
enable_raw_mode()?;
execute!(stdout(), Hide)?;
// ... read keys, render UI ...
execute!(stdout(), Show)?; // always restore
disable_raw_mode()?;
Ok(())
}