【090】15周 如何向 Things、OmniFocus、Reminders 批量添加任务

契丹神童
2017年12月07日

如何向 Things、OmniFocus、Reminders 批量添加任务

| 本文为付费栏目文章,您已订阅,可阅读全文 |

需求

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 OmniFocusAdd 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 ThingsAdd List to OmniFocus 向软件中创建任务是通过两者提供的 URL Scheme 实现,由于这些 URL Scheme 的功能限制,在脚本运行时会跳转至 Things 或 OmniFocus 中,需要用户对每一条新创建的任务进行确认。

上一期
不一定要 PPT,Paste 让你三分钟做出好看好用的幻灯片 | 工具推荐
下一期
MarsEdit、Paper 53、Yoink、Screenshot Maker Pro | App 奏折 015
 
精选评论(3) 我的评论
  • 李曦鹏(Xipeng Li)
    Alfred里面不支持设置其他scpt为环境。因此直接使用subprocess在python中调用。

    #!/usr/bin/env python

    import sys
    import subprocess as sp
    import os

    my_env = os.environ.copy()
    my_env["PATH"] = "/usr/local/bin:" + my_env["PATH"]

    into_OF = '''
    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
    '''

    notification = '''
    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!"
    else
    set news_title to nr & " Tasks added!"
    end if
    end if
    display notification news with title news_title
    end run
    '''

    n = 0

    # Note: The first argument is the script's path
    for arg in sys.argv[1:]:
    todos = arg.split('\n')
    for todo in todos:
    todo = todo.strip()
    if todo != "":
    args = [todo]
    p = sp.Popen(['osascript', '-'] + args, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, universal_newlines=True)
    p.communicate(into_OF)
    n += 1

    args = [str(n), todo]
    p = sp.Popen(['osascript', '-'] + args, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, universal_newlines=True)
    p.communicate(notification)
    05月14日
  • 盐没完
    最近正好在 iOS 上做了一个 [「向导式添加 Omnifocus 任务」](https://workflow.is/workflows/6cc98a2601e54d98967671ec90ff6448) 的 Workflow 里面也考虑到了多行批量添加。
    虽然是针对我的使用情境,但应该也可以供大多数人参考。

    这个 Workflow 的主要思路:
    * 以 Today Widget 或 Action Extension 形式启动
    * Action Extension 启动接受任何内容,检测内容类型,如果是文本就作为标题,如果不是则作为附件。
    * 对于 Today Widget 启动或没有接收到文本的情况,提示输入文本。
    * 对于收到或输入的文字,以每一行为单位进行分项处理。
    * 根据我 对 Omnifocus 的组织,项目分在几个目录,由于系统限制无法获取项目列表,但目录是相对固定的,所以我会给每个项目起一个 2-6 个字容易记忆的短名,然后每个项目添加会用列表形式询问那个目录,然后手动输入项目短名,通过这种折中方法效率还是有一定保证。
    * 对于其他杂项,我增加了一个判断直接添加到项目。如果大家的大部分项目都是固定的,可以全部参照这个杂项做成 List,这样就可以避免手动输入了。
    * 另外,可以根据需要,加入对于旗标、推迟时间的向导式输入
    这里再多说几句,虽然「标准」 GTD 的流程当中「收集」和「整理」是分开的,但出于个人使用习惯和任务性质,往往会希望在收集时就将任务的基础信息填写好,而对于相对成熟的使用体系来说,向导式输入可以大大节省「整理」时间提高效率。
    另外,即使按「收集」和「整理」分开的流程,也可以更方便的实现整理,比如可以把收集这件事情交给 Drafts 来做,每个任务另起一行,等到需要整理的时候统一发送到 Ominfocus ,然后通过向导式操作集中批量整理每一个任务。
    2017年12月08日
  • mieq
    这两周的 Power+ 都挺不错啊,特别喜欢Hum、Minja还有神童的文章
    2017年12月08日 1