跳至主要內容

Fish Shell:告別 Bash 的配置地獄,擁抱現代終端體驗

6 分鐘閱讀 1,000 字

Fish Shell:告別 Bash 的配置地獄,擁抱現代終端體驗

多數開發者花了大量時間在設定 Bash 或 Zsh:安裝 oh-my-zsh、挑選 plugins、調整 .zshrc、修復奇怪的速度問題。Fish(Friendly Interactive SHell) 採取了截然不同的哲學:開箱即用,不需要外掛就能擁有完善的使用體驗。

安裝

# macOS
brew install fish

# Ubuntu/Debian
sudo apt-add-repository ppa:fish-shell/release-3
sudo apt-get update
sudo apt-get install fish

# 設定為預設 shell
echo /opt/homebrew/bin/fish | sudo tee -a /etc/shells
chsh -s /opt/homebrew/bin/fish

開箱即用的功能

1. 自動建議(Autosuggestions)

這是 Fish 最讓人驚艷的功能。Fish 會根據你的歷史記錄和目前目錄的內容,自動用灰色文字顯示可能的補全建議:

$ git commit -am "fix bug"█
                            ↑ 灰色建議:(昨天你輸入過的指令)

End 接受建議,Alt+→ 接受一個單字。完全不需要任何設定。

2. 語法高亮

Fish 在你輸入時就即時標示語法:

  • 有效的指令:藍色
  • 無效的指令:紅色
  • 字串:黃色
  • 參數:白色

讓你還沒按 Enter 就知道是否有打錯字。

3. Tab 補全

Fish 的 Tab 補全是目前 shell 中最完善的。它會顯示補全選項的說明文字,而且支援大多數常見工具(git、npm、docker、kubectl...):

$ git ch<Tab>
checkout  (Switch branches or restore files)
cherry-pick  (Apply some existing commits)
clean       (Remove untracked files)

4. 網頁設定介面

fish_config

執行這個指令會在瀏覽器開啟一個網頁介面,讓你用視覺化方式:

  • 選擇色彩主題(超多內建主題)
  • 管理縮寫(abbreviations)
  • 查看函式和環境變數

Fish 的語法差異

Fish 的語法與 POSIX shell(Bash/Zsh)不相容,這是最大的取捨。

變數設定

# Bash
export NAME="Alice"
VERSION=1.0

# Fish
set NAME "Alice"
set -x NAME "Alice"  # -x 表示匯出到子程序(等同 export)
set -U EDITOR nvim   # -U 表示全域持久(Universal,跨 session 保留)

條件判斷

# Fish
if test -f ~/.config/fish/config.fish
    echo "設定檔存在"
else
    echo "設定檔不存在"
end

# 更簡潔的寫法
if status is-interactive
    echo "這是互動式 shell"
end

迴圈

# for 迴圈
for file in *.ts
    echo "處理 $file"
end

# while 迴圈
set count 0
while test $count -lt 5
    echo "count = $count"
    set count (math $count + 1)
end

函式

# 定義函式
function greet
    set name $argv[1]
    echo "Hello, $name!"
end

greet "World"

# 帶說明的函式
function mkcd --description "建立目錄並進入"
    mkdir -p $argv[1] && cd $argv[1]
end

設定檔

Fish 的設定檔在 ~/.config/fish/config.fish

# ~/.config/fish/config.fish

# 環境變數
set -x EDITOR nvim
set -x LANG zh_TW.UTF-8

# 路徑(Fish 使用 list,不是冒號分隔的字串)
fish_add_path /opt/homebrew/bin
fish_add_path ~/.local/bin

# 縮寫(比 alias 更智慧,在輸入時展開)
abbr -a gs git status
abbr -a gp git push
abbr -a gc git commit
abbr -a d docker
abbr -a dc docker-compose

# 讀取 nvm / pyenv
if test -f ~/.nvm/nvm.sh
    bass source ~/.nvm/nvm.sh
end

縮寫(Abbreviations)vs 別名(Aliases)

Fish 的縮寫是獨特的功能:輸入縮寫後按空格或 Enter,會展開為完整指令顯示在命令列上:

$ gs<Space>
↓ 展開為
$ git status

這比 alias 好的地方在於:

  1. 你看得到實際執行的指令
  2. 可以在展開後繼續修改
  3. 別人看你的螢幕時知道你在做什麼

函式管理

Fish 的函式可以儲存為獨立的檔案,放在 ~/.config/fish/functions/

# ~/.config/fish/functions/gpr.fish
function gpr --description "建立 GitHub Pull Request"
    set branch (git branch --show-current)
    set base $argv[1]
    if test -z "$base"
        set base main
    end
    gh pr create --base $base --head $branch
end

Fish 會自動載入這個目錄中的所有 .fish 檔案。

常用第三方工具整合

fisher(套件管理器)

# 安裝 fisher
curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source
fisher install jorgebucaran/fisher

# 安裝常用套件
fisher install jorgebucaran/nvm.fish      # Node 版本管理
fisher install pure-fish/pure             # 精簡漂亮的 prompt
fisher install PatrickF1/fzf.fish         # fzf 整合

Starship(跨 shell prompt)

# 安裝 Starship(比任何 shell 特定的 prompt 都好用)
brew install starship

# ~/.config/fish/config.fish
starship init fish | source

處理 POSIX 不相容的問題

有時需要執行 Bash 腳本或來自網路的指令:

# 臨時切換到 bash 執行一行指令
bash -c 'export FOO=bar && some-bash-script.sh'

# 安裝 bass(讓 fish 可以 source bash 腳本)
fisher install edc/bass
bass source ~/.nvm/nvm.sh

Fish vs Zsh

特性 Fish Zsh + oh-my-zsh
開箱即用 需大量設定
自動建議 內建 需外掛
語法高亮 內建 需外掛
POSIX 相容
腳本撰寫 獨立語法 與 Bash 相似
啟動速度 視外掛數量而定

小結

Fish 最適合的使用者是:不想花太多時間設定 shell,但想要優秀互動體驗的開發者。它的 POSIX 不相容性是取捨,但如果你主要用 shell 做日常開發工作(不是寫可攜式腳本),Fish 的使用體驗遠超 Bash 和設定繁複的 Zsh。試用一週,你大概就不想回去了。

分享這篇文章