跳到主要内容
ansicode

DECAWM ?7 — 自动换行模式

切换光标到达右边距时是否自动换到下一行(默认开启)。

字节形式

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

\\x1b[\x1b[?7h (enable wrap) \x1b[?7l (disable)
\\033[\033[?7h / \033[?7l
\\e[\e[?7h / \e[?7l
ESC [ESC [ ? 7 h / l
hex1b 5b 3f 37 68 / 6c

说明

DEC 自动换行模式(DECAWM)—— DEC 私有模式 7,记录于 xterm-ctlseqs 与最早的 VT100 参考手册,是最早的 DEC 模式之一。启用字节序列为 \x1b[?7h(终端的*初始*状态 —— 自动换行默认开),关闭为 \x1b[?7l。换行启用时,超出最右列的字符会换到下一行的第 1 列,若光标在最后一行则滚动视口。换行关闭后,光标停在末列,新字符在原位覆盖前一个 —— 这对状态栏和 TUI 在屏幕边缘精确绘制(避免意外滚动)非常有用。「幻影列」行为是 DECAWM 开启下的特性:把字符写入末列时,光标处于延迟态(视觉上在第 N 列,但下次写入会触发换行而非覆盖),让终端在滚动前多出一列容量 —— 这是无数 TUI 差一错的根源。

模拟器间的可移植面异常一致,因为 DECAWM 是最古老的 DEC 模式之一 —— Linux console / fbcon 实现,ConPTY 1809+ 转发(ConPTY 之前的旧 cmd.exe 把 ?7l 视为空操作且始终换行),Apple Terminal.app / iTerm2 / kitty / alacritty / wezterm / gnome-terminal / Konsole / Ghostty / Windows Terminal 都实现两种状态。陷阱在 wrap-at-eol-confusion pitfall:许多 TUI 库在客户端跟踪光标位置时,会在终端实际换行*之前*一列就*预测*换行(因为前述幻影列行为),与终端关于光标位置的认知不一致 —— 表现为绘制的字符出现在错位的一行上,全屏 TUI 右下角尤其明显。客户端 TUI 代码的修复方法是:要么在引发该问题的写入后用 DSR \x1b[6n 查询光标位置,要么在边缘精确绘制期间设 ?7l 并依赖显式定位。tmux 按 pane 遵守 DECAWM;screen 4.x5.0 都遵守,但若中间发生外层终端 resize,每个窗口的状态在 detach / reattach 间不一定能正确往返。

使用 \x1b[?7l 关闭、\x1b[?7h 恢复。把终端交还给用户之前务必恢复 —— 否则用户的 shell 提示符与命令行编辑器会表现异常(长行明显被截断,readline 的光标计算与显示位置不一致)。健壮模式是 XTSAVE / XTRESTORE(\x1b[?7s / \x1b[?7r),让退出时的状态匹配父进程原状,而非无条件开。DECAWM 还与 DECOM(?6 —— origin mode,控制光标坐标参考是全屏还是滚动区域)以及 DECSTBM(CSI r —— 设滚动边距)相互作用:在 DECOM 也激活时,边缘换行是在*滚动区域内*换行。相关:alt-screen(TUI 进入 alt-screen 后通常切到 ?7l 做边缘精确绘制)、cursor-position(CUP —— 幻影列绊倒你时替代客户端位置预测)、dec-origin-mode(与 DECAWM 联合决定真实换行边界的 DECOM 模式)。

规范出处: xterm-ctlseqs (DEC Private Mode 7, DECAWM)

示例

bash
printf '\033[?7l'   # disable wrap for status bar\nprintf '\033[?7h'   # restore
python
import sys; sys.stdout.write('\x1b[?7l')
go
fmt.Print("\x1b[?7l")
javascript
process.stdout.write('\x1b[?7l')
c
printf("\x1b[?7l");

在哪里用到

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

  • cat, less long-line behaviourDECAWM 打开(`\x1b[?7h`,默认)时长行在右边距换行;`less -S` 切换到水平滚动模式,对可见行而言语义等价于关闭 DECAWM
  • vim, neovim `:set wrap` / `:set nowrap``textwidth` 与 `wrap` 与 DECAWM 互动 —— `nowrap` 依赖终端在右边距的 DECAWM-off 行为,让编辑器自身的水平滚动接管
  • tput rmam / tput smam`tput rmam` 发 `\x1b[?7l`(关自动边距 / DECAWM reset),`tput smam` 发 `\x1b[?7h` —— 用于绘制定宽表格的 curses 脚本,不希望第 N 列的杂字触发隐式换行
  • column, pr, fmt fixed-width output按列对齐的输出假设 DECAWM 打开(默认)且终端遵守右边距换行 —— 超长行优雅地降级到新行而非截断
  • GNU readline / bash line-editingreadline 跟踪 DECAWM 状态以计算提示符换行点;判错会让换行后光标落到错误行(经典的 `\[ \]` PS1 转义 bug 即源于此)

常见问题

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

DECAWM 启用时,为什么 TUI 的列有时会错位一格?
「幻影列」问题。?7h 下(默认),把字符写到末列时*不立即*换行 —— 终端把光标置于延迟态,*下一次*写入才触发换行。可见光标在第 N 列,但下个字符落到下一行的第 1 列。客户端追踪光标位置的 TUI 库常常提前一列预测换行,与终端的认知不一致。修复方法:(a) 在靠近右边距的写入后用 DSR \x1b[6n(见 csi-dsr)查询实际位置,或 (b) 在边缘精确绘制期间切到 ?7l 并用 CUP 显式定位,交还控制权前恢复 ?7h
程序退出时把 \x1b[?7l 留作设置安全吗?
不安全 —— 永远别让 wrap-off 作为退出状态。用户的 shell 提示符、基于 readline 的命令编辑器、less / man 都会行为异常:长输入行在右边距处视觉截断,而 readline 的光标计算继续推进,造成经典的「输入掉出屏幕」症状。务必在终端恢复的 atexit / 信号处理器里恢复 \x1b[?7h(或用 XTSAVE / XTRESTORE 对 \x1b[?7s / \x1b[?7r 还原父进程原状)—— 含 SIGINT、SIGTERM 与崩溃路径。健壮模式:启动时 \x1b[?7s 保存、期间设 \x1b[?7l、退出时 \x1b[?7r 恢复。与恢复 ?25(光标可见性)、?1049(alt-screen)、?1000+(鼠标模式)天然配对 —— 是完整的 TUI 退出卫生检查表。

终端支持

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

相关序列