按编程语言使用 ANSI 转义码
为各主流编程语言提供推荐库与常用写法,用于发送 ANSI / VT 转义序列。每段示例都对应站内的某条序列文档 —— 点击链接查看字节形式与终端支持。
按语言分类的速查
- Python
Python 标准库未提供颜色辅助,但你可以直接把 `\x1b` 字节写在字符串里。跨平台场景(1909 之前的 Windows `cmd.exe` 默认不解析 ANSI)请用 `colorama`。如需更丰富的 TUI,`rich` 与 `prompt_toolkit` 都建立在本站记录的字节序列之上。
- Go
Go 的 `fmt.Print*` 是字节透传的 —— `\x1b[31m` 在 Unix 与 Windows 10+ 上均可工作(需启用 `ENABLE_VIRTUAL_TERMINAL_PROCESSING`,可通过 `golang.org/x/sys/windows` 翻转)。多于少量转义时,请用 `fatih/color`;要构建完整 TUI,请用 Charmbracelet 系列(`lipgloss` + `bubbletea`)。
- JavaScript / Node.js
Node 的 `process.stdout.write` 与 `console.log` 都按字节透传。浏览器控制台(DevTools)只接受通过 `%c` 传递的 CSS 风格样式,不接受 ANSI 字节 —— ANSI 仅在真实终端中生效。便利性方面,`chalk` 是经典选择,`picocolors` 以约 1/100 体积实现同样能力。
- TypeScript (Deno / Bun / Node)
TypeScript 本身会被转译 —— 实际写入终端的字节与 JavaScript 一致。三种 TS 运行时的差异在于**标准库的写入调用**:Node 用 `process.stdout.write`,Deno 用 `Deno.stdout.writeSync`(或 `console.log`),Bun 同时支持 Node 的 `process.stdout` shim 与自身的 `Bun.write(Bun.stdout, …)`。三者都按字节透传。带类型的便利 API 可选 `picocolors`(零依赖,通过 `npm:` / `jsr:` / 直接 import 在每个运行时中可用)、Deno 自带的 `@std/fmt/colors`,或更小巧、同构的 `kolorist`。`chalk` 5+ 仅支持 ESM,可在 Node / Bun / Deno(`npm:chalk`)下使用。
- Node.js (CLI tools)
Node CLI 工具的实战面,`/use/javascript` 仅勾勒了大致:`process.stdout.isTTY` 用于能力检测(管道、重定向、CI 下均为 false)、`process.stdout.columns` 适配终端宽度、chalk 5+ 仅支持 ESM 导致 CommonJS 项目频繁踩坑,以及 `node:tty` + `readline` 用于解码 ANSI 按键序列。如果你在交付 CLI 二进制(npx、`bin/` 入口、oclif、commander),这是你的页面;如果只是为 Next.js / Vite 应用挑选颜色库,请看 JavaScript 页。
- PowerShell
PowerShell 7.2+ 自带 `$PSStyle`,一个带类型的自动变量,可能是所有语言标准库中最现代的颜色 API —— 通过 `$PSStyle.OutputRendering`(`Ansi`/`PlainText`/`Host`)做能力门控,把每个 SGR 码枚举为命名属性(`$PSStyle.Foreground.Red`、`$PSStyle.Bold`、`$PSStyle.Reset`),并与 host 协作,使管道接收的 `Get-ChildItem` 自动去色。PS 5.1(Windows 默认)可退回到 `Write-Host -ForegroundColor`,或用 `` `e `` 转义符(PS 7+)/ `[char]27`(PS 5.1)写原始 VT。Windows 10+ Conhost 与 Windows Terminal 原生解析 ANSI —— 不再需要 `colorama` 类适配。
- Bash / shell
Bash 有两种可靠方式输出转义字节:`printf` 配合 `\033` / `\x1b`(符合 POSIX,最便携);以及 `tput`(基于 terminfo,因为它适配 `$TERM`,最稳妥)。`echo -e` 在 bash 中可用但 dash / sh 不支持,可移植脚本应避免。字面 `$'\e[...'`(ANSI-C 引用)形式仅 bash/zsh 支持,但可读性极佳。
- C
C 没有 ESC 的转义字面量 —— 请写 `\x1b`(十六进制)或 `\033`(八进制)。`printf` 与 `fputs` 在所有平台均按字节透传;在 Windows 10+ 上需先用 `SetConsoleMode(..., ENABLE_VIRTUAL_TERMINAL_PROCESSING)` 启用虚拟终端处理。任何接近 TUI 的需求(菜单、窗口、鼠标)请直接链接 `ncurses`,不要自行实现。
- C#
C# 字符串字面量原生支持 `\x1b` —— `Console.Write("\x1b[31merror\x1b[0m")` 在 macOS / Linux 以及 Windows 10 1709+ / Windows Terminal / Windows 11(Conhost 默认解析 VT)上均按字节透传。需要更丰富功能时,`Spectre.Console` 是现代 .NET 事实标准 TUI / 样式控制台库(标记语法 `[red]error[/]`、表格、进度条、提示),`Pastel` 提供单行扩展方法(`"hello".Pastel(Color.Red)`)。在 1607 之前的旧 Windows 上,首次写入前需通过 `SetConsoleMode` P/Invoke 启用 `ENABLE_VIRTUAL_TERMINAL_PROCESSING`。设置 `Console.OutputEncoding = Encoding.UTF8` 可保持制表符与表情符号完整。
- F#
F# 字符串字面量原生支持 `\x1b`(F# 4.5+,2018 年 8 月)、`\u001b`(Unicode 码点 —— 所有 F# 版本包括 .NET Framework F# 2.0 都可用),以及 `\NNN` 三元组 —— 但 **F# 的 `\NNN` 是十进制,不是八进制**(与 C# / VB.NET / PowerShell 共享的 .NET 运行时怪异,与 C / Erlang / Java 中 `\033` 是八进制 27 相反)。可移植性陷阱:把 `"\033[31m"` 从 C / Erlang / Bash 片段复制到 F# 中得到的是字节 33(= `!`),不是 ESC。请使用 `"\x1b"`(F# 4.5+)或 `"\027"`(十进制三元组,全版本)或 `"\u001b"`(Unicode 码点,全版本)—— 永远不要写 `"\033"`。 规范的 F# 单行写法是 `printfn "\x1b[1;31merror:\x1b[0m %s" msg` —— `printf` / `printfn` 是 F# 的类型检查 printf 系列(格式字符串在**编译时**解析,与 C# / Java 在运行时校验格式字符串相反)。`%s` 插入字符串,`%d` 插入整数,`%A` 通过结构化美化打印任意值。嵌在格式字符串中的转义字节原样传递给 `System.Console.Out`。`printfn` 的换行符是平台相关的(Windows 上 `\r\n`、Unix 上 `\n`)—— 增量构建单行时请使用纯 `printf`。 需要比临时转义更丰富时,**`Spectre.Console`** 是事实标准的现代 .NET 控制台工具包 —— F# 中用法完全相同(`AnsiConsole.MarkupLine "[bold red]error:[/] permission denied"`)。配合 **`Argu`**(F# 规范的 CLI 解析器 —— 自动着色的 `--help` 输出,通过判别联合提供类型安全的参数记录)即可获得完整的 F# 脚本人体工学。F# 风格的模板化彩色输出选 **`BlackFox.ColoredPrintf`** —— `cprintfn "$red[error:] %s" msg` 使用 `$colour[...]` 模板语法,编译为标准 ANSI。F# 构建脚本(FAKE)选 **`Fake.Core.Trace`** 模块,发出着色的步骤标题、成功 / 失败标记,以及 FAKE DSL 原生的结构化日志。 **F# Interactive (FSI) REPL 注意**(本页主要 SERP 差异化):从普通终端提示符运行的 `dotnet fsi` 解析 `printfn` 输出中的 ANSI —— 颜色按预期工作。但在 Visual Studio 的 *F# Interactive* 工具窗口和 VS Code Ionide 的 *F# Interactive* 输出窗格内部,ANSI 转义字节被**字面**渲染为 `\x1b[31m...` 文本 —— 这些窗格是文本控件,不经过 VT 终端模拟器分发。修复方法:通过 `not Console.IsOutputRedirected && not (isNull (Environment.GetEnvironmentVariable "VSAPPIDDIR"))` 检测(Visual Studio 设置 `VSAPPIDDIR`;Ionide / VS Code 设置 `VSCODE_PID` 和 `TERM_PROGRAM=vscode`)从而在 IDE 内嵌 FSI 会话中跳过 ANSI,或在 FSI 启动配置中设置 `NO_COLOR=1`。 能力门控:`System.Console.IsOutputRedirected`(管道 / 重定向时为 true —— 跳过颜色以避免污染文件)、`System.Environment.GetEnvironmentVariable("NO_COLOR")`(通用退出)、`System.Console.OutputEncoding <- System.Text.Encoding.UTF8`(制表符 + 表情符号安全 —— 不同 OS / 区域设置下默认值不同)。
- Swift
Swift 字符串字面量用 `\u{1b}` 表示 ESC 字节 —— **不是** `\x1b`(这是把 C / Rust / Python 配方复制到 Swift 时最常见的卡点)。`print("\u{1b}[31mred\u{1b}[0m")` 可在 macOS Terminal、iTerm2,以及面向服务器端的 swift-on-server 上工作。需要顺手的彩色 API 时选 `Rainbow`(Swift 中星标最多的 ANSI 字符串库),它为 `String` 添加 `"error".red.bold` 这类扩展。Apple 自家的 `swift-argument-parser` 通过相同原语提供彩色 `--help` 输出。需要完整 TUI(面板、鼠标、原始模式)时可选 ncurses 风格的 `TermKit`。能力检测使用 `Darwin` / `Glibc` 的 `isatty(STDOUT_FILENO)`,或 Swift 5.7+ 的 `FileHandle.standardOutput.isTerminal`(桥接到底层 isatty)。
- Rust
Rust 字符串字面量原生支持 `\x1b` —— `println!("\x1b[31mred\x1b[0m")` 无需任何依赖即可工作。需要符合人体工学的彩色 API,可选 `owo-colors`(零分配,编译期)或 `colored`(更动态)。要省掉 NO_COLOR / isatty 判断,`termcolor` 与 Go 一脉相承。完整 TUI 场景(窗口、光标、原始模式、鼠标)用 `crossterm`;更高层的布局再叠加 `ratatui`(原 tui-rs)。
- Ruby
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`。
- PHP
PHP CLI 模式(`php -r`、`php script.php`)的 STDOUT 按字节透传 —— `echo "\e[31mred\e[0m"` 自 PHP 5.4 起可用(该版本将 `\e` 引入双引号字符串;更早代码请用 `"\x1b"` 或 `chr(27)`)。Windows Conhost 自 Windows 10 1709 起原生解析 VT,但 PHP 官方建议显式调用 `sapi_windows_vt100_support(STDOUT, true)`(PHP 7.2+)切换模式,保证跨 host 与 CGI 回退一致。 超出零散 echo 的场景,**Symfony Console** 是 PHP CLI 框架的事实标准 —— Composer、Laravel `artisan`、Symfony `console`、Drupal `drush` 的底层。其 `OutputFormatter` 使用类 XML 标签(`<info>...</info>`、`<fg=red;bg=white;options=bold>...</>`)在底层编译成 ANSI,输出到非 TTY 时自动去色。**Termwind** 提供终端版 Tailwind CSS(`text-red-500`、`bg-blue-500`、`font-bold` 之类的 class 名),是 PHPStan、Pest、Laravel Zero 的底层。**laravel/prompts** 提供现代交互提示,可在 Laravel 之外独立使用。
- Java
Java 字符串字面量没有 `\e` 转义 —— 请写 `\033`(八进制)或 `\u001b`(Unicode 转义)。`System.out.println("\033[31mred\033[0m")` 在任意 JVM 上均按字节透传。Windows 10 1709+ 的 Conhost 原生解析 VT,但为了兼容更早的 Conhost(并处理 Maven / Gradle / IntelliJ 输出包装常常去色的情形),可调用 **Jansi** 的 `AnsiConsole.systemInstall()` —— 它替换 `System.out` 与 `System.err` 包装,在旧主机上将 ANSI 翻译为 Win32 控制台 API 调用,在新主机上透传。 超出零散 print 语句的场景:**JLine 3** 是 Java 的 `readline`(原始模式、行编辑、历史、补全、密码遮罩、终端能力检测)—— Spring Shell、JBang、Groovy `groovysh`、OpenJDK `jshell` 的底层。**picocli** 通过注解驱动 CLI 参数解析,并经 `Help.Ansi.AUTO` 自动彩色化帮助文档(遵守 `NO_COLOR` 与 `isatty`)。完整全屏 TUI 请用 **Lanterna** —— 以 Swing 式的 `Window` / `Panel` / `Component` 层次渲染到 ANSI。
- Kotlin
Kotlin 字符串字面量用 `\u001B` 表示 ESC 字节 —— Kotlin 没有 `\x` 十六进制转义,只有 `\u####` Unicode 转义(与 Java 一致)。`println("\u001B[31mred\u001B[0m")` 在 macOS / Linux 以及 Windows 10+(stdout 默认启用 VT)上按字节透传。需要顺手的颜色 + 表格 + 进度条 + Markdown 渲染时选 `mordant`,Kotlin 最受欢迎的 ANSI 库 —— 自动检测终端能力、尊重 `NO_COLOR`、被管道时优雅降级。需要完整交互 TUI 时 `kotter` 提供协程友好的 DSL。`picocli`(JVM CLI 参数解析器)为 `--help` 内建 ANSI 颜色,同时需要 CLI 解析时的自然选择。 **Gradle / IDE 注意**:IntelliJ Run 控制台启用 ANSI,但 Gradle daemon 默认剥离颜色 —— 传 `--console=plain`(或在 `gradle.properties` 设置 `org.gradle.console=plain`)以原样查看转义字节。Android Logcat 不解析 ANSI;目标为 Android 时使用 `mordant` 的 `Theme.PlainAscii` 或先做能力检测。
- Dart
Dart 的 `dart:io` 已通过 `stdout` 暴露了其他生态通常要你自己实现的标准能力检测 —— `stdout.supportsAnsiEscapes` 在懂得 VT 序列的 TTY 上返回 `true`,被管道、重定向,或运行在未启用 VT 的旧 Conhost 上时返回 `false`。搭配原始 `stdout.write('\x1B[31m…\x1B[0m')`(Dart 同时接受 `\x1B` 与 `\u001B`),即可在 macOS、Linux 与 Windows Terminal / Conhost 1709+ 上获得零依赖的可移植起点。需要顺手的彩色 API 时选 `chalkdart`(Dart 中最受欢迎的 ANSI 库 —— 链式扩展 API 仿自 Node 的 `chalk`)、`tint`(紧凑现代)或 `cli_util`(Google 官方 CLI 工具集,内含 ANSI 模块)。Flutter SDK 自带的 `flutter` CLI 即用这些原语 —— 其进度 / 构建状态输出是 Dart 风格能力门控的标准参考。
- Perl
Perl 在双引号字符串中支持 `\e` 转义 —— 本站记录的所有可输出 ANSI 的语言中最顺手的 ESC 字面形式。`print "\e[31mred\e[0m\n"` 在 Perl 5.000(1994 年发布)之后的所有版本,以及 macOS、Linux、BSD、现代 Windows(Windows Terminal / Conhost 1709+)上均可工作。标准辅助选 **`Term::ANSIColor`**,自 5.6 起随解释器一起分发的核心模块 —— `color("bold red")` 返回转义字符串,`colored(["bold red"], "text")` 包裹文本并自动重置,`colorstrip("\e[31mred\e[0m")` 干净地去除 ANSI(一个常见长尾 SERP 目标)。能力门控使用 Perl 惯用的 `-t STDOUT` 文件测试(在 TTY 上返回真)、`IO::Interactive::Tiny::is_interactive`(可移植包装),以及跨语言通用的 `$ENV{NO_COLOR}` 开关。需要完整 TUI 时链接 **`Curses::UI`**(Perl 的 ncurses 绑定);要查 termcap/terminfo 数据库时用 **`Term::Cap`**。 Perl 仍是系统管理一行命令与日志处理流水线的标准胶水语言 —— 单是 `colorstrip` 一招就服务于「如何从日志文件中剥离 ANSI」这类落到 Stack Overflow Perl 一行命令的大量搜索需求。
- R
R 在双引号字符串中支持 `\033`(八进制)—— 自 R 诞生以来所有版本中最具可移植性的 ESC 字面形式。`cat("\033[31mred\033[0m\n")` 在每一个解释器、以及 macOS、Linux、BSD、现代 Windows(Windows Terminal / Conhost 1709+ 原生解析 ANSI)上都可工作。现代 R(≥ 4.0)也接受 `"\u{1b}"` Unicode 与 `"\x1b"` 十六进制(严格 2 位)转义。标准辅助选 **`crayon`** —— 事实上的 R ANSI 库,被 tidyverse、testthat、pkgdown、devtools 使用:`crayon::red("error")` 返回带样式的字符串,`crayon::bold` 等可自由组合(`bold(red(...))`),`make_style("#ff8000")` 工厂式构造 truecolor 样式函数。现代 hadley/r-lib 配套 **`cli`** 在 crayon 原语之上添加语义化辅助(`cli_alert_danger()`、`cli_h1()`、复数化内联标记)。**`glue`** 在 `glue_col("{red error}")` 中模板化同样的词汇。处理 ANSI 感知的字符串操作(R 中标准的日志清洗器在此),**`fansi::strip_sgr`** 干净地移除每一条 CSI 序列,`fansi::nchar_ctl`/`substr_ctl` 在不破坏字节的前提下统计显示宽度并切片。 R 中的能力门控:`crayon::has_color()` 是权威调用 —— 它已经考虑了 `NO_COLOR`、`isatty(stdout())`、`crayon.enabled` 选项,以及 **RStudio Source 面板 vs Console 面板的差异**(「为什么我的 crayon 输出显示成原始转义码」最常见的 SERP 点击源 —— `source()` 运行走另一条剥离 ANSI 的输出通道;Console 面板正确解析)。knitr / rmarkdown 渲染也默认关闭颜色以保持输出可移植。
- Haskell
Haskell 的字符串字面量支持 `"\ESC"` —— 标准、易读、按控制字符命名的 ESC 转义形式。它与 `"\27"`(十进制)和 `"\x1B"`(十六进制)解析为完全相同的字节,但 `\ESC` 是 Haskell 惯用的形式(在本站记录的所有语言中独一无二 —— 只有 Haskell 把字面量关键字 `\ESC` 渲染成字节 27)。`putStr "\ESC[31mred\ESC[0m\n"` 在 GHC 7.0 以来的所有版本,以及 macOS、Linux、BSD、Windows 10+ 的 Conhost 1709+ / Windows Terminal(均原生解析 ANSI)上工作。对较旧的 Windows(1607 前的 Conhost),**`ansi-terminal`** 库把 `SetConsoleMode` 调用藏在 `hSupportsANSI` 后面。 标准辅助选 **`ansi-terminal`** —— 声明式 `setSGR [SetColor Foreground Vivid Red, SetConsoleIntensity BoldIntensity]` API,明确的 `Reset`、跨平台 Windows VT 启用、命名的光标 / 擦除 / 滚动辅助,以及编译期捕捉坏组合的类型安全形式。**`rainbow`** 在其上叠加流畅的 `Text` / `String` 着色 DSL —— `chunk "error" & fore red & bold` 构造 `Chunk`,`putChunkLn` 渲染输出。需要完整 TUI 时链接 **`brick`**(基于 vty,声明式面板与事件循环架构 —— 被 `lorri`、`matterhorn`、`ghcid` TUI、`tasty-bench`-tui 使用)。要做 REPL 风格的行编辑(历史、补全、多行)选 **`haskeline`** —— GHCi 自己使用的 readline 等价物。 能力门控:`ansi-terminal` 的 `hSupportsANSI stdout` 是标准能力检测(统一处理 macOS/Linux/BSD 的 isatty 与 Windows 的 VT 启用);当你想跳过这个库依赖时,搭配 `lookupEnv "NO_COLOR"`(`System.Environment`)与 `hIsTerminalDevice stdout`(`System.IO`)即可。GHCi REPL 在现代终端宿主中解析 ANSI;`cabal repl` 与 `stack ghci` 有时会包装 stdout —— 已知的摩擦点。
- Julia
Julia 的字符串字面量直接支持 `\e` —— 除 bash、zsh、perl、php 之外少数几种把反斜杠-e 解析为字节 27 的语言之一。`"\e[31m"` 与 `"\x1b[31m"`(十六进制)、`"\033[31m"`(八进制)、`"\u1b[31m"`(Unicode)完全等价 —— 任选其一即可。`println("\e[1;31merror:\e[0m permission denied")` 在 Julia ≥ 0.6 的所有版本,以及 macOS、Linux、BSD、Windows 10+ 的 Conhost 1709+ / Windows Terminal(均原生解析 ANSI)上工作。 惯用辅助 —— **优先用标准库** —— `printstyled(io, xs...; color=:red, bold=true, italic=true, underline=true, blink=true, reverse=true, hidden=true)` 是 Julia 标准的样式化打印函数。`color` 可以是命名 `Symbol`(`:red` / `:light_blue` / `:cyan`)、`0–255` 的整数(256 色板)或 `(r, g, b)` 三元组(在能力允许时 truecolor)。`Base.text_colors` 与 `Base.disable_text_style` 字典暴露原始 SGR 码,便于手工输出。可组合的字符串级样式选 **`Crayons.jl`** —— 事实上的第三方 Julia ANSI 库 —— `Crayon(foreground = :red, bold = true)` 构造可复用样式,通过 `*` 组合(`bold_red = Crayon(foreground=:red, bold=true) * Crayon(underline=true)`),`Box(content; foreground = :green)` 在值前后包裹起止字节。完整 TUI 链接 **`Term.jl`**(FedeClaudi)—— 面板、语法高亮打印、进度条、树形渲染、`tprint("[red bold]error[/red bold] denied")` 标记解析器。方向键交互菜单使用标准库 **`REPL.TerminalMenus`** —— 内置 `RadioMenu` / `MultiSelectMenu`,Pkg.jl 本身就用它做交互式包选择。 能力门控:`Base.have_color` 是标准标志位 —— Julia 在启动时从 `--color=auto|yes|no` 推断(`auto` 在 stdout 是 TTY 且未设置 `$NO_COLOR` 时为 `true`)。将 Julia 输出管道到 `less -R` 也按预期工作。**关键注意**:在 Jupyter / IJulia / Pluto notebook 前端中 `Base.have_color` 为 `false`,ANSI 转义会原样透传为文本 —— 在那里需要切换到 HTML 或按 MIME 类型化的渲染路径。Documenter.jl 使用 **`ANSIColoredPrinters.jl`** 将捕获的 ANSI 输出转换为 HTML 用于文档构建 —— 是从终端着色 `@example` 输出到渲染 HTML 的标准桥梁。
- Scala
Scala 字符串字面量**不**支持 `\e` 或 `\x1b` —— 与 Java、Kotlin 相同的约束。可移植的写法是 Unicode 转义 `\u001B`,在 Scala 2(自 2.0 起)与 Scala 3 上都可用。Scala 2 还接受八进制 `\033`,但 Scala 3 从字符串字面量中移除了八进制转义,因此希望在所有现代 Scala 上编译就写 `"\u001B[31m"`。`println("\u001B[1;31merror:\u001B[0m permission denied")` 在 JVM ≥ 8 的所有版本、以及 macOS、Linux、BSD、Windows 10+ 的 Conhost 1709+ / Windows Terminal(均原生解析 ANSI)上工作。 惯用辅助选 **`fansi`**(`com.lihaoyi::fansi`)—— Li Haoyi 的标准 Scala ANSI 库,被 Ammonite、mill、Scalafix、scalafmt 以及现代 Scala 生态大量采用。`fansi.Color.Red("error")` 返回带结构化颜色 span 的 `fansi.Str` 值(而非嵌入字节);`++` 拼接 span,`.overlay(fansi.Bold.On, 0, 5)` 在子区间上叠加属性,`.render` 物化为字节字符串。**`scala.io.AnsiColor`** 是标准库 mixin —— `Console.RED + "error" + Console.RESET` 风格的常量,便于在不引入第三方库的情况下输出一次性字节。**`pprint`**(同样 Li Haoyi)是标准的彩色漂亮打印器 —— `pprintln(value)` 输出缩进、fansi 着色的结果,Ammonite REPL 把它作为默认的 `println` 替换。需要更丰富的终端能力(行编辑、原始模式、能力探测)选 **JLine 3** —— Scala REPL 自身使用的 JVM 终端抽象。 能力门控:`System.console() != null` 是 JVM 可移植的检查(当 stdin/stdout 被重定向时返回 `null`)。搭配 `sys.env.get("NO_COLOR")` 处理 env 约定。**SBT 注意**:SBT 包装构建的 stdout 以注入自己的进度 UI,子进程的 ANSI 输出有时丢失颜色 —— 在 SBT 命令行加上 `-Dsbt.color=always`,或在 `build.sbt` 中设置 `ThisBuild / outputStrategy := Some(StdoutOutput)`,再启动需要真实颜色直通的脚本。`scala-cli` 与 `mill` 没有这个问题。
- Clojure
Clojure 继承 Java 字符串字面量规则 —— 只支持 `\u####` Unicode 转义。`\e` 不支持、`\x1b` 不支持、`\033` 不支持。写 `"\u001b[31m"`,且 `\u` 后的十六进制必须小写(Clojure 读取器对 Unicode 转义形式区分大小写)。`(println "\u001b[1;31merror:\u001b[0m permission denied")` 在 JVM 宿主的 Clojure ≥ 1.0 以及 ClojureScript(编译到 JS,`"\u001b"` 同样有效)上工作。在 macOS、Linux、BSD、Windows 10+ 的 Conhost 1709+ / Windows Terminal 中,终端原生解析 ANSI。 惯用辅助选 **`clansi`** —— 经典的最小 Clojure ANSI 库 —— `(clansi.core/style "error" :red :bold)` 返回带 SGR 前缀与 reset 的样式化字符串。需要 Leiningen 级结构化输出与彩色栈追踪选 **`io.aviso/pretty`** —— Leiningen 自身彩色错误格式化所用的库;`io.aviso.ansi/red`、`io.aviso.ansi/bold-red`,以及 `io.aviso.exception/format-exception` 用于漂亮的栈追踪。需要数据结构的彩色漂亮打印选 **`mvxcvi/puget`** —— 标准 Clojure pretty-printer,被 `cider` 的检查器以及 deps.edn 工具链用作人类可读 EDN;`(puget.printer/cprint value)` 输出 ANSI 着色的缩进 EDN。需要 Windows VT 启用(Conhost 1709 之前)与 JVM 可移植终端能力时,通过 Java 互操作使用 **`jansi`** —— `(org.fusesource.jansi.AnsiConsole/systemInstall)` 在每个支持 JVM 的平台启用 VT。 能力门控:`(some? (System/console))` 是 JVM 可移植的检查(stdin/stdout 重定向时返回 `nil`)。搭配 `(System/getenv "NO_COLOR")` 处理 env 约定。**CIDER nREPL 注意(本页主 SERP 差异化)**:编辑器附着的 REPL(Emacs 的 CIDER、VSCode 的 Calva、IntelliJ 的 Cursive)使用 nREPL bencode 协议 —— 它们消费返回的 `:value` 字段并自行渲染,**不会**直接管道 stdout。`:value` 字符串里的 ANSI 转义会原样穿透但大多数编辑器 REPL 会按字面文本显示。终端附着的 REPL(`lein repl`、`clj`、`bb`)会解析 stdout 的 ANSI。在编辑器 REPL 中确实需要彩色输出时,向 `*err*` 打印(CIDER 会原样透传 stderr,让宿主终端渲染颜色),或安装 `cider-nrepl` 的 `print-color` 中间件 —— 它把 SGR 码映射为编辑器字体修饰。
- Crystal
Crystal 拥有所有现代语言中最人体工学的标准库 ANSI 支持。`"..."` 字符串字面量接受所有常见的 ESC 形式 —— `"\e"`、`"\033"`(八进制)、`"\x1b"`(十六进制)、`"\u001b"`(4 位 Unicode)、`"\u{1b}"`(变长 Unicode)—— 团队读起来最快的就用哪种。`puts` 与 `print` 直接写原始字节(在刚装好的编译器上、不装任何 shard,`puts "\e[1;31merror:\e[0m permission denied"` 直接可用)。在 macOS、Linux、BSD、Windows 10+ Conhost 1709+ 上终端原生解析这些字节。 首选标准库 **`Colorize`** 模块(`require "colorize"`)—— 随编译器一起发布,API 读起来像英语:`"error".colorize.red.bold`、`"warning".colorize(:yellow)`、`"hot".colorize.fore(255, 80, 0)` 给 truecolor、`"x".colorize.fore(196)` 给 256-palette。Colorize **首次使用时自动检查 `STDOUT.tty?`**,重定向到文件或管道时静默 no-op —— 零能力门控样板就得到正确行为。 光标移动 / 清屏 / 滚动 / 保存恢复选 **`term-cursor`** shard(`Term::Cursor.move(0, 0)`、`Term::Cursor.clear_screen`、`Term::Cursor.save`)。TTY 大小 —— Crystal 标准库刻意省略公开的终端大小 API —— 引入 **`term-screen`** shard(`Term::Screen.size # => {height, width}`)。需要完整的 blessed 等价 TUI 运行时(窗口、焦点、鼠标、重绘循环)选 **`crysterm`**,Crystal 最成熟的 TUI 库。 能力门控:`STDOUT.tty?` 是标准库检查 —— stdout 重定向到文件、管道或非终端 IO 时返回 `false`。搭配 `ENV["NO_COLOR"]?` 处理通用 env 约定;`Colorize.enabled = false` 全局强制禁用。**Windows VT 注意**:Crystal 编译为原生二进制 —— 在 Conhost 1709 之前的 Windows 上,终端要等到你用 `ENABLE_VIRTUAL_TERMINAL_PROCESSING` 调用 `LibC.SetConsoleMode` 才会解析 ANSI 字节。Crystal 的编译期 `{% if flag?(:win32) %}` 宏是惯用门控:libc 绑定只在 Windows 目标上编译,因此一份源文件在所有受支持平台都干净构建。
- Nim
Nim 的标准库 `std/terminal` 是任何编译型语言中最全面的、开箱即用的终端模块 —— 一次 import 就拥有 SGR 颜色(`setForegroundColor(fgRed)`)、文本样式(`setStyle({styleBright, styleUnderscore})`)、通过 `Color(...)` 的 256-palette、truecolor(需要显式 `enableTrueColors()` 启用)、光标定位、清屏、终端大小查询、raw-mode 切换、isatty 检查 —— 全在一个地方。多数应用的依赖列表到此为止。 字符串字面量形式:Nim 接受 `"\e"`(ESC 命名转义)、`"\x1b"`(十六进制,恰好 2 位)、`"\u001b"`(4 位 Unicode)、`"\u{1b}"`(变长 Unicode)。**Nim 的妙处** —— 也是本页的主要 SERP 差异化 —— 在于 `"\NNN"` 是**十进制**,不像所有 C 族语言那样是八进制。Nim 中 `"\27"` 是字节 27(ESC);同一字面量在 C、Crystal、Python、Ruby 中是字节 `\002` 后跟字符 `'7'`。若你正从其他语言移植 ANSI 代码而 `"\033[31m"` 抛出解析错误,修复方法是 `"\27[31m"`(十进制)或 `"\x1b[31m"`(十六进制)或 —— 最可读 —— `"\e[31m"`。 `std/terminal` 之外选用:**`std/colors`**(标准库颜色名表 —— `colWhite`、`colAliceBlue`,完整 HTML/CSS 调色板作为 `Color` 常量,搭配 `enableTrueColors()` 从命名常量发出 `38;2;R;G;B`);**`chronicles`**(status-im 的结构化日志库 —— Nim 规范日志库,开箱即用 ANSI 着色主题 / 级别 / 时间戳格式化,被所有 Nim 以太坊 / 区块链栈使用);**`illwill`**(johnnovak 的无 curses TUI 库 —— Nim 对 ncurses 的现代回答,自带 ANSI 后端,与 `std/terminal` 干净组合用于非全屏输出)。 能力门控:`std/terminal` 的 `isatty(stdout)` 在 stdout 重定向时返回 `false`。搭配 `getEnv("NO_COLOR")` 处理通用退出、`getEnv("FORCE_COLOR")` 处理强制启用。Windows VT 模式:`std/terminal` 在首次使用任何颜色辅助时自动用 `ENABLE_VIRTUAL_TERMINAL_PROCESSING` 调用 `SetConsoleMode`,所以你不需要在颜色调用周围加 `when defined(windows)` 门 —— Nim 处理它。Windows 10 1709 之前的构建(无 VT 支持的 Conhost)回退到直接 Win32 console-API 颜色调用,对你的代码透明。
- OCaml
OCaml 字符串字面量支持 `"\027"`(十进制 —— 规范的 OCaml ESC 形式,在 OCaml 1.0 起的所有版本中可用)、`"\x1b"`(十六进制,OCaml 4.06+)以及 `"\o033"`(八进制,OCaml 4.06+)。**OCaml 的妙处**:`"\NNN"` 是**十进制**,不像 C 那样是八进制 —— Nim 用户踩到的同一个陷阱。C 中 `"\033"` 是字节 27(八进制);OCaml 中 `"\033"` 是字节 33(十进制 —— 字符 `!`)。从 C 移植时规范修复是 `"\027"`(十进制)或 —— 在 OCaml 4.06+ —— `"\x1b"`(十六进制)或 `"\o033"`(八进制,当你想保留字面看起来一样时)。没有 `\e` 命名转义。`print_string "\027[1;31merror:\027[0m permission denied\n"` 通过运行时的 `stdout` 通道写原始字节,在 macOS、Linux、BSD、Windows 10+ Conhost 1709+ 上原生解析。 选 **`ANSITerminal`**(opam 包,OCaml 规范 ANSI 库)—— `ANSITerminal.print_string [red; Bold] "error: "` 读作一个样式列表后跟文本,自动发出 reset,在 Windows 上通过原生 console-mode 切换处理能力检测。**结构化 / 格式化输出**选 **`fmt`**(Dune 默认格式化器)—— `Fmt.pr "@{<red>error@}: %s@." msg` 把语义标记标签解析为 SGR 序列并尊重 `Fmt.set_style_renderer Format.std_formatter `Ansi_tty`。将 `fmt` 与 **`logs`** 配对做结构化日志,每个来源 / 级别带彩色前缀(`Logs.info (fun m -> m "started on %d" port)` 在 stdout 是 TTY 时产生彩色 `[INFO]` 前缀)。完整 TUI 运行时选 **`notty`** —— pqwy 的高质量声明式 TUI 库,带图像组合(`I.string A.(fg red) "error"` 返回 `Notty.image`,用 `<|>` / `<->` 组合,经 `Notty_unix.Term` 渲染)。 能力门控:`Unix.isatty Unix.stdout`(`unix` 库,随多数 OCaml 安装一起)在 stdout 重定向时返回 `false`。搭配 `Sys.getenv_opt "NO_COLOR"` 处理通用退出。**utop REPL 注意**(本页主要 SERP 差异化):utop 内的 `print_string "\027[31mfoo\027[0m"` **确实**渲染红色(utop 将 stdout 管道到底层 lambdaterm 解析 ANSI)。然而当 REPL 显示顶层绑定的**值**(`let s = "\027[31mfoo\027[0m";;`),utop 把 OCaml 字符串字面量原样回显给你 —— 转义字节作为 `\027[...]` 字面显示,而非颜色。修复方法:显式打印字符串(`let () = print_string s`)而非让 utop 回显值,或安装 `utop-full` 并使用 `UTop.set_phrase_terminator` / `UTop.set_show_box` 定制 REPL 渲染。
- Erlang
Erlang 字符串字面量接受本站记录的所有语言中最广泛的 ESC 形式集合 —— `"\e"`(命名 ESC)、`"\x1b"`(十六进制)、`"\033"`(八进制 —— Erlang 的 `\NNN` 是八进制,与 C 相同),以及 `"\^["`(脱字号控制字符记法 —— `^A` 到 `^Z` 映射到 ASCII 1..26,`^[` 映射到 ASCII 27 = ESC)。Erlang 中字符串是 charlist(整数列表);二进制 `<<"...">>` 也是一等公民。`io:format("\e[1;31merror:\e[0m ~s~n", [Msg])` 是规范的 Erlang 单行写法 —— `~s` 插入第二个参数列表、`~n` 是平台换行符、ANSI 字节通过 `io:format/2` 原样传给调用进程的 `group_leader`(shell 附着的代码下即用户终端)。 SGR 辅助选 **`cf`**(project-fifo/cf —— "Erlang Colour Format")—— 扩展 `io:format` 的 `~` 指令语法加入 `~!r`(红)、`~!g`(绿)、`~!b`(蓝)、`~!_`(粗体)、`~!!`(reset)等。`cf:format("~!rerror:~!! permission denied~n")` 比原始字节形式更简洁。结构化日志选 OTP 标准库的 **`logger`** 模块(OTP 21+ 内置 —— 2018 年 3 月)—— `logger:info("started", #{port => 8080})` 在默认处理器附着 TTY 时产生带颜色的级别前缀,重定向时产生 JSON。生产中仍能见到的 OTP-21 之前的代码库选 **`lager`**(basho 的结构化日志库 —— logger 之前的规范选择,每级别 ANSI 着色前缀,基于 sink 的每应用过滤)。 **OTP release 模式注意**(本页主要 SERP 差异化):每个 Erlang 进程都有一个 `group_leader` 处理其 I/O。交互式 shell 或 escript 中,`group_leader` 就是用户终端 —— ANSI 透传。当你构建 OTP release(`rebar3 release` → `bin/myapp daemon` 或 `foreground`),`group_leader` 被重新分配:`daemon` 模式下它是写入 `log/erlang.log.N` 的 logger 进程,ANSI 字节作为 `\e[31m...` 文本**字面**出现在日志文件中。修复方法:使用 `logger` 模块的着色 handler(当其输出目标不是 TTY 时去除 ANSI —— 通过 `io:rows()` 返回 `{error, enotsup}` 自动检测),或通过 `application:get_env(kernel, standard_io_handler)` 检测并显式门控 `io:format` 颜色调用。 能力门控:`io:rows()` 在 stdout 是 TTY 时返回 `{ok, Rows}`,重定向时返回 `{error, enotsup}`。搭配 `os:getenv("NO_COLOR")` 处理通用退出。现代 Erlang shell(`erl`,OTP 25+)在所有平台包括 Windows 上原生解析 `io:format` 输出中的 ANSI(BEAM 模拟器在首次 ANSI 字节时处理 `SetConsoleMode`)。
- Lua
Lua 没有 `\e` 转义字面,但 `\27`(十进制)在 Lua 5.1 起的所有解释器中都可用,`\x1b`(十六进制)自 Lua 5.2 起可用。`io.write` 与 `print` 在 PUC-Rio Lua(5.1 / 5.2 / 5.3 / 5.4)、LuaJIT 以及随 Neovim、OpenResty、Redis、Wireshark 嵌入的解释器中均按字节透传。**注意**:长括号字符串 `[[...]]` **不**展开转义序列 —— 只有常规 `"..."` 字符串会展开,因此输出 ANSI 字节时必须使用双引号字符串。 人体工学方面:**ansicolors.lua**(kikito 的经典 gem)将 `colors('%{red bold}error:%{reset} permission denied')` 之类的模式字符串解析为 SGR 序列 —— 单文件依赖,可经 LuaRocks 安装或直接 vendor 拷入。**term.lua**(hoelzro 移植自 kikito 的终端控制库)覆盖非 SGR 一侧:`term.clear()`、`term.cleareol()`、`term.cursor.goto(x, y)`、`term.cursor.hide()`、备用屏 + 光标保存恢复。完整全屏 TUI 链接 **lcurses**(Lua 的 ncurses 绑定)。能力门控 —— `isatty()`、`TIOCGWINSZ`、termios 原始模式 —— 用 **LuaPosix**。
- Zig
Zig 标准库没有颜色辅助,但字节字面量是一等公民 —— `"\x1b[31m"` 是 `*const [5:0]u8`,可直接通过 `std.io.getStdOut().writer().print`(或 `std.debug.print` 用于快速原型)输出,无需任何编码处理。自 Zig 0.11 起,规范的能力门控是 `std.io.tty.detectConfig(std.io.getStdOut())` —— 它返回带标签的联合(`.no_color`、`.escape_codes`、`.windows_api`),遵守 `NO_COLOR`、检查 `isatty(2)`,并在 VT 之前的 Windows Conhost 上选择正确的后端。将写入站点包在 `switch (config) { ... }` 内,仅在 `.escape_codes` 分支输出原始转义。 超出零散 print 的场景:**libvaxis**(rockorager/libvaxis)是现代全屏 TUI 库 —— 纯 Zig 实现、可在支持时使用 kitty 键盘协议、自带渲染管线。**mibu**(xyaman/mibu)是小而精的 ANSI 辅助库,用于非全屏输出(`mibu.color.print(.{ .fg = .red }, "error", .{})`)。**zig-spoon** 提供最小化的终端控制(原始模式 + 光标定位),无需完整 TUI 框架。三者都建立在本站记录的字节序列之上。
- Elixir
Elixir 标准库提供 `IO.ANSI` 模块 —— 每个命名 SGR 和少量光标 / 屏幕辅助都是返回其字节形式的函数(`IO.ANSI.red()` 返回 `"\e[31m"`)。规范用法是 `IO.ANSI.format/2`,它接受混合原子(命名转义)与二进制(你的文本)的列表,返回适合 `IO.puts/1` 或 `IO.write/1` 的 iolist —— 例如 `IO.puts(IO.ANSI.format([:bright, :red, "error: ", :reset, "permission denied"]))`。`IO.ANSI.enabled?/0` 是内置于标准库的能力门控:遵守 `:elixir` 应用环境 `:ansi_enabled`(`iex` 在 tty 上设为 true、在管道上设为 false)以及 `NO_COLOR` 环境变量。 超出零散 print 的场景:**Bunt**(savonarola/bunt)为 `IO.ANSI` 加糖,支持字符串内的命名颜色标签 —— `Bunt.puts([:red, "error: ", :default_color, "permission denied"])` 或行内形式 `Bunt.puts("[red]error:[/red] permission denied")`。**Owl**(fuelen/owl)是现代输出工具集(盒子、表格、进度条、多行 spinner、ANSI 超链接)—— 被 Phoenix 生成的 CLI 任务、`mix` 扩展、`livebook` 启动输出使用。完整全屏 TUI 请用 **Ratatouille**(ndreynolds/ratatouille),Elm 风格的 `model / update / view` 架构经 termbox2 渲染为 ANSI。