编写Emacs插件:修改osascript -e显示的OS X原生通知图标方法
解决Emacs插件中通过osascript自定义OS X通知图标的方案
好问题!我之前在开发Emacs通知相关工具时也踩过terminal-notifier的坑——虽然它功能全,但依赖安装的要求对普通用户太不友好了。下面给你几个无需额外依赖、直接通过osascript实现自定义图标的实用方案:
方案1:直接引用本地.icns图标文件
OS X的display notification命令支持直接指定本地.icns格式的图标文件路径,完全不需要bundle包。
示例AppleScript代码
display notification "这是来自Emacs的通知内容" with title "Emacs通知" subtitle "自定义图标测试" with icon file "/Users/your-username/.emacs.d/assets/emacs-custom.icns"
在Emacs中集成的写法
你可以用Emacs的函数把相对路径转成系统能识别的绝对路径,同时处理路径中的空格问题:
(defun my-emacs-notify (title content icon-path) (let* ((abs-icon-path (expand-file-name icon-path user-emacs-directory)) (escaped-icon (shell-quote-argument abs-icon-path)) (cmd (format "osascript -e 'display notification \"%s\" with title \"%s\" with icon file %s'" content title escaped-icon))) (shell-command cmd))) ;; 使用示例 (my-emacs-notify "编译完成" "你的代码已经编译成功!" "assets/emacs-custom.icns")
注意:图标文件必须是
.icns格式,如果只有PNG/JPG,可以用系统自带的sips命令转换:sips -s format icns your-icon.png --out your-icon.icns
方案2:直接调用系统应用的内置图标
如果不想额外携带图标文件,可以直接引用OS X系统中已安装应用的图标,比如Emacs自身的图标:
示例AppleScript代码
# 通过应用名称调用 display notification "内容" with title "标题" with icon application "Emacs" # 或者通过Bundle ID调用(更稳定,避免重名应用冲突) display notification "内容" with title "标题" with icon application id "org.gnu.Emacs"
在Emacs中集成的写法
这个方案更简洁,不需要处理文件路径:
(defun my-emacs-notify-simple (title content) (let ((cmd (format "osascript -e 'display notification \"%s\" with title \"%s\" with icon application id \"org.gnu.Emacs\"'" content title))) (shell-command cmd))) ;; 使用示例 (my-emacs-notify-simple "任务完成" "你的Emacs插件已经加载完毕!")
方案3:临时嵌入图标(进阶,不推荐日常使用)
如果必须把图标嵌入到代码中(比如不想让用户看到额外文件),可以把.icns文件转成Base64字符串,在osascript中解码并临时保存为文件后使用。不过这个方法比较繁琐,性能也不如前两个方案,只适合特殊场景:
set iconBase64 to "这里替换成你的.icns文件的Base64字符串" set tempIconPath to (path to temporary items as text) & "temp-icon.icns" do shell script "echo " & quoted form of iconBase64 & " | base64 --decode > " & quoted form of POSIX path of tempIconPath display notification "内容" with title "标题" with icon file tempIconPath do shell script "rm " & quoted form of POSIX path of tempIconPath
内容的提问来源于stack exchange,提问作者Petrosyan Alexander
相关产品推荐
相关产品推荐

