跳到主要内容
ansicode

DECSCUSR — 光标形状

切换光标形状:方块、下划线或竖线(可选是否闪烁)。

字节形式

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

\\x1b[\x1b[N\x20q (N = 0..6)
\\033[\033[1 q
\\e[\e[1 q
ESC [ESC [ N SP q
hex1b 5b <N> 20 71

说明

DEC 设置光标样式(DECSCUSR)。标准 CSI 序列,但末字节 q(0x71)前有一个 SPACE(0x20)中间字节:\x1b[<N>\x20q。参数在单一数值里同时编码 *形状* 与 *闪烁* —— 0 = 恢复用户默认、1 = 闪烁方块(出厂默认)、2 = 实心方块、3 = 闪烁下划线、4 = 实心下划线、5 = 闪烁竖线、6 = 实心竖线。首发于 xterm patch 282(2013 年 9 月);此后被每个现代 GUI 模拟器采纳。经典「编辑器模式」用法:vim 通过 t_SI / t_EI 终端串选项,把 \x1b[6\x20q(竖线)配为插入模式、\x1b[2\x20q(方块)配为普通模式;不少 shell(fish、zsh-vi-mode)在 vi 命令行编辑里做同样的事。

可移植性 —— xterm、iTerm2、kitty、alacritty、wezterm、gnome-terminal、Konsole、Ghostty、Windows Terminal、ConPTY 1809+ 全部完整支持 DECSCUSR。Linux console 部分支持(framebuffer 驱动接受形状变化但多数发行版忽略闪烁位)。Windows 旧 cmd.exe 部分支持 —— ConPTY 之前忽略;ConPTY 转发。Apple Terminal.app 晚期才加入,但能工作。最大的作者陷阱是 SPACE 中间字节:\x1b[6q(无空格)*不是* DECSCUSR —— 没有 SP 中间字节,末字节 q 会被解析成另一序列(多数模拟器上是 DECSTBM 相关)而光标毫无变化。字节序列必须严格为 ESC [ <N> SPACE q。terminfo 为 DECSCUSR 定义了 Ss cap(set cursor style),但多数 terminfo 条目并未填充,因此应用通常直接硬编字节。tmux 在现代版本中能正确把 DECSCUSR 转发给外层终端。

退出时恢复是可持久的清理。崩溃且未恢复用户偏好形状的编辑器,会让终端停留在 DECSCUSR 最后设定的竖线 / 下划线上 —— 用户回到 shell 提示符时被打个措手不及。标准清理是退出时发 \x1b[0\x20q(参数 0 = 「恢复用户默认」),通常接入到编辑器的 t_EIatexit 钩子。更重的锤子是 DECSTR(\x1b[!p,见 decstr-soft-reset),它会在不清回滚的前提下顺带重置 DECSCUSR 等私有模式。注意「用户默认」由终端定义 —— 多数模拟器把参数 0 映射为闪烁方块,但 kitty / wezterm / iTerm2 尊重用户配置的默认,所以同一句 \x1b[0\x20q 在不同终端可能产生不同形状 —— 这是预期行为,不是 bug。相关:cursor-visibility(DECTCEM ?25 —— 与形状正交:可见性与形状,崩溃后都需要清理)、cursor-position(CUP —— 位置,第三个光标维度)、dec-cursor-blink(DECSET ?12 —— 仅闪烁开关、不动形状,需要单独覆盖闪烁而不强制形状时的替代品)。

规范出处: xterm-ctlseqs (DECSCUSR, CSI Ps SP q)

参数

0用户默认光标
1闪烁方块
2实心方块
3闪烁下划线
4实心下划线
5闪烁竖线
6实心竖线

示例

bash
printf '\033[6 q'   # vertical bar (insert mode)\nprintf '\033[2 q'   # block (normal mode)\nprintf '\033[0 q'   # restore default
python
import sys; sys.stdout.write('\x1b[6 q')
go
fmt.Print("\x1b[6 q")
javascript
process.stdout.write('\x1b[6 q')
c
printf("\x1b[6 q");

在哪里用到

实际会发出该序列的工具——把抽象字节锚定到你已经用过的命令上。

  • vim, neovim`guicursor` 按模式写 DECSCUSR——normal 用块,insert 用竖线,replace 用下划线
  • fish默认 `fish_vi_cursor` 在 vi 模式切换时改变光标形状
  • zsh + zsh-vi-mode pluginNORMAL 块、INSERT 竖线——在 line-init 钩子中发出
  • bash with `bind 'set show-mode-in-prompt on'`支持 vi 模式的提示符在 command/insert 切换时发出 DECSCUSR
  • starship — `vicmd_symbol` companion that also sets cursor shape

常见问题

针对这条序列,开发者真正会去搜索的问题的简短回答。

为什么 \x1b[6q 不改光标形状,而 \x1b[6 q 可以?
DECSCUSR 在末字节 q 之前需要一个空格(0x20)作为*中间字节*:线上形态严格是 ESC [ <N> 空格 q。没有空格时,\x1b[6q 会被解析成另一条(与 DECSTBM 相关的)CSI,光标完全不变。在 \e 引号字符串里别忘了空格——printf '\e[6 q' 正确,printf '\e[6q' 静默错误。
为什么 vim 退出后光标仍是方块,而不是恢复成竖线?
vim 通过 t_SI / t_EI 为*自己的*插入 / 正常模式配置光标形状,但除非 t_te 发出 \x1b[0\x20q(DECSCUSR 0 = 恢复终端默认),它退出时并不还原用户先前的形状。.vimrclet &t_EI = "\e[2 q" | let &t_te ..= "\e[0 q",或在提示符里发 \x1b[0\x20q 让每个新行重画。neovim 自 0.4 起开箱即用就正确处理。

终端支持

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

相关序列

在家族食谱中

CSI 食谱 · 6. 插入 / 删除 / 光标形状 —— IL / DL / ICH / DCH / ECH + DECSCUSR