在 Ruby 中使用 ANSI 转义码
Ruby 的双引号字符串支持 `\e` 作为 ESC 字面(无需写 `\x1b` 或 `\033`),`puts` / `print` / `STDOUT.write` 在所有平台都按字节透传。Ruby 3.0+ 在 Windows 上自动为标准流启用 `ENABLE_VIRTUAL_TERMINAL_PROCESSING`,因此 `\e[31m` 在 Conhost 与 Windows Terminal 上无需 `colorama` 类适配层即可生效。 人体工学方面:`colorize` 在 `String` 上注入链式颜色方法(`"oops".red.bold`);`term-ansicolor`(Florian Frank 的经典 gem —— `pry`、`rspec` 的底层)同时提供模块调用(`Term::ANSIColor.red(...)`)与混入两种形态;`pastel`(TTY 工具包)将 SGR 辅助封装在独立模块,自动检测 `NO_COLOR` 与 `CLICOLOR_FORCE`,不污染 `String`。完整 TUI 请用 TTY 工具包其余组件 —— `tty-prompt`、`tty-spinner`、`tty-cursor`、`tty-progressbar`。
推荐库
- colorize
在 `String` 上注入链式颜色方法 —— `"oops".red.bold.on_white`。下载量约 3000 万,单脚本与 Rakefile 输出的首选。支持 8 个命名颜色 + 通过 `colorize(color: :red, mode: :bold, background: :white)` 使用扩展调色板。
- term-ansicolor
Florian Frank 的经典 gem(自 2009 起维护)—— 既支持模块调用(`Term::ANSIColor.red("text")`),也支持混入风格(`include Term::ANSIColor; red("text")`)。`pry`、`rspec`、`cucumber` 及大量 Ruby CLI 工具的底层。1.7.0 起遵守 `NO_COLOR`。
- pastel
模块内封装的 SGR 辅助 —— `Pastel.new.red.bold("oops")`,不污染 `String`。TTY 工具包推荐的颜色层;`Pastel.new(enabled: nil)` 自动通过 `tty?` + `NO_COLOR` + `CLICOLOR_FORCE` 检测能力。支持装饰器(`pastel.decorate("text", :red, :bold)`)以及 256 色 `on_<color>` 链式调用。
- tty-prompt
交互式提示 —— `select`、`ask`、`multi_select`、`mask`(密码)、`yes?`/`no?`,外观抛光、支持键盘导航。与 `tty-spinner`、`tty-progressbar`、`tty-cursor` 配套构成完整 TUI 栈。Hanami、Pry、Bundler 风格安装器与 Foreman 都在用。
常用写法
puts "\e[1;31merror:\e[0m permission denied"require 'colorize'
puts "error:".red.bold + " permission denied"
puts "ok".green
puts "deprecated".yellow.on_blackrequire 'pastel'
# Pastel.new(enabled: nil) auto-detects:
# STDOUT.tty? AND NO_COLOR not set AND CLICOLOR != '0'
# CLICOLOR_FORCE=1 forces colour even when redirected.
pastel = Pastel.new
puts "#{pastel.red.bold('error:')} permission denied"
puts pastel.decorate('lavender truecolor', :on_blue, :bold)
# Disable globally — e.g. in CI:
plain = Pastel.new(enabled: false)
puts plain.red('this prints as plain text')STDOUT.print "\e[?25l" # hide cursor
at_exit { STDOUT.print "\e[?25h" } # restore on any exit path
100.times do |i|
# \r returns to col 1, \e[K erases to end of line
STDOUT.print "\r\e[K#{i + 1}% complete"
STDOUT.flush
sleep 0.02
end
puts