第 3.8 章 優秀 workflow 推薦
Workflow 中文的意思是工作流,它表示把多個事件聯合在一起,形成一個連貫的開發體驗。如果想使用 Workflow,必須購買 Alfred 的 PowerPack,價格在 19 - 35鎊不等。
如果沒有額外說明地址,下面的 Workflow 都可以在我的 GitHub 上面下載。
Evernote
當下大多數資歷中使用的還是 v8 版本的 Workflow,根據我的測試已經無法使用,推薦下載使用 v9 版本。
我本人只把 Evernote 當做收藏集(也就是只收錄文章,不自己編輯),所以只有搜索的需求。可以輸入 ens 進行全文搜索,或者用 ent 來搜索標題。
在 ens 命令后面還可以加上 @ 來指定筆記本,或者加上 # 來指定標簽。
命令 enn 用于新建一條筆記,同樣支持 # 和 @ 語法。
AppLauncher
這是我獨立開發的一個 Workflow,用來全局快速打開 App:
所有 App 快捷鍵都以 Command + Ctrl 開頭,這樣選擇是因為不容易和系統快捷鍵產生沖突。如果你交換過 Ctrl 和 Caps Lock 鍵,就會發現觸發起來非常方便、
Dash
如果電腦上裝了 Dash,這個 Workflow 允許我們快速搜索文檔:
IP
這個 Workflow 比較簡單, 可以顯示自己的內網 IP 和公網 IP:
有道詞典
有道詞典已經把 API 遷移到了有道智云,所以需要自行注冊 API Token,關于 Workflow 的下載和使用,請參考這個 GItHub 倉庫。
使用效果如下:
GitHub
作為程序員,難免要和 GitHub 打交道,這個 Workflow 能幫助我們快速搜索、操作 GitHub:
Hash/BASE64 工具
提供了一些 md5、hash、sha1 計算工具和 base64 加密解密的功能:
layout
這是一個調整窗口布局的工具,可以設置窗口全屏或者擺放位置,甚至還可以切換屏幕。詳情參考:alfred2-layout
color
這是一個顏色格式轉換的工具,可以把英文單詞轉換成各種格式的顏色寫法,也可以直接讀取 16 進制的顏色:
快遞查詢
如果在淘寶買了個 MacBook/iPhone 之類的大件,等快遞的過程真是心急如焚,恨不得過一會兒就查一次快遞到哪了,此時用上快遞查詢這個 Workflow 了:
第 3.9 章 Chrome 插件介紹
插件管理技巧
有些插件是屬于不需要交互,默默在后臺運行的那種,比如屏蔽廣告、顯示 GitHub 倉庫大小等等,這類插件可以設置為在 Chrome 中隱藏,這樣 Chrome 就不會顯得特別亂了。
對于那些需要手動點擊,使用頻率還很高的插件,我們還可以設置快捷鍵,打開 chrome://extensions/
點擊左上角的設置,選擇 鍵盤快捷鍵:
比如我經常用印象筆記收藏文章,所以就可以給它配上快捷鍵:
應用這兩種管理方式后,插件欄就會很簡潔,高頻交互類和非交互類插件都可以隱藏,只會留下少數低頻(不值得設置快捷鍵)交互類插件。
Vimium++
一個致力于無鼠標操作 Chrome 的插件,因為按鍵規則類似于 Vim 風格而得名,主要功能有:
f/F: 在當前/新頁面打開鏈接
x/X:關閉/恢復頁面
j/k:向下/上滑動網頁
J/K:左右切換標簽頁
H/L:瀏覽記錄前進后退
u/d:向上/下滑動半頁
b/B:在當前/新頁面打開收藏夾內的頁面,支持搜索
o/O:在當前/新頁面打開新的網址,支持歷史記錄搜索
gs:查看網頁源碼
gi:鼠標定位到輸入框
gu/U:前往網頁的上一層或根路徑
yy:復制當前網址
yf:復制某個鏈接的地址
p/P:在當前/新頁面打開剪貼板中的網址
使用體驗如下:
GitHub Repo Size
顧名思義,可以查看 GitHub 中某個 Repo 的大小,是一個小巧實用的工具:
FE 助手
這是一個工具集合,包含了字符串編解碼、二維碼生成器、網頁轉圖片、網頁取色、時間戳轉換、BASE64 加解密、頁面性能檢測等工具。
這些功能都屬于二級入口,如果有特別高頻的使用場景,可以考慮使用單獨的插件。下圖展示了開啟 JSON 格式化前后的區別(左側開啟 VS 右側關閉):
Adblock plus
自動屏蔽廣告
印象筆記·剪裁
一鍵收藏喜歡的文章
Vue
開發模式下可以用來調試 Vue 界面
Toby
可以跨設備同步 Chrome 的標簽
第 4 章 編輯器之神:Vim
Vim 是純鍵盤操作,因此在本書開頭就描述過的誤區同樣適用于 Vim:
一些極端的人不夠了解 Vim,感受不到 Vim 的價值,因此拒絕學習 Vim。
另一些極端的人過于沉迷于 Vim,想把 Vim 從編輯器打造成 IDE。因此在本章開頭我就想強調的是:
Vim 就是個編輯器,用來輸入、標記文本的,編程相關的東西交給 IDE 就好了
所以最理想的方案應該是:選擇一款 IDE,給它裝上 Vim 插件。
但曾經的我,在 JetBrains 系列 IDE 和 Vim 之間猶豫不決,甚至還花了相當一段時間研究怎么用 Vim 開發 iOS,至于 Atom 和 Sublime 就根本沒考慮過,一切的原因都在于:雖然很多 IDE 都有 Vim 模式,但都不支持 Vim 的插件。
不要小瞧 Vim 插件,很多插件真的是** Life-Changing** 系列的,本章第五篇文章就包含了我對一些 Vim 插件的介紹。
最后我放棄了 JetBrains 家的 IDE 套裝,主要理由有:
JetBrains 系列的 IDE 太龐大,繁重了。如果你要寫不同語言,就要裝不同的軟件,而且每一個都很占用資源
VSCode 確實是地球上最好的 IDE,微軟的技術真的很強。而且 VSCode 有著極活躍的社區,只需要安裝這一個 App,配合上各種插件,就可以開發絕大多數語語言。
最終我的編輯器選型為:
前端/Node/其它腳本開發:VSCode + Vim 插件
iOS 開發:Xcode,沒有選擇 XVim 是因為經常遇到詭異問題,而且不支持 Vim 插件根本沒法用
Android 開發:Android Studio + Vim 插件
客戶端開發其實沒什么選擇的,因為暫時沒有能完全替代官方 IDE 的東西。而 VSCode 功能就比較強大了,在我的日常工作中它基本上已經取代了原生的 Vim,最后一章會介紹一些 VSCode 中的用法和插件。
我使用了 neovim 來替代 vim,主要區別在于 neovim 更加先進,并且支持插件的異步加載。在使用上和 Vim 幾乎是一致的
安裝 NeoVim 需要以下幾步:
brew install nvim
pip3 install --trusted-host pypi.python.org neovim jedi ipython
pip3 install --user --upgrade --trusted-host pypi.python.org PyYAML
# 下載配置
git clone https://github.com/bestswifter/vim-config.git ~/.config/nvim
ln -s ~/.config/nvim ~/.vim
用 nvim 命令打開文件后可以看到如下效果:
第 4.1 章 Vim 基本操作
Vim 分為三種模式:
輸入模式:這就很普通的編輯器一樣,光標在某個位置上閃爍,表示我們可以輸入內容了。
普通模式:在輸入模式下按下 Esc鍵可以退出輸入模式,進入到普通模式。
命令模式:執行搜索、替換等命令或調用插件。
普通模式是 Vim 的一大特色,能夠進行很多操作,比如:
快速移動光標
快速替換、刪除某些內容
進入輸入模式或命令模式
使用 nvim 打開文件后,默認進入普通模式,如果我們要編輯文本,可以按下 i進入編輯模式,編輯完后再按下 Esc鍵可以退出輸入模式,進入到普通模式。
如果想退出 nvim,則需要借助命令模式。按下 : 并輸入以下內容之一:
q:退出
q!:如果對文件作了修改,無法用 q 退出,此時 q! 表示丟棄修改并退出
x:保存并退出
因為每次按下冒號還挺麻煩,所以我對我的 Vim 做了配置,無需進入命令模式,直接在普通模式就可以退出:
q:退出
Ctrl-q:丟棄修改并退出
Ctrl-x:保存并退出
這種效果可以使用 Vim 的 map 配置來實現:
nnoremap <silent><buffer> q :pclose!<CR>:quit<CR>
nnoremap <C-x> :x<CR>
// nnoremap 表示普通模式下的 map,等價于先輸入冒號再輸入 quit
// inoremap 表示輸入模式下的 map,因此輸入模式下也可以用 C-q 快捷鍵
nnoremap <silent> <C-q> :<C-u>:quit!<CR>
inoremap <silent> <C-q> <Esc>:<C-u>:quit!<CR>
第 4.2 章 Vim 光標移動
上一節中我們介紹了 Vim 的基本操作,靠著 i 、:x等指令,配合上方向鍵,基本上能在 Vim 的世界里幸存下來了。勉強編輯一下服務器上的文件不是問題。
如果你的打字手勢標準的話,你會發現方向鍵其實挺難觸摸到,至少會破壞右手的姿勢。因此在 Vim 中不鼓勵使用方向鍵,可以用 hjkl 來代替:
h:向左移動一個字符
l:向右移動一個字符
j:向下移動一行
k:向上移動一行
重復移動
如果要向上移動 5 行,或者向右移動 10 個字符,我們是不是要重復按下很多次呢?顯然只有方向鍵才要這么做,Vim 中可以用數字來表示重復:
10j: 向下移動 10 行
5l:向右移動五個字符
這個操作雖然簡單,但是引出了兩個很有意思的話題。首先,Vim 中的行號應該配置為相對行號 + 絕對行號:
圖中左側高亮顯示的 22 是當前的絕對行號,上下都是相對偏移量。這樣的好處在于既方便知道當前的位置,又方便通過相對行號進行跳轉。
另一個話題則是貫穿 Vim 始終的核心思想:就像英語、中文有語法一樣,Vim 也有語法。
Vim 的操作可以由若干個部分組合而成,每個部分又有多個可選值(比如光標移動就分上下左右)。Vim 的入門難度高,是因為每個部分都要學習,一下子需要掌握很多新知識點。但 Vim 后期的學習成本很低,因為無非就是各種組合而已。
還是以光標移動為例,5j 由重復次數和動作組成,后面我們會介紹更多的動作,而且它們的前面都可以加上數字表示重復。
單詞移動
前面我們講過利用 Option 鍵進行單詞間移動,得益于普通模式和語法,Vim 支持更強大的單詞間移動:
w移動光標到下一個單詞的詞首\(word\)
b 移動光標到上一個單詞的詞首\(begin\)
e移動光標到下一個單詞的結尾\(end\)
ge移動光標到上一個單詞的結尾\(不知道怎么解釋了。。。\)
這里的單詞是有嚴格約定的,而且不是那么顯然,所以個人感覺這幾個鍵并不是特別好用(往往你以為的跳轉地址和真實跳轉地址并不一致)。
不過如果你把空格當做單詞的分隔符,倒是有比較簡單的跳轉方式,前三個命令都有大寫格式:
W 移動光標到下一個單詞的詞首\(word\)
B 移動光標到上一個單詞的詞首\(begin\)
E 移動光標到下一個單詞的結尾\(end\)
這里的單詞特指以空格分割。
同樣的,這些移動也支持重復任意多次
在后面的插件一節中,我會介紹如何用 EasyMotion 來讓光標移動變得簡單。
行和屏幕移動
在行內,^ 表示移動到行首,它會自動忽視掉行首的空格,大部分情況下這是符合預期的,尤其是在代碼縮進的情況下。如果想回到行首的空格上,可以用 0 。$ 表示移動到行尾。
Vim 的翻頁快捷鍵是:
Ctrl + f:向后翻一頁(forward)
Ctrl + b:向前翻一頁(backward)
Ctrl + d:向后翻半頁(down)
Ctrl + u:向前翻半頁(up)
很巧的是,前兩個命令和系統輸入框內的,向左向右移動一個字符的快捷鍵是一樣的。后兩個命令(u 和 d)則被 Vimium 借鑒,用于瀏覽器的翻頁。
還有幾個快捷鍵可以用于調整頁面布局:
zz:讓當前行居中顯示,方便瀏覽上下文
zt:讓當前行顯示在最上方,方便瀏覽后面的內容(t 表示 top)
zb:讓當前行顯示在最下方,方便瀏覽前面的內容(b 表示 bottom)
高級移動
代碼中經常遇到括號(包括 (、[ 和 {,也就是大中小三中括號),如果當前光標停留在括號上,按下 % 即可匹配到對應的括號上。
除此以外,*和#分別表示匹配當前光標下的單詞,并移動到下一個單詞和上一個單詞
第 4.3 章 Vim 文本編輯
閱讀完前兩章,相信讀者以及能夠在 Vim 中自如的移動光標了,不過我們的編輯方式還比較簡陋,只能進入編輯模式,像往常一樣逐個字符的輸入和刪除,本節會介紹一些更高級的操作。
基礎文本編輯
在普通模式下,按下 o會快速進入輸入模式,并且在下一行進行編輯。如果按下大寫的O會在上一行編輯:
如果想在當前光標位置開始編輯,可以按下 a 或 i,前者表示在光標所在字符的右側開始編輯,后者表示在左側開始編輯。
我們還可以用 I 前往行頭開始編輯,或者用 A 跳轉到行尾編輯。
按下 dd 可以快速刪除一行,此時被刪除的那一行會保存在 Vim 的剪貼板中。這一點類似于系統的 Ctrl + X 剪切,我們可以通過配置 Vim 來選擇是否要與系統共享剪貼板。
普通模式下,按下 p 可以把 Vim 剪貼板中的內容再拷貝出來,注意這里總是會拷貝到下一行或者光標的右側。因此如果想交換當前行和下一行,可以輸入:ddp,這是因為當前被刪除的行會復制到下一行的下面。
如果只想復制,不想刪除,可以把命令 p 換成 y(表示:yank)。如果想刪除后進入編輯模式,可以把 p 換成 c,比如 cc 表示刪除當前行并且從行首開始編輯。
注意這里的 p、c、y、d 都是動作,和前面說的 j、k、l、h、w、b、e 一樣,都支持用數字來重復,比如 2dd 表示刪除兩行。
撤銷與重做
如果想撤銷上一次修改,可以用 u,類似于系統的 Command + z 快捷鍵。
如果想重做,可以用 Ctrl + R,類似于系統的 Command + Shift + z 快捷鍵。
文本對象
Vim 的文本對象能極大幅度的提高編輯效率,也是 Vim 進階之路上必須要掌握的概念。
對于上文介紹的 c、d、y 這些動作來說,作為單獨的動作用處并不大,無非就是連續按兩下對當前行做一些操作,而文本對象則扮演了語法中名詞的概念,提供了更細粒度的操作。比如以下幾種操作:
diw: 刪除一個單詞(word)
ca":刪除雙引號內的文本并編輯(包含雙引號自身)
yi":復制雙引號內的文本(不包含雙引號自身)
dtx:向右刪除,直到遇到遇到字符 x(不包含 x)
以上三個命令都屬于同一大類操作,它們普遍遵循以下模式:
命令 = 動作 + 數量 + 描述詞 + 文本對象
這類命令通常由三個到字母組成:
第一個字母是動詞,包括上文介紹的 c、y、d等,表示你這個命令的主要目的。
第二個字母是可選的,表示重復幾次
第三個字母是對范圍的描述,比如 a 表示包含邊界,i 不包含,t 表示向右查找,T 向左。
第四個字母是文本對象,可以是內容的字面量描述,比如 "、'、<、`、{、( 等等,也可以是固定單詞
這里詳細介紹下文本對象,除了字面量外,以下單詞有特定的含義:
p:表示段落
s:表示句子
w:表示單詞
t:特指標簽,一定要具備 <xx>abc</xx> 的結構,此時的 t 代表 abc
對于字面量的文本對象,除了 "、' 和 這三個引號外,另外幾個括號都可以用 b 來表示(block),這樣就不用區分大中小和尖括號了。
搜索與替換
使用 / 進行搜索,我的搜索默認是忽略大小寫的,使用 /pattern\C 可以強制匹配大小寫。
使用 :范圍s/oldpattern/newpattern/替換模式 可以進行替換。
如果我們已經進行過搜索,那么 oldpattern 可以省略不寫,默認就是上一次的搜索內容。
最常用的范圍是 begin,end,其中 begin 是開始行號,end 是結束行號,表示在第 begin 行到第 end 行之間進行替換,比如::1,10s/hello/hallo/g 表示把第 1 - 10 行中所有的 hello 換成 hallo。
范圍還有一些簡單的表示法:
.,10 表示當前行到第 10 行,點表示當前行
.,$ 表示當前行到文件末尾,美刀符號表示文件結尾
% 表示 1,$,也就是整個文件,比如全文替換通常寫成 :%s/old/new/g
.,+2 表示當前行和接下來的兩行
上文反復提到的字母 g 其實是一種替換模式,表示替換這個范圍內所有出現的 oldpattern,如果不寫則只替換第一次出現。常用的模式還有 c,表示替換需要確認(Confirm),i 表示大小寫不敏感,I 表示大小寫敏感。
如果需要替換光標停留的單詞,并不需要搜索,或者手動輸入它。直接使用 <Leader + s> 即可。接下來只需要輸入替換后的內容和替換模式。這種替換是全局替換。
大小寫切換
以下是幾個常用的,切換大小寫的命令
guu 當前行全部小寫,gUU 當前行全部大寫
~ 當前光標下的字符切換大小寫, 3~ 當前光標下后面三個字符切換大小寫
guiw 當前單詞全部小寫,gUiw 當前單詞全部大寫
g~iw 當前單詞每個字符大小寫交換
列操作
如果有多行文本要做相同的操作,可以借助 Vim 中列操作的概念來快速完成,舉一個實際實際的例子,假設有以下這段代碼:
int a;
int b;
int c;
// ...
int z;
有一天我們發現 int 不是很準確,要改成:
uint8_t a;
uint8_t b;
uint8_t c;
// ...
uint8_t z;
難道還要手動復制粘貼不成?請看列操作大法:
首先按下 Ctrl + V 進入列操作模式
然后用 j、k 進行跳轉,表示你要操作多少行
這時你對每一行的操作都會應用到所有行上,比如輸入 ec,刪除單詞進入編輯模式
輸入 uint_8,按下 Esc 退出編輯,Vim 會自動應用到所有行上。
宏
列操作的本質是多行同時操作,如果每一行的操作類似,但都有細微差別,就需要引入 錄制、回放 的概念了。此時可以用 Vim 中的宏。
一個典型的場景是,我們在寫 Markdown:
1. 第一條
2. 第二條
3. 第三題
...
10. 第十條
寫著寫著突然發現,第一條和第二條中間還要加一條,左邊的序號就不好處理了,因為我們要把原來的序號 2 到 10 分別加一。
在 Vim 中,我們“只”需要輸入 qajC-aq6@a,相信你一定很想打我,這特么一點也不簡單啊。別急,拆開來看:
qa(q 表示開始錄制宏,a 表示錄制內容存儲在寄存器 a 中)
j(向下一行)
Ctrl + a(數字加一)
q(再按一次 q 表示結束錄制)
6@a(把存儲在寄存器 a 中的宏執行 6 次)
是不是感覺 So Easy(錄像中我用的是大寫 Q,因為小寫 q 被映射了):
第 4.4 章 Vim 神級插件
在本章的開頭,我就提到目前的主力 IDE 是 VSCode,其實和 Atom/Sublime 這類 IDE 一樣,它也是模擬了 Vim 的按鍵,并不支持 .vimrc配置文件。不過 VSCode 的強大之處在于,它支持了部分 Vim 的插件。
我想,不需要我做過多解釋,讀者也能明白這幾個被支持的插件的重要性了,必然都是 Life-Changing 系列的。下面就逐個介紹一下:
Easymotion
從名字就能看出,這個插件的目的是快速光標跳轉。它支持按行跳轉,按字符/字符串跳轉和按單詞跳轉等。跳轉時還可以選擇方向為向前或者向后, 不過這就增加了一倍的復雜度,作為一個懶人,我一般選擇全屏跳轉。
我配置的快捷鍵有:
;s:按字符串跳轉(跳轉到開頭)
;w:按單詞的開頭跳轉
;e:按單詞的結尾跳轉
;c:按字符串跳轉
;l:按行首跳轉(忽略空格)
完整的快捷鍵列表可以查看文檔。
Surround
上一節中介紹過文本對象(Text Object)的概念,它主要用來描述括號和引號中間的文本,但考慮一下變換:
"hello" -> 'hello'
如果想把雙引號換成單引號,就遠遠比改變 hello 這個單詞難了。而 Surround 這個插件的目的,就是為了方便對引號和括號做修改。
它支持以下幾種用法:
y s motion + <char>:給指定范圍添加 surround 字符,比如:ysaw" 表示用雙引號包裹單詞。
d s <char>:刪除周圍的 surround,比如 ds" 表示刪除兩側的雙引號
c s <old-char> <new-char>:更換周圍的 surround,比如 cs"'表示把周圍的雙引號換成單引號。
Comment
大多數 IDE 都支持 Command + / 給當前行添加注釋,而且會根據語言自動選擇注釋方式。
在 Vim 中,給當前行添加/取消注釋的方式是用 gcc,雖然多了一個按鍵,但按起來更容易了,而且支持多行注釋。這里前兩個字符 gc 表示按行注釋,最后一個 c 表示當前行。如果想注釋當前行和下面一行,可以輸入 gcj。
美中不足的是,有些語言(如 HTML)中 VSCode 會用 /* ... */ 的寫法進行多行注釋,這樣如果想取消注釋,就只能去注釋開始或結束的那一行把注釋全部取消,而不能只單獨取消中間某一行的注釋。
輸入 gC 可以注釋某一塊代碼,后面接一個文本對象,比如 gCi( 表示注釋括號內的東西(不包含括號)。不過個人認為注釋小括號的需求幾乎不存在,但下面這個場景還是有的,考慮這段代碼:
if (1 > 0) {
printf("Hello");
printf("wrold");
}
有時候我們只想注釋掉那兩行 printf,寫點別的邏輯,有時候會注釋掉整個 if。問題是,怎么用文本對象來表示呢?下一個插件可以讓我們用文本對象的方式來表示某一塊縮進
Indent
其實很簡單,一般就兩個文本對象:
ii:表示某一塊縮進,不包含上一層,比如上面例子中的兩個 printf
aI:表示某一塊縮進,包含上一層,比如上面例子中整個的 if 語句
其實還有一個不太常用的,ai 表示某一塊縮進,和它的上面一行,也就是上面例子中的前三行,不包括第四行的大括號。這在 Python 中非常常用,因為它沒有大括號,完全靠縮進來區分代碼塊。
因此,注釋掉兩行 printf 的語法是 gCii,注釋掉整個 if 語句的方法是 gCaI。
Sneak
sneak 是和 EasyMotion 差不多的插件,主打快速跳轉的功能。用法是 s<char><char>,即按下 s 鍵后輸入兩個字符,可以跳轉到下一個,這倆字符連續出現的位置。
然而相比原生的插件,VSCode 似乎有一個很嚴重的問題:不支持搜索高亮,這就導致我根本無法肉眼看出在當前位置和我的目標位置之間,隔了多少個 <char><char>,導致無法用重復來跳轉,也不支持標簽跳轉。更何況這個功能以及由 EasyMotion 實現了(快捷鍵 ;s),所以我就不再研究了。
第 4.5 章 VSCode 最佳實踐
基本設置
在 VSCode 中,按下 Command + ,可以編輯配置,配置分為全局配置和項目配置,項目配置的優先級高于全局配置。
按下 Command + k + Command + s鍵可以管理快捷鍵。
按下 Command + p 可以在項目中根據名稱搜索并打開文件。
按下 Command + Shift + p 可以打開命令面板,那些不記得快捷鍵的命令,都可以在這里找到。
掌握這些就可以初步使用 VSCode 了,下面會列舉一些我的配置和插件,更多關于 VSCode 的配置介紹,請參考:vscode-tips-and-tricks
通用插件
Beautify:代碼格式化插件,可以將 JS、CSS 和 HTML 代碼格式化
Code Outline :支持多種語言的 outline 提取
Code Runner:可以運行多種語言,我配置的快捷鍵為 Command + R。注意新的文本文件因為沒有后綴名,要用快捷鍵 Command + K + M 手動切換語言類型。
Dash:使用快捷鍵 Ctrl + h 快速打開 Dash 查找當前單詞
MarkdownLint:Markdown 語法檢查,幫助你寫出標準的 Markdown
Project Manager:幫助你管理項目,在多個項目間切換,快捷鍵 Option + P(首先要添加進項目列表)
TODO Highlight:高亮顯示 TODO
VSCode Icons:根據文件和文件夾名稱展示恰當的圖標
Bracket Pair Colorizer:給成對的括號配上顏色,方便區分
File Size:在底部 bar 中顯示文件大小
Path Intellisense:自動補全文件路徑
前端插件
Auto Close Tag:自動補全另一側的 Tag
Auto Rename Tag:修改一個 Tag 時,另一側的 Tag 自動修改
Color Highlight:遇到顏色字符串,自動在旁邊顯示顏色,方便預覽
CSS Peek:
ESLint:代碼格式化,支持實時監測和保存時自動修改
HTML Snippets:HTML 語法片段,方便快速輸入
IntelliSense for CSS class:CSS 自動補全
JavaScript code snippets:JS 的語法片段,方便快速輸入
Modern JavaScript Snippets:補充了一些更新的語法片段
HTML CSS Support:方便在 HTML 中插入 CSS 代碼
SASS:sass 格式文件的代碼補全和高亮
Vetur:Vue 開發必備的插件,提供代碼補全、高亮等功能
Vue 2 Snippets:Vue 2 的代碼片段
Vue peek:快速跳轉定義
語法插件
一般用什么語言就裝什么插件就行了。比如 Node、Bash、Python、Go、Ruby 等。
集成終端
VSCode 集成了一個終端,可以直接讀取 .zshrc 中的配置(也就是說使用起來和 iTerm 幾乎是一模一樣的)。相關快捷鍵有:
cmd + \: 水平切割,生成一個新的終端界面
cmd + 數字:當光標停留在終端時,通過數字來選擇要聚焦的窗口
cmd + w:當光標停留在終端時,關閉當前終端
cmd + t:當光標停留在終端時,新建一個終端
cmd + l: 在 VSCode 內嵌的終端和代碼編輯器中互相切換,再也不用跳出到 iTerm 了
``ctrl + ```:隱藏/展示 終端
第 5 章 Git 從入門到進階
對于很多人來說,Git 只是一種代碼同步工具,他們要做的無非就是在 Source Tree 或 Tower 這樣的應用上,先把代碼同步下來,然后選中本地的修改,推送到遠程倉庫而已。
有了這么傻瓜式的 GUI 工具,為什么還要學習 Git 呢?在我看來,主要有以下原因:
GUI 工具底層還是通過 git 命令行來實現,學習多個 GUI 工具的使用,不見得比學習 git 來得快。
git 命令博大精深,GUI 工具只支持一些最基本的操作,很多強大的命令無法通過 GUI 工具來實現。
git 命令能讓你從本質上去了解 git 的設計思想,這樣的思想將來可能會在別的場景下復用。
GUI 工具的操作無法自動化,而 git 命令可以借助 Shell 腳本,部署在任何機器上,與任何上下游服務串聯。
本章將由淺入深,首先介紹基本的 Git 配置,然后介紹 log、branch、tag、push、commit、diff、stash、reset、checkout、grep等操作。最后則會介紹一些進階配置和 Git 的核心原理。
由于本書的目的是提高效率,因此不會過多介紹每個命令的基礎用法,而是側重于分享很多人可能不清楚的進階用法,展示 git 命令行工具強大、高效的一面。
第 5.1 章 Git 配置
入門配置
配置文件原理
在 Git 中,我們一般只需要關注兩個配置文件,gitconfig 和 .gitignore,前者用來對 git 的行為進行配置,后者則用來指定文件的忽略規則。如果命中了規則,就不會添加到 Git 的版本管理中。
對于某個 Git 倉庫來說,一般同時有兩個 gitconfig 文件生效,一個是 ~/.gitconfig,它是全局的配置,另一個則位于每個 git 倉庫下的 .git/config。如果有重復的配置項,項目配置的優先級高于全局配置,否則兩者是相輔相成的關系。
.gitignore 文件也是類似,分為全局和項目兩個配置,區別在于在 git 倉庫中的任意一個目錄都可以有 .gitignore 文件,當然這個文件只對此目錄內的文件生效
配置 GPG 秘鑰
GPG 秘鑰可以確保提交的安全性,和 HTTPS 有些類似的是,使用 GPG 秘鑰的提交在 GitHub 上會顯示成綠色的 Verified 字樣。
為了實現這個效果,需要進行以下幾步:
如果使用我的安裝腳本可以跳過這一步,否則執行 brew install gpg 來安裝依賴。
輸入 gpg --full-generate-key 并按照配置安裝,注意第三步選擇時長時,如果是個人使用可以填 0,表示永不過期,避免以后的麻煩。最后填寫密碼時可以不填。
安裝完成后輸入 gpg --list-keys 查看剛剛生成的秘鑰,在 pub 下面有一長串數字和字母,這個是 GPG-ID。
輸入 gpg --armor --export pub GPG-ID 把公鑰復制出來,拷貝到 [GitHub GPG Keys](https://github.com/settings/keys) 上。
輸入 git config --global user.signingkey GPG-ID 來配置使用哪個 key。
單次提交時使用 git commit -s 參數來開啟 GPG key,或者使用git config --global commit.gpgsign true 設置為全局默認使用。
輸入 gvc <commit_hash> 來檢查某次提交的 GPG 簽名情況,如果沒有輸出,說明沒有簽名。它是git verify-commit命令的縮寫。
配置個人信息
首先要配置個人的名字和郵箱:
gce ktzhang@bestswifter.com:配置郵箱,這是我的簡寫,完整的命令是:git config user.email
gcn bestswifter:配置用戶名,完整的命令是 git config user.name
配置忽略規則
在 .gitignore 文件中我們可以配置需要忽略哪些文件和文件夾。注意,這個文件僅對還沒有被納入 git 版本管理的文件生效,一旦某個文件被暫存過,再配置 .gitignore 就無效了,此時我們需要先把所有的文件取消暫存,再重新暫存。
我配置了命令 reignore 專門用于解決這類問題,它的完整定義如下:
alias reignore='git rm -r --cached . && git add .'
如果某個文件不小心命中了忽略策略,就無法暫存到 git 中,而且 git 給出的提示并不友好。尤其是如果有多個 .gitignore 文件,很難知道哪一條規則導致了文件被忽略,此時可以使用 whyignore file_name 命令,它的完整定義時:
alias whyignore='git check-ignore -v'
進階配置
scmpuff
scmpuff 是一個 git 拓展,支持數字快捷鍵的操作,如圖所示:
尤其是當文件路徑較長時,我們可以用數字來代替文件,同時也支持 1-3 這種寫法,表示多個文件。
icdiff
git 默認的對比是上下對比,但個人認為不夠直觀。尤其是在大屏顯示器上,浪費了大量空間。
icdiff 是一個左右水平顯示的 diff 工具,在 git 中也可以使用:
function gdt() {
params="$@"
if brew ls --versions scmpuff > /dev/null; then
params=`scmpuff expand "$@" 2>/dev/null`
fi
if [ $# -eq 0 ]; then
git difftool --no-prompt --extcmd "icdiff --line-numbers --no-bold" | less
elif [ ${#params} -eq 0 ]; then
git difftool --no-prompt --extcmd "icdiff --line-numbers --no-bold" "$@" | less
else
git difftool --no-prompt --extcmd "icdiff --line-numbers --no-bold" "$params" | less
fi
}
然后用 gdt 來代替 git diff 即可,效果如圖所示:
尤其是當兩行只有少數變化時,默認的 git diff 會展示太多無用的干擾信息,而 icdiff 的輸出就非常簡潔直觀了。
非文本文件 Diff
默認情況下,對于圖片或者二進制文件,git 不會顯示它們的具體變化。但如果我們自己配置了 diff 工具,就可以顯示特定類型文件的變動。如果使用我的配置,默認自帶了圖片和 plist 文件的 diff 的功能。
也可以手動開啟,首先編輯 ~/.gitconfig 文件:
[core]
attributesfile = ~/.gitattributes
[diff "exif"]
textconv = exiftool
[diff "plist"]
textconv = plutil -convert xml1 -o -
然后編輯 ~/gitattributes 文件:
*.png diff=exif
*.jpg diff=exif
*.plist diff=plist
最后再安裝一下依賴:
brew install exiftool
最終 plist 文件的 diff 效果如圖所示:
第 5.2 章 查看提交記錄
Git 做為版本管理工具,最重要的特色之一就是強大的記錄查詢,可以花式查看各種提交歷史和變動,同時也支持過濾和篩選。本章主要介紹 log、diff 等工具的使用
Log
通過 git log 命令可以查看過去的提交記錄。這個命令非常常用,但也非常復雜,常見的有以下幾種:
基礎命令
在我的配置中,輸入 gg,它會單行展示提交歷史,也支持展示分支的關系,如圖所示。
它的完整命令是:
alias gg='git lg'
lg 命令可以通過上一節介紹的 gitconfig 來配置:
[alias]
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%ci) %C(bold blue) <%an>%Creset' --abbrev-commit
常用拓展
如果只想簡單的查看提交歷史,使用 gg 命令就足夠了。但如果想查看更細的內容,gg 就不太夠用了。我們可以輸入 ggs 命令,它在 gg 的基礎上會展示每次提交具體改動的文件,等價于命令 gg --stat,如圖所示:
如果想查看某次提交具體的變動,可以使用 ggp 命令。它在 gg 的基礎上會展示文件的具體改動,等價于命令 gg -p,如圖所示
進階使用
輸入 gga,可以展示所有的分支,一般建議用它代替 gg,它等價于命令 gg --all
不管是gg,還是衍生出來的 ggs 和 ggp,后面都可以加上 -n,比如 ggs -2,或者 ggp -1,表示只顯示前 n 個提交
如果想看某一個區間內的 log,可以輸入 gg HEAD~3..HEAD,注意區間是左開右閉,所以這個命令會查看三次提交的記錄。注意較早的提交要寫在左邊。
如果只記得某次提交內容\(content\)里有一個詞,比如 networksetup,可以用 ggp -G networksetup 來查找所有提交內容中包含 networksetup 的提交。-G 選項和 -S 選項主要有兩個區別, 前者可以接收正則,而后者只會查找那些導致 string 出現次數發現變動的提交,比如把 name:0 換成 name:1,用 -S 就無法搜索到 name, 因為它的出現次數并沒有改變,但是用 -G 可以。
如果只記得某次提交記錄\(message\)里有一個詞,比如 highlight,可以用 ggp --grep highlight 來查找所有提交記錄中包含 highlight 的提交
如果想查看某個文件中某一段代碼的提交記錄,可以用 ggp -L start,end:file_name 命令,詳情請參考 Git grep 這一節的用法。
如果想查看某個文件或者文件夾的改動歷史,可以輸入 gg file_name,當然 ggs 和 ggp 也都是支持的。
Diff
輸入 gd 即可查看工作區內的變動,等價于命令 git diff
輸入 gds 可以查看暫存區的變動,也就是查看那些被 git add 了的文件的變動,等價于命令 git diff --staged
輸入 gdc 可以查看最近一次提交的變動,等價于命令 git diff HEAD^ HEAD
輸入 gdcr 可以倒過來查看某次提交的變動,它的第一個參數是提交的 SHA-1 值,如果不寫則是 HEAD,所以 gdcr 和 gdc 是恰好相反的 diff。這樣的好處是如果 想撤銷某次提交,只要用 gdcr sha-1 就可以獲得那次提交的逆提交,如果想要精確到只恢復某個文件,第二個參數可以是文件名。比如 gdcr sha-1 file_name | git apply
輸入 gdt 即可用外部 diff 工具查看 diff,它是 git difftool --no-prompt --extcmd "icdiff --line-numbers --no-bold" "$@" | less 命令的縮寫,這個命令依賴 icdiff 這個工具,可以用 homebrew 安裝。
輸入 gdts 和 gdtc 可以對應的用外部 diff 查看已暫存和上次提交的變動,這些和 gds 與 gdc 命令基本上是一樣的,區別在于使用外部 diff 工具,會更美觀一些(當然速度也會更慢),效果如圖所示
Grep
這個命令和 grep 的區別在于運行更快,而且可以指定搜索范圍(比如是否搜索未跟蹤文件,搜索某個特定的 tag等),如果當前目錄是 git 目錄,可以用 ggrep 來替代 grep
ggrep 是 git grep --break --heading -n 命令的縮寫,第一個參數表示不同文件的搜索結果間用空格分割,便于閱讀。第二個參數非常有用,它不再在每一行輸出前面加上文件名,而是在所有屬于同一個文件的匹配之前加上一次文件名, 這樣輸出結果的可讀性更高,-n 表示輸出行號。
以查找 gignore 這個命令的歷史為例,先輸入 ggrep gignore,得到如圖所示的結果,這告訴我們它定義在 zsh-config/git.sh 這個文件的第 25 行
然后輸入 ggp -L 25,25:./zsh-config/git.sh,參數 —L 表示行內查找,即查找這個文件的第 25-25 行的提交記錄,得到的結果如圖所示:
提交的 SHA-1 值、日期、提交者等信息就完全顯示出來了
提交區間
git 的提交區間指的是用兩個點 A..B 或者三個點 A...B 的語法將 AB 兩個提交連接起來,從而表示一系列提交。
這是非常容易讓人產生疑惑的一個話題,主要是因為它沒有固定的含義,需要根據不同的命令來記憶。本文主要結合 diff、log 這兩個命令來介紹。
首先,假設我們基于初始提交建立了 a 和 b 兩個分支,各有一次提交,如圖所示。分支 a 的提交是數字,分支 b 的提交是字母。
diff
此時,雙點語法 A..B 表示對比這 AB 兩個提交的差異:
git diff branch_a..branch_b
# 直接對比兩個 commit
# 等價于直接寫空格
git diff branch_a branch_b
這個結果還是非常符合常識的,就不多解釋了。
三點語法 A...B 則表示:AB 兩次提交的共同祖先和 B 之間的 diff
git diff branch_a...branch_b
兩個分支的共同祖先是第一次提交,因此上述命令其實是展示分支 b 和 b 的父提交之間的 diff。如圖所示,
需要注意的是,如果兩次提交在同一個分支上,那么雙點和三點語法的效果是一致的。
log
log 的雙點語法 A..B 和 diff 的三點寫法具有相同的含義,都表示僅在 B,但不在 A 的那些提交。如圖所示:
比如:
ggp branch_b..branch_a
這個命令只會輸出分支 a 的日志,如圖所示:
三點語法 A...B表示的是那些只屬于 A 提交,和只屬于 B 提交的那些提交,如圖所示:
例如:
ggp branch_b...branch_a
這個命令將單獨得到分支 b 和 分支 a 上的各一次提交:
另外需要注意的是,根據我的實踐,git show 中的雙點、三點表示法和 git log 是一致的,就不另外說明了。
最后用一張圖來總結: