知道了也没什么用的小知识:终端标题与转义序列
起因
事情的起因是这样的,我在 archlinux (以下简称 arch) 下的端模拟器(以下简称终端)使用 set -x
来调试,发现每次按回车都会一条类似下面这样的输出:
++ printf '\033]0;%s@%s:%s\007' nanpuyue arch '~'
然后我手动执行了这条命令也看不到任何输出和变化,着实令人费解。
OSC 转义序列
一番查找过后在 /etc/bash.bashrc
中找到了源头:
case ${TERM} in
xterm*|rxvt*|Eterm|aterm|kterm|gnome*)
PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }'printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
;;
screen*)
PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }'printf "\033_%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
;;
esac
原来这条命令是输出特殊的转义序列,用来更改终端的标题,相关的信息可以查看这篇文档 XTerm Control Sequences。
其中一个表格有相关内容:
OSC 0 ST - yes yes set window and icon title
OSC 1 ST - yes yes set icon label
OSC 2 ST - yes yes set window title
OSC 3 ST - n/a yes set X server property
OSC I ST yes yes yes set icon to file
OSC l ST yes yes yes set window title
OSC L ST yes yes yes set icon label
总结起来就是我们可以用 \033]0;title\007
来设置终端标题,其中\033
也可以用 \e
代替,\007
可以用 \a
代替,\033]0;
换成 \033];2
也是可以的。
就像上面提到的文档中描述的一样,他们管这种转移序列叫 OSC (Operating System Commands) 转义序列。
deepin-terminal
大部分终端都是支持这种转义序列的,发行版们也一般会把这样的转移序列默认配置到 PS1
变量或 PROMPT_COMMAND
变量中,用来在终端标题显示一些信息。两者的区别在于 PS1
变量一条命令结束接受下一条命令的输入之前由 shell 直接显示出来的,而 PROMPT_COMMAND
中存储的是可以执行的命令,由 shell 在显示 PS1
之前执行。
我测试了 tilix 和 gnome-terminal,都是支持的,唯独我日常使用的 deepin-terminal 不支持,这也是我一开始手动执行命令那条 printf
命令没有效果的原因。
然后我扒了一下 deepin-terminal 的源码,原来之前老王自己实现了一套逻辑,默认情况下会将标题显示为当前目录名。代码中当 vte (deepin-terminal 也是基于 vte 的) 的 window_title_changed
信号会触发 deepin-terminal 更新终端标签的标题,上面提到的转移序列能都产生 window_title_changed
信号,仅仅是 shell 中的命令退出而不输出上述转移序列的话是不会产生 window_title_changed
信号的。
所以我把终端标题更新这里的逻辑改成了与 gnome-terminal 一样,遵从 OSC 转义序列设置的标题,如果用户想要自定义终端标题的更新方式,应该修改 PS1
或 PROMPT_COMMAND
变量。
诶。。。乔帮主也用Arch了?
嗯