跳到主要内容
ansicode

副 DA 回复解码器 — `CSI > Pp ; Pv ; Pc c` 型号 / 固件 / 卡带

副 Device Attributes 回复的解码参考 —— 每个 Pp 型号码的含义,以及 kitty / wezterm / alacritty / iTerm2 / Ghostty 如何把自身版本编入 Pv。

字节形式

涵盖所有常见的字符串字面量写法,方便正反查找。

\\x1b[\x1b[>Pp;Pv;Pcc
\\033[\033[>0;276;0c
\\e[\e[>0;276;0c
ESC [ESC [ > Pp ; Pv ; Pc c
hex1b 5b 3e ... 63

说明

副 DA 的*回复*形状(请求侧参见 `csi-da`)。程序发送 `\x1b[>c`(或 `\x1b[>0c`);终端在标准输入回复 `\x1b[>Pp;Pv;Pc c`。TUI 通常用 **Pp** 选特性集,用 **Pv** 启用版本针对性的 workaround —— 本页即是查表参考。 **Pp —— 型号码**: - `0` — DEC VT100(或声称 VT100 兼容的终端 —— 常见于极简嵌入式模拟器)。 - `1` — DEC VT220。 - `2` — DEC VT240 / VT241。 - `18` — DEC VT330。 - `19` — DEC VT340。 - `24` — DEC VT320。 - `28` — DEC VT330(替代值)。 - `32` — Tek 4014。 - `41` — DEC VT420。 - `61` — DEC VT510(以及多数 **xterm 类**模拟器,含 **xterm 自身** patch ≥ 95)。 - `64` — DEC VT520。 - `65` — DEC VT525(**Kitty**、**Alacritty**、**WezTerm**、**iTerm2** 按惯例都用 65 作「现代 xterm 类」标记;**Ghostty** 同样用 65)。 - `82` — rxvt。 - `83` — Eterm。 - `84` — sun terminal。 - `85` — rxvt-unicode(urxvt)。 **Pv —— 固件 / 版本**: - DEC 硬件:实际 ROM 版本(如 xterm patch level → Pv = 95+)。 - **xterm**:Pv 为 xterm patch level —— `\x1b[>61;392;0c` 表示 xterm patch 392。 - **Kitty**:Pv 编码版本 —— Pv = `主*10000 + 次*100 + 修订`,故 0.41.1 → 4101(旧版用 100 进制,请以当前行为为准)。 - **WezTerm**:Pv 为年-月构建号 —— 如 4604 ≈ 2024.10。 - **Alacritty**:Pv 固定为 `0`(Alacritty 不通过此处暴露版本;改用 XTVERSION,见 `xtversion`)。 - **iTerm2**:Pv 固定为 `95`(兼容性冻结在最初的 xterm-95 标记上;真实版本用 XTVERSION)。 - **Ghostty**:Pv 为构建 patch level。 - **Windows Terminal**:Pv 为 WT 版本 主*100 + 次(如 1.0 = 0,1.18 = 18)。 **Pc —— 卡带 / 序列号**: - DEC 硬件:ROM 卡带号,仅串口型几乎全为 `0`。 - 软件模拟器:恒为 `0`。 - 非零 Pc 仅作信息用 —— 无可移植语义。 **推荐消费模式**: ``` match (Pp, Pv) { (65, v) if v >= 1000 => 'modern xterm-class' # Kitty / WezTerm / Alacritty / iTerm2 (64, _) => 'VT520 or VT520-compat' (61, _) => 'xterm or xterm-class' (41, _) => 'VT420 or VT420-compat' (1, _) => 'VT220 or VT220-compat' (0, _) => 'VT100 or minimal' _ => 'unknown — feature-detect via XTVERSION or DECRQM' } ``` **不要用 DA2 做细粒度特性检测** —— Pp 覆盖很粗、Pv 编码因模拟器而异。「此终端是否支持特性 X」请用 **XTVERSION**(`xtversion`)拿模拟器名与版本,再以 `DECRQM`(`decrqm`)查询具体模式位。DA2 只用于粗粒度的型号分桶。

规范出处: xterm-ctlseqs (Secondary DA reply) / DEC VT320+ DA2

参数

Pp型号码 —— 0 VT100、1 VT220、41 VT420、61 xterm 类、64 VT520、65 现代 xterm 类(Kitty/WezTerm/Alacritty/iTerm2/Ghostty)、82 rxvt、85 urxvt。
Pv固件 / 版本 —— 编码因模拟器而异(xterm patch、Kitty 主*10000+次*100+修订、WezTerm 年-月构建、Alacritty=0、iTerm2=95)。可移植版本检测请用 XTVERSION。
Pc卡带 / 序列号 —— 软件模拟器几乎恒为 0;仅作信息用。

示例

bash
# Ask + decode model bucket.\nold=$(stty -g); stty -echo raw min 0 time 1\nprintf '\033[>c' > /dev/tty\nIFS= read -r -d c reply < /dev/tty\nstty "$old"\npp=$(echo "$reply" | sed -nE 's/.*>([0-9]+);.*/\\1/p')\ncase "$pp" in\n    0)   echo 'VT100 / minimal' ;;\n    1)   echo 'VT220-compat' ;;\n    41)  echo 'VT420-compat' ;;\n    61)  echo 'xterm-class' ;;\n    65)  echo 'modern xterm-class (Kitty/WezTerm/Alacritty/iTerm2/Ghostty)' ;;\n    82)  echo 'rxvt' ;;\n    85)  echo 'urxvt' ;;\n    *)   echo "unknown model: $pp" ;;\nesac
python
import sys, termios, tty, re\nMODELS = {0:'VT100/minimal',1:'VT220',41:'VT420',61:'xterm-class',64:'VT520',65:'modern xterm-class',82:'rxvt',85:'urxvt'}\nfd = sys.stdin.fileno(); old = termios.tcgetattr(fd); tty.setraw(fd)\ntry:\n    sys.stdout.write('\x1b[>c'); sys.stdout.flush()\n    buf = b''\n    while not buf.endswith(b'c'): buf += sys.stdin.buffer.read1(64)\n    m = re.search(rb'>(\d+);(\d+);(\d+)c', buf)\n    pp, pv, pc = (int(x) for x in m.groups())\n    print(f'model={MODELS.get(pp, "unknown")} ({pp}); version={pv}; cart={pc}')\nfinally:\n    termios.tcsetattr(fd, termios.TCSADRAIN, old)
go
// Decode the (Pp, Pv) bucket — Pc is informational.\nvar models = map[int]string{0:\"VT100\",1:\"VT220\",41:\"VT420\",61:\"xterm-class\",64:\"VT520\",65:\"modern xterm-class\",82:\"rxvt\",85:\"urxvt\"}\nfunc decodeDA2(reply string) (string, int) {\n    var pp, pv, pc int\n    fmt.Sscanf(reply, \"\\x1b[>%d;%d;%dc\", &pp, &pv, &pc)\n    return models[pp], pv\n}
javascript
// Parse a DA2 reply string into a labelled bucket.\nfunction decodeDA2(reply) {\n    const m = reply.match(/>(\d+);(\d+);(\d+)c/);\n    if (!m) return null;\n    const [pp, pv, pc] = m.slice(1).map(Number);\n    const models = {0:'VT100',1:'VT220',41:'VT420',61:'xterm-class',64:'VT520',65:'modern xterm-class',82:'rxvt',85:'urxvt'};\n    return { model: models[pp] || `unknown(${pp})`, version: pv, cartridge: pc };\n}
c
/* Decode a DA2 reply already buffered in `reply`. */\nint pp = 0, pv = 0, pc = 0;\nif (sscanf(reply, \"\\x1b[>%d;%d;%dc\", &pp, &pv, &pc) == 3) {\n    /* branch on pp / pv */\n}

终端支持

xterm
支持
Linux console (fbcon)
部分
macOS Terminal.app
部分
iTerm2
支持
Windows Terminal
支持
cmd.exe / ConPTY
部分
kitty
支持
alacritty
部分
WezTerm
支持
Ghostty
支持
GNOME Terminal
支持
Konsole
支持
tmux
不支持
GNU screen
不支持

相关序列

在家族食谱中

CSI 食谱 · 4. 查询 —— DA、DA2、DSR、DECRQM