【Zsh】大改造ターミナル環境【Zinit】

:::note info
続きの記事
[【Zsh】続・大改造ターミナル環境 〜zeno.zshでCLI操作を快適にする〜【Zinit】 - Qiita](https://qiita.com/obake_fe/items/da8f861eed607436b91c)
:::

エンジニアの必須アプリである**ターミナル**。
どうせなら格好良くて使いやすいようにカスタマイズしたいですよね。

自分もエンジニアになりたての頃、[こちらのQiitaの記事](https://qiita.com/kinchiki/items/57e9391128d07819c321)を参考に**Zsh**のフレームワークである**Prezto**でターミナル環境を整えていましたが、そろそろ自分の好きなようにカスタマイズしたくなってきました。

本記事は、数あるZshプラグインマネージャの中でもターミナル起動速度が早いといわれる**Zinit**を使用し、ターミナル環境を整えていくやり方の備忘録となります。

# 手順
①ターミナルアプリの**iTerm2**をインストール
②macOS用パッケージマネージャである**Homebrew**をインストール
③Homebrewから**Zsh**をインストール
④Zsh用プラグインマネージャである**Zinit**をインストール
⑤Zinitで**便利なプラグイン**をインストール

※過去に別のフレームワークやパッケージマネージャを使用している場合は、それらを事前にアンインストールしておきましょう。

```shell:例）zpreztoのアンインストール
$ rm -rf ~/.zprezto ~/.zlogin ~/.zlogout ~/.zpreztorc ~/.zprofile ~/.zshenv ~/.zshrc
```
**参考**：[Macにzshとpreztoのインストール＆アンインストール、諸々の設定 - Qiita](https://qiita.com/s_s_satoc/items/e3c1b9b3545fd572dd1c)


## ①iTerm2

デフォルトのターミナルアプリだと設定できる項目が物足りないです。
そのため拡張版のターミナルアプリである**iTerm2**をインストールしましょう。

[公式サイト](https://iterm2.com/index.html)からDLする、もしくはすでにHomebrewをインストールしているならば、こちらのコマンドでcliからインストールすることもできます。

```shell
$ brew install --cask iterm2
```

### (1) ホットキー設定

iTerm2を使うなら、これだけは絶対にやってほしい設定。
設定したキーを押すだけで、ターミナルウインドウを出したり消したりできます。

**参考**：[iTerm2のおすすめ設定〜ターミナル作業を効率化する〜 - Qiita](https://qiita.com/ruwatana/items/8d9c174250061721ad11)
![c1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/9f196111-4bfe-f8d3-f4e1-89f19a941a4d.gif)

### (2) 設定同期

会社の端末と私物PCで同じ設定にしたい。。
そんなときは設定ファイルをGitHubやiCloudにアップすることで、複数の端末で設定を同期できます。

**参考**：[ITerm2の設定をGitHubで共有……できんやんけ！って思ってたけどそうでもなかった - めっちゃいいタイトル思いついたんだけど風呂入ったら忘れちゃった](https://ry-2718.hatenablog.com/entry/2019/04/02/021006)
![iterm2douki.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/f9bad5c1-1d2e-29b7-19f0-f13b447d9616.png)

## ②Homebrew

以下コマンドで、Homebrewがインストールされているか確かめることができます。
インストール済みの場合はHomebrewのバージョンが表示されます。

```shell
$ brew -v
```

### (1) Homebrewインストールがまだの人

#### xcode-selectインストール

Homebrewを使用するためには、**xcode-select**と呼ばれるコマンドラインツールが必要です。
まずはインストールされているか確かめます。

```shell
$ xcode-select -v
xcode-select version 2373.
```

バージョンが表示されればインストール済みです。

まだの人はこちらのコマンドでインストールできます。

```shell
$ xcode-select --install
```

#### Homebrewインストール

続いてHomebrewについて。
以下コマンドでインストールできます。公式サイトは[こちら](https://brew.sh/index_ja.html)。

```shell
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

バージョンが表示されれば、インストール完了です。

```shell
$ brew -v
Homebrew 2.6.0
```

### (2) Homebrewをインストール済みの人

#### アップデート

ついでにやってしまいましょう。

```shell
$ brew update
```
**参考**：[brewのupdateとupgradeの違い - Qiita](https://qiita.com/okhrn/items/aa71b066a525456550c0)

#### 問題チェック

`brew doctor`コマンドはHomebrewの問題をチェックしてくれるコマンド。 
何も問題がない場合は、以下のように表示されます。

```shell
$ brew doctor
Your system is ready to brew.
```

**参考**：[Homebrewの問題を確認する"brew doctor"コマンドとWarning対策集[macOS] - 一馬力のメモ帳](https://ichibariki.com/entry/2018/03/24/213524)

## ③Zsh

macOSでは**「Catalina」**バージョンから、デフォルトのシェルが**Bash**から**Zsh**に変わりました。
ただし、デフォルトで入っているものは大抵古いバージョンのため、ここでは新規Zshをインストールし直すところから始めます。

### (1) Zshのインストール

HomebrewからZshをインストールします。

```
$ brew install zsh
```

### (2) ログインシェルの変更

シェルをインストールしただけでは、ターミナルに反映されません。
起動時にこのシェルを使用するよ！という設定が必要となります。

#### ログインシェルの確認

まずは現在のログインシェルの確認です。

```shell
$ echo $SHELL
/bin/zsh
```

特に変更を行っていない場合は、`/bin/bash`とか`/bin/zsh`と出力されていると思います。
これはmacOSのデフォルトのシェルです。

こちらを先程インストールしたZshに変更しましょう。

#### シェルの変更設定

シェルを管理しているファイルは`/etc/shells`というファイルです。
こちらに今回HomebrewでインストールしたZshのパスである、`/usr/local/bin/zsh`を記入します。

vimで編集する場合は、rootでないと書き込み保存不可のため`sudo`で編集してください。

```
$ sudo vi /etc/shells
```

```shell:/etc/shells
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/usr/local/bin/zsh # 追記しました
```

`chsh`コマンドでログインシェルを切り替えます。

```shell
$ chsh -s /usr/local/bin/zsh
```

ターミナルを再起動して、再度ログインシェルを確認します。

```shell
$ echo $SHELL
/usr/local/bin/zsh
```

これでログインシェルが、HomebrewでインストールしたZshに変更されました。

### (3) エラーが起こる場合

#### 権限エラー

シェルを切り替えてターミナルを立ち上げたら、以下のエラーがでてしまいました。

```shell
zsh compinit: insecure directories, run compaudit for list.
Ignore insecure directories and continue [y] or abort compinit [n]?
```
どうやらZshの管理フォルダがinsecureになっているためのようです。

言われた通りコマンドを実行すると、insecureなディレクトリを教えてくれるため、

```shell
$ compaudit
There are insecure directories:
/usr/local/share/zsh/site-functions
/usr/local/share/zsh
```

それらの権限を変更してあげましょう。

```shell
$ chmod 755 /usr/local/share/zsh/site-functions
$ chmod 755 /usr/local/share/zsh
```

ターミナルを再起動すると、エラーが消えているはずです。

## ④Zinit

:::note info
※2022/10 追記

Zinitは一度プロジェクトごと削除されたため、公式の場所が変わりました。
詳細な経緯などは以下の記事が詳しいです。
[zsh の zinit (旧zplugin) が消滅しちゃったよ！ 経緯と解決法 - Qiita](https://qiita.com/taiyodayo/items/c1ebdc863e6baa18ea06)
:::

次にZshのプラグインをインストールするためのプラグインマネージャをインストールしましょう。
不安な方は、[公式](https://github.com/zdharma-continuum/zinit#install)を参照してください。

```shell
$ bash -c "$(curl --fail --show-error --silent --location https://raw.githubusercontent.com/zdharma-continuum/zinit/HEAD/scripts/install.sh)"
```

インストールが成功すると、ホームディレクトリに`.zinit`というフォルダが生成されているはずです。
Zinitをアクティブにするために`~/.zshrc`ファイルを再読込みし、Zinit自身も最新化しておきましょう。

```shell
$ source ~/.zshrc
$ zinit self-update
```



## ⑤Zshプラグイン

ここからが本題です。
便利なプラグインをインストールして、快適ターミナル環境を作っていきます！

### (1) テーマ設定

まずは見た目の変更です。
ここでは**[Powerlevel10k](https://github.com/romkatv/powerlevel10k)**と呼ばれるZshテーマをインストールします。

プロンプトにアイコンを表示できるところがお気に入りです。
![terminal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/39112305-0db6-3f73-6898-015cbc849a1e.png)

#### フォント
Powerlevel10kを使いこなすために、まずは**Meslo Nerd Font**と呼ばれる推奨のフォントをインストールします。
GitHubのREADMEからインストール可能です。
https://github.com/romkatv/powerlevel10k#fonts

インストールが完了したら、ターミナルのフォント設定を**MesloLGS NF**に変更してください。
![font.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/ac0a0ef8-a687-72c8-9494-dc4c673c0827.png)

#### テーマ

次に**Powerlevel10k**本体をインストールします。
https://github.com/romkatv/powerlevel10k#installation

```shell:Powerlevel10kインストール
$ git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
$ echo 'source ~/powerlevel10k/powerlevel10k.zsh-theme' >>~/.zshrc
```

インストール後にターミナルを再起動すると、Powerlevel10kの設定が始まります。
1項目ずつスタイルについて聞かれるので、好きな見た目を選択してください。
![powerlevel10k.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/3fd88afc-a5e2-4d58-7268-b3001faf204f.png)
やり直したい場合は、`p10k configure`コマンドでもう一度始めから設定できます。

細かい設定を変更したい場合は、管理ファイルである`~/.p10k.zsh`を直接編集してください。
ちなみに、以下コマンドで設定できるカラーの一覧を表示できます。

```shell
for i in {0..255}; do print -Pn "%K{$i}  %k%F{$i}${(l:3::0:)i}%f " ${${(M)$((i%6)):#3}:+$'\n'}; done
```

### (2) zsh-completions

[zsh-completions](https://github.com/zsh-users/zsh-completions)
コマンド補完のプラグインです。
コマンドやファイル名の入力中にTabキーを押すことで、入力候補一覧を表示してくれる機能ですね。
![zsh-completions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/7d3d9cb8-2b62-7801-7c99-643afabd2e28.png)

```shell:~/.zshrc
## コマンド補完
zinit ice wait'0'; zinit light zsh-users/zsh-completions
autoload -Uz compinit && compinit

## 補完で小文字でも大文字にマッチさせる
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

## 補完候補を一覧表示したとき、Tabや矢印で選択できるようにする
zstyle ':completion:*:default' menu select=1 
```
- `~/.zshrc`に設定を記述しておくことで、Zsh起動時に足りないプラグインが自動的にインストールされます。便利！
- `zinit ice wait'0';`という記述。これは非同期でプラグインを読み込むオプションです。Zsh起動後すぐに必要のないプラグインを非同期で読み込むことで、ターミナル起動の初速を上げています。

**参考**：[Zplugin (zinit) を使ってみる](https://blog.katio.net/page/zplugin)

### (3) zsh-syntax-highlighting

[zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting)
コマンドラインの文字の色付けを行うシンタックスハイライトプラグインです。
![syntax-highlighting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/7bd67ffa-a1d2-aa19-db37-b7a8c939b2f7.png)

```shell:~/.zshrc
## シンタックスハイライト
zinit light zsh-users/zsh-syntax-highlighting
```

#### lsコマンドでハイライトが効かない場合
自分の環境だと`ls`コマンドでシンタックスハイライトが効かなかったのですが、GNU版のコマンド群をインストールすることで上手くいきました。

```
$ brew install coreutils
```

さらにデフォルトコマンドでGNU版のコマンドを実行できるようエイリアスを設定しておきます。

```shell:~/.zshrc
# alias
alias ls="gls --color=auto"
```

これで`ls`コマンドでもハイライトが効くようになりました。

**参考**：[bashの表示色をカスタマイズ - Qiita](https://qiita.com/soramugi/items/a726bd64330e08daa9e5)

### (4) zsh-autosuggestions

[zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions)
こちらも入力補完のプラグイン。コマンド入力中に過去の入力履歴を検索し、サジェストを表示してくれます。
![zsh-autosuggestions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/3cd8288a-b1a5-ae04-e590-0b1522e282b3.png)

```shell:~/.zshrc
## 履歴補完
zinit light zsh-users/zsh-autosuggestions
```

サジェストのカラーも変更しておきました。
https://github.com/zsh-users/zsh-autosuggestions#suggestion-highlight-style

```shell:~/.zshrc
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=244"
```

### (5) pecoで検索を便利にする

インタラクティブなフィルタリングツールである**[peco](https://github.com/peco/peco)**。
上手く使用すれば、ターミナル作業効率が跳ね上がります・・！

まずはHomebrewから**peco**をインストール。

```shell
$ brew install peco
```

#### コマンド履歴検索
historyファイルに保存されているコマンド履歴を検索する設定です。
文字を入力することで、インタラクティブに履歴を絞り込むことができます。
![peco-min.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/432b12e1-614b-6602-6dba-541bfac8b4e9.gif)

以下コードでは`control` + `R`で起動するようにしてますが、キー設定は好みで。

```shell:~/.zshrc
## コマンド履歴検索
function peco-history-selection() {
  BUFFER=`history -n 1 | tac  | awk '!a[$0]++' | peco`
  CURSOR=$#BUFFER
  zle reset-prompt
}
zle -N peco-history-selection
bindkey '^R' peco-history-selection
```

#### ディレクトリ移動（コマンド履歴）

`control` + `E`で、過去にcdコマンドで移動したことのあるディレクトリを検索・移動できる設定です。

```shell:~/.zshrc
## コマンド履歴からディレクトリ検索・移動
if [[ -n $(echo ${^fpath}/chpwd_recent_dirs(N)) && -n $(echo ${^fpath}/cdr(N)) ]]; then
  autoload -Uz chpwd_recent_dirs cdr add-zsh-hook
  add-zsh-hook chpwd chpwd_recent_dirs
  zstyle ':completion:*' recent-dirs-insert both
  zstyle ':chpwd:*' recent-dirs-default true
  zstyle ':chpwd:*' recent-dirs-max 1000
  zstyle ':chpwd:*' recent-dirs-file "$HOME/.cache/chpwd-recent-dirs"
fi
function peco-cdr () {
  local selected_dir="$(cdr -l | sed 's/^[0-9]* *//' | peco)"
  if [ -n "$selected_dir" ]; then
    BUFFER="cd ${selected_dir}"
    zle accept-line
  fi
}
zle -N peco-cdr
bindkey '^E' peco-cdr
```

#### ディレクトリ移動（カレントディレクトリ以下のディレクトリ）

こちらは`control` + `X`で、カレントディレクトリ以下の階層にあるディレクトリを検索・移動できます。

```shell:~/.zshrc
## カレントディレクトリ以下のディレクトリ検索・移動
function find_cd() {
  local selected_dir=$(find . -type d | peco)
  if [ -n "$selected_dir" ]; then
    BUFFER="cd ${selected_dir}"
    zle accept-line
  fi
}
zle -N find_cd
bindkey '^X' find_cd
```

#### Gitリポジトリディレクトリに移動

pecoとリポジトリ管理ツールである**[ghq](https://github.com/x-motemen/ghq)**を組み合わせれば、Gitリポジトリ間の移動が簡単になります。
![ghq-min.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321338/d2ae7837-d534-8fbc-85e6-7a42df100a2a.gif)
まずはHomebrewからghqをインストール。

```shell
$ brew install ghq
```

次にghqで管理するディレクトリのrootを設定します。
普段Gitリポジトリをcloneしているディレクトリを指定してください。

```shell:~/gitをrootに設定する場合
$ git config --global ghq.root ~/git
```

最後にこれまで同様`~/.zshrc`を編集します。
以下は先程設定したルートディレクトリを元に、`control` + `G`でGitディレクトリを検索・移動できる設定です。

```shell:~/.zshrc
## gitリポジトリ検索・移動
function peco-src () {
  local selected_dir=$(ghq list -p | peco)
  if [ -n "$selected_dir" ]; then
    BUFFER="cd ${selected_dir}"
    zle accept-line
  fi
}
zle -N peco-src
bindkey '^G' peco-src
```

### (6) その他便利設定

やっておくと便利な設定です。

```shell:~/.zshrc
## 履歴保存管理
HISTFILE=$ZDOTDIR/.zsh-history
HISTSIZE=100000
SAVEHIST=1000000

## 他のzshと履歴を共有
setopt inc_append_history
setopt share_history

## パスを直接入力してもcdする
setopt AUTO_CD

## 環境変数を補完
setopt AUTO_PARAM_KEYS
```

**参考**：[MacBook Proが届いたのでシェルの設定をする - すだめブログ](https://sudame.hatenablog.com/entry/2019/04/03/194540)

# dotfiles管理

ここまで`~/.zshrc`ファイルを編集してきましたが、iterm2の設定と同様に、シェルの設定も他端末と同期したいですよね。

シェル設定ファイルに限らず、ホームディレクトリに存在する`.`（ドット）から始まる隠しファイルのことを**dotfiles**と呼び、それらをGitリポジトリ上で管理することで複数端末で設定を同期する手法が存在します。（**dotfiles管理**）

今回設定した`~/.zshrc`ファイルについても、dotfiles管理してみました。
https://github.com/obake-fe/dotfiles/blob/master/.zsh/.zshrc

設定がうまく行かないときは、上記リンク先のファイルと見比べてみてください。

**参考**
・[ようこそdotfilesの世界へ - Qiita](https://qiita.com/yutakatay/items/c6c7584d9795799ee164)
・[最強の dotfiles 駆動開発と GitHub で管理する運用方法 - Qiita](https://qiita.com/b4b4r07/items/b70178e021bef12cd4a2)

# さらにカスタマイズしたい人向け

ここで紹介した以外にも、Zshには数え切れないほど様々なプラグインがあります。
興味が湧いた人は自分でカスタマイズしていき、自分好みのターミナル環境を作っていきましょう！

**参考**
・[zshの外部プラグインまとめ - Qiita](https://qiita.com/mollifier/items/1220c0eeaa93e82f8afc)
・[awesome-zsh-plugins \| Curated list of awesome lists | Project-Awesome.org](https://project-awesome.org/unixorn/awesome-zsh-plugins)
・[Zinit Wiki](http://zdharma.org/zinit/wiki/INTRODUCTION/)

# 全体参考
- [【zsh高速化】え～、そんなプラグインマネージャーがあるんだったらもっと早く教えてよ、と姉が怒り出した - Zinit (旧名Zplugin) - Qiita](https://qiita.com/9sako6/items/23b164a95b91c644aade)
- [bashからzshに変更したので、インストール方法をまとめてみた \| ぐるたかログ](https://gurutaka-log.com/bash2zsh-install#STEP2zsh-completions)
- [bashからzshに移行したときのメモ - Qiita](https://qiita.com/hiroyuki827/items/4e87ce517a4894f092e8)
- [zinitでzsh環境をいい感じにしたメモ - Qiita](https://qiita.com/crossroad0201/items/17270127732dc20fa8b2)
- [MacBook Proが届いたのでシェルの設定をする - すだめブログ](https://sudame.hatenablog.com/entry/2019/04/03/194540)
- [ターミナルをいい感じにして楽しむ - Qiita](https://qiita.com/szk07/items/b15c38ec73e547a23439)
- [pecoを使って端末操作を爆速にする - Qiita](https://qiita.com/reireias/items/fd96d67ccf1fdffb24ed)
- [history不要！pecoでLinuxコマンド履歴を爆速で検索](https://suwaru.tokyo/history%E4%B8%8D%E8%A6%81%EF%BC%81peco%E3%81%A7linux%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E5%B1%A5%E6%AD%B4%E3%82%92%E7%88%86%E9%80%9F%E3%81%A7%E6%A4%9C%E7%B4%A2/)
- [コマンドライン編集機能 Zsh Line Editor を使いこなす - Qiita](https://qiita.com/b4b4r07/items/8db0257d2e6f6b19ecb9)