极具潜力的效率启动器 App,Raycast 脚本功能详解

效率启动器是一类工具的总称,主要方便通过键盘操作快速检索信息、开启应用、甚至完成一系列自定义工作流。Mac 上的 Spotlight 搜索实际上可以看作是系统自带的效率启动器,默认情况下你可以通过 ⌘ + 空格键 快速唤出,并执行文件搜索、天气查询、词典查询、计算器等一系列方便实用的操作。

Spotlight 词典查询

不过 Spotlight 正如它的名字一样,功能更偏重于搜索。相比之下,Mac 上最具代表性的第三方效率启动器 Alfred 和 LaunchBar 则拥有更强大的功能。特别是第三方效率启动器支持的脚本功能,能够实现大量的自定义操作。

Alfred 的脚本通过 Workflows 功能中的 Run Script Action 执行,支持 Bash、PHP、Ruby、Python、Perl、AppleScript 和 JavaScript 等多种语言。

Alfred Workflows 示例

同样,LaunchBar 也支持 Bash、Ruby、Python、Swift、AppleScript 和 JavaScript 等常用的脚本语言,并通过 Action Editor 进行管理。

Action Editor 界面

相比之下,Raycast 支持的脚本语言最少,目前只支持 Bash、Swift、AppleScript 等 3 种。对脚本语言支持较少是 Raycast 目前的劣势,但相比之下 Raycast 创建和管理脚本的方式最为简洁,入门成本最低。

创建脚本

使用 Raycast 创建一个脚本非常简单,没有 Alfred 和 LaunchBar 复杂流程和选项,只需要在 Raycast 中搜索 Create Script Command 命令即可。

通过命令新建自定义脚本

接下来,你会进入到创建脚本的引导界面。此时,需要选择脚本语言和运行模式,并输入脚本名称和脚本描述。界面中还有 2 个复选框,分别是运行脚本前需确认、以及脚本支持传入参数的选项。

自定义脚本模版初始化

点击右下角的 Create Script 创建并保存脚本。此时,非常建议大家在 iCloud Drive 或者你其它常用的云同步应用中新建一个名为 Raycast Scripts 的文件夹用于存放脚本。这会极大地方便你在不同设备之间同步创建的自定义脚本。

保存自定义脚本到指定目录

创建完成之后,使用编辑器打开相应的脚本文件,你会看到 Raycast 创建好的脚本模板。

#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Echo SSPAI
# @raycast.mode compact
# Optional parameters:
# @raycast.icon   

echo "Hello World!"

上面是一个简单的 Bash 脚本,通过 echo 命令支持打印出 Hello World! 字符串。其中,注释掉的部分是脚本配置项。其中包含参数:

schemaVersion
title
mode
icon

此外,Raycast 脚本还支持的配置参数有:

argument
needsConfirmation
packageName
iconDark
refreshTime
currentDirectoryPath
author
authorURL
description

运行模式

@raycast.mode 参数所支持配置的脚本运行模式是 Raycast 脚本功能中最为值得一提的特性,目前支持:

fullOutput
compact
silent
inline

默认情况下,Raycast 的脚本运行模式为 compact ,即在窗口下方显示运行状态和打印输出结果。例如上方的示例脚本采用 compact 模式执行之后的效果如下,呈现在左下角的小窗口是否简洁,同时还能展示较少的关键信息。

compact 模式显示效果

fullOutput 模式则适合脚本输出信息较多的情况,因为 compact 显示的信息长度有限。例如在一个支持 Ping 服务的脚本中,需要打印较多的信息,那么这些信息则会在单独的窗口中显示出来。

支持 Ping 服务器的自定义脚本

silent 模式很好理解,即脚本在后台静默执行,例如下面清空废纸篓 Empty Trash 的脚本中,我们不需要打印任何输出,只需要脚本执行即可。

silent 模式下不会展示任何输出

Empty Trash 的脚本源码如下:

#!/usr/bin/osascript

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Empty Trash
# @raycast.mode silent
# @raycast.packageName System
# Optional parameters:
# @raycast.icon   

# Documentation:
# @raycast.description Empty the trash.

tell application "Finder" to empty trash

inline 则直接在 Raycast 窗口中显示脚本输出信息。该模式下,我们不需要回车执行脚本,而脚本支持配置 refreshTime 参数支持固定频率刷新,并将输出信息缓存在 Raycast 界面中。

inline 模式直接在界面展示信息

例如上方显示系统 CPU 和内存占用信息的脚本中,代码配置了 5s 刷新一次。这种模式下,我们期望少量的信息直观呈现,而不需要多余的交互。

#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title System Activity
# @raycast.mode inline
# @raycast.refreshTime 5s
# @raycast.packageName Dashboard
# Optional parameters:
# @raycast.icon :chart_with_upwards_trend:

cpu_mem=$(ps -A -o %cpu,%mem | awk '{ cpu += $1; mem += $2} END {print "CPU: "cpu"% MEM: "mem"%"}')
echo "${cpu_mem}"

总之,Raycast 提供的四种运行模式各有适用场景:

fullOutput
compact
silent
inline

参数输入

Raycast 1.2 版本中,自定义脚本正式支持传入参数,这是里程碑式的特性。之前不能传参的脚本功能更为死板,没有可交互的能力。而支持参数输入之后,你就可以打造更多更有意思的脚本。

脚本传入参数的方式非常简单,只需要在脚本中添加参数配置项即可。例如上方演示的 Ping 脚本中,其支持通过参数输入需要 Ping 的域名或服务器地址,所以我们可以输入 sspai.com 测试相应的 Ping 值。

#!/bin/bash

# @raycast.title Ping
# @raycast.author Caleb Stauffer
# @raycast.authorURL https://github.com/crstauf
# @raycast.description Ping an IP address or URL.
# @raycast.icon :globe_with_meridians:
# @raycast.mode fullOutput
# @raycast.packageName Internet
# @raycast.schemaVersion 1
# @raycast.argument1 { "type": "text", "placeholder": "URL or IP address" }

ping -i 0.25 -t 3 "$1"

脚本代码中的 argument1 即为支持的第一个参数,而后方的字典配置项中支持定义参数的默认类型和占位提示信息。如果你的脚本需要传入多个参数,则可以使用 argument2 这样罗马数字递增的方式,添加更多的参数配置项目即可。

而在 Bash 脚本中,我们只需要使用脚本内获取参数的标准格式 $N 即可获取参数值。

Python 脚本

目前,Raycast 仅支持 Bash、Swift、AppleScript 等 3 种脚本语言。如今是全民学 Python 的时代,尚不支持如此「时髦」的语言有点说不过去了。

但实际上,只要我们的脚本能够通过命令行运行,都可以结合 Bash 采用曲线救国的方式来编写脚本代码,在 Raycast 脚本中运行 Python 代码自然可行。

例如上方的 Hello World 代码中,我们除了可以使用 Bash 支持的 Echo 命令直接打印信息,还可以结合 Python 来打印输出。

#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Echo SSPAI
# @raycast.mode fullOutput
# Optional parameters:
# @raycast.icon   

# 方法 1:使用 Bash 执行
echo "Bash: Hello World!"

# 方法 2:使用 Python 输出结合 Bash 执行
echo $(python -c "print('Python: Hello,World.')")

运行输出如下:

2 种方法下的输出信息

再例如,我之前分享过一个 《Setapp 设备一键解绑 LaunchBar 动作》 ,该动作用于一键删除 Setapp 登录设备,方便登录设备超出限额时使用。这个 LaunchBar Action 是通过 Python 代码实现。那么如果将其转写成 Raycast 脚本,实际上也非常简单。

首先,我们在 Raycast 脚本目录中单独创建一个 Python 脚本文件,比如命名为 delete-setapp.py 。下面的代码中,我们可以在 Python 脚本中基于 Setapp 提供的 API 来删除已登录的设备。

import json
import requests

# 配置 Setapp 登录名和密码
EMAIL = "邮箱"
PASSWORD = "密码"

def auth():
    """获取 token

    """
    response = requests.post(
        url="https://user-api.setapp.com/v1/auth",
        headers={
            "Accept": "application/json",
            "Content-Type": "text/plain; charset=utf-8",
        },
        # 请在此处填入用户名和密码
        data=json.dumps(
            {"email": EMAIL, "password": PASSWORD, "remember": True})
    )
    token = response.json()['data']['token']
    return token
    
