FZF and Vim Talk - Dorian Karter 影片詳細介紹如何在 VIM 中使用 fzf ,也就是透過安裝 fzf.vim 為 VIM 裝上強大的模糊搜尋的功能。
然而 fzf 強大的功能並不僅限於 VIM ,對於經常使用終端機進行開發的開發者而言,也有很多地方其實可以結合 fzf 增加效率,例如 fzfを活用してTerminalの作業効率を高める 一文就結合 fzf 與 git ,令 git 的使用變得更順手。
本文將透過幾個實例介紹 fzf 如何與終端機開發生活的結合。
fzf 是什麼?
fzf 可以說是 command-line 版本的 macOS Finder ,但卻又更加靈活,讓人可以利用其功能打造屬於自己的 fzf 應用。
上方 fzf 開發者所提供的預覽圖,多多少少揭露 fzf 所具有的功能:
- 模糊搜尋
- 選擇搜尋結果
- 預覽搜尋結果
首先最底下是搜尋列,可以任意輸入字串, fzf 會用模糊搜尋(fuzzy search)的方式進行搜尋,所以就算沒有使用完整的關鍵字也沒關係,搜尋上方顯示的是搜尋結果,同時可以用方向鍵選擇感興趣的搜尋結果,同時位於右側的預覽視窗(preview window)中會顯示其內容。
雖然 fzf 預設是搜尋資料夾內的所有檔名,但 fzf 是可以接受 pipe 進來的資料,以行為單位搜尋,例如搜尋 22 通訊埠(port)通常是什麼服務(service):
$ alias fp="cat /etc/services | fzf"
$ fp
有興趣的話建議可以進一步閱讀官方的 README & Wiki 。
接著就透過幾個實例說明 fzf 各項功能。
本文環境
- macOS 10.13.6
- iTerm2 3.2.5
- fzf 0.17.4
- zsh 5.5.1
macOS 安裝指令:
$ brew install fzf
flsof4
在開發後端伺服器時經常會不小心碰到 IP 或者 Port 衝突的情況,所以經常要 lsof -Pn -i4 | grep <ip_or_port>
進行查詢,這種情況相當適合用 fzf 解決:
$ alias flsof4="lsof -Pn -i4 | awk '{printf \"%10s %6s %5s %4s %-20s\n\", \$1, \$2, \$3, \$8, \$9}' | fzf --border --cycle --ansi --header-lines=1"
$ flsof4
上述指令用 lsof -Pn -i4
列出現在主機正在執行的 IPv4 網路服務,接著用 awk
取出需要的欄位,最後丟給 fzf 處理。
--border
指的是為 fzf 顯示邊框。
--cycle
指的是啟用循環捲動,用方向鍵移動選擇列的話,到底部之後會從頂部開始,或者到頂部之後,會跳回底部開始。
--ansi
則是啟用支援 ANSI color ,所以有些指令用 ANSI color 顯示色彩的話, fzf 的顯示結果也同樣會顯示色彩。
--header-lines=1
則是指,第 1 行視為標題列,所以標題列就不會被搜尋。
gcob
用 git 切換 branch 時,也結合 fzf ,將 branch 列出來之後,交給 fzf 處理,選擇完按 Enter ,就會切換 branch :
$ alias gcob='git checkout $(git branch | fzf --cycle --border --ansi)'
$ gcob
gadd
編者有個習慣是在 git add 檔案之前,需要先稍微瞄一下 diff ,判斷要不要一起 commit 。
這些動作同樣可以結合 fzf 的預覽視窗(preview window)功能,顯示檔案的 diff 在預覽視窗,減少打指令的次數:
$ alias gadd="git status --short | fzf --multi --color=dark --cycle --border --ansi --preview-window=up:70% --preview=\"git diff --color {+2}\" | awk '{print \$2}' | xargs git add"
$ gadd
--multi
指的是啟用多選的功能,所以可以按 Tab 同時選擇多個檔案。
--preview-window=up:70%
指的則是將預覽視窗顯示在上方,高度則佔整個視窗的 70% 。除了 up
之外還有 down
, left
, right
可選。
設定預覽視窗之後,還需要透過參數 --preview
設定要顯示的內容,因此 --preview=\"git diff --color {+2}\"
指的就是顯示檔案的 diff ,而 {+2}
指的就是選擇列所在的第 2 個欄位(預設以空格分隔,所以 {+1}
會取得 M
或 ??
)。
指令的最後則是結合 awk 與 xargs 將選擇的檔案交給 git add 。
gco
與 gadd
相同的技巧,也能夠應用在 git checkout
上,用來取消檔案變更:
$ alias gco="git diff --name-only | fzf --multi --color=dark --cycle --border --ansi --preview-window=up:70% --preview=\"git diff --color {+1}\" | xargs git checkout"
gustg
除了取消檔案變更,也可以將 staged 的檔案變回 modified:
$ alias gustg="git diff --name-only --cached | fzf --multi --color=dark --cycle --border --ansi --preview-window=up:70% --preview="git diff --color --staged {+1}" | xargs git reset HEAD"
$ gustg
gbrd
將 fzf 與 git branch -d
結合,讓刪除 branch 更加方便:
$ alias gbrd="git branch --color=always | fzf --multi --color=dark --cycle --border --ansi | sed 's/*//' | awk '{print \$1}' | xargs git branch -d"
fls
最後的範例(僅限 macOS)利用 fzf 提供的 key bindings 功能,讓我們可以設定快捷鍵在 fzf 的介面中觸發設定好的功能:
$ alias fls="fzf --multi --color=dark --cycle --border --ansi --preview-window=up:70% --preview=\"head -n 25 {+1}\" --bind 'ctrl-v:execute(vim {} < /dev/tty)' --bind 'ctrl-o:execute(open \$(dirname {}))' --bind 'ctrl-x:execute(echo {} | pbcopy)'"
$ fls
--bind 'ctrl-v:execute(vim {} < /dev/tty)'
按 Ctrl + v 會用 VIM 打開選擇列所選擇的檔案, execute()
內則可以放任何我們想要執行的功能,而 {}
就代表選擇列目前所選的字串。
--bind 'ctrl-o:execute(open \$(dirname {}))'
按 Ctrl + o 會打開該檔案的資料夾。
--bind 'ctrl-x:execute(echo {} | pbcopy)'
按 Ctrl + x 則會將檔案路徑複製到剪貼簿中。
總結
fzf 是十分強大的工具,運用得當的話,可以有效增加工作效率。除了本文介紹的幾個功能之外,其實還有許多功能讓人可以製作符合自己需求的 fzf 應用,建議可以閱讀官方文件,也許會有意想不到的收穫!
References
https://github.com/junegunn/fzf
https://www.youtube.com/watch?v=aXPQTesFdTI
https://qiita.com/kamykn/items/aa9920f07487559c0c7e