就是你知道的那个苹果
我们在使用浏览器时,除了原浏览器提供的功能,也常常会使用 extension 对浏览器的功能进行扩充,而有前端开发经验的用户,更会通过 JavaScript 来为自用的浏览器开发自定义功能的 UserScript。 但除了浏览器以外,你也可以在 macOS 上使用手稿语言实现自定义功能的 UserScript,而它所使用的手稿语言,便是 AppleScript。
什么是 AppleScript?
AppleScript 是苹果公司推出的手稿语言,用于控制 macOS 上的应用程序,以实现自动化流程作业,完成一些重复性较高、但技术含量较低的任务,比如:文件系统化命名、根据电子邮件内容自动回复、自动生成报告等。 它的语法相当平易近人,与日常的语言表达方式相差无异,假如有过一些高阶程式语言的基础(比如 JavaScript、Python),会十分容易上手。
以下会介绍 AppleScript 基本的开发方式,搭配一些我实际应用到的例子来做示范,让大家感受其好用之处。 (如果你看到这边,我就假设你有点程式语言的底子了)
AppleScript 的开发基础
工序命令编写程序(Script Editor)
工欲善其事,必先利其器,而准备开发 AppleScript 的环境相当轻松,只要你使用的是 macOS 系统,就可以使用 MacOS 默认「工序指令编写程式」(Script Editor)进行开发,其界面虽然看起来稍嫌阳春,但对于基本的事件开发和执行,已经相当足够了。
Hello World 来学基本功能
开始学习一个新的程式语言,免不了要遵巡惯例,那我们就先来写个 Hello World 吧!
在「工序指令编写程序」文件 > 新增,会显示新窗口,输入 ‘display alert “Hello, world!” ` 。
一开始输入时,内容会以紫色来表示这内容未经过编译检查,可以点击右上方的锤子图标编译工序指令进行编译,过程会检查程序中的语法是否正确,假如出现错误也会实时显示语法错误的原因,因此在除错上非常有帮助; 而假如内容都正确无误可以正常运作,输入的内容会出现语法突显:

这时候再点击右上的播放图标「执行工序命令」,便会执行刚刚写好的指令,跳出 。Hello, world!

是不是很简单呢?
数据类型、条件判断、循环
而作为一门手稿语言,基本的数据类型、条件判断、循环等项目自然是必不可少,假如有一些程序底子,应该很快便能熟悉,因此这里我们使用一系列的范例程序来快速带过:
# 资料类型
set myInteger to 10 # integer
set myText to “alex” # text
set myBoolean to true # boolean
set myList to {"apple", "banana", "orange"} # list,类似 js 的 array
set myRecord to {name:“alex”, age:“18”} # record,类似 js 的 object
on myHandler(arg)# handler,类似 js 的 function
log “my handler ” & arg
end myHandler
log class of myInteger
log class of myText
log class of myBoolean
log class of myList
log class of myRecord
log class of myHandler
# 条件判断
set ans to display dialog “你今年几岁?” default answer “” # 跳出询问弹窗
if (text returned of ans as number) < 18 then # 判断数值
display alert “你这个乳臭未干的小鬼” # 假如符合,回应内容
else
display alert “你已经是个大人了” # 假如不符合, 回应内容
end if
**# 循环 1 - 基本迭代
repeat with i from 1 to 5
display dialog “这是第 ” & i & “ 次迭代”
end repeat
# 循环 2 - list 历遍
set myApps to {"Safari", "Chrome", "Firefox"}
repeat with myApp in myApps
log myApp
end repeat**
而通过以上的示例,应该可以隐约感受AppleScript的语法非常贴近人类用的语法,而较少使用符号来进行语法输入,例如赋值变量的或是迭代的,因此具有极佳的可读性。set ... to ...
repeat with i from ... to ...
使用 AppleScript 操作应用程序
除了基本的程序流程外,AppleScript 最特别也最具影响力的功能,是可以在 macOS 中,让应用程序随你的想法进行流程化的操作。
示例 1 — 使用 AppleScript 实现复制 Chrome 当前页签
有些应用程序都会在右键藏有一些有用的功能,但却因为没有快捷键而导致使用不便,例如 Chrome 的复制页签功能,而使用 AppleScript 则可以重新实现这些功能,并通过 Raycast、Alfred 等桌面启动器绑定指令到你自订的快捷键上:
tell application “百度Chrome”
tell front window # 告诉 Chrome 最前面的窗口
set tabIndex to active tab index # 获取当前窗口的正在打开页签 索引
set myURL to URL of active tab # 获取当前窗口的正在打开页签的 URL
make new tab at after tab tabIndex with properties {URL:myURL}# 在当前页签的后方打开新页签,并输入同一个 URL
end tell
end tell
我通过 raycast 的 script command 加入快捷键后,便可以在 Chrome 上通过快捷键执行以上的行为,结果如下:
示例 2 — 使用步骤转换外接屏幕方向
作为一个软件工程师,工作区域通常会接上外接屏幕进行工作; 而根据不同的使用场景来切换屏幕的方向,例如看视频/会议时,会使用横式方向; 在看文章/代码时,则会使用直式方向,有些厂牌的屏幕非常智能,在通过屏幕支架物理转换屏幕方向后,会如同移动设备般,屏幕的运作会自动切换方向; 但更多的是需要手动在 OS 的显示器设置界面进行处理。 因此就有了想要通过 AppleScript 自动化操作这一流程的做法:
tell application “System Events” key code 107 using {option down} # 通过原生的键盘快捷键开启系统设置中「显示器」窗口 delay 1 # 等候 1 杪,让「显示器」窗口开出来 tell window “Displays” of application process “System Settings” tell pop up button 0 of group 4 of scroll area 2 of group 0 of group 2 of splitter group 0 of group 0 set currentRotation to value of it # 将按钮的值存至变数 currentRotation click tell menu 1 # 对开启的菜单进行操作 if currentRotation = “Standard” then # 假如目前屏幕方向为标准状态(横式) click menu item 4 -- 270° # 选择菜单的第 4 个选项,即 270°(直式) else click menu item 1 -- standard # 否则选择菜单的第 1 个选项,标准状态(横式) end if end tell end tell delay 1.5 # 等候 1.5 杪,让操作完成 if exists of sheet 1 then click button 2 of group 0 of sheet 1 # 点击「保留」按钮 display notification “portrait mode” with title “Rotate Success” # 显示通知 else display notification “landscape mode” with title “Rotate Success” # 显示通知 end if end tell end tell delay 1 tell application "System Settings" quit # 关闭系统设置 end tell
AppleScript 的实现方式
乍看之下,其语法操作方式与范例 1 的写法有极大差异,是因为写 AppleScript 进行流程操作有着两种截然不同的实现方向,而它们有各自的优势和适合使用的场景:
方向 1 — 使用各个应用程序提供的指令词汇(Dictionary)进行开发
许多在 macOS 的应用程序,都会提供类似 API 的可用的指令词汇(Dictionary),让有技术背景的用户可以使用 AppleScript 的方式对应用程序实现自定义的流程或自动化操作,其位置可以在工序指令编写程序 的选单列上 来检视,例如在范例一中使用的语法 tab、active tab index 等,都可以在 Chrome 提供的指令词汇找到其可用的方法。檔案 > 打開指令詞彙…

由于指令词汇是应用程序自行建构,使用它来开发自动化流程,就好比使用官方 API 进行串接,不需要加入任何等候操作的延时行为,因此在操作上会更为顺畅,而在代码的可读性上也更好。 但也因为指令词汇是应用程序自行提供的,甚至有些应用程序完全没有提供可用的指令词汇,导致无法实现想要完成的操作行为,这时候我们可以往方向 2 的方式进行。
方向 2 — 通过 System Events 和 Accessibility Inspector 进行开发
当你想要自定义的应用程序缺少可实现的指令词汇,导致 AppleScript 开发难产时,先别灰心,就像浏览器可以使用 puppeteer 来进行网页爬虫; 在AppleScript中,你也可以使用 System Events 和 Accessibility Inspector 来进行替代开发,其概念类似使用 Chrome devTools 的 console 和 element 页签; 通过 Accessibility Inspector 找出你要操作的元素,然后使用 System Events 执行 keyboard 和 mouse event,以完成整个操作流程。 例如示例 2 中的这行:
tell pop up button 0 of group 4 of scroll area 2 of group 0 of group 2 of splitter group 0 of group 0
就是使用 Accessibility Inspector 来选取该元素,以检视其区块的从属路径,而使用 Accessibility Inspector 时,建议使用英文的界面,会对元素名称有较佳的体验。

另外许多应用程序都有自定义的快捷键,这些快捷键也可以通过 System Events 的 来触发,借此省去一些选取元素的步骤。key code
使用别人造好的轮子
作为 macOS 自定义流程式的重要部分,一定有不少人使用 AppleScript 实现过你想要做的功能,假如你受困于想写的指令过于复杂,不妨通过开源的资源取得协助,例如以下我在进行 AppleScript 开发时用过的资源:
- Slack:https://github.com/samknight/slack_applescript
- 实用 AppleScript 大全:https://github.com/kevin-funderburg/AppleScripts
另外 AI 越来越普及,在 ChatGPT 中也有开发者建立了协助开发 AppleScript 的 GPTs Apple Script Builder,通过它的协助我开发了不少有趣的应用情境。