LaunchBar Actions 动手写
#0
试用了一下 LaunchBar 6,发现它已经支持中文了:虽然还不能用中文作为指令, 但是可以在按空格之后的输入框里输入中文。作为启动器的话,这种程度的中文支持已经可以让我满意了。
但尝试把 Alfred 上面自己写的 workflow 往 LaunchBar 上面迁移的时候才发现 LaunchBar 的 action 社区实在是…荒芜,官方论坛里十年不过积累了十页帖子,其中还有小半是上来求助问题的,官方的文档1也是惜字如金,连Google 上都没搜到很多 action 开发相关的文章,不管是中文还是英文。
摸索着把自己常用的一个新开启终端窗口的 workflow 写成了 LaunchBar 的action,顺手把过程记录在下面,也是给其他人(还有一段时间后肯定会忘光的自己)留个路标吧。不过我并不打算把它写成一个 step-by-step 的教程,毕竟Action Editor 的操作挺直观的,官方文档页不算完全无用,我只打算记录下我踩的坑,和文档中含糊不清的地方。
#1
我自己在 Alfred 下常用的这个 workflow 是这样的:在 iTerm 里我有一套的profile,对应日常不同的场景,然后每种分别有浅色和深色各一套。分别是:Light/Dark/Light code/Dark code/Light read/Dark read。因为这是日常中几乎最常用到的操作,我需要一个简洁且快速的方式来打开我需要的终端窗口。
workflow 在不带参数的情况下用默认的 profile 打开一个新窗口,带参数的情况用以参数为名字的 profile 打开新窗口。另外在提示的时候可以把待选择的profile 的名字显示出来。
新打开 iTerm 窗口用到的两条 Applescript 分别是2:
- 用默认 profile 打开:
create window with default profile
- 用指定 profile 打开:
create window with profile "name"
#2
首先打开 Action Editor 新建一个 action,因为这个 action 有可能接受参数, 但不是必须接受参数,所以选上了 “Accepts string argument” 但没有选”Requires argument”。
这里的参数设定在文档里有基本的说明:
https://developer.obdev.at/launchbar-developer-documentation/#/action-info-plist
语言的选择,我的第一选择是 Applescript,虽然不是专家,但毕竟简单🙄;其次是各种脚本语言,考虑到从 Yosemite 起 Javascript(JXA) 也被作为系统脚本语言,Javascript 是次选的优先。
回到 #1 里描述的需求,我们需要的是:
- 一个不需要 argument 能直接运行(打开默认 profile)的操作
- 一个能把候选 profile 名单列出来,并且随着输入实时缩小候选项的操作
- 从 2. 的结果里选择最终需要的 profile,或者直接完成输入后,回车用当前 profile 打开新窗口的操作
#2.1
这个最简单,按照文档的描述,所有 action 都必须有 Default Script,然后Default Script 里的 run
函数会被回车键直接触发,所以只需要在 Default Script 文件里放上这样一段就全解决了(考虑到 Default Script 里会直接操作 iTerm,我选择了 Applescript):
on run
tell application "iTerm"
activate
create window with default profile
end tell
end run
#2.2
这里会遇到一个坑(*_*)
翻完文档之后会发现要让 LaunchBar 的 action 显示一段返回值作为候选列表有多种选择:Default Script 里的 handle_string
或者 runWithString
函数;语焉不详的 “Live feedback enabled” 选项;还有 Suggestions Script里的 handle_string
或者 runWithString
。
文档里对这三者的区别基本没有提及,通过摸索,得出的区别是:
- Suggestion Script 会实时接收输入的文字,换句话说,每一个字母/文字的输入都会触发一次脚本里的
handle_string
或者runWithString
函数。函数运行的返回值会显示在交互的列表里,并等待下一次的输入。 - Default Script 只会在回车确认输入的时候触发脚本里的
handle_string
或者runWithString
函数。 - 如果 “Live feedback enabled” 被选上的话,每一次输入都会触发 Default Script,并显示函数的返回值,但是回车不会触发。
根据上面的总结的话,这里需要一个 Suggestion Script 来过滤输入,返回过滤后的 profile 列表,然后在 Default Script 里需要有函数来接收最终的选项(不管是直接来自输入还是来自选择列表),用对应的 profile 打开 iTerm窗口。最后不选 “Live feedback enabled”。
考虑到操作字符串的容易程度,我选择了用 Javascript 来写 Suggestion Script。因为并不是很大的 profile 列表,也不是很实时的操作,作为 Y 分钟3 速成出来的 JS 小白,并没有花时间做优化=_=
function runWithString(string)
{
var profiles = ["Light", "Dark", "Light code", "Dark code", "Light read", "Dark read"]
var ret = [];
var input = string.toLowerCase();
for (var p in profiles) {
if (profiles[p].toLowerCase().includes(input)) {
ret.push({title: profiles[p]});
}
}
return ret;
}
#2.3
回车接收输入的 Default Script 的写法也很简单,只是跟前面的 run
函数略有不同:
on handle_string(_string)
tell application "iTerm"
activate
create window with profile _string
end tell
end handle_string
#3
到这里一个 action 基本就成型了,除了文档的坑之外我觉得 LaunchBar 的action 开发比 Alfred 的 workflow 要来得略容易一些。Alfred 的拖拽式开发看似简单,但用起来感觉并不太直观,各种组件的用法和参数的传递都有点绕。
如果是打算操作 Terminal.app 的话过程稍微不一样一点,因为 Terminal.app 并不支持 Applescript 操作窗口和 tab,所以只能靠万能的 Applescript 菜单和键盘访问:
-- 默认 profile
tell application "System Events" to keystroke "n" using {command down}
-- 指定 profile profileName
click menu item profileName of menu of menu item "New Window" of menu "Shell" of menu bar 1
#4
Fin.