判断一个终端是「一块会滚动的屏幕」还是「理解你命令的工具」,看它有没有 Shell Integration 就够了。
Shell Integration 的本质,是 shell 在执行命令的间隙,通过 OSC 转义序列向终端上报结构化信息:当前目录是什么、一条命令从哪里开始到哪里结束、退出码是多少。有了这些信息,终端就从「显示字符」升级成「知道发生了什么」。
上报了什么,就能做什么
Docklark 这轮实现的 Shell Integration 覆盖了几件每天都会用的事:
- 显示每条命令的当前目录和退出码,跑完一眼看到成功还是失败
- 在前后命令之间跳转,长日志里找上一条命令不用肉眼扫
- 选中最近一条命令的输出,贴去别处不用拖拽瞄准
- 在确认终端主机与 SFTP 主机一致后,直接用 SFTP 打开终端当前目录
最后一条值得单独说:终端里显示的主机和文件面板连的主机,不一定是同一台。跳板机、嵌套 SSH 都会造成这种错位,所以打开目录前必须先确认,不能默认它们一致。
为什么 Zsh 自动、Bash 手动
Zsh 有 precmd 和 preexec 这样的钩子,注入集成脚本的位置是明确的,所以 Docklark 对本地 Zsh 自动启用。
Bash 则依赖 PROMPT_COMMAND 拼接,而这个变量几乎每个重度用户都改过。自动注入很容易和用户已有的提示符逻辑打架,弄坏别人的提示符是最失礼的事。所以 Bash 会话(以及不想自动注入的 Zsh 会话)保留手动启用:一条命令,只对当前会话生效。
OSC 52:最好用也最该默认关掉的能力
OSC 52 允许远端程序通过转义序列读写本机剪贴板。用它复制内容确实方便:在服务器上 cat 一个文件,内容直接进本地剪贴板。
但反过来,它也允许远端读取你的剪贴板,而剪贴板里可能正躺着密码、密钥或者内部链接。
所以 Docklark 把 OSC 52 的写和读拆成两个独立开关,都默认关闭。写入可以单独打开。读取永远默认关,而且每次读取都要单独确认。宁可多按一次确认,也不让远端悄悄拿走剪贴板。
一些踩过的坑
- 提示符重绘和终端历史重排必须分开处理,否则窗口缩放时未提交的命令草稿会错位
- 拖文件进本地终端时,插入的是经过 shell 引用的路径,而且不会自动执行,拖拽直接变成一条命令是老牌终端的经典事故
- 后台会话收到响铃时要有独立标记,切回去之前就知道哪个标签在叫你
这些细节单独看都小,但终端是每天盯八小时的东西,小细节的复利最大。Docklark 的完整功能清单和发布状态在 项目页。