注:视频内提到的脚本和代码,在文章中附有相关连接。此外,文章的内容相比视频更完整丰富。


和 Mac 平台的 AppleScript 相比,无论是通过 URL Scheme 或是快捷指令,OmniFocus for iOS 上的自动化始终显得不那么 「Pro」,让 power user 感觉有些隔靴搔痒。

终于,在上架一年半之后,OmniFocus 3.8 推出了基于 JavaScript 的自动化脚本 —— Omni Automation。第一次,OmniFocus for iOS 将拥有和 Mac 版一样的深度定制可能性。

关于应用脚本和 Omni Automation 可以聊的话题非常多,这次我们将专注于最基本也最重要的两点:

  1. 怎么在 macOS 和 iOS 上使用 Omni Automation 脚本?
  2. 相比 AppleScript、快捷指令和 URL Scheme,Omni Automation 有无过人之处?值不值得花时间深入研究?

Omni Automation 的安装与使用

每一种应用脚本都有特定的使用方式:快捷指令是以功能模块为基本单位进行组合,在快捷指令应用中使用;URL Scheme 是将应用提供的接口编写成一条 URL ,然后在可以执行 URL Scheme 的应用(例如 Launch Center Pro)中启动;而 AppleScript 则是需要编写独立的脚本文件。

每种方式都有它的应用场景和局限,而 Omni Automation 则是「通吃」了这三种使用方式。它既可以像 AppleScript 一样,以脚本文件的形式使用;也可以像 URL Scheme 一样,以「Omni Automation URL」的形式,插入 AppleScript 甚至 HTML 中。由于 Omni Automation 其实就是 JavaScript 代码,于是也可以在 Automator 中,调用相关模块,借此运行 Omni Automation。

以脚本文件的形式使用

无论是 macOS 还是 iOS 上,将 OmniFocus 升级到 3.8 版本(专业版)后,就会发现独立的 Omni Automation 入口。

macOS & iOS 上的 Automation 菜单

在 Mac 版的 Automation 窗口中点击 +,就能创建新的脚本文件。不过更节省时间的办法,是根据自己的需求,从网上直接下载脚本文件,例如 OmniFocus 官方网站上,就提供了 50 多个脚本。

在官网下载脚本文件并解压缩后,可能会发现存在两种文件类型,后缀名分别是.omnijs(例如 Create Packing List for Trip 脚本)和 .omnifocusjs (例如 Plug-In Template 脚本)。

macOS 上的安装

不论 .omnijs 还是 .omnifocusjs 文件,安装方式是一样的。在 macOS 中,右键点击文件,选择「打开方式」为 OmniFocus;在 iOS 中,长按文件后会弹出菜单,选择「共享 - 在 “OmniFocus” 中打开」。

iOS 上的安装

打开文件后会弹出安装窗口,此时要注意选择脚本的存储位置。因为 Omni Automation 是可以同时运行在两个平台上,所以这里建议选择「OmniFocus in iCloud Drive」作为存储位置,以后任何脚本只用安装一次,就可以无缝同步。选择好存储位置后点击「Install Plug-In」,就完成了脚本的安装。

macOS 上运行脚本

Omni Automation 的使用非常简单。安装好的脚本,都会显示在 Omni Automation 窗口中,直接点击就可以执行,在 iOS 上还有专门运行的快捷窗口。

既然安装与使用方式一模一样,那么.omnijs 和 .omnifocusjs 这两种文件有什么不同呢?

在 官方文档中,将 .omnijs 称为 Plug-In,而 .omnifocusjs 则称为 Bundle Plug-In。其实简单地说,前者是一个文件对应一个 Omni Automation 脚本,后者就是多个脚本的集合。 Bundle Plug-In 会在 Omni Automation 窗口多一个层级,以供用户选择不同的脚本。

从文件属性上看, Bundle Plug-In 其实是一系列文件的组合,其中可以放入图片文件,作为脚本的图标,可以放入多个脚本文件。如果你使用 Plug-In 编写一个复杂的脚本, 只能将所有的代码放在一个文件中,从编程的角度来说是不推荐这么做的。而使用 Bundle Plug-In 的话,则可以将不同功能的代码拆分到不同的文件中,方便日后进行代码重构。

删除脚本文件

想要删除脚本文件,也非常简单。在 iOS 中的 Omni Automation 窗口中左划即可选择删除。或者直接在 iCloud 的 OmniFocus 文件夹中,删掉脚本文件即可。

