Rust ANSI终端格式化库ansiterm的使用,支持跨平台彩色文本输出和样式控制

Rust ANSI终端格式化库ansiterm的使用,支持跨平台彩色文本输出和样式控制

ansiterm-rs是未维护的ansi-term库的延续,用于在ANSI终端上控制颜色和格式,如红色粗体文本或蓝色带下划线的文本。

安装

注意:该crate仍在开发中,尚未在crates.io上发布

我们承诺保持API稳定,不会破坏原始crate中已经工作的任何功能。

基本用法

这个crate中有三个主要类型需要关注:ANSIStringStyleColour

Style保存样式信息:前景色和背景色,文本是否应为粗体、闪烁或其他属性。 Colour枚举表示可用的颜色。 ANSIString是与Style配对的字符串。

Color也可作为Colour的别名使用。

要格式化字符串,在StyleColour上调用paint方法,将要格式化的字符串作为参数传递。例如,以下是如何获取一些红色文本:

use ansiterm::Colour::Red;

println!("This is in red: {}", Red.paint("a red string"));

重要的是要注意,paint方法实际上并不返回带有ANSI控制字符的字符串。相反,它返回一个ANSIString值,该值有一个Display实现,在格式化时返回字符。这允许以最少的String分配在幕后执行字符串打印。

如果您确实想获取转义码,则可以像处理任何其他Display值一样将ANSIString转换为字符串:

use ansiterm::Colour::Red;

let red_string = Red.paint("a red string").to_string();

**Windows 10用户注意:**在Windows 10上,应用程序必须先启用ANSI支持:

let enabled = ansiterm::enable_ansi_support();

粗体、下划线、背景和其他样式

对于比纯前景色更改更复杂的任何内容,您需要构造Style值本身,而不是从Colour开始。您可以通过基于新的Style(使用Style::new()创建)链接方法来实现这一点。每个方法创建一个具有该特定属性集的新样式。例如:

use ansiterm::Style;

println!("How about some {} and {}?",
         Style::new().bold().paint("bold"),
         Style::new().underline().paint("underline"));

为了简洁起见,这些方法也已在Colour值上实现,因此您可以为样式提供前景色,而无需从空的Style值开始:

use ansiterm::Colour::{Blue, Yellow};

println!("Demonstrating {} and {}!",
         Blue.bold().paint("blue bold"),
         Yellow.underline().paint("yellow underline"));

println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!"));

您可以使用的完整样式列表是: bolddimmeditalicunderlineblinkreversehiddenon用于背景颜色。

在某些情况下,您可能会发现更改现有Style上的前景比从适当的Colour开始更容易。您可以使用fg方法执行此操作:

use ansiterm::Style;
use ansiterm::Colour::{Blue, Cyan, Yellow};

println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!"));
println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!"));

您可以使用normal方法将Colour转换为Style。这将生成与直接在Colour上使用paint方法完全相同的ANSIString,但在某些情况下很有用:例如,您可能有一个返回Styles的方法,并且需要使用相同类型的值表示"红色粗体"和"红色但不粗体"样式。Style结构还有一个Default实现,如果您想要一个没有任何设置的样式。

use ansiterm::Style;
use ansiterm::Colour::Red;

Red.normal().paint("yet another red string");
Style::default().paint("a completely regular string");

扩展颜色

您可以通过使用Colour::Fixed变体访问256色的扩展范围,该变体采用要使用的颜色编号作为参数。这可以在您使用Colour的任何地方包含:

use ansiterm::Colour::Fixed;

Fixed(134).paint("A sort of light purple");
Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup");

这些值的前十六个与普通和粗体标准颜色变体相同。没有什么阻止您将这些用作Fixed颜色,但这样做也没有什么好处。

您还可以通过使用Colour::RGB变体访问完整的24位颜色,该变体为红色、绿色和蓝色采用单独的u8参数:

use ansiterm::Colour::RGB;

RGB(70, 130, 180).paint("Steel blue");

组合连续的彩色字符串

将ANSI转义码写入终端的好处是它们可以堆叠:如果后面的文本具有相似的样式,则不需要以重置代码结束每个彩色字符串。例如,如果您想要一些蓝色文本后跟一些蓝色粗体文本,可以发送蓝色的ANSI代码,后跟粗体的ANSI代码,并以重置代码结束,而不必在两个字符串之间有一个额外的代码。

这个crate可以优化在这种情况下打印的ANSI代码,使您的终端渲染器更轻松。ANSIStrings结构接受几个ANSIString值的切片,并将遍历每个值,仅打印需要作为其格式化例程一部分更新的样式代码。

以下代码片段使用此方法将显示为红色粗体文本的二进制数括在一些红色但不粗体的括号中:

use ansiterm::Colour::Red;
use ansiterm::{ANSIString, ANSIStrings};

let some_value = format!("{:b}", 42);
let strings: &[ANSIString<'static>] = &[
    Red.paint("["),
    Red.bold().paint(some_value),
    Red.paint("]"),
];

println!("Value: {}", ANSIStrings(strings));

这里有几件事需要注意。首先,paint方法可以采用拥有的String或借用的&str。在内部,ANSIString保存一个写时复制(Cow)字符串值,以同时处理拥有的和借用的字符串。这里使用它来显示String,即format!调用的结果,使用与一些静态可用的&str切片相同的机制。其次,ANSIStrings值的工作方式与其单数对应物相同,具有Display实现,仅在需要时执行格式化。

字节字符串

这个库还支持格式化[u8]字节字符串;这支持使用未知编码文本的应用程序。StyleColour支持绘制[u8]值,产生ANSIByteString。此类型不实现Display,因为它可能不包含UTF-8,但它确实提供了一个方法write_to,用于将结果写入任何实现Write的值:

use ansiterm::Colour::Green;

Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap();

类似地,类型ANSIByteStrings支持以最少的转义序列写入ANSIByteString值列表:

use ansiterm::Colour::Green;
use ansiterm::ANSIByteStrings;

ANSIByteStrings(&[
    Green.paint("user data 1\n".as_bytes()),
    Green.bold().paint("user data 2\n".as_bytes()),
]).write_to(&mut std::io::stdout()).unwrap();

完整示例代码

// 启用ANSI支持(Windows 10需要)
let _enabled = ansiterm::enable_ansi_support();

// 基本颜色使用
use ansiterm::Colour::Red;
println!("红色文本: {}", Red.paint("这是红色文字"));

// 样式组合
use ansiterm::Colour::{Blue, Yellow};
println!("组合样式: {} 和 {}",
    Blue.bold().paint("蓝色粗体"),
    Yellow.underline().paint("黄色下划线"));

// 背景色
println!("黄色背景蓝色文字: {}", Blue.on(Yellow).paint("哇!"));

// 扩展颜色
use ansiterm::Colour::Fixed;
println!("扩展颜色: {}", Fixed(134).paint("浅紫色"));

// RGB颜色
use ansiterm::Colour::RGB;
println!("RGB颜色: {}", RGB(70, 130, 180).paint("钢蓝色"));

// 组合多个ANSI字符串
use ansiterm::{ANSIString, ANSIStrings};
let strings: &[ANSIString<'static>] = &[
    Red.paint("["),
    Red.bold().paint("42"),
    Red.paint("]"),
];
println!("组合字符串: {}", ANSIStrings(strings));

// 字节字符串
use ansiterm::ANSIByteStrings;
ANSIByteStrings(&[
    Green.paint("数据1\n".as_bytes()),
    Green.bold().paint("数据2\n".as_bytes()),
]).write_to(&mut std::io::stdout()).unwrap();

1 回复

Rust ANSI终端格式化库ansiterm使用指南

ansiterm是一个Rust库,用于在终端中输出带颜色和样式的文本,支持跨平台操作。

基本功能

  • 支持16种标准颜色和256色模式
  • 支持粗体、斜体、下划线等文本样式
  • 跨平台支持(Windows/macOS/Linux)

使用方法

添加依赖

Cargo.toml中添加:

[dependencies]
ansiterm = "0.12"

基本示例

use ansiterm::{Colour, Style};

fn main() {
    // 简单的彩色文本
    println!("{}", Colour::Red.paint("红色文本"));
    
    // 组合样式
    let style = Style::new()
        .bold()
        .underline()
        .on(Colour::Black)
        .fg(Colour::Yellow);
    println!("{}", style.paint("加粗黄色带下划线的黑底文本"));
}

256色模式

use ansiterm::Colour;

fn main() {
    // 使用256色
    println!("{}", Colour::Fixed(42).paint("256色模式的文本"));
    
    // RGB颜色
    println!("{}", Colour::RGB(255, 0, 128).paint("RGB颜色文本"));
}

样式组合

use ansiterm::{Colour, Style};

fn main() {
    let warning = Style::new()
        .bold()
        .fg(Colour::Yellow)
        .on(Colour::Red);
    
    println!("{}", warning.paint("警告信息!"));
}

条件性样式应用

use ansiterm::{Colour, Style};

fn main() {
    let error_style = Style::new().fg(Colour::Red).bold();
    let success_style = Style::new().fg(Colour::Green);
    
    let result = false; // 假设这是某个操作的结果
    
    println!("操作结果: {}", 
        if result {
            success_style.paint("成功")
        } else {
            error_style.paint("失败")
        }
    );
}

Windows支持

在Windows 10之前版本上,需要启用ANSI支持:

#[cfg(windows)]
use ansiterm::enable_ansi_support;

fn main() {
    #[cfg(windows)]
    enable_ansi_support().unwrap();
    
    // 其他代码...
}

性能考虑

对于频繁的样式应用,可以预先创建并重用样式对象:

use ansiterm::{Colour, Style};

lazy_static! {
    static ref HEADER_STYLE: Style = Style::new()
        .bold()
        .underline()
        .fg(Colour::Blue);
        
    static ref ERROR_STYLE: Style = Style::new()
        .bold()
        .fg(Colour::Red);
}

fn main() {
    println!("{}", HEADER_STYLE.paint("章节标题"));
    println!("{}", ERROR_STYLE.paint("错误信息"));
}

完整示例代码

// 引入必要的库
use ansiterm::{Colour, Style};
use lazy_static::lazy_static;

// 预定义样式
lazy_static! {
    // 标题样式:蓝色、加粗、带下划线
    static ref HEADER_STYLE: Style = Style::new()
        .bold()
        .underline()
        .fg(Colour::Blue);
        
    // 错误样式:红色、加粗
    static ref ERROR_STYLE: Style = Style::new()
        .bold()
        .fg(Colour::Red);
        
    // 成功样式:绿色
    static ref SUCCESS_STYLE: Style = Style::new()
        .fg(Colour::Green);
}

fn main() {
    // Windows平台启用ANSI支持
    #[cfg(windows)]
    ansiterm::enable_ansi_support().unwrap();

    // 使用预定义样式
    println!("{}", HEADER_STYLE.paint("=== 应用程序日志 ==="));
    
    // 基本颜色使用
    println!("{} {}", Colour::Red.paint("[错误]"), "这是一个错误消息");
    println!("{} {}", Colour::Green.paint("[成功]"), "操作成功完成");
    
    // 256色模式
    println!("{}", Colour::Fixed(214).paint("256色模式 - 橙色文本"));
    
    // RGB颜色
    println!("{}", Colour::RGB(100, 200, 255).paint("自定义RGB颜色文本"));
    
    // 组合样式
    let warning = Style::new()
        .bold()
        .fg(Colour::Yellow)
        .on(Colour::Red);
    println!("{}", warning.paint("警告:系统资源不足!"));
    
    // 条件性样式应用
    let operations = vec![true, false, true];
    for (i, &result) in operations.iter().enumerate() {
        println!("操作 {}: {}", 
            i + 1,
            if result {
                SUCCESS_STYLE.paint("成功")
            } else {
                ERROR_STYLE.paint("失败")
            }
        );
    }
    
    // 复杂样式组合
    let complex_style = Style::new()
        .italic()
        .underline()
        .fg(Colour::RGB(128, 0, 128))
        .on(Colour::Fixed(230));
    println!("{}", complex_style.paint("复杂样式组合示例"));
}

这个完整示例展示了ansiterm库的主要功能,包括:

  1. 基本颜色使用
  2. 256色和RGB颜色模式
  3. 样式组合
  4. 条件性样式应用
  5. 预定义样式重用
  6. Windows平台支持

要运行此示例,需要在Cargo.toml中添加以下依赖:

[dependencies]
ansiterm = "0.12"
lazy_static = "1.4"
回到顶部