AppleScript 是 Apple 平臺 用來操控系統(tǒng)及 app 的一種腳本語言, 簡單使用時非常便利, 但是在一些靈活場景下便難以勝任, 這篇談談我遇到的 variable expansion
問題
事件背景: EuDic 提供了 AppleScript 腳本控制功能, 我想要寫一個 AppleScript 腳本來快速查找單詞, 但是 EuDic 有 Pro / Lite 兩種版本,
- Pro
- app name:
Eudic.app
- bundle id:
com.eusoft.eudic
- app name:
- Lite
- app name:
Eudb_en_free.app
- bundle id:
com.eusoft.freeeudic
- app name:
因此我必須在腳本中區(qū)分出用戶安裝的版本, 然后進行相應版本的調用
在腳本編寫過程中, 我發(fā)現(xiàn) AppleScript 在某些位置是不支持 variable expansion
的
-- script1.applescript
set appName to "EuDic"
tell application "System Events"
tell application appName
activate
show dic with word "hello"
end tell
end tell
-- script2.applescript
tell application "System Events"
tell application "EuDic"
activate
show dic with word "hello"
end tell
end tell
運行 script1
腳本會報錯: script error: Expected end of line, etc. but found identifier. (-2741)
, 運行 script2.applescript
則完全沒有問題,
這就讓我感到很奇怪了, 難道一個 AppleScript 連 variable expansion
能力都沒有? 經(jīng)過了大量資料查找后, 我發(fā)現(xiàn)它真的沒有這個能力...
因為 AppleScript 編譯器采用了各種技巧來支持那些花哨的類英語關鍵字. 這些技巧中最主要的是尋找 tell application "..."
行, 這樣它就知道在 tell
塊中編譯語句時要查找哪些特定于應用程序的關鍵字.
大多數(shù)情況下, 這對于簡單的代碼來說已經(jīng)足夠了, 但是一旦你想讓你的代碼更加靈活, 這種聰明反而會為你帶來羈絆. 因為腳本直到運行時才提供應用程序名稱,
編譯器在編譯時不知道查找該應用程序的術語, 因此只能使用 AppleScript 中預定義的那些關鍵字和任何加載的 osaxen
.
在我們這個例子中, show dict with word
術語是由 EuDic
定義的, 但是直到運行時, AppleScript 才知道他要找的術語是 EuDic
提供的, 這時如果直接運行
show dic with word
術語, 那么就會報錯(在這種情況下, activate
并不會報錯, 因為 activate
是預定義的術語), 對于這種情況,
我在網(wǎng)上找到的解決辦法大致如下:
直接使用原始
"com.eusoft.eudic"
-
將相關代碼包含在
using terms from application ...
塊中. 這明確告知編譯器在編譯所附代碼時從何處獲取附加術語.set appName to "EuDic" tell application "System Events" tell application appName activate using terms from application "EuDic" show dic with word "hello" end using terms from end tell end tell
很明顯, 上面兩種方式需要直接把 "EuDic" 寫死, 那么到底有沒有方法能在 AppleScript 中動態(tài)地 variable expansion
呢? 我想到了在 Shell 中調用 AppleScript
的方式. 根據(jù) so 的回答, 我們有三種方式可以在 shell 中調用
AppleScript, 其中 Here Doc
方式是支持 variable expandsion
的, 因此我的方案就是 Shell + AppleScript + Here Doc
Shell 的 here doc
默認支持 variable expansion
(當然, 我們可以使用引號 <<'EOF'
使該功能關閉), 具體實現(xiàn)如下:
#!/usr/bin/env bash
if [[ -d /Applications/Eudb_en_free.app ]]; then
eudicID=$(osascript -e 'id of app "Eudb_en_free"')
elif [[ -d /Applications/Eudic.app ]]; then
eudicID=$(osascript -e 'id of app "Eudic"')
fi
if [[ -z "$eudicID" ]]; then
osascript <<EOF
display dialog "Please install EuDic"
EOF
exit
fi
osascript <<EOF
tell application "System Events"
do shell script "open -b $eudicID"
tell application id "$eudicID"
activate
show dic with word "$1"
end tell
end tell
EOF
這樣, 我們便可以同時利用 AppleScript 的便利性與 Shell 的靈活性了.
這是目前我自己能想到的比較好的解決辦法, 如果你有更好的方法可以留言交流 ??
Project
hanleylee/alfred-eudic-workflow