跳到主要内容
ansicode

DECRQDE / DECRPDE —— 请求 / 回报显示区范围(`CSI " v` / `" w`)

VT420+ 的分页查询 —— 询问终端当前显示多少行 / 列,以及滚动窗口在页内存中的位置。让主机不必依赖 `tput lines / cols` 就能得知可视视口。

字节形式

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

\\x1b[\x1b["v DECRQDE (request)\n\x1b[<Ph>;<Pw>;<Pml>;<Pmt>;<Pmp>"w DECRPDE (reply)
\\033[\033["v / \033[<Ph>;<Pw>;<Pml>;<Pmt>;<Pmp>"w
\\e[\e["v / \e[<Ph>;<Pw>;<Pml>;<Pmt>;<Pmp>"w
ESC [ESC [ " v / ESC [ Ph ; Pw ; Pml ; Pmt ; Pmp " w
hex1b 5b 22 76 / 1b 5b … 22 77

说明

**DECRQDE**(*请求显示区范围*,`\x1b["v`)让终端描述*它对页内存的可视视口*。回复(**DECRPDE**,`\x1b[Ph;Pw;Pml;Pmt;Pmp"w`)携五个数: - **Ph** —— 视口可见行数(几乎总等于终端高度)。 - **Pw** —— 视口可见列数(几乎总等于终端宽度)。 - **Pml** —— 视口在页内的左列(1 起算;视口最左列相对页内存的位置)。 - **Pmt** —— 视口在页内存中的顶行(1 起算;通常为 `1`,除非页比屏幕高且已滚动)。 - **Pmp** —— 当前活动页号(在所有单页模拟器上为 1;只在有多页内存的 DEC VT525 上才有意义)。 **为何需要单独的查询**:在经典 DEC VT420/VT525 硬件上,*页内存*可能比屏幕大 —— 终端持有例如 480 行缓冲,仅显示其中 24 行,主机要在不重绘的情况下得知屏上是哪片。它是 **DECSCPP**(设每页列数)与 **DECSLPP**(设每页行数)的往返伙伴 —— 主机设几何,终端经 DECRPDE 回执。 **现代用法**:2026 年几乎所有模拟器都是单页 == 单视口 == 单屏大小缓冲,回复退化为 —— `Ph` 等于 `LINES`、`Pw` 等于 `COLUMNS`、`Pml`/`Pmt`/`Pmp` 皆为 `1`。今日*有用*的角色是作**特性探测**:会回报的终端宣称 VT420 级兼容,强相关于支持 DECRQTSR / DECRSTS、DECCARA、矩形操作族。要门控「真 VT420 血统」的程序发 `\x1b["v`,把任意回复视作「可走」。 **安全读取回复** - 向 stdout 发 `\x1b["v`。 - 以 50–150 ms 超时从 stdin 读。对不回复的终端(多数现代模拟器),超时触发后认为*无 VT420 支持*。 - 解析 `\x1b\[([0-9]+);([0-9]+);([0-9]+);([0-9]+);([0-9]+)"w` —— 锚定开头 CSI 与末尾 `"w`,避免在多查询并行的慢连接上错框。 - **要点**:若多个查询并行飞行,终端可能前后串其他回报 —— 匹配 `"w` 末字节,而非位置。 **覆盖度**:**xterm** = 完整(基准实现)。**mlterm** + **Konsole** + **gnome-terminal** = 完整。**WezTerm** = 部分(会回,但不管实际滚动 `Pmt` 永远 `1`)。**iTerm2** = 静默。**Kitty** + **Alacritty** + **Ghostty** + **Windows Terminal** + **cmd / ConPTY** + **macOS Terminal** + **Linux console** = 静默。该查询可无条件发 —— 不回的终端忽略字节;会回的产出 5 个小十进制字段,30 字节内可解析。

规范出处: DEC VT420 / VT525 RM (DECRQDE / DECRPDE) / xterm-ctlseqs (CSI " v / " w)

参数

Ph回复字段:视口可见行数。
Pw回复字段:视口可见列数。
Pml回复字段:视口在页内存中的最左列(1 起算)。
Pmt回复字段:视口在页内存中的顶行(1 起算)。
Pmp回复字段:当前活动页号(单页模拟器上为 1)。

示例

bash
# Probe DECRQDE with a 100 ms read timeout.\nprintf '\\033["v'\nIFS= read -rs -d 'w' -t 0.1 reply </dev/tty 2>/dev/null\necho \"extent reply: ${reply}w\"   # e.g. \\x1b[24;80;1;1;1\"w
python
import sys, re, select\nsys.stdout.write('\\x1b["v')\nsys.stdout.flush()\nif select.select([sys.stdin], [], [], 0.1)[0]:\n    reply = sys.stdin.buffer.read1(64)\n    m = re.search(rb'\\x1b\\[(\\d+);(\\d+);(\\d+);(\\d+);(\\d+)\"w', reply)\n    if m:\n        h, w, ml, mt, mp = (int(x) for x in m.groups())\n        print(f'viewport: {h}x{w}, page-offset ({mt},{ml}), page {mp}')
go
// Feature-probe — treat any DECRPDE reply as 'VT420-class emulator'.\nimport (\n    \"fmt\"\n    \"os\"\n)\nfmt.Fprint(os.Stdout, \"\\x1b[\\\"v\")\n// Read with timeout (omitted); a non-empty reply => assume VT420 features.
javascript
// Trigger DECRQDE, log any reply.\nprocess.stdout.write('\\x1b[\"v');\nprocess.stdin.once('readable', () => {\n  const m = /\\x1b\\[(\\d+);(\\d+);(\\d+);(\\d+);(\\d+)\"w/.exec(process.stdin.read()?.toString('binary') ?? '');\n  if (m) console.error('extent:', m.slice(1));\n});
c
/* Send DECRQDE; the host expects DECRPDE within ~100 ms or gives up. */\nfputs(\"\\x1b[\\\"v\", stdout);\nfflush(stdout);\n/* Then poll stdin with select() and scanf the 5 decimal fields. */

终端支持

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

相关序列