DECSC / DECRC — 保存与恢复光标
保存并恢复光标状态(位置 + 属性)。
字节形式
涵盖所有常见的字符串字面量写法,方便正反查找。
\x1b7 (save) \x1b8 (restore)\0337 / \0338\e7 / \e8ESC 7 / ESC 81b 37 / 1b 38说明
DECSC(ESC 7,十六进制 1b 37)与 DECRC(ESC 8,十六进制 1b 38)是 DEC 私有的 2 字节转义 —— *不是* CSI 序列。没有前导 \x1b[,也没有参数;第二个字节是 ASCII 字面 7 或 8(不是控制字符 0x07 BEL)。DECSC 把完整光标状态压入终端侧的 1 层深栈:位置(行 + 列)、活动 SGR 属性(加粗 / 斜体 / 下划线 / 前景 / 背景)、G0..G3 字符集选择、origin mode 标志(DECOM ?6)、wraparound 标志(DECAWM ?7)、光标可见性标志。DECRC 把它弹回来。ECMA-48 §8.3.79 与 §8.3.80 称之为「SCS / RCS」;xterm-ctlseqs 的「DECSC / DECRC」是事实标准。栈深为 1 —— 第二次 DECSC 会覆盖之前的保存状态,因此这套原语无法跨嵌套重绘递归使用。
CSI 兄弟 \x1b[s(SCOSC —— 保存)与 \x1b[u(SCORC —— 恢复)源自 SCO 控制台,历史上*只*保存光标位置而不保存属性;xterm 与所有现代模拟器把 SCO 与 DEC 两套视为等价,但 screen 4.x、非常老的 framebuffer Linux console、少量 Windows console 模拟器(ConPTY 1809 之前)仍以「只位置」实现 SCOSC / SCORC。decsc-vs-scosc 的区别在你于保存 / 恢复块内绘制带 SGR 颜色并期望属性被恢复时显形 —— 在「只位置」实现上光标跳回去但 SGR 状态停在最后发出的值。Linux console / fbcon 实现了 DECSC / DECRC;ConPTY 1809+ 正确转发;tmux 在 pane 内透传(但每个 pane 的保存状态不会跨 tmux detach / attach 持久化)。在 alt-screen 内(DECSET ?1049 或 ?1047),多数终端为主缓冲区与 alt 缓冲区维护*相互独立*的 DECSC 栈 —— 因此主缓冲区上发出的 DECSC 在 alt 缓冲区不可恢复。
没有单独的「关闭」—— DECSC / DECRC 本身是一对平衡操作。跨模拟器 TUI 的可移植规则是:需要在绘制后恢复「位置 + 属性」对就用 DECSC / DECRC,需要恢复任意 DEC 私有模式(鼠标、括号粘贴、光标可见性)就用显式 XTSAVE / XTRESTORE 栈(\x1b[?Pn s / \x1b[?Pn r)。多次 DECSC *不能嵌套*;如果你的 TUI 流程是保存光标 → 绘制菜单 → 用户按箭头 → 再保存 → 用户取消 → 恢复,第二次 DECSC 已经覆盖了第一次保存,光标会落错位。修复办法要么是用 cursor-position(CUP)做显式绝对定位,要么在应用内维护一份保存栈。相关:cursor-position(CUP —— 绝对定位,当 1 层深 DEC 栈不够用时的替代)、cursor-move(CUU / CUD / CUF / CUB —— 不需要保存 / 恢复对的相对移动)、sco-save-restore(CSI 兄弟对,在旧实现上只保存位置)。
规范出处: DEC STD 070 / xterm-ctlseqs
示例
printf '\0337move\033[5;5HHERE\0338back\n'print('\x1b7\x1b[5;5HHERE\x1b8')fmt.Print("\x1b7\x1b[5;5HHERE\x1b8")process.stdout.write('\x1b7\x1b[5;5HHERE\x1b8')printf("\x1b7\x1b[5;5HHERE\x1b8");在哪里用到
实际会发出该序列的工具——把抽象字节锚定到你已经用过的命令上。
- bash, zsh readline在提示符重绘前后保留用户输入位置
- npm, pnpm, yarn progress bars保存光标 → 写进度行 → 恢复,让下一条日志落到新一行
- ora, cli-spinners (Node)
- tmux status-line updates
常见问题
针对这条序列,开发者真正会去搜索的问题的简短回答。
- DECSC / DECRC 与 SCOSC / SCORC 有什么区别?
- DECSC(
\x1b7)/ DECRC(\x1b8)保存并恢复光标位置外加完整的渲染状态(SGR 属性、字符集、原点模式)。SCOSC(\x1b[s)/ SCORC(\x1b[u)只保存恢复光标位置。TUI 快照默认用 DECSC 更安全;只是临时跳一下光标、不关心颜色恢复时用 SCOSC 也行。某些终端在 DEC 私有模式 69 下把\x1b[s重用为 DECSLRM——DECSC 没有这个歧义。 - DECSC / DECRC 可以嵌套使用吗?
- 不能。DECSC 在每个缓冲区(主屏 / 备用屏各一份)只保留一个保存槽。第二次 DECSC 会覆盖第一次,所以「保存→保存→恢复→恢复」时两次恢复都会取到第二次保存的值。需要嵌套临时跳转,自己维护栈:把当前行 / 列存进程序内存,靠 CUP(
\x1b[r;cH)跳回。
终端支持
- 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 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |