2 个版本
0.1.1 | 2024 年 6 月 10 日 |
---|---|
0.1.0 | 2024 年 6 月 9 日 |
#185 in 命令行界面
54 每月下载次数
105KB
1.5K SLoC
ansiconst
查看 Rustdoc
内容
ANSI 常量
一个用于在 const 上下文中声明可嵌套 ANSI 样式的库。
动机
这个crate的主要动机是提供一种能力,通过语义而不是字面意义来识别 ANSI 颜色/效果,以便在命令行程序中使用 ANSI 颜色。
例如,当调用 println!
时,将样式 绿色,加粗 应用到输出上,而不是应用一个名为 副标题 的样式,当渲染(或“格式化”)时,会产生激活 绿色,加粗 样式的输出。
此外,语义样式应该是可嵌套的,就像 HTML 的 CSS 这样的样式框架。例如,应该能够将带有 制造商 名称的文本样式嵌套在带有 产品详情 名称的文本样式内,并自动应用这些语义样式转换到的实际样式。嵌套样式的属性应该根据需要暂时覆盖或替换父样式的属性。
此 crate 的第二个关键动机是在编译时支持上述功能。即定义语义样式为 const
,然后在整个命令行程序中使用它们,以最小的开销。
其他 crate 也提供终端样式功能,但没有一个完全支持上述用例。本 crate 为支持此用例提供的 API 在下一节中介绍。
主要功能
编译时
将 ANSI 代码声明为 const
。这意味着编译器将在它们使用的任何地方内联它们,这可能会提高运行时性能。
示例
use ansiconst::*;
use ansiconst::Colour::{Green, Blue};
use ansiconst::Effect::{Bold, Underline, Italic};
// Define styles as Ansi structs:
const HEADING_ANSI: Ansi = ansi!(Green, Bold, Underline);
const SUBHEADING_ANSI: Ansi = ansi!(Blue, Italic);
const RESET_ANSI: Ansi = Ansi::reset();
assert_eq!( HEADING_ANSI.to_string(), "\x1B[1;4;32m");
assert_eq!(SUBHEADING_ANSI.to_string(), "\x1B[3;34m");
assert_eq!( RESET_ANSI.to_string(), "\x1B[0m");
// Or, define styles as ANSI codes:
const HEADING_CODE: &str = ansi_code!(Green, Bold, Underline);
const SUBHEADING_CODE: &str = ansi_code!(Blue, Italic);
const RESET_CODE: &str = ansi_code!(Ansi::reset());
assert_eq!( HEADING_CODE, "\x1B[1;4;32m");
assert_eq!( SUBHEADING_CODE, "\x1B[3;34m");
assert_eq!( RESET_CODE, "\x1B[0m");
小型
Ansi
实例被设计得尽可能小。例如,Effect
在内部使用位标志而不是简单的 bool
来表示。
因此,使用 Ansi256
和 Rgb
颜色受功能标志控制,因为支持它们意味着 Ansi
实例必须略微增大。考虑内存大小
类型 | 字节 |
---|---|
Ansi |
6 |
Ansi功能=Ansi256 |
8 |
Ansi功能=Rgb |
12 |
&'static str |
16 |
简单宏
使用宏应用ANSI代码
styled!
创建不进行插值的 ANSI 样式值(例如&'static str
,u8
)。styled_format!
,styled_format_args!
与format!
,format_args!
类似,但它们创建 ANSI 样式结果。styled_write!
,styled_writeln!
与write!
,writeln!
类似,但它们写入 ANSI 样式输出。paint!
,paintln!
,epaint!
,epaintln!
与print!
,println!
,eprint!
,eprintln!
类似,但它们打印 ANSI 样式输出。
示例
use ansiconst::{*, Colour::Red, Effect::Bold};
let pet = "cat";
let age = 5;
let string1 = styled!(Red, Bold, "My cat is 5 years old").to_string();
let string2 = styled_format!(Red, Bold, "My {} is {} years old", pet, age);
let string3 = styled_format_args!(Red, Bold, "My {} is {} years old", pet, age).to_string();
assert_eq!(string1, "\x1B[1;31mMy cat is 5 years old\x1B[22;39m");
assert_eq!(string2, "\x1B[1;31mMy cat is 5 years old\x1B[22;39m");
assert_eq!(string3, "\x1B[1;31mMy cat is 5 years old\x1B[22;39m");
// Print "\x1B[1;31mMy cat is 5 years old\x1B[22;39m\n" to stdout and stderr:
paintln! (Red, Bold, "My {} is {} years old", pet, age);
epaintln!(Red, Bold, "My {} is {} years old", pet, age);
// Write "\x1B[1;31mMy cat is 5 years old\x1B[22;39m\n" to a writer:
use std::fmt::Write;
let mut sink = String::new();
styled_writeln!(&mut sink, Red, Bold, "My {} is {} years old", pet, age).unwrap();
assert_eq!(sink, "\x1B[1;31mMy cat is 5 years old\x1B[22;39m\n");
轻松嵌套
ANSI 代码的嵌套会自动处理,并且在嵌套级别之间转换时使用最小的 ANSI 代码序列。
此外,可以完全禁用嵌套的 ANSI 代码,或者按属性逐个禁用。父 Ansi
可以通过使用例如 .protect_attrs()
和 .only()
的方法,在外部 Ansi
中 保护 这些属性,从而防止嵌套的 Ansi
为任何/所有属性渲染 ANSI 代码。
示例
use ansiconst::{*, Effect::{Bold, Underline}};
const INNER: Styled<&str> = styled!(Underline, "Inner");
const INNER_PROTECTED: Styled<&str> = styled!(Underline.only(), "Inner");
// Example 1: blended styles
assert_eq!(
styled_format!(Bold, "Bold {INNER} Bold again"),
// "Inner" is both Bold and Underline
"\x1B[1mBold \x1B[4mInner\x1B[24m Bold again\x1B[22m"
);
// Example 2: protected inner style
assert_eq!(
styled_format!(Bold, "Bold {INNER_PROTECTED} Bold again"),
// "Inner" is not Bold, only Underline, due to inner's .only()
"\x1B[1mBold \x1B[22;4mInner\x1B[24;1m Bold again\x1B[22m"
);
// Example 3: protected outer style
assert_eq!(
// Note: outer Bold.only() this time
styled_format!(Bold.only(), "Bold {INNER} Bold again"),
// Entire string is Bold, nested Underline was ignored
"\x1B[1mBold Inner Bold again\x1B[22m"
);
// Example 4: both protected
assert_eq!(
// Note: Bold.only() again
styled_format!(Bold.only(), "Bold {INNER_PROTECTED} Bold again"),
// Entire string is Bold, because outer's .only() takes precedence over inner's
"\x1B[1mBold Inner Bold again\x1B[22m"
);
注意:通过在静态变量 thread_local!
中存储最后应用的 ANSI 样式,实现了嵌套样式的自动处理,因此该库需要 std
。有关详细信息,请参阅 Styled<T>
。
示例
use ansiconst::*;
use ansiconst::Colour::{Green, Cyan, Yellow, Purple};
use ansiconst::Effect::{Bold, NotBold, Italic, Underline, Blink};
const HEADING: Ansi = ansi!(Green, Bold, Underline);
const SUBHEADING: Ansi = ansi!(Cyan, Italic);
const STRONG: Ansi = ansi!(Yellow, Bold);
const STRONGER: Ansi = ansi!(Blink);
const STRONGEST: Ansi = ansi!(Purple, NotBold);
// Styling with paintln!
paintln!(HEADING, "The Book of Rust");
paintln!();
paintln!(SUBHEADING, "Chapter 1");
paintln!();
// Styling with println!
println!("This sentence shows how {} as you would expect.",
styled_format_args!(STRONG, "styles can be {}, and they combine",
styled_format_args!(STRONGER, "nested to {} depths",
styled_format_args!(STRONGEST, "arbitrary")
)
)
);
println!("This sentence shows another {} colours/effects.",
styled_format_args!(Green, Italic, "way of styling {} i.e. with inline",
styled_format_args!(Yellow, Bold, "your text,")
)
);
版本历史
版本 | 日期 | 评论 |
---|---|---|
v0.1.1 | 2024年6月10日 | 修复错误/文档发布
|
v0.1.0 | 2024年6月9日 | 首次发布 |
许可
MIT 协议
依赖项
~110KB