← 返回所有文章

给 Mac 终端加 Shell Integration:当前目录、命令跳转与输出选中

Shell Integration 是「终端只是一块屏幕」和「终端理解你的命令」之间的分界线。这篇记录在 Mac 原生客户端里实现当前目录上报、命令间跳转、最近输出选中和 OSC 52 安全边界的过程。

判断一个终端是「一块会滚动的屏幕」还是「理解你命令的工具」,看它有没有 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 的完整功能清单和发布状态在 项目页。

感谢阅读。

继续探索更多文章 →