以 Omni Automation URL 的形式使用

注:下文需要一定的 URL Scheme 基础知识,如果你对 URL Scheme 尚不了解,可以先阅读的《入门 iOS 自动化:读懂 URL Schemes》。

通过脚本文件,可以在 iOS 或者 macOS 版的 OmniFocus 中非常方便地管理、运行 Omni Automation,但是这一切都必须在 OmniFocus 应用中进行。有没有什么办法,在运行其他应用时,也能使用 Omni Automation 呢?

想实现「在一个应用调用外部应用的功能」的效果,在 iOS & macOS 平台上自然会想到 URL Scheme。实际上OmniFocus 的开发者也是这么想的,将 Omni Automation 的脚本代码写成 URL Scheme 格式,就变成了 Omni Automation URL。Omni Automation URL 可以在其他应用中启动,实现打开 OmniFocus 并运行脚本的效果。

以下面这行简单的脚本为例:

task = new Task("My Task")

官方网站上,提供了专门将脚本源代码翻译成 Omni Automation URL 的工具,将这行代码粘贴进窗口,选择「Encode Script」,就能得到相应的 Omni Automation URL。

Encode Script

使用 Omni Automation URL 的方式则和 URL Scheme 是一样的。 以 iOS 上的 Launch Center Pro 为例,创建新动作,将翻译好的脚本像普通 URL Scheme 一样写进「URL」一栏中即可。点击尝试运行,就能看到 OmniFocus 已启动,并询问是否执行脚本。

在 Launch Center Pro 中运行

看到这里可能会有些疑惑:OmniFocus 本来就是支持 URL Scheme 的,为什么要发明 Omni Automation URL 这个新概念呢?

我们回头仔细看一下刚才的 Omni Automation URL:

omnifocus://localhost/omnijs-run?script=task%20%3D%20new%20Task%28%22My%20Task%22%29

对照 OmniFocus 给出的 URL Scheme 官方文档,会发现 localhostomnijs-run 动作以及 script 参数都没有在文档中提到过。 同时观察 Omni Automation URL 的运行过程,点击运行 URL Scheme 后,一般会直接完成动作,而 Omni Automation URL 则停在了询问窗口。由此我们不难推理出:Omni Automation URL 是一条特殊的 URL Scheme,它的作用是向 OmniFocus 传递一段 Omni Automation 脚本,并申请执行。

和标准的 URL Scheme 相比,Omni Automation URL 不受文档中参数类型的限制,可以完全使用属于 Omni Automation 的 API,这无疑使得 Omni Automation URL 功能更加强大。

以源代码的形式使用

注:阅读这节需要一定 JavaScript 基础,如果发现阅读起来有些困难可以先跳过。

如果你理解了 Omni Automation URL,就会意识到它几乎完美地实现了「从外部应用运行 Omni Automation 的需求」。唯一的缺憾在于:一条 Omni Automation URL 的内容是提前编写好的,在应用中运行时无法修改。这又该如何解决呢?

回想一下编写 Omni Automation URL 的过程,我们先是写好代码,然后进行了一次编码,从而生成一条 Omni Automation URL。如果我们能在代码中留出空位,运行时填写需要的内容,然后再编码,就可以实现动态修改 Omni Automation URL 的目的。

而且由于 Omni Automation 使用的是标准的 JavaScript 语法,所以在任何支持运行 JavaScript 的应用中,我们都可以使用 Omni Automation。我们就以 macOS 上的 Drafts 为例来演示。

在 Drafts 中运行

在 Drafts 中创建一个新动作,加入「Script」步骤以运行 JavaScript。然后将这段代码粘贴进去:

(() => {
	// 定义动作
	function addNewTask(stringsArray){
		task = new Task(stringsArray)
	};

	// 读取 Drafts 当前文本
	const stringsArray = editor.getText();
	
	// 运行 Omni Automation URL
	app.openURL(
		'omnifocus://localhost/omnijs-run?script=' +
		encodeURIComponent(
			'(' + addNewTask + ')' +
			'(' + JSON.stringify(stringsArray) + ')'
		)
	);
})();

这段代码分为三部分。第一部分定义了函数 addNewTask,可以看到,其中的语句完全与 Omni Automation 脚本中一样。这个函数与接受一个文本 stringsArray,并以它为标题,在 OmniFocus 中创建一个新动作。第二部分则是在读取 Drafts 中当前的文本内容。第三部分则是将前两部分结合起来,再编码成 Omni Automation URL。

