iOS程序員效率提升利器之AppleScript
這篇文章和大家分享我平時工作時,用來提升效率的神器之一:AppleScript。
AppleScript 雖然是一種腳本語言,但在我看來是最接近自然語言和最不具備計算機特質(zhì)的編程語言了。即使沒有計算機基礎,在閱讀基礎文檔和幾個樣例腳本之后,馬上就能動手寫出實用的腳本工具。
我感覺很多使用 Mac 系統(tǒng)的同學可能都沒意識到,與自己每天作伴的 Mac 系統(tǒng)上還有這么一個強大高效的腳本語言,可以從各個方面提升自己的工作效率。接下來的文章和大家分享我使用 AppleScript 的兩個場景。
在開始之前,先簡單概括下 AppleScript 的應用環(huán)境。我們的 Mac 系統(tǒng)從應用的角度來看,其實就是一堆 App 的集合,系統(tǒng)自帶的 App(Mail,Safari,Terminal 等)和安裝的第三方 App(Firefox,Chrome,Outlook,iTerm 等),這些主流的 App 其實都向系統(tǒng)暴露了一些實用接口,用來將一些高頻操作自動化。誰來調(diào)用這些接口呢?AppleScript。AppleScript 可以將這些 App 和 App 內(nèi)部的數(shù)據(jù),都當作對象來訪問,甚至可以將不同 App 串聯(lián),自動化之后形成一個 workflow。
如何編寫 AppleScript 呢?Mac 自帶腳本編輯和運行工具,通過 Spotlight Search 搜索 Script Editor 即可。運行 Script Editor 之后,通過菜單 File -> Open Dictionary 即可打開如下圖所示一個文檔,里面列出來所有支持 AppleScript 的 App,以及各個 App 所支持的接口調(diào)用。
提升工作效率,避免重復勞動
我最近在研究如何降低 App 的 Crash 率,每天都要實時監(jiān)控是否有新的 crash 發(fā)生。所有可能嚴重的 crash 警報都通過郵件發(fā)送到我郵箱,一旦收到警報我需要將郵件中的 crash id 復制出來,去另一個網(wǎng)頁工具里查詢。每天早上看著一大堆警報,如果要將所有的 crash id 手動復制出來,一個個貼入網(wǎng)頁里查詢,操作很繁瑣。AppleScript 可以輕松將這個流程自動化,一鍵搞定。步驟如下:
郵件分類
郵件都是保存在 Microsoft Outlook 中,我首先設置一個 rule,將所有郵件標題包含 Trending Crash:xxx 字樣的郵件都存入一個子文件夾:iOS-Crash。
遍歷郵件
再通過 AppleScript 遍歷 iOS-Crash 目錄下所有文件:
- tell application "Microsoft Outlook"
- set theMessages to messages of folder "iOS-Crash" of default account
- repeat with theMessage in theMessages
- end repeat
- end tell
上面這段腳本讀起來是不是一目了然?就像是在和 siri 聊天一樣,告訴 siri 遍歷某個目錄下的全部郵件。
提取 Crash ID
AppleScript 的另一個強大之處是可以和系統(tǒng)自帶的各類常用命令行工具(比如 grep,sed,awk 等)交互,這意味著對文本和文件的操作可以游刃有余。接下來我要通過 sed 工具來提取郵件中的 Crash ID:
- tell application "Microsoft Outlook"
- set theMessages to messages of folder "iOS-Crash" of default account
- set crash_id_set to {}
- repeat with theMessage in theMessages
- set msgContent to plain text content of theMessage
- tell me to set crash_id to do shell script "echo " & quoted form of msgContent & " | sed -E -n 's_.* crash_id:(.+)}_\\1_1p'"
- if crash_id is not in crash_id_set and the length of crash_id > 0 then
- set crash_id_set to crash_id_set & crash_id
- end if
- end repeat
- end tell
關鍵代碼是這一行:
- tell me to set crash_id to do shell script "echo " & quoted form of msgContent & " | sed -E -n 's_.* crash_id:(.+)}_\\1_1p'"
AppleScript 用 tell xxx 的方式來切換腳步運行環(huán)境,比如
- tell application "Microsoft Outlook"
是切換到 Outlook 的進程中。
- tell me to
是切換到當前用戶的運行環(huán)境,因為我們要執(zhí)行命令行腳步,需要更高級權限,所以要切換到當前用戶進程。
接下來通過 echo 將郵件的內(nèi)容傳遞給 sed,并提取出 crash-id,將值傳回 AppleScript 中的便利 crash_id,放入數(shù)組中。
拼裝 url 并在瀏覽器中打開
這是最后一步,將上面提取結(jié)果在瀏覽器中打開:
- tell application "Microsoft Outlook"
- set theMessages to messages of folder "iOS-Crash" of default account
- set crash_id_set to {}
- set param to ""
- repeat with theMessage in theMessages
- set msgContent to plain text content of theMessage
- tell me to set crash_id to do shell script "echo " & quoted form of msgContent & " | sed -E -n 's_.* crash_id:(.+)}_\\1_1p'"
- if crash_id is not in crash_id_set and the length of crash_id > 0 then
- set crash_id_set to crash_id_set & crash_id
- end if
- end repeat
- repeat with crash_id in crash_id_set
- set param to param & "%22" & crash_id
- end repeat
- tell me to do shell script "cat ~/Documents/AppleScripts/ios_crash_url | sed -n -E s_crash_ids_" & quoted form of param & "_p | xargs open "
- end tell
url 原始信息保存在文件 ios_crash_url 中,使用 sed 做簡單替換之后,將 url 傳遞個 open 命令即可。
最后添加個命令 alias,就可以做到一鍵完成了。
- alias ioscrash='osascript /Users/fenggao/Documents/AppleScripts/outlook_ios_crash.scpt'
代碼重構(gòu)
我還使用過 AppleScript 來重構(gòu) Objective C 代碼,原理很簡單,將 Xcode 中選中的代碼以 text 的形式傳遞給 AppleScript,再通過 AppleScript 傳遞給命令行來操作。或者將 Xcode 當前打開的類文件 path 通過 AppleScript 傳遞給命令行工具,接下來就是基礎的文件操作了,各類工具任由你選,比如我們可以使用本地編譯好的 clang 來分析類文件,來進行針對 Objective C 語法特征的文本修改。當我們有大量的代碼文件需要修改,而且修改的規(guī)則遵循某個相同的 pattern 時,使用腳本能起到事半功倍的效果。
通過 osascript 命令執(zhí)行 AppleScript 是方式之一,另一種方式是通過 Service。每個 App 在菜單里都有 Services 一項。我們可以通過 Automator 來添加每個 App 都能使用的 Service。
我們可以把一個 Service 想象成一個 workflow,而一個 workflow 可以包含若干個 action,執(zhí)行 AppleScript 就可以是其中的一個 action。
首先通過 Spotlight Search 啟動 Automator,啟動之后選擇創(chuàng)建 Service。之后可以看到所以支持的 action,選擇 Run AppleScript 并拖動到右側(cè)的 workflow 區(qū)域,即可執(zhí)行某個 AppleScript 了。當然也可以拖動 Run Shell Script 到 workflow 區(qū)域,各個 action 之間可以通過 stdin 傳遞數(shù)據(jù)。如下圖所示:
所有創(chuàng)建保存之后的 service 都會自動保存到 ~/Library/Services/ 目錄下,一旦保存我們就可以在應用的 services 目錄下看到我們的目標,比如我保存 xcode-text.workflow 之后。我在 Xcode 中選擇某些代碼,右鍵就可以看到我所創(chuàng)建的 service 了,如圖:
關鍵字:automator->service->action->applescript
總結(jié)
AppleScript 的應用場景很廣泛,且很容易上手。一些 Mac App 的核心功能甚至都是利用 AppleScript 來編寫的。比如 Mac 上的剪貼板工具,就是通過 AppleScript 來操作其他應用的當前編輯文本,來實現(xiàn)歷史查找和插入功能。工具的強大與否在于使用之人如何用之,工具都是越用越稱手。