需求
macOS 版的 Things 3 中自带了一个「Add to Things」的服务,可以把选中的文字作为任务存入 Things。也可以运用 LaunchBar 的快速发送到这三个服务上,以把文字保存至对应的任务管理工具。但这个服务功能存在的一个问题是,无法将多行文字保存成多个任务,即把每一行文字创建成一个任务。
例如,我想要把下面这个网页中列出的前十名电影在 Things 3 中创建为任务:
如果点击通过右键菜单选择服务,效果如下所示:
如果使用 LaunchBar 把所选的文字快速发送(Instant Send)此服务,效果如下所示:
如果你想要把这十个电影保存成十项任务,则需要对每一行分别进行一次保存,非常繁琐,如果是把这一百部电影全都存入你的观影表单,那可能就应该直接完全放弃了。
同样,OmniFocus 和系统原生的备忘录(Reminders)也有类似的服务,但都不支批量导入任务,从下图出可见:与在 Things 3 中相同,这十个条目也被 OmniFocus 和备忘录分别创建成了一项任务:
面对这样的重复出现的操作,我们都可以把它交给电脑自己来做,我为这三个软件分别做了一个简单的 LaunchBar 的 Action,点击名称即可下载:
它们的使用效果如下所示:
Things:
OmniFocus:
备忘录(Reminders):
制作方法
如果你对这三个动作的制作方法不感兴趣,可以跳过此节。
这三个动作的原理都相同:先把获取的文字逐行拆分,再在程序中依次把每一行文字创建成一项任务。
对于第一步,字符串的处理,使用 Python 非常方便;对于第二步,以上的三款软件都对 AppleScript 有比较完善的支持。所以我们选择 Python 和 AppleScript 来完成这些动作。
以动作 Add List to Things 为例。首先,在 Action Editor 中新建一个动作,命名为「Add List to Things」:
上图 General 标签页中的各项内容之后再填写。先在 Scripts 标签页中,分别勾选下图中的几项:
Run in background
Requires argument
Accepts string argument
接着从右上方的下拉菜单出选择 Python,按右面的 Edit 按钮。在打开的文本编辑器中粘贴入如下内容,其中「# ↓注释:」是对下方代码的解释,可以删除:
import sys
import subprocess as sp
import os
my_env = os.environ.copy()
# my_env["PATH"] = "/usr/local/bin:" + my_env["PATH"]
# ↓注释:计数器,用于计算任务数量
n = 0
# ↓注释:argv 是一个列表,第 0 项为脚本路径,第 1 项起是 LaunchBar 接受的一组/多组文本
# ↓注释:依次对每一组文本进行操作
for arg in sys.argv[1:]:
# ↓注释:把每一行拆分开,组成一个列表
todos = arg.split('\n')
# ↓注释:依次对每一行文本进行操作
for todo in todos:
# ↓注释:删除此行文字前后的空白字符
todo = todo.strip()
# ↓注释:如果此行文字不是空的
if todo != "":
# ↓注释:创建在 Shell 中运行 AppleScript 的命令
# ↓注释:其中 into_Things.scpt 是调用的 AppleScript,作用是把文本在 Things 中创建为任务
my_command = ["osascript", "into_Things.scpt", todo]
# ↓注释:计数器加 1,表示新加入了一条任务
n += 1
# ↓注释:运行上面创建的 Shell 命令
sp.check_output(my_command, env=my_env)
# ↓注释:创建在 Shell 中运行 AppleScript 的命令
# ↓注释:其中 notification.scpt 是调用的 AppleScript,作用是在完成所有任务的创建后弹出通知
my_command = ["osascript", "notification.scpt", str(n), todo]
# ↓注释:运行上面创建的 Shell 命令
sp.check_output(my_command, env=my_env)
复制粘贴后保存退出。
接着在 Action Editor 的当前标签页(Scripts )最下面选择两次 New Script,输入上面代码中调用到的两个 AppleScript 的文件名:
into_Things.scpt
notification.scpt
按右边的 Edit 按钮在脚本编辑器中打开第一个脚本 into_Things.scpt,粘贴如下内容,用于把输入的文本在 Things 中创建为任务:
# ↓注释:argv 是此脚本接受的文本,即任务名
on run argv
tell application "Things3"
set newToDo to make new to do ¬
with properties {name:item 1 of argv}
end tell
end run
其中的 Things 3 的 AppleScript 语法可在其官方文档中查阅。 保存退出脚本编辑器,接着打开第二个脚本 notification.scpt,粘贴如下内容,用于弹出通知提示任务创建完成:
on run argv
set nr to item 1 of argv
set news to ""
if nr = "0" then
# ↓注释:如果未创建项目,提示如下:
set news_title to "Nothing added!"
else
if nr = "1" then
# ↓注释:如果创建了一个项目,提示如下并显示项目内容
set news_title to "A Task added!"
set news to " " & item 2 of argv
else
# ↓注释:如果创建了多个项目,只提示任务数量
set news_title to nr & " Tasks added!"
end if
end if
display notification news with title news_title
end run
保存并退出脚本编辑器,就完成了这个动作核心功能的部分了。
最后在 Action Editor 的 Resources 标签页中加入 Things 3 的图标图片,并在 General 标签页中填入这个图片的文件名,这个动作就完成了。
对于 Add List to OmniFocus 和 Add List to Reminders 两个动作,则只需把第一部分的 Python 代码中调用的第一个 AppleScript 的文件名分别改为「into_OF.scpt」和「into_Reminders.scpt」。再在这两个文件中分别粘贴入如下内容:
into_OF.scpt:
on run argv
tell application "OmniFocus"
tell default document
parse tasks into it with transport text item 1 of argv
end tell
end tell
end run
into_Reminders.scpt:
on run argv
tell application "Reminders"
set newremin to make new reminder
set name of newremin to item 1 of argv
end tell
end run
由上可见,针对不同的任务管理软件,只需对第二个脚本进行根据不同软件提供的 AppleScript 语法进行简单的修改,再在第一个脚本出把调用的第二个脚本的名称进行相应修改即可。可以说非常方便了。
iPhone 和 iPad
我的 iPad 上没有购入 Things 3, 但由于可以在其它设备的 Things 上直接把备忘录中某个列表的任务一键导入,因此我也把上面的 Python 脚本稍微修改之后用在了 iPad 上的软件 Pythonista 中,也可以实现把在任意软件中选择的文本批量创建成为备忘录中的任务,操作效果如下:
此时在 iPhone 上打开 Things,可以在 inbox 中直接把这些任务导入:
也可以在 Mac 上进行相同操作,打开 Things 导入任务:
Pythonista 的脚本请点击下载:
其中 Add List to Things 和 Add List to OmniFocus 向软件中创建任务是通过两者提供的 URL Scheme 实现,由于这些 URL Scheme 的功能限制,在脚本运行时会跳转至 Things 或 OmniFocus 中,需要用户对每一条新创建的任务进行确认。