现在你就可以先在 Drafts 中写下动作的名字,再运行这个动作,就会看到像运行 Omni Automation URL 一样,在 OmniFocus 打开脚本窗口,然后创建一个新动作。

这个例子虽然简单,但已经完全实现了我们的需求。相比直接运行编码好的 Omni Automation URL,使用源代码运行 Omni Automation 无疑会更加灵活。不仅是 Drafts,其他应用(例如 macOS 上的 Automator),只要能运行 JavaScript 脚本,就能将 Omni Automation 与之结合起来使用。

Omni Automation 值得我们花时间去学习吗?

作为老牌的 macOS/iOS 开发商,OmniFocus 在自动化脚本上非常完善。OmniFocus for Mac 支持 AppleScript,OmniFocus for iOS 上有 URL Scheme,在快捷指令应用中也支持不少动作。那为什么这次又要推出 Omni Automation 呢?

Omni Automation 最重要的特性,当然是跨 macOS/iOS 平台运行代码级脚本。AppleScript 是非常强大的脚本语言,几乎可以实现对 OmniFocus 任何精细操作,不过只能运行在 macOS 平台上,同时因为这个原因,它的推广度也一直不温不火。URL Scheme 其实也是可以同时运行在 macOS/iOS 平台的,但是受到它本身设计的限制,在功能丰富度上远远不及 AppleScript 和 Omni Automation。例如 Packing List Plug-In 脚本可以调用一个对话框,让用户选择日期,这样的功能 URL Scheme 是无法实现的。

用脚本调用对话框

所以相较于 AppleScript 和 URL Scheme,Omni Automation 同时做到了「跨 macOS/iOS 平台运行」与「代码级脚本」两点,让它可以兼备强大的功能和通用性。

其次值得注意的是,Omni Automation 的出现使得 OmniFocus 与其他自动化应用的交互变得更加方便。正如上文展示过的,OmniFocus Automation URL 可以任意插入其他应用中,例如 Drafts、Automator、快捷指令等。并且借着 JavaScript 的风行,OmniFocus Automation 可以以源代码的形式和其他应用结合起来使用,这一点哪怕是 AppleScript 也做不到。

作为代码级的脚本,「在 Omni Automation 中调用其他应用」的需求也可以很方便地实现,例如 Launch Chosen Shortcut 脚本就可以在 OmniFocus 选择预设好的快捷指令并运行。上文展示过从 Drafts 中调用 OmniFocus,其实反过来,通过 Omni Automation 从 OmniFocus 也可以抓取信息放进 Drafts。

可以说,Omni Automation 是非常值得我们花时间去深入研究。虽然相较于 URL Scheme 和快捷指令它的入门门槛更高,但是它能实现的功能会比两者丰富得多,相比同样功能强大的 AppleScript,它的应用场景又更加丰富。

要明白的是,学习 Omni Automation 就等于在学 JavaScript。可以看得出来,JavaScript 正在逐渐取代 AppleScript 的作用,成为专业用户的选择。一方面这是得益于 JavaScript 语言本身的风行,另一方面苹果也对 JavaScript 提供了技术支持。无论是 Omni Automation、Drafts 还是 JSBox,底层其实都是依赖苹果 JavaScriptCore 官方库。可以想象,会有越来越多的应用借助 JavaScriptCore 实现自动化,所以学习 Omni Automation 的经验,以后也可以应用于其他应用中。

从技术上看 Omni Automation 无疑是潜力巨大的,回到使用者角度,我们有必要去学习它吗?

不可否认的是,快捷指令这种图形化的自动化工具,还是会成为更主流的选择。它相较于 Omni Automation 的优势不言自明:平滑的学习曲线,官方加持下的开发力度,与其他应用的高度结合。也难怪苹果官方要收购它,使其成为第一方应用。但是回看 AppleScript 与 OmniFocus 的过往,可以预见围绕 Omni Automation 将形成一个「少数专业用户编写脚本,普通用户使用脚本」的社区。即使你没有兴趣编写 Omni Automation,学会使用和简单地修改脚本,就能让你赚回购买 OminFocus 专业版的钱。

> 订阅 OmniFocus 使用指南,教你搭建一套属于自己的任务管理系统 ⚙️

> 下载少数派 客户端、关注 少数派公众号,获取更多数码资讯 📱

> 特惠、好用的硬件产品,尽在 少数派 sspai 官方店铺 🛒