副 DA 回复解码器 — `CSI > Pp ; Pv ; Pc c` 型号 / 固件 / 卡带
副 Device Attributes 回复的解码参考 —— 每个 Pp 型号码的含义,以及 kitty / wezterm / alacritty / iTerm2 / Ghostty 如何把自身版本编入 Pv。
字节形式
涵盖所有常见的字符串字面量写法,方便正反查找。
\x1b[>Pp;Pv;Pcc\033[>0;276;0c\e[>0;276;0cESC [ > Pp ; Pv ; Pc c1b 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;仅作信息用。 |
示例
# 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" ;;\nesacimport 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)// 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}// 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}/* 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
- 不支持
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 支持 | 部分 | 部分 | 支持 | 支持 | 部分 | 支持 | 部分 | 支持 | 支持 | 支持 | 支持 | 不支持 | 不支持 |