ZshとNeoVimの設定見直し で設定したZshrcをベースにして愛用してきましたが、生成AI(ChatGPT-5.2)の力を借りて設定を見直した。
改善点
- 壊れてた判定関数を正しく(return $(…) をやめる)
- localeは触らない(LC_ALL は特に事故りやすい)
- 補完は初回から効くように(zinit遅延ロード×compinit順序の地雷回避)
- 重い一覧は ll/la に隔離して、普段の ls を遅くしない
背景:.zshrc は「便利」と「破壊」が紙一重
zshrcの改善って、見た目やalias追加よりも「間違った書き方が静かに壊す」系の地雷が多い。今回ハマりどころだったのはこの4つ:
- _has/_try の return $(…)
- locale(LC_ALL の上書き)
- zinit の遅延ロードと compinit の順序
- ls 相当を重くしすぎる alias
1) _has/_try: return $(…) は“出力を終了ステータスにする”事故
return が返すのは 0〜255 のステータス。ここに $(…) の標準出力を食わせると、空文字/文字列になって壊れる(意図とズレる)。
修正はシンプルで、「そのコマンドを実行して終了ステータスを返す」だけ。
_has() {
whence -w -- "$1" >/dev/null 2>&1
}
_try() {
eval "$*" >/dev/null 2>&1
}ポイント:
- “$1” / “$*” は必ずクォート(空白や特殊文字で壊れるのを防ぐ)
- _try は eval なので使い所は限定(今回は既存設計を崩さず安全側に寄せた)
2) locale:LC_ALL は“全部上書き”なので .zshrc で触らない
一度 LC_ALL をexportすると、LC_CTYPE や LC_MESSAGES など全カテゴリが強制される。結果として日本語が化ける・コマンドの出力が変わる・想定外の挙動になる。
今回は .zshrc 内で LC_ALL は設定しない方針にして、LANG が空なら UTF-8 を入れるだけにした。
if [[ -z ${LANG-} ]]; then
export LANG=ja_JP.UTF-8
fi
# NOTE:
# Avoid setting LC_ALL here. It overrides all LC_* categories and can easily
# cause mojibake. If you need C locale for a single command, do:
# LC_ALL=C <cmd>運用tips:
- 「ソートだけCでやりたい」みたいな用途は、そのコマンドだけ LC_ALL=C cmd にするのが安全。
3) 補完:zinit遅延ロードとcompinitの順序で“初回だけ効かない”が起きる
補完ソース(例:zsh-completions)を遅延ロードしておいて、先に compinit を走らせると、初回だけ補完が微妙になることがある。
今回は補完系は遅延しないで先に読み、compinit -C(キャッシュ)で軽くした。
zinit light zsh-users/zsh-completions
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
zstyle ':completion:*:default' menu select=1
autoload -Uz compinit && compinit -C4) alias:重い ls 互換は ll/la に隔離
eza のオプション盛り盛り(icons/git/time-style/all/long)は気持ちいいけど、ディレクトリが大きいと普通に遅い。
なので「重いのは明示コマンドへ」で、ll/la を生やした。
which eza > /dev/null && alias ll='eza --icons --git --time-style relative -al'
which eza > /dev/null && alias la='eza --icons --git --time-style relative -a'ついでに潰した地雷:スマートクォートで alias が死ぬ
alias dc=‘docker-compose’ みたいなスマートクォート混入は、その行だけ無効になるやつ。ASCII ’ に統一した上で、docker v2優先のフォールバックにした。
if _has docker; then
if _try "docker compose version"; then
alias dc='docker compose'
elif _has docker-compose; then
alias dc='docker-compose'
fi
fi検証:最低限これだけ
- 文法チェック(副作用なし)
zsh -n ~/.zshrc- 反映(新しい環境で評価)
exec zsh -l※ 文字化けが出た時は「古いシェル/ターミナルが古い環境を保持してた」ことがあるので、必要ならターミナル再起動。
まとめ
- .zshrc は “便利さ” より先に 壊れないこと を優先した方が、結局気持ちよく使える
- LC_ALL は局所化、補完は順序、重い表示は ll/la に逃がす
- return $(…) は論外(出力≠終了ステータス)
参考
- Zsh builtins / compinit: man zshbuiltins, man zshcompsys
- Zinit: https://github.com/zdharma-continuum/zinit