Zsh 是個蠻有名的 Shell,因為有 Oh My Zsh
的緣故可以讓人很輕鬆的有個漂亮、方便好用的 Shell。
我原本也是使用這個,不過我覺得它的效能有點慢,自訂性其實也沒那麼強,所以就研究看看了怎麼透過自己寫自己的
.zshrc
去達成一些自訂功能,然後分享一下我的作法。
要看我寫文章時的 Shell 長怎樣的可以看:
https://asciinema.org/a/7vvdQ5xpUNJu3FAWdLvUIDsDc
這個是我寫文章當下的
.zshrc
,想看的可以到這邊看。而這個 dotfiles
的
repo 也有包含其他我用在 WSL 上的一些 dotfiles。
Zinit 與第三方插件
我雖然是從 Oh My Zsh 轉走,不過還是有些 Oh My Zsh
的功能我還想繼續用,所以打算找個方法可以只使用部分的功能。然後經過一些研究就發現說原來
Zsh 還有 Plugin Manager 之類的東西,如 Antigen 之類的,而 Zinit 就是其中之一。
Zinit 是一款功能多、強大的一個 Plugin
Manager,但使用起來也很複雜,有一定的學習門檻。建議先從官網的 Introduction
開始看過一遍會比較好。 還有它有個 turbo mode
的部分也相當重要,會延遲加載一些功能來提升開啟 Zsh
的效能,以達成馬上就能用的效果。
我使用了它來載入了一些 Oh My Zsh 的一些功能以及一些其他的好用插件,而
Prompt 則是使用了 Powerlevel10k,一樣使用了
Zinit 來載入的。 最後我還用它來自動下載並載入一些方便的工具,如
jq
, rg
之類的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| source ~/.zinit/bin/zinit.zsh
zinit snippet OMZL::history.zsh zinit wait lucid for \ OMZL::key-bindings.zsh \ OMZP::sudo
zinit wait lucid light-mode for \ zsh-users/zsh-history-substring-search \ atinit"zicompinit; zicdreplay" \ zdharma/fast-syntax-highlighting \ atload"_zsh_autosuggest_start" \ zsh-users/zsh-autosuggestions \ blockf atpull"zinit creinstall -q ." \ zsh-users/zsh-completions
zinit ice depth=1 zinit light romkatv/powerlevel10k
zinit lucid for \ as"program" pick"bin/n" tj/n
zinit lucid from"gh-r" as"program" for \ pick"jq-*" mv"jq-* -> jq" stedolan/jq \ pick"ripgrep-*-linux-*" extract mv"*/rg -> rg" BurntSushi/ripgrep \ pick"exa-linux-*" extract mv"exa-* -> exa" ogham/exa \ pick"bat-linux-*" extract mv"*/bat -> bat" @sharkdp/bat
|
WSL 相關設定
我使用這個的地方主要是在一個 WSL2 的環境中使用的,所以會有些和 WSL
有關的設定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| if [[ -v WSL_DISTRO_NAME ]] then alias ex=/mnt/c/Windows/explorer.exe upd_ssh(){ rm -rf ~/.ssh /bin/cp -rf "/mnt/c/Users/$(whoami)/.ssh" ~/.ssh chmod 600 ~/.ssh/* } WIN_PATH=$(echo $PATH | tr ':' '\n' | grep '/mnt/c' | tr '\n' ':' | sed 's/.$//') export PATH=$(echo $PATH | tr ':' '\n' | grep -v '/mnt/c' | tr '\n' ':' | sed 's/.$//') zinit wait'3' lucid atinit'export PATH="$PATH:$WIN_PATH"' nocd for /dev/null fi
|
關於 Zsh 在 WSL2
中的效能問題
WSL 預設是會自動把 Windows 的 PATH
中加入 WSL 的
PATH
的,在一般情況下應該要不成問題。但是 Zsh 會自動為了
Autocomplete 去你的 PATH
中搜尋,而 WSL2 中存取 NTFS
的速度又很慢就導致了啟動的效能問題。參考 WSL#4256。
解決方法之一是直接把加入 Windows PATH
的功能關閉如下,但這個又會讓你沒辦法方便的存取一些 Windows 的功能。
1 2 3
| [interop] appendWindowsPath = false
|
所以我就想能不能透過 Zinit 的延遲功能來幫我把 PATH
給延遲掉,然後也真的能達成我想要的目標。結果就是上面的那三行:
1 2 3
| WIN_PATH=$(echo $PATH | tr ':' '\n' | grep '/mnt/c' | tr '\n' ':' | sed 's/.$//') export PATH=$(echo $PATH | tr ':' '\n' | grep -v '/mnt/c' | tr '\n' ':' | sed 's/.$//') zinit wait'3' lucid atinit'export PATH="$PATH:$WIN_PATH"' nocd for /dev/null
|
SSH
Agent
1 2 3 4
| if (( $+commands[keychain] )) && [[ -a ~/.ssh/id_rsa ]] then eval `keychain --quiet --eval --agents ssh id_rsa` fi
|
這部分其實就上面短短的幾行,不過會使用到 keychain 來保留 agent 的
session 所以需要先安裝。在類 Debian 的系統上用下面的指令就能安裝了:
1
| sudo apt install keychain
|
Autocomplete
Zsh 的 SSH 自動補全預設會來自很多的地方,包括 /etc/hosts
裡面的域名都會自動補全,但 ~/.ssh/config
卻不會...
所以我想讓它只 autocomplete 我 ~/.ssh/config
裡面的伺服器就好,所以就稍微研究了一下弄出了下面這一段。
1 2 3 4 5 6 7 8 9 10
| zstyle ':completion:*:ssh:argument-1:*' tag-order hosts h=() if [[ -r ~/.ssh/config ]]; then h=($h ${${${(@M)${(f)"$(cat ~/.ssh/config)"}:#Host *}#Host }:#*[*?]*}) fi if [[ $#h -gt 0 ]]; then zstyle ':completion:*:ssh:*' hosts $h zstyle ':completion:*:slogin:*' hosts $h fi
|