跳到主要内容
ansicode
Rust

在 Rust 中使用 ANSI 转义码

Rust 字符串字面量原生支持 `\x1b` —— `println!("\x1b[31mred\x1b[0m")` 无需任何依赖即可工作。需要符合人体工学的彩色 API,可选 `owo-colors`(零分配,编译期)或 `colored`(更动态)。要省掉 NO_COLOR / isatty 判断,`termcolor` 与 Go 一脉相承。完整 TUI 场景(窗口、光标、原始模式、鼠标)用 `crossterm`;更高层的布局再叠加 `ratatui`(原 tui-rs)。

推荐库

  • owo-colors

    对几乎所有字符串类型的零分配彩色扩展 —— `"error".red().bold()` 不产生堆分配。通过 const generics 提供编译期颜色样式。仅 ANSI,不查询 terminfo。

  • colored

    最早的 `"text".red().bold()` API —— 比 owo-colors 更灵活(运行期调色板、自定义颜色),代价是会分配内存。默认遵循 `NO_COLOR` 与 `CLICOLOR_FORCE`。

  • termcolor

    ripgrep 的彩色输出层 —— 基于 `WriteColor` trait 封装 stdout/stderr:POSIX 走 ANSI,Windows 走控制台 API。`ColorChoice::Auto` 自动处理 NO_COLOR 与 isatty。

  • crossterm

    完整的跨平台终端工具包 —— 光标、颜色、原始模式、备用屏、鼠标 / 焦点 / 粘贴事件、键盘输入。`ratatui` 的底层。CLI 直接用 crossterm;全屏 TUI 在其之上叠加 ratatui。

常用写法

println! 直接写字面转义
fn main() {
    println!("\x1b[1;31merror:\x1b[0m permission denied");
}
owo-colors 的彩色 API
use owo_colors::OwoColorize;

fn main() {
    println!("{} permission denied", "error:".red().bold());
}
用 termcolor 处理 NO_COLOR 与 isatty
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(())
}
crossterm 进入原始模式并隐藏光标
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(())
}

相关序列

其他语言