跳到主要内容
ansicode

DECSC / DECRC — 保存与恢复光标

保存并恢复光标状态(位置 + 属性)。

字节形式

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

\\x1b[\x1b7 (save) \x1b8 (restore)
\\033[\0337 / \0338
\\e[\e7 / \e8
ESC [ESC 7 / ESC 8
hex1b 37 / 1b 38

说明

DECSC(ESC 7,十六进制 1b 37)与 DECRC(ESC 8,十六进制 1b 38)是 DEC 私有的 2 字节转义 —— *不是* CSI 序列。没有前导 \x1b[,也没有参数;第二个字节是 ASCII 字面 78(不是控制字符 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

示例

bash
printf '\0337move\033[5;5HHERE\0338back\n'
python
print('\x1b7\x1b[5;5HHERE\x1b8')
go
fmt.Print("\x1b7\x1b[5;5HHERE\x1b8")
javascript
process.stdout.write('\x1b7\x1b[5;5HHERE\x1b8')
c
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
支持

相关序列