擺脫瞎忙人生,從自動(dòng)化做起。作為一名職場(chǎng)人,有沒有為忘發(fā)匯報(bào)郵件而煩惱過,有沒有因繁忙的工作而丟三落四過;作為一名程序員,有沒為每天早上 pull 代碼后漫長(zhǎng)的編譯時(shí)間而煩躁過,有沒有為各種無腦的系統(tǒng)配置而無聊過。每天我們都在這些重復(fù)枯燥的事情中,浪費(fèi)著我們寶貴的生命。如何提高工作效率成為我們至關(guān)重要的事情 ,這篇文件將會(huì)帶領(lǐng)我們通過自動(dòng)化的方式,來有效地提高我們的工作效率。
本文大部?jī)?nèi)容是基于 MacOS 環(huán)境的,非 Mac 黨也可以借鑒其中的一些思想。
Shell Script
Shell 與 Shell Script
在談自動(dòng)化之前,我們先來了解下 Shell Script 這門有點(diǎn)古老而又非常強(qiáng)大的腳本語言,首先我們要分清一個(gè)概念性的問題,Shell 和 Shell Script 之間的區(qū)別:
Shell 是指一種應(yīng)用程序,這個(gè)應(yīng)用程序提供了一個(gè)界面,用戶通過這個(gè)界面訪問操作系統(tǒng)內(nèi)核的服務(wù)。
Shell 腳本(Shell Script),是一種為 Shell 編寫的腳本程序。
這里先給大家科普下概念,但大多的時(shí)候,我們都統(tǒng)稱 Shell Script 為 shell,文中的其它地方的 "shell" 指的同樣是 Shell Script。關(guān)于 shell 的基礎(chǔ)語法,并不在本文的討論范圍內(nèi),但在開始實(shí)踐如何通過 shell 來提高我們工作效率之前,我來我簡(jiǎn)單介紹 shell 幾個(gè)常用而又強(qiáng)大的功能。
常用串聯(lián)命令
管道
管道是 shell 中非常常用的功能之一,它允許不同腳本、命令之間互相傳遞數(shù)據(jù),例如:
ls | grep 'pars'
該命令意思是將 ls 輸出的內(nèi)容傳遞到 grep 'pars' 命令,grep 會(huì)把包含 'pars' 的內(nèi)容過慮出來。我們?cè)倥e個(gè)栗子,通過 shell 獲取 git 倉庫里中的當(dāng)前分支名:
currentBranch=`git branch | grep "*"`
currentBranch=${currentBranch/* /}
重定向
大多數(shù) UNIX 系統(tǒng)命令從終端接受輸入并將所產(chǎn)生的輸出發(fā)送回終端。一個(gè)命令通常從一個(gè)叫標(biāo)準(zhǔn)輸入的地方讀取輸入,默認(rèn)情況下是終端。同樣,一個(gè)命令通常將其輸出寫入到標(biāo)準(zhǔn)輸出,默認(rèn)情況下也是終端。如果你需要修改輸入或輸出,就需要使用到重定向功能。
| 命令 | 說明 |
|---|---|
| command > file | 將輸出重定向到 file。 |
| command < file | 將輸入重定向到 file。 |
| command >> file | 將輸出以追加的方式重定向到 file。 |
輸出重定向,指將一條命令的輸入位置重新定義,舉個(gè)例子:
ls > ls.txt
ls 輸出結(jié)果應(yīng)顯示在終端,而上面命令將 ls 的輸出結(jié)果寫到 ls.txt 這個(gè)文件中。需要注意,用 > 重定向到 ls.txt 文件默認(rèn)是覆蓋的,如果需要用追加的方式寫入文件,則需要使用 >>:
pwd >> ls.txt
輸入重定向:
pbcopy < ls.txt
上面的命令的意思是,將 ls.txt 的內(nèi)容復(fù)制到粘貼板。
之所以簡(jiǎn)單介紹這幾個(gè)常用功能,是因?yàn)槿绻欢@些功能,會(huì)影響理解下面的內(nèi)容。如果你對(duì) shell 腳本不熟悉,建議你抽空學(xué)習(xí)一下,日常工作中,用到 shell 的頻率還是非常高的。
實(shí)踐是檢驗(yàn)學(xué)習(xí)的唯一標(biāo)準(zhǔn)
簡(jiǎn)單聊完 shell 這幾個(gè)常用而又強(qiáng)大的功能后,我們開始實(shí)踐如何通過 shell 來提高工作效率。
雙網(wǎng)卡自動(dòng)配置
因我日常工作的需要,電腦需要配置雙網(wǎng)卡,這里以配置電腦的雙網(wǎng)卡為例,先附上部分配置腳本:
inside_ssid=\"WIFINAME\";
en0_ssid=\"$(networksetup -getairportnetwork en0 | sed 's/.*[:] //')\"
if [ \"$en0_ssid\" != \"$inside_ssid\" ]; then
echo -n \"請(qǐng)先將內(nèi)網(wǎng)卡設(shè)置到$inside_ssid\"
else
inside_adaptor_index=\"$(netstat -rn|grep default |grep en0 -n | cut -d: -f1)\"
if [ \"$inside_adaptor_index\" = 1 ]; then
echo -n \"請(qǐng)開啟外網(wǎng)卡,且服務(wù)順序在內(nèi)網(wǎng)卡前\"
else
inside_gateway=\"$(netstat -rn|grep default |grep en0|awk '{print $2}')\"
sudo echo \"刷新配置成功\";
sudo route -n delete -net 10.*.*.128;
sudo route -n delete -net 10;
sudo route -n delete -net 30;
sudo route -n add -net 10.*.*.128 $inside_gateway;
sudo route -n add -net 10 $inside_gateway;
sudo route -n add -net 30 $inside_gateway
fi
fi
這里不解析這些腳本的作用,我們的重點(diǎn)在于如何進(jìn)一步提高效率上。由于每次重啟電腦,都需重新配置雙網(wǎng)卡,才能正常同時(shí)使用內(nèi)外網(wǎng),也就是說,每次重啟電腦需要重新執(zhí)行一次這個(gè)操作。懶是人類的天性,如果我們連執(zhí)行一下腳本也不想干的話,那么我們需要怎么做呢?
我們可以在在電腦開機(jī)時(shí)設(shè)置自啟動(dòng)任務(wù)。首先我需要?jiǎng)?chuàng)建一個(gè) plist 文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>LaunchOnlyOnce</key>
<true/>
<key>Label</key>
<string>com.dengyonghao.xxxx</string>
<key>ProgramArguments</key>
<array>
<string>/Users/xxxxx/work/Tools/xxxx.sh</string>
</array>
</dict>
</plist>
簡(jiǎn)單解析下各個(gè) key 的作用,LaunchOnlyOnce 指定開機(jī)后只執(zhí)行一次,不指定則每隔一段時(shí)間就會(huì)執(zhí)行一次。Label 指定該 plist 的唯一標(biāo)識(shí)。ProgramArguments 則是設(shè)置執(zhí)行腳本的路徑,指向你想要啟動(dòng)時(shí)自動(dòng)執(zhí)行的腳本路徑。
完成上面操作后,把創(chuàng)建的 plist 文件拷貝到 ~/Library/LaunchAgents目錄下,表示僅對(duì)當(dāng)前用戶生效,然后執(zhí)行:
sudo launchctl load ~/Library/LaunchAgents/xxxxxx.plist
將這個(gè)文件注冊(cè)到系統(tǒng)中,然后電腦啟動(dòng)時(shí)就會(huì)自動(dòng)執(zhí)行,完成雙網(wǎng)上的配置。這里有一個(gè)問題,如果啟動(dòng)時(shí)自動(dòng)執(zhí)行上面的雙網(wǎng)卡配置腳本,真的能正常運(yùn)行嗎?
事實(shí)上是不行的,因?yàn)?sudo 命令需要你輸入管理員密碼,但你并沒有地方輸入,所以是沒有權(quán)限進(jìn)行這些操作的。故我們需要用到 Apple Script,從而引出下一節(jié)的內(nèi)容,這里先附上 Apple Script 腳本:
do shell script "
inside_ssid=\"WIFINAME\";
en0_ssid=\"$(networksetup -getairportnetwork en0 | sed 's/.*[:] //')\"
if [ \"$en0_ssid\" != \"$inside_ssid\" ]; then
echo -n \"請(qǐng)先將內(nèi)網(wǎng)卡設(shè)置到$inside_ssid\"
else
inside_adaptor_index=\"$(netstat -rn|grep default |grep en0 -n | cut -d: -f1)\"
if [ \"$inside_adaptor_index\" = 1 ]; then
echo -n \"請(qǐng)開啟外網(wǎng)卡,且服務(wù)順序在內(nèi)網(wǎng)卡前\"
else
inside_gateway=\"$(netstat -rn|grep default |grep en0|awk '{print $2}')\"
sudo echo \"刷新配置成功\";
sudo route -n delete -net 10.*.*.128;
sudo route -n delete -net 10;
sudo route -n delete -net 30;
sudo route -n add -net 10.*.*.128 $inside_gateway;
sudo route -n add -net 10 $inside_gateway;
sudo route -n add -net 30 $inside_gateway
fi
fi" with administrator privileges
這里只是用 Apple Script 來提供一個(gè)圖形界面來要求用戶先輸入管理員密碼,才允許他繼續(xù)執(zhí)行腳本。腳本使用了 Apple Script,故開機(jī)啟動(dòng)項(xiàng)的 plist 的文件也要做相應(yīng)的變化:
<key>ProgramArguments</key>
<array>
<string>osascript</string>
<string>/Users/xxxx/work/Tools/xxxx.scpt</string>
</array>
關(guān)于 Apple Script 的內(nèi)容將在下一節(jié)詳細(xì)介紹,這里我們先思考一個(gè)問題:設(shè)置開機(jī)執(zhí)行后,就能解決上面說的痛點(diǎn)了嗎?
事實(shí)上并不能解決所有問題,比如說,開機(jī)的時(shí)候外置網(wǎng)卡沒有插上,那么自動(dòng)執(zhí)行的腳本就會(huì)配置失敗,這時(shí)就又回到最初的場(chǎng)景,需要我們?nèi)フ业竭@個(gè)腳本文件,然后通過終端執(zhí)行。那么我們可以怎么去優(yōu)化這個(gè)流程呢?我們帶著這個(gè)問題,繼續(xù)后面的內(nèi)容,然后來再回來解決它。
集思廣益
在給團(tuán)隊(duì)成員分享的過程中,隊(duì)友們提出 sudo 可以明文設(shè)置管理員密碼,不需要每次運(yùn)行時(shí)手動(dòng)輸入,命令格式如下:
echo password | sudo -S xxxxxxxxx
需要注意的是,明文保存密碼存在泄露的風(fēng)險(xiǎn),建議使用這種方式前先評(píng)估風(fēng)險(xiǎn)。
Apple Script
Apple Script 是什么?
AppleScript 是 Apple 創(chuàng)建的腳本語言,用于自動(dòng)執(zhí)行 Macintosh 操作系統(tǒng)及其許多應(yīng)用程序操作的語言。可以用來控制運(yùn)行于 macOS 上的程序,以及 macOS 本身的部分內(nèi)容。你可以創(chuàng)建腳本來自動(dòng)執(zhí)行重復(fù)性任務(wù),或組合多個(gè)可編寫腳本的應(yīng)用程序的功能來創(chuàng)建復(fù)雜的工作流程。
我們使用 AppleScript 創(chuàng)建備忘錄、管理網(wǎng)絡(luò)、處理圖像、備份文件等等,AppleScript 是功能非常強(qiáng)大的自動(dòng)化工具,它內(nèi)置于 macOS 系統(tǒng)中,通過 腳本編輯器 應(yīng)用來編寫和運(yùn)行,任何用戶都可以免費(fèi)使用它。
腳本編輯器
macOS 中默認(rèn)已經(jīng)提供編寫 AppleScript 的工具:腳本編輯器,我們可以通過應(yīng)用程序中找到并啟動(dòng)它。

我們第一個(gè) AppleScript 腳本
我們打開腳本編輯器并選擇新建文稿,輸入以下內(nèi)容:
tell application "Finder" to open the startup disk
點(diǎn)擊運(yùn)行后,系統(tǒng)會(huì)在桌面打開一個(gè)新的Finder窗口,顯示啟動(dòng)盤的內(nèi)容,這里我們已經(jīng)完成了第一個(gè) AppleScript 腳本。
再舉個(gè)栗子,通過 AppleScript 打開或者關(guān)閉 Xcode:
tell application "Xcode"
activate
--quit
end tell
從上面腳本可以看出,AppleScript 和自然語言非常接近,編寫起來十分簡(jiǎn)單,但至于如何去學(xué)習(xí) AppleScript 的語法,這里不會(huì)多做講解,有興趣的同學(xué)可以通過官方文檔學(xué)習(xí)。
如何學(xué)習(xí) AppleScript
巧用文檔

Dash,程序員神器之一,強(qiáng)烈推薦一波。
我們?cè)趯W(xué)習(xí)一門新的編程語言時(shí),當(dāng)在使用某個(gè) API 遇到問題時(shí),最靠譜的解決方法不是 Google,而是先看下它的文檔 。我們可以通過 Dash 下載 AppleScript 文檔,遇到問題時(shí),我們可以快速查閱,并且 AppleScript 的文檔并不多,空閑時(shí)可以通讀一次(估計(jì)2-3小時(shí)),逐步加深對(duì) AppleScript 的了解。
讀懂 AppleScript 詞典

實(shí)踐出真知
匯報(bào)郵件提醒&自動(dòng)生成
下面我們直接開始實(shí)操,來實(shí)現(xiàn)一個(gè)自動(dòng)提醒發(fā)送重點(diǎn)項(xiàng)目進(jìn)度的工具,除了提醒功能外,該工具還會(huì)自動(dòng)幫你創(chuàng)建郵件模塊,包括收件人、主題、內(nèi)容模板等,我們來看實(shí)現(xiàn)腳本:
on callback()
tell (current date) to get (its year as integer) & "-" & (its month as integer) & "-" & day
set dataText to the result as text
set mailTitle to "-重點(diǎn)項(xiàng)目進(jìn)度" as text
set mailTitle to dataText & mailTitle
tell application "Microsoft Outlook"
set newMessage to make new outgoing message with properties {subject:mailTitle, content:"Dear xx:<br/>以下是我的重點(diǎn)項(xiàng)目進(jìn)度情況,詳細(xì)請(qǐng)查看附件:<br/><br/><br/>Best Regards"}
make new recipient at newMessage with properties {email address:{name:"xxx", address:"xxxx@pingan.com.cn"}}
#make new cc recipient at newMessage with properties {email address:{name:"Name", address:"test@example.com"}}
open newMessage
end tell
end callback
display dialog "又到周一了,趕緊發(fā)重點(diǎn)項(xiàng)目進(jìn)度" buttons {"現(xiàn)在發(fā)", "一會(huì)發(fā)"} default button 1
if the button returned of the result is "現(xiàn)在發(fā)" then
callback()
end if
這里我們通過 AppleScript 訪問 Microsoft Outlook 并自動(dòng)生成郵件模板,以上腳本只給郵件內(nèi)容填充了模塊,但實(shí)際上還可以實(shí)現(xiàn)自動(dòng)把你的重點(diǎn)項(xiàng)目進(jìn)度excel統(tǒng)計(jì)表附件進(jìn)來,再進(jìn)一步的話,可以直接通過 AppleScript 讀取 excel 的內(nèi)容,然后填充到郵件內(nèi)容中,只要你在完成重點(diǎn)項(xiàng)目?jī)?nèi)容后,及時(shí)更新 excel 統(tǒng)計(jì)表中的內(nèi)容,那么到每周一發(fā)重點(diǎn)項(xiàng)目的時(shí)候,你只需要一個(gè)命令就可以自動(dòng)完成匯報(bào)郵件。
我們完成了自動(dòng)生成郵件模板的功能后,還需提供自動(dòng)提醒的功能,關(guān)于自動(dòng)提醒功能,我們可以使用 mac 的啟動(dòng)服務(wù)來實(shí)現(xiàn),和自動(dòng)配置雙網(wǎng)上的方式一模一樣,我們創(chuàng)建相應(yīng)的 plist 文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.dengyonghao.viproject</string>
<key>ProgramArguments</key>
<array>
<string>osascript</string>
<string>/Users/dengyonghao/work/Tools/viproject.scpt</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key>
<integer>1</integer>
<key>Minute</key>
<integer>30</integer>
<key>Hour</key>
<integer>10</integer>
</dict>
</dict>
</plist>
需要注意的是這里多了 StartCalendarInterval 這個(gè) key,這個(gè) key 是用來控制你腳本的執(zhí)行周期或者時(shí)間的,這里設(shè)置為每周一上午 10:30 時(shí)就會(huì)自動(dòng)執(zhí)行腳本。
AppleScript 的內(nèi)容就簡(jiǎn)單介紹到這里,總之 AppleScript 非常強(qiáng)大,具體怎么使用,建議空閑時(shí)共同探討一下。
推薦閱讀
Automator
Automator 是什么?

Automator 是蘋果公司為 macOS 系統(tǒng)開發(fā)的一款軟件,只要通過點(diǎn)擊拖拽鼠標(biāo)等操作就可以將一系列動(dòng)作組合成一個(gè)工作流程,從而幫助你自動(dòng)的(可重復(fù)的)完成一些復(fù)雜的工作。Automator 實(shí)際上是一些列動(dòng)作組合在一個(gè)工作流文檔里,然后按順序去執(zhí)行這些動(dòng)作,與我們上面所以說的腳本非常類似,但 Automator 可以橫跨多個(gè)程序進(jìn)行,并提供圖形界面進(jìn)行操作,用戶操作起來非常方便。
腳本轉(zhuǎn)應(yīng)用
關(guān)于 Automator,我們可以通過實(shí)現(xiàn)腳本轉(zhuǎn)應(yīng)用的例子進(jìn)行了解,首先我們打開 macOS 自帶的 Automator,選新建文稿-->應(yīng)用程序-->實(shí)用工具-->運(yùn)行xxx腳本,然后把你的腳本填寫進(jìn)去,然后保存生成一個(gè)應(yīng)用。生成的應(yīng)用默認(rèn)是 Automator 的圖標(biāo),如果你想去改變圖標(biāo),則可以右擊應(yīng)用—>顯示包內(nèi)容-->Contents-->Resources,然后把 AutomatorApplet.icns 替換成你想要的圖標(biāo)就可以了。
我們可以把常用的腳本生成應(yīng)用,放到常用的位置,雙擊一下就能執(zhí)行,這樣也是挺爽歪歪的,但是這并不是我想要的,我想在任意的地方法都可以快速執(zhí)行,所以這里就引入了 Alfred 這個(gè)工具了。
推薦閱讀
關(guān)于 Automator 網(wǎng)上有不少教程,想進(jìn)一步了解的同學(xué),推薦閱讀:Automator 簡(jiǎn)單介紹及入門玩法 | Matrix 精選
Alfred & WorkFlows
Alfred 是什么?可能只能說是神器,不吹不黑,但這里我是不會(huì)講如何去使用 Alfred 的,沒有用過的小伙伴自行百度。
Workflow 又是什么梗呢,Workflow 工作流的意思,它表示把多個(gè)事件聯(lián)合在一起,形成一個(gè)連貫的動(dòng)作。
自我學(xué)習(xí)
這里省略成千上萬的字,需要你自行去學(xué)習(xí) Alfred 的使用,或許它 --> Google 可以幫你
問題回顧
講到這里,我們可以思考下文章開始配置雙網(wǎng)卡的那個(gè)問題,估計(jì)大家都會(huì)有更好的方法了。
我們可以把配置雙網(wǎng)卡的 AppleScript 寫成 Alfred 的一個(gè) workflows。比如我設(shè)置了 Alfred 的快捷打開鍵為 double com,雙網(wǎng)上配置 workflows 的 keyword 為 doublenet,這樣的話,我可以在電腦的任意界面輸入:double com + doublenet + 回車,即可完成雙網(wǎng)卡的配置。
一鍋亂燉
上面介紹了一堆的工具,看到這里,可能還是一臉懵逼,現(xiàn)在我們來通過實(shí)操,來把它們一鍋燉了。
Goto iTerm
作為一名程序員,從 Finder 目錄跳轉(zhuǎn)到 iTerm 的場(chǎng)景非常多,大多數(shù)時(shí)候我們都是通過拖動(dòng)目錄到 iTerm,然后 cd 進(jìn)去,效率非常低,通過學(xué)習(xí)上面的內(nèi)容,我們可以通過 AppleScript + Hotkey 快速在 iTerm 中打開當(dāng)前 Finder 的目錄。
首先我們可以通過 AppleScript 獲取當(dāng)前 Finder 窗口的目錄:
tell application "Finder"
set pathFile to selection as text
set pathFile to get POSIX path of pathFile
--防止目錄存在空格跳轉(zhuǎn)不了
set pathFile to quoted form of pathFile
end tell
然后通過 iTerm 提供的 AppleScript API 跳轉(zhuǎn)到指定目錄:
ell application "Finder"
set pathFile to selection as text
set pathFile to get POSIX path of pathFile
--防止目錄存在空格跳轉(zhuǎn)不了
set pathFile to quoted form of pathFile
set pathFile to "cd " & pathFile
--set the clipboard to pathFile
tell application "iTerm"
create window with default profile
tell current session of current window
write text pathFile
end tell
end tell
end tell
我們完成腳本后,則可以通過 Alfred 配置一個(gè) Hotkey,用來快速執(zhí)行該腳本:

我這里面配置的 Hotkey 是 com + T,所以我只要按下 com + T,則會(huì)自動(dòng)打開 pwd 在當(dāng)前 Finder 窗口的目錄下的 iTerm。
速記大法
每次開周會(huì)時(shí),在一周回顧環(huán)節(jié)中,總是拼命回顧這周我做了那些事情,特別是分享亮點(diǎn)和不足的時(shí)候,就各種詞窮。這里介紹一個(gè)非常有效的方法,就是每天記一記,周會(huì)不糾結(jié)。其實(shí)這個(gè)方法大家都知道,只是大家都懶得記,或者是沒有找到一個(gè)好的工具,我曾經(jīng)用印象筆記記錄過一段時(shí)間,但用了一段時(shí)間后,發(fā)現(xiàn)每當(dāng)腦子突然靈光一閃,有好的 idea 并想記錄下來時(shí),然而印象筆記并沒有打開,接著自己又懶得打開來記錄了。為了避免再次發(fā)生這種事情,我通過 notes + applescript + alfred 來實(shí)現(xiàn)一個(gè)速記事情工作流:
on alfred_script(q)
tell application "Notes"
tell account "iCloud"
tell (current date) to get (its year as integer) & "-" & (its month as integer) & "-" & day
set dataText to the result as text
set mailTitle to dataText & "-速記"
make new note at folder "PANote" with properties {name:mailTitle, body:q}
end tell
end tell
end alfred_script
這段 applescript 的意思是把 alfred 獲取到內(nèi)容,保存到 PANote 文件下。現(xiàn)在我們實(shí)現(xiàn)了快速記錄的功能后,我們還需要快速來查找,我們也是通過 applescript + alfred 來實(shí)現(xiàn):
use framework "Foundation"
property NSRegularExpressionSearch : a reference to 1024
property NSString : a reference to current application's NSString
property NSJSONSerialization : a reference to current application's NSJSONSerialization
property NSUTF8StringEncoding : a reference to current application's NSUTF8StringEncoding
on run argv
set output to {}
tell application "Notes"
set folderNames to name of folders in default account
repeat with folderIndex from 1 to number of folders in default account
set folderName to item folderIndex of folderNames
if folderName is "PANote" then
set currentFolder to (a reference to item folderIndex of folders in default account)
set noteIDs to id of notes of currentFolder
set noteNames to name of notes of currentFolder
set noteBodies to body of notes of currentFolder
repeat with i from 1 to count of noteIDs
set noteBody to (NSString's stringWithString:(item i of noteBodies))
set noteBody to (noteBody's stringByReplacingOccurrencesOfString:"<[^>]*>|
" withString:" " options:NSRegularExpressionSearch range:{0, noteBody's |length|()})
set noteBody to (noteBody's stringByReplacingOccurrencesOfString:"^ +| +$| +(?= )|" withString:"" options:NSRegularExpressionSearch range:{0, noteBody's |length|()}) as text
set match to (item i of noteNames) & " " & folderName & " " & noteBody
if length of noteBody is less than 100 then
set subtitle to noteBody
else
set subtitle to text 1 thru 100 of noteBody
end if
set subtitle to folderName & " | " & subtitle
set end of output to {title:(item i of noteNames), arg:(item i of noteIDs), subtitle:subtitle, match:match, uid:(item i of noteNames)}
end repeat
end if
end repeat
end tell
set output to {|items|:output}
set output to NSJSONSerialization's dataWithJSONObject:output options:0 |error|:(missing value)
set output to (NSString's alloc()'s initWithData:output encoding:NSUTF8StringEncoding) as text
return output
end run
這里的代碼看起來非常多,其實(shí)原理非常簡(jiǎn)單,首先遍歷 default account 下的所有文件夾,然后找到 PANote 這個(gè)文件夾,把查找到的內(nèi)容格式化后傳給 output,alfred 會(huì)幫我們把 output 的內(nèi)容以列表形式展示出來。當(dāng)我們選中展示中的內(nèi)容時(shí),我們還需要在 Notes 里面打開相應(yīng)的內(nèi)容,故我們?cè)賹?shí)現(xiàn)一個(gè)打開 Notes 的腳本:
on alfred_script(q)
tell application "Notes"
show note id q
end tell
end alfred_script
需要注意的是,這個(gè)方法 id 參數(shù)是從上一段代碼中的:
output to {title:xxxx, arg:xxxx, subtitle:xxxx, match:xxxx, uid:xxxx}
arg 里面獲取的,這個(gè)是 alfred 定義的格式,我們無須關(guān)心他是如何實(shí)現(xiàn)的,只要按照 alfred 的規(guī)范來傳參就可以了。
自動(dòng)拉代碼并編譯
每天早上我到公司的時(shí)候,首先是去洗杯打水,然后拉代碼編譯,接著等待漫長(zhǎng)的編譯時(shí)間,日復(fù)一日,風(fēng)雨無阻~~但在某個(gè)發(fā)呆的瞬間,突然有一個(gè)想法,為啥不讓系統(tǒng)在我到公司前把代碼編譯好呢,我到公司的時(shí)候就可以直接工作,不用等待漫長(zhǎng)的編譯過程了。
有了這種想法,就要?jiǎng)邮秩プ觯覀儼讶蝿?wù)一步步地拆分,首先是拉代碼,在拉代碼前,我們需要先檢查倉庫是否干凈,然后默默寫下以下腳本:
checkGitWorkspaceClean() {
echo "Action - checkGitWorkspaceClean"
if [ $# -lt 1 ]; then
echo "One param is required - the check dir.";
exit 1;
fi
if [ ! -d $1 ]; then
echo "The dir does not exist - $1";
exit 1;
fi
currentDir=`pwd`
cd $1
result=`git status -s`
if [ -n "$result" ]; then
echo "The git workspace is not clean - $1"
exit 1
fi
cd $currentDir
}
這里通過 git status -s 命令來判斷當(dāng)前倉庫是否是可拉取代碼狀態(tài),如果不可拉取就直接退出。
接著下一步是拉取當(dāng)前所有分支的最新代碼,我們需要獲取分支名并拉取該分支的最新代碼:
pullLatestCode() {
echo "Action - pullLatestCode"
if [ $# -lt 1 ]; then
echo "One param is required - the check dir.";
exit 1;
fi
if [ ! -d $1 ]; then
echo "The dir does not exist - $1";
exit 1;
fi
currentDir=`pwd`
cd $1
currentBranch=`git branch | grep "*"`
currentBranch=${currentBranch/* /}
`git pull git pull --rebase origin ${currentBranch}`
cd $currentDir
}
有沒有覺得這些代碼很熟悉,其實(shí)在 shell 那節(jié)都有介紹過的,這里只是把上面說的內(nèi)容應(yīng)用到實(shí)際的場(chǎng)景中而已。
拉取完成代碼后,我們就可以通過 xcodebuild 編譯代碼,xcodebuild 參數(shù)可以參考 apple 官方幫助文檔,這里你默認(rèn)使用模擬器進(jìn)行編譯:
buildProject() {
echo "Action - pullLatestCode"
if [ $# -lt 1 ]; then
echo "One param is required - the check dir.";
exit 1;
fi
if [ ! -d $1 ]; then
echo "The dir does not exist - $1";
exit 1;
fi
currentDir=`pwd`
cd $1
xcodebuild -workspace ${PARS_PROJECT_NAME}.xcworkspace -scheme ${PARS_PROJECT_NAME} -sdk iphonesimulator build
cd $currentDir
}
這樣我們整個(gè)拉取和編譯流程都可以通過代碼來實(shí)現(xiàn)了,但是在編譯代碼前,應(yīng)該先檢查下倉庫是否有沖突,如果有沖突就不開始編譯,所以正確的流程是:
checkGitWorkspaceClean $PARS_PROJECT_DIR
pullLatestCode $PARS_PROJECT_DIR
checkGitWorkspaceClean $PARS_PROJECT_DIR
buildProject $PARS_PROJECT_DIR
當(dāng)不能正常完成編譯時(shí),可以通過 AppleScript 顯示一些可視化的提示,比如彈窗之類的,這一些優(yōu)化依據(jù)個(gè)人習(xí)慣添加就可以,不過多講解。
如果你覺得在終端編譯不夠直觀,無法直接看到編譯進(jìn)度,我們則可以通過 AppleScript 來優(yōu)化代碼編譯流程,直接調(diào)用 Xcode 來編譯或者運(yùn)行代碼:
tell application "Xcode"
open "/Users/xxxxx/xxxx/xxxxx/xxxxx.xcworkspace"
set workspaceDocument to workspace document "xxxxx.xcworkspace"
repeat 120 times
if loaded of workspaceDocument is true then
exit repeat
end if
delay 1
end repeat
if loaded of workspaceDocument is false then
error "Xcode workspace did not finish loading within timeout."
end if
set actionResult to run workspaceDocument
repeat
if completed of actionResult is true then
exit repeat
end if
delay 1
end repeat
end tell
到這,已經(jīng)把最關(guān)鍵的拉取和編譯代碼的功能講完,至于如何定時(shí)執(zhí)行,在上文已經(jīng)詳細(xì)介紹過,這里不重復(fù)講解。但是定時(shí)任務(wù)存在一個(gè)不太方便的問題,就是當(dāng)你電腦關(guān)機(jī)或者休眠時(shí),這個(gè)定時(shí)任務(wù)就不會(huì)啟動(dòng)。設(shè)置電腦一直待機(jī)不休眠也不太好,畢竟公家財(cái)產(chǎn)也是要愛護(hù)的,比較折中的方法是把這個(gè)腳本寫成 alfred 的 workflows,我們到公司時(shí),可以先花 1-2 秒時(shí)間來執(zhí)行這個(gè) workflows,然后再去洗杯打水吃早餐之類的,等你把亂七八糟的事情搞定了,代碼也快編譯好了。
集思廣益
在給團(tuán)隊(duì)成員分享的過程中,隊(duì)友們就自動(dòng)拉代碼并編譯時(shí)機(jī)方面,提出了更好的方案:每天晚上12點(diǎn)(大家都下班的時(shí)候)時(shí)執(zhí)行腳本,執(zhí)行完成后通過腳本讓電腦休眠,從而避免電腦長(zhǎng)時(shí)間待機(jī)。
總結(jié)
本文簡(jiǎn)單分享如何通過工具,來處理日常工作中遇到的一些煩瑣的事情 ,通過使用腳本等方式來實(shí)現(xiàn)自動(dòng)化,從而提升個(gè)人的工作效率。這里僅提供一個(gè)思路和一些例子,至于如何發(fā)揮,就得看你自己如何去使用這些工具了,總之,工具是越用越合手的。