def delete():
    """删除用户

    """
    try:
        token = auth()
        headers = {
            "Authorization": f"Token {token}",
            "Content-Type": "application/json",
            "Accept": "application/json",
        }
        devices = requests.get(
            url="https://user-api.setapp.com/v1/devices", headers=headers).json()
        if len(devices['data']) == 0:
            return "无在线设备"
        else:
            device_id = devices['data'][0]['id']
            r = requests.delete(
                f'https://user-api.setapp.com/v1/devices/{device_id}', headers=headers)
            if r.status_code == 204:
                return f'成功删除设备 {device_id}'
            else:
                return f'删除失败,返回值 {r.status_code}'
    except:
        return '请求失败'
      
if __name__ == "__main__":
    print(delete())

接下来,我们基于 Bash 创建一个 Raycast 脚本,其中只需要添加一行 echo 命令将 Python 脚本执行的返回结果打印输出即可。

#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Delete Setapp Device
# @raycast.mode compact
# Optional parameters:
# @raycast.author huhuhang
# @raycast.authorURL https://github.com/huhuhang
# @raycast.icon icons/delete.png
# @raycast.packageName Delete Setapp Device

echo $(python delete-setapp.py)

最后,在 Raycast 中执行该脚本即可看到运行结果。

使用 compact 模式删除 Setapp 设备

虽然 Raycast 目前官方支持的脚本语言不如 Alfred 和 LaunchBar 多,但理论上你均可以使用 Bash 实现曲线救国方案,结合你自己熟悉的脚本语言来实现更多自定义操作。

脚本管理

效率启动器的脚本管理是绕不开的话题。以我熟悉的 LaunchBar 为例,创建和管理脚本都需要依赖于 Action Editor 功能。虽然我长期使用 LaunchBar,但却对其管理脚本的方式并不满意,因为它太复杂了。

如下图所示,实际上到目前为止我都不知道 Action Editor 中的一部分功能和选项是什么意思。例如界面中的 Default Script,Suggestions Script,Action URL Script 三者有何区别、该怎样使用?虽然我知道 LaunchBar 官方应该提供了相应的说明文档,但是其对于普通用户而言,上手门槛实在太高了。我相信很多人应该和我一样,看到这个复杂界面的时候就已经头大了。

LaunchBar 复杂的脚本管理界面

相比之下,Raycast 的脚本管理界面就简洁很多。因为其支持直接从文件夹中加载包含的全部脚本。还记得我在文章一开始提到推荐大家在 iCloud Drive 或者你其他常用的云同步应用中新建一个名为 Raycast Scripts 的文件夹用于存放脚本吗?如果你这样做,只需要在 Raycast 设置中关联相应的文件夹即可加载文件夹下的全部脚本。

Raycast 的脚本管理界面

如果有需要的话,你还可以将不同类型的脚本存放在不同的文件夹中,Raycast 支持关联多个文件夹,并实现脚本的自动 Reload,即在脚本代码更新之后自动更新,保证 Raycast 会执行最新的脚本。

如果你习惯使用 Git,那么对创建的脚本进行版本管理也就十分方便了,直接在脚本文件夹中初始化 Git 仓库即可。

脚本推荐

除了我文章中提到的部分脚本,目前 Raycast 官方维护了一个 GitHub 脚本仓库用于分享 社区开发的实用脚本 。虽然 Raycast 的社区脚本共享量还远不如 Alfred 和 LaunchBar,但由于 Raycast 本身的定位就是开发人员,随着用户越来越多,相信也会有更多实用的脚本被分享出来。

自定义脚本解决的核心需求往往并不具有普适性,所以我个人经常使用的脚本无法分享出来,因为仅和自己所做的事情有关,用于提升我个人的工作效率。授人以鱼不如授人以渔,如果你期望用好 Raycast 或者其他效率启动器的脚本功能,可以尝试学习 Bash 或者 Python 等任意一种脚本语言,实际上掌握基础语法写一个简单脚本并不困难,网络上免费的学习资源也非常丰富。

如果你想了解 Raycast 作为效率启动器的基础功能,可以搜索并阅读相关文章。目前,Raycast 完全免费,可以 前往官网下载 使用。

> 下载少数派客户端、关注少数派公众号,发现更多实用 App :rocket:

> 年度回顾、好物推荐…… 更多精彩尽在少数派 2020 年度盘点 :tada: