ちなみに

仕事用のマシンをM1 MacBook Proに交換してもらったので、開発環境を整え直しました。

2年ほど fish を使ってきたのだけれど、普段は良いのだけれど、ちょっと自動化したくなったときに、やはりPOSIX準拠じゃないシェルはなかなか難しかった。macOSの標準も zsh になったことだし、久しぶりに戻ってみることにした。

導入

現代なので XDG Base Directory Specification に乗っかっておくことにする。
Arch Linux の Wiki がよくまとまっていて助かるのでこれを参考にして進めた。

zshの場合は ZDOTDIR を指定するといいのだけれど、これをどこで指定するのかという問題がある。zshの起動時に最初に読み込まれるユーザー設定は ~/.zshenv なのだけれど、ここに ZDOTDIR を書くということは .zshenv だけホームディレクトリに残ってしまう。これはちょっと気持ち悪い。

あんまり嬉しくはないのだけれど、諦めて /etc/zshenv に書くことにします。

ZDOTDIR=

$HOME

/.config/zsh

これで zsh のユーザー毎の設定ファイルは ~/.config/zsh から読まれることになります。(仕事用の macOS だし自分しかユーザーはいないしまあいいでしょ)

次に仕様に沿った環境変数を ~/.config/zsh/.zshenv 設定していきます。
特にひねることはないので推奨のディレクトリにしておきます。
(GOPATH~/local に ghq のルートディレクトリを ~/local/src にしているので ~/.local はちょっと気持ち悪くはあります。)

export

XDG_CONFIG_HOME=

"

$HOME

"

/.config

export

XDG_CACHE_HOME=

"

$HOME

"

/.cache

export

XDG_DATA_HOME=

"

$HOME

"

/.

local

/share

export

XDG_STATE_HOME=

"

$HOME

"

/.

local

/state

はい、これで基本的な準備は整いました。

zsh は最新のものを使いたいので Homebrew でインストールしておきます。

$ brew install zsh

Zim

zsh をそのまま使うなんてことは出来ないので、設定をごりごり書いていきたい訳ですが、最近はもう自分で設定を書くのは面倒になっています。
もうちょっと若いときは無限に設定ファイルを触っていられたのですが、こうやってどんどん新しいことを学べなくなっていくのです。

設定なしに良い感じになって、かつ Oh My Zsh の遅さに辟易としていたのでとにかく速いのを探しました。

いくつか見て回って Zim が良さそうだったのでこれを導入します。

導入は最近よく見る curl を叩くやつ。

$ curl -fsSL https://raw.githubusercontent.com/zimfw/install/master/install.zsh 

|

zsh

.zshrc にいくつか設定が書き込まれます。よく見ると設定が読み込まれたときにさらに本体のダウンロードを行うようです。

なんとこれだけでまあまあ良い感じに動きます。そして起動が速い!!!

asciiship という Spaceship や Starship を ASCII 文字だけで表現したテーマがデフォルトになっているのですが、もうこれでいいや感があったのでそのままにしています。どんどんこだわりが失われていっている。

他にもテーマがあったり、公式のモジュールもあるので ドキュメント を参照してください。

その他の設定

履歴ファイルの設定だけ .zshenv に書いても効いてくれなかったので以下のように .zshrc に書きました。
zim が上書きしている感じなのですが、設定済なら無視するように書かれているように見えるので多分何かを間違っているだけなはず。しかし調べる元気がない。

export

HISTFILE=

"

$XDG_DATA_HOME

"

/zsh/

history

あとは cdr とか AUTO_CD 周りの設定を少し書いた。
AUTO_CD 自体は Zim が有効にしてくれている。

 

autoload

-Uz chpwd_recent_dirs cdr add-zsh-hook add-zsh-hook chpwd chpwd_recent_dirs

zstyle

':completion:*:*:cdr:*:*'

menu selection

zstyle

':chpwd:*'

recent-dirs-max

100

zstyle

':chpwd:*'

recent-dirs-default

true

zstyle

':chpwd:*'

recent-dirs-insert

true

zstyle

':chpwd:*'

recent-dirs-file

"

$XDG_DATA_HOME

"

/zsh/chpwd-recent-dirs cdpath=(~ ..)

u というリポジトリのルートディレクトリに移動する関数を書いておく。
これはたしか ujihisa さんの設定から持ってきたのをずっと使っている気がする。
今回は補完関数も書いたけど、そこまで便利じゃないしバグがある。

function

u() {

cd

./

"

$(

git rev-parse --show-cdup

)

"

if

[

$#

=

1

];

then

cd

"

$1

"

fi

} _u() { _values

$(

fd --type d --base-directory

$(

git rev-parse --show-cdup

))

} compdef _u u

fishで一番良かったのが abbr だったと思うので、これを zsh でも再現させたい。
abbr は alias とは違って、省略形のコマンドを入力すると省略しない形に展開してくれるやつ。
g って入力してスペース打つと git に展開してくれる。
alias を覚えるのがつらくなってきたので展開してくれる方が元のコマンドに紐付けて覚えるので助かる。

zsh で同じ機能を実現するのに zsh-abbr が使えるのでこれを導入した。

zim にはプラグイン機構もあるのでこれを使って導入する。

$DOTDIR/.zimrc に以下の一行を加えて zimfw install というコマンドを打つだけ。

zmodule olets/zsh-abbr

これで導入が完了するので設定していく。abbr コマンドを使っても設定できるが $DOTDIR/abbreviations に書いておくと一括で指定出来る。
僕は以下のようにしている。

abbr b=

"bundle"

abbr be=

"bundle exec"

abbr d=

"docker"

abbr dc=

"docker compose"

abbr di=

"git diff"

abbr e=

"exit"

abbr g=

"git"

abbr gd=

"git diff --cached"

abbr ggrep=

"git grep"

abbr gl=

"git log"

abbr gr=

"git restore"

abbr gs=

"git switch"

abbr l=

"git log"

abbr p=

"git pull"

abbr pick=

"git cherry-pick"

abbr pop=

"git stash pop"

abbr s=

"git status -sb"

abbr st=

"git stash"

fzf

これまではコントリビュートする程度には peco を使ってきたのですが、気分を変えようと fzf に移行しました。
なんか勝手に重いイメージだったけれど、別にそんなことはなかった。
fzf は preview が出せるのが見た目が良くて楽しい。

導入はREADMEに従って Homebrew でインストールした。

$ brew install fzf
$ $(brew --prefix)/opt/fzf/install

補完の設定が生成されるので、それを .zprofile とかで読み込んでおく。

[ -f ~/.fzf.zsh ] && 

source

~/.fzf.zsh

ここまですると Ctrl-r で zsh の履歴検索、 Ctrl-t でカレントディレクトリ以下のファイル検索が fzf 経由で出来るようになる。

モダンなコマンド達と組み合わせるために fzf module を追加しておく。
モダンなコマンドというのは fd と bat のことです。

zmodule fzf

$DOTDIR/.zimrc に追加して zimfw install する。

これでファイルの検索が爆速になるし、プレビューがカラフルで見やすくなる。

あとは良い感じのをいくつか定義しておく。

まずはデフォルトの設定を .zshenv に書いておく。peco のデフォルトに慣れているので --layout=reverse だけは外せない。あとはお好みで。

export

FZF_DEFAULT_OPTS=

'--layout=reverse --border --exit-0'

最近はほとんどを VSCode の中で過ごしているので使う機会は限られているのだけれど、必要そうなのを書いておく。

ghqでリポジトリを選んで移動するやつ。最低限これさえ出来ればあとはどうでもいい。

fzf-ghq() {
  

local

repo=

$(

ghq list

|

fzf --preview

"ghq list --full-path --exact {} | xargs exa -h --long --icons --classify --git --no-permissions --no-user --no-filesize --git-ignore --sort modified --reverse --tree --level 2"

)

if

[ -n

"

$repo

"

];

then

repo=

$(

ghq list --full-path --exact

$repo)

BUFFER=

"cd

${repo}

"

zle

accept-line

fi

zle

clear-screen }

zle

-N fzf-ghq

bindkey

'^[s'

fzf-ghq

プルリクを検索しつつそのブランチに switch するやつ。
仕事では JIRA を使っていて、ブランチ名をチケットの番号にしているので目的のブランチを探すのが大変なことがある。
そんな時にはプルリクから検索して切り替えられると便利なので追加した。
gh が必要なのでインストールしておきましょう。
最近 id:shiba_yu36 さんが pecoで似たようなこと をされていた

fzf-pullreq() {
  

local

pullreq=

$(

CLICOLOR_FORCE=

1

GH_FORCE_TTY=

100

% gh pr list

|

tail -n

+4

|

fzf --ansi --bind

"change:reload:CLICOLOR_FORCE=1 GH_FORCE_TTY=100% gh pr list -S {q} | tail -n+4 || true"

--disabled --preview

"CLICOLOR_FORCE=1 GH_FORCE_TTY=100% gh pr view {1} | bat --color=always --style=grid --file-name a.md"

)

if

[ -n

"

$pullreq

"

];

then

pullreq=

$(

echo

$pullreq

|

awk

'{ print $1 }'

)

BUFFER=

"gh pr checkout

\"

${pullreq}

\"

"

zle

accept-line

fi

zle

clear-screen }

zle

-N fzf-pullreq

bindkey

'^[p'

fzf-pullreq

Git のブランチを切り替えるやつ。特におもしろみはない。

 
fzf-branch() {
  

local

format=

"\

%(color:yellow)%(refname:short)%(color:reset)|\

%(color:bold red)%(objectname:short)%(color:reset) \

%(color:bold green)(%(committerdate:relative))%(color:reset) \

%(color:bold blue)%(authorname)%(color:reset) \

%(color:yellow)%(upstream:track)%(color:reset)|\

%(contents:subject)"

local

branch=

$(

git for-each-ref --color=

always

--sort=-committerdate

"refs/heads/"

--format=

"

$format

"

|

column -ts

"|"

|

fzf --preview

"git log --color {1}"

)

if

[ -n

"

$branch

"

];

then

branch=

$(

echo

$branch

|

awk

'{ print $1 }'

)

BUFFER=

"git switch

${branch}

"

zle

accept-line

fi

zle

clear-screen }

zle

-N fzf-branch

bindkey

'^[b'

fzf-branch

前半で設定した cdr のディレクトリを選択して移動できるやつ。

 
fzf-cdr(){
    

local

dir=

$(

cdr -l

|

fzf --preview

'f(){ zsh -c "exa -h --long --icons --classify --git --no-permissions --no-user --no-filesize --git-ignore --sort modified --reverse --tree --level 2 $1" }; f {2}'

)

if

[ -n

"

$dir

"

];

then

dir=

$(

echo

$dir

|

awk

'{ print $1 }'

)

BUFFER=

"cdr

${dir}

"

zle

accept-line

fi

zle

clear-screen }

zle

-N fzf-cdr

bindkey

'^[r'

fzf-cdr

しれっと exa を使っているのでこれもインストールしておきましょう。
ls などを exa に読み替えてくれるモジュールがあるのでこれも入れておく。いつも通り .zimrc に追加して zimfw install です。

zmodule exa

ls の 挙動 をちょっと弄りたかったので以下のようにしています。

alias

ls=

'exa --classify --icons -h --reverse'

これで fzf を最低限は使えるようになりました。

この記事は Cornelius で書きました。