前言

最近正在使用 Warp 作为常用的终端,有一些细节体验做的真的很不错,无论是命令提示还是补全都很厉害。其中有一个细节我认为对于我来说非常实用,就是长时间执行完成之后的命令提醒。

举个例子🌰:当你在终端进行 make 编译或者打包镜像的时候,往往需要比较长的时间,而你一般不会一直等着它执行完成,而是执行完成之后就切到别的地方去工作(摸鱼)了,然后你无法及时知道命令执行完成了,而只能是不是过来看下执行情况。

而在 warp 执行命令完成之后,就有这样一个通知提醒,我就能时刻关注到命令什么时候执行完成了。

warp提醒

当然,这必须依赖于你使用 warp,但我们常常在 IDE 下方的命令行中执行命令,而非单独使用其他终端,因为切换窗口也比较麻烦。于是乎我就想,能否利用 zsh 来实现这个功能呢?

实现

1
vim ~/.zshrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 设置要匹配的字符串
string_to_match=("docker build" "go build" "echo linkinstar")

# 定义函数
function remind_me {
# 获取上一个命令
previous_command=$(fc -lnr -1)

# 检查上一个命令是否包含要匹配的字符串
for string in $string_to_match; do
if [[ $previous_command == *"$string"* ]]; then
osascript -e 'display notification "命令已执行完成" with title "命令提醒" sound name "Blow"'
fi
done
}

# 添加add-zsh-hook
add-zsh-hook precmd remind_me
1
2
source ~/.zshrc
echo linkinstar

执行完成提醒

其实原理非常简单,就是通过 add-zsh-hook 的钩子,在执行命令之之前(当前命令执行结束)判断,上一个命令是否在我的匹配列表中,如果这个命令需要提示则使用 osascript 进行提示,其中通过 fc -lnr -1 获取上一个执行的命令。

使用者只需要在 string_to_match 数组中添加你需要进行提醒的命令就可以了,因为通常我们不希望所以执行的命令都有一个提醒,而只需要包含特定功能的命令的进行提醒就可以了。比如:只要包含 go build 字符的编译命令执行完成之后就进行提醒。

有关提示声音

其中,通知提示的声音可选项在 /System/Library/Sounds 目录下的文件名称,个人认为 Blow 还可以,其他声音有点小。当然如果你不需要声音提醒的话,去掉 sound name "Blow" 就可以了。

你还可以自定义声音,只需要将声音文件下载,并转换到 aiff 格式,并放到 ~/Library/Sounds 目录下就可以了,在脚本中只需要写文件名,不需要写后缀的 aiff
一般下载的格式是 wav,可以到 https://cloudconvert.com/wav-to-aiff 进行转换,当然网上有很多在线工具。

其他尝试与问题

  • 我尝试过通过判断上一个命令的执行时间比如超过 10 秒的命令就才进行提示,但实际使用效果并不好,有时候 9 秒的命令就很尴尬,所以还是认为指定具体命令效果更好
  • osascript 还支持 alert,但效果一般,需要手动确认,还是通知更加合理,虽然通知有时候会被忽略,但开启声音之后我觉得就很不错了
  • 你还可以尝试将命令的内容放到通知的内容里面,提示会更加友好,对于我来说现在的提示足够了,所以我就没做
  • 目前有一个小 bug,就是当使用完成一个命令之后,如果重新打开一个命令行窗口,就会有一个提示,这是由于打开命令行窗口 zsh 也会触发 add-zsh-hook,但好在问题也不大
  • 多个终端同时跑可能会有冲突,但目前还没有发现
  • 最后注意给到终端必要的通知权限