PopClip 插件
关于 PopClip,其实很早就安装了,但一直没有找到很好的运用场景。最近终于正式用上了,顺手写个 Extension 玩玩。
环境信息
PopClip: 2019.10(3032)
PopMaker: 0.3 (10)
顺便扯点别的。很久没更新博客了,实在是太忙。每天很多繁杂的事情需要处理,而且很多事情,转头就忘,所以我一直在和 TODO List 作斗争,尝试过相当多的 TODO 类 App,也自己写过。最近终于找到一个比较 smooth 流程。当然,我会单独拿一篇博客来写(年底了,冲一波量)。
如果有人点进这篇博客,但还不知道 PopClip 是什么,那么可以把它理解为是 macOS 文字选中增强的 App。功能看下面这张图应该就明白,对于选中的文字,可以加一些操作啥的(是的,比如加到 TODO List)。
官方有一些很不错的 Extension,可以下载尝试一下,文末也会介绍一些。
目标
先来明确一下最终要做个什么东西吧。痛点和平时的开发流程有关,比如有一个 Crash,需要通过这个 Crash 的链接,自动创建一个 Jira 单。所以列了一下步骤以及优先级(P0-P2,P0 最高):
- [P0] - 在选中链接的时候,弹出 PopClip,点击能请求到 Crash 的 Title、版本号等基本信息
- [P0] - 创建完后,返回 Jira URL
- [P0] - 支持用户填写自己的 Jira Token
- [P1] - 支持修改/新增自动获取到的信息。比如需要填写对应的 QA,或者 Bug 引入原因等
- [P1] - 支持不使用链接触发(因为不是每个 Bug,都有 Crash 链接。可能是一个普通的体验 Bug,或者 UI Bug,顺便能复用,支持快速提单)
配置介绍
PopMaker
这篇文章不是用来介绍插件使用的,而是插件开发。首先需要下载 PopMaker,见名知意,就不说了(看完文章,就明白这个 App 不是必须要下载的,它只是将输入生成了一个模板,既然是模板,复制粘贴也是一样的,所以熟悉以后就不用了)。
是的,界面很丑,但就像官网说的:It’s ugly right now, but it works,管它呢,好使就行。主要介绍一下各个参数吧:
名称 | 描述 |
---|---|
Author | 作者 |
Extension name | 插件名称。这个名称是点击 PopClip 窗口,展现 Extension 列表的时候展示的(即配置页面),不会在选中 text 的时候展示(我们把这个操作叫做 pop 吧) |
Description | 描述 |
Menu title | 这个就是 pop 展示的 Title 了,如果选择了 icon,那么 pop 的时候,会直接展示 icon。icon 最好是大于 256*256 的 PNG 图片,并且图像是黑色,背景色透明。最后再 pop 上看到的图片,会处理为白色;在配置页面,展示的是原图 |
Extension Type-Surround | 环绕式。这种就是对选的 text 做处理。选择这个类型,会多出两个输入框:[Text before] [selection] [Text after] 。讲真最开始我真的没看懂,上手试了一下,原来是指:- [seletion] : 选中的文本 - [Text before] : 要在选中文本之前拼接的文字- [Text after] : 和 before 对应,就是在之后拼接。官网提到可以用来格式化 Markdown,比如要给某个 text 加粗。 [before] 和 [after] 都填 ** 就可以了,这样 text 前后就加上了 `** |
Extension Type-Search | 链接式。直译是搜索,但其实他的功能其实是支持自定义链接,选中的参数会以 ${query} 传入。官网提到,这里的 URL 可以是 URL Scheme,所以如果知道某个 App 的 scheme,能直接用来操作 App。比如给印象笔记新增一个 Note(我用的 Bear,所以直接贴 Bear 的 scheme 吧) |
最后就是保存和安装,保存每次会有一个「询问是否安装」的弹窗,可以关掉:
defaults write com.pilotmoon.popclip LoadUnsignedExtensions -bool YES |
在 Debug 的时候,如果想要输出到控制台,可以执行:
defaults write com.pilotmoon.popclip EnableExtensionDebug -bool YES |
点击安装以后,可以在 ~/Library/Application Support/PopClip/Extensions 中找到 xxx.popclipext 文件。这个文件是打包以后的,右键 Show Package Contents 能看到一些文件(比如 Config.plist),后面再提。
支持的事件
具体可以看 PopClip-Extensions,不得不说,这个地址藏得是真的深,至少在官网上一眼看不到,README 的内容比较干,可以学习一下。其中提到几种事件,这里事件意思是能通过 PopClip 触发的事件。
Service
很多 App 都支持一些 Service,比如 Finder 支持 Reveal in Finder,或者官方文档提到的 Make Sticky,可以将选中的文字添加到系统便利贴。Service 的配置体现在 Config.plist 的 Actions/Service 字段里。
如果想自己新增一个 Service 的 Action,比如选中路径,用 Finder 打开。那么需要先知道 Finder 都有哪些 Service 提供:
- Service 存储在:~/Library/Caches/com.apple.nsservicescache.plist 中
- 在一级目录里面的
ServicesCache
可以找到对应的 App,比如 Finder 叫 /System/Library/CoreServices/Finder.appservice_dicts
的NSMenuItem
的值就是 Finder 所支持的 Service。可以看到 Reveal in Finder 的 Service name 叫Finder/Reveal
。改改 Config.plist 就可以了
在 Service 列表中,还能看到一些 Workflow,或者自己没有装的 App。这些有可能是安装某类 App 的时候自动安装的。比如 iTerm2 会自动装 New iTerm2 Tab Here 的 Service。所以 Service 是可以自定义的,详见 Automator 文档,如果以后有机会,我另写一篇。
AppleScript/Shell Script
文档中是两个 Action,但我觉得这是一类:自定义脚本。他们区别在于…他们没啥区别,只是 Config.plist 中指定脚本的方式不同,但最后都是执行自定义的脚本(🌰 BBEdit,Say)
// AppleScript:AppleScript File 后面放脚本名 |
URL
类似于之前提到 Search,触发一个 URL(🌰 GoogleTranslate)。
Keypress
触发物理按键。比如触发 Delete,物理按钮的映射可以看这个。目前想到关于这个 Action 的操作比较鸡肋,除了触发 Delete、CMD+C 这类的按键,应该还能触发某个 App 支持的快捷键(没有实操过),但都不是很好,希望各位可以分享一下。
Config.plist
Config.plist 是插件中的非常重要的文件,包含了所有的配置。配置项最好直接看文档,这里直说一些比较有意思的。
key | value |
---|---|
Required Apps | 仅在某些 App 中展示这个 pop |
Regular Expression | 仅在满足正则的条件下,展示这个 pop。比如给特定的链接加 xxx 功能 |
Stay Visible | 不自动消失,而是在点击以后消失 |
Long Running | 会展示一个 Loading,用于执行时间较长的脚本。比如网络请求这类的 |
Actions/Before | Actions 中可以设置 Before/After 的 key,类似于钩子,会在执行 Actions 前后自动执行指定的操作 |
Options | 提供给用户配置的窗口,后面会介绍到 |
文档的 Script Fields 部分约定了环境变量,比如选中的文本,会赋值给 POPCLIP_TEXT
。
开始写吧
再重新看一次需求,还不确定所有功能 PopClip 都支持,尽量实验。优先级由核心功能 → 自定义配置,逐级递减:
- [P0] - 在选中链接的时候,弹出 PopClip,点击能请求到 Crash 的 Title、版本号等基本信息
- [P0] - 创建完后,返回 Jira URL
- [P0] - 支持用户填写自己的 Jira Token
- [P1] - 支持修改/新增自动获取到的信息。比如需要填写对应的 QA,或者 Bug 引入原因等
- [P1] - 支持不使用链接触发(因为不是每个 Bug,都有 Crash 链接。可能是一个普通的体验 Bug,或者 UI Bug,顺便能复用,支持快速提单)
[P0] - 获取 Crash 基本信息并创建 Bug
创建 PopClip 插件前面说了很多,就不单独说了。我选择的是自定义脚本,语言是 Ruby。考虑到兼容性问题,选择 Ruby2.3 API,并且所有都用原生调用,避免依赖环境有问题。
当前插件目录结构与 Actions:
// - Config.plist |
由于涉及隐私,外部调用只有封装的方法,里面就一堆请求,不是重点:
#!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby |
因为里面包含了多个请求,并且部分请求之间有先后顺序,耗时大概在 2s 左右。所以加了一个 Long Running 的参数:
<key>Long Running</key> |
[P0] 支持用户填写自己的 Jira Token
可以看到,在之前的脚本中,author
这个字段是写死的,这样就没办法共用,需要找一个地方配置自定义参数。对于这个需求来说,有两个输入框:邮箱 + Token。其实这类需求很常见,另一种表现形式是三方登录或鉴权,比如通过 Google 登录等。
这里会用到之前 Config.plist 结构略过的 Options
参数,结合需求来看下文档:
Key | Value |
---|---|
Option Identifier | 唯一标识(注意小写)。可以理解为每个输入框的 key,比如这里叫 name 和 jira 。后续脚本中,可以用 POPCLIP_OPTION_NAME 读取输入框内容(AppleScript 为全小写)。 |
Option Type | 输入类型。支持三种:string/boolean/multiple。分别对应:输入框/勾选框/下拉框 |
Option Label | 描述。用于补充说明。比如「Token 可以在 xxx 获取」 |
Option Default Value | 默认值(可选)。 |
Option Values | 下拉框需要提供的选项。 |
除了 Options 的配置以外,发现很有必要介绍两个 undocument 的东西:
status code
文档在 Script Returning Result 中,简单介绍脚本的 Status Code 的含义(即 exit 0/1/2
):
- 0:没有错误
- 1:通用错误码
- 2:预置错误码。如果配置了
Options
,这种错误码会重新执行一次Options
,也就是重新弹窗 - 4:等待回调。三方登录这类操作,需要等待用户授权和三方平台回调。这种情况需要触发一个 Loading(和 Long Runing 的 Loading 不同,这个 Loading 会在 PopClip 的 StatusBar 上),等回调以后,再继续执行脚本(文档没有写这个错误码,可以参考 Trello 的 auth.py)
Options After/Before
在 Trello 的 Config.plist 中,有两个文档中没有的参数:
<key>Option Available After Auth</key> |
结合 Trello 安装后的操作流程,来解读一下这个配置(下面是 Trello 的配置,有删改):
// Trello 安装后: |
左边:控制先后顺序;右边未控制
对于创建 Bug 这个需求来说,流程和解决方案为:
- 没有登录逻辑,只需要提醒用户配置。所以新增
Options
配置,包含两个输入框; - 执行创建逻辑前,先验证是否有设置过 name 与 token,如果没设置,通过
exit 2
,重新触发弹窗 - 如果验证通过,则直接用 name 和 token 创建 Bug
这里没有处理 name 和 token 合法性的校验,有必要可以加上。Options
和 Trello 的类似,就不贴代码了,参数校验为:
prefix = ENV['POPCLIP_OPTION_NAME'] |
最后
最后还剩余两个 P1 的需求:
- 支持修改/新增自动获取到的信息:PopClip 在参数修改上不是很灵活,比如不能给人员名单,下拉筛选。最终决定在创建成功后,跳转至 Bug 详情。
- 支持不使用链接触发:用文字触发,只是少了解析 Crash 信息,基本流程一致
除此之外,还有选中特定链接的情况下,才展示插件等细节还没处理,再说吧。真的被 PopClip 坑好多,本来加上博客几个小时就能搞定的,结果写了大半天,先缓缓。
一些实用的插件分享,会不定期更新(也可能不会更新)。官方 Repo 里有各种插件源码,很多作业可以抄。