zsh移行手順メモ

[Nextremer Advent Calendar 2017](https://qiita.com/advent-calendar/2017/nextremer)の1日目。

今までfish shellを使っていたのですが、anyenv→pyenv導入でコケたりfish shellの記法覚えるのが辛かったりで、最終的に何故か突然壊れたので、社用Macを換えたついでにzshに移行することにしました。
メモ代わりに手順晒しときます。
今までありがとうfish shell (｀;ω;´)ゞ

## インストール
兎にも角にもインストールから。
MacなのでHomeBrew使ってインストールする。

```
brew install zsh zsh-autosuggestions zsh-completions zsh-syntax-highlighting
```

## zshの設定ファイルについて
`.zshrc`と`.zprofile`だけじゃなくて`.zshenv`とか`.zlogin`とかもあるっぽい。読み込み順は[この記事](https://qiita.com/muran001/items/7b104d33f5ea3f75353f)を参照。

できるだけ設定ファイル系はXDG_CONFIG_PATHに置くようにしたいので、zshの設定ファイル一式もXDG_CONFIG_PATHで管理するようにする。

そのためには`ZDOTDIR`を設定してやればよいのだが、それを設定するために`.zshenv`だけはホームディレクトリに置かざるを得ないのがツラいところ（`/etc/zshenv`を編集してもいいんだけど、できるだけlocalで設定してやりたい）

最終的には以下のように管理することにした

```
~/
  - .zshenv # XDG_PATH系の設定 + ZDOTDIRの設定のみ
  - .config/
    - zsh/
        - .zenv # その他の環境変数の設定
        - .zshrc
        - .zprofile
        - その他独自設定ファイル
```

独自の設定ファイルは[この記事](http://vorfee.hatenablog.jp/entry/2015/03/05/211447)を~~パクった~~参考にさせていただいた。

## 設定内容
### 補完
zshといえば補完だ。と色々なところで耳にしていたので、まずは補完用の設定を書く。

以下を設定ファイルに書くことで補完が有効になるらしい。
```
autoload -U compinit
compinit
```

さて、ここから補完の設定を書いていくぞと意気込んでみたが、`zstyle`とやらの複雑怪奇な記法に秒で心を折られたので、色々なサイトの設定を参考に、っぽい設定を書くことにした。

作成した設定はこんな感じ。参考にしたサイトが複数あるため、若干キメラみたいになっている気もするが不都合あるまではこれで。

```zsh:~/.config/zsh/.zcomp
### 補完
autoload -U compinit; compinit -C

### 補完方法毎にグループ化する。
zstyle ':completion:*' format '%B%F{blue}%d%f%b'
zstyle ':completion:*' group-name ''

### 補完侯補をメニューから選択する。
### select=2: 補完候補を一覧から選択する。補完候補が2つ以上なければすぐに補完する。
zstyle ':completion:*:default' menu select=1

### 補完候補に色を付ける。
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"

### 補完候補がなければより曖昧に候補を探す。
### m:{a-z}={A-Z}: 小文字を大文字に変えたものでも補完する。
### r:|[._-]=*: 「.」「_」「-」の前にワイルドカード「*」があるものとして補完する。
### +m:{A-Z}={a-z}: 追加で大文字を小文字に変えてみて補完する
# zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z} r:|[-_.]=**' '+m:{A-Z}={a-z} r:|[-_.]=**'

### 補完候補
### _oldlist 前回の補完結果を再利用する。
### _complete: 補完する。
### _match: globを展開しないで候補の一覧から補完する。
### _history: ヒストリのコマンドも補完候補とする。
### _ignored: 補完候補にださないと指定したものも補完候補とする。
### _approximate: 似ている補完候補も補完候補とする。
### _prefix: カーソル以降を無視してカーソル位置までで補完する。
#zstyle ':completion:*' completer _oldlist _complete _match _history _ignored _approximate _prefix
zstyle ':completion:*' completer _expand _complete _match _prefix _approximate _list _history

## 補完候補をキャッシュする。
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path "${XDG_CACHE_HOME}/zsh/compcache"
```

```zsh:~/.config/zsh/.zoptions
###
# Completions
setopt complete_in_word       # カーソル位置で補完する。
setopt always_to_end          # 補完後に末尾に移動する
# setopt path_dirs              # Perform path search even on command names with slashes.
setopt auto_list              # 補完候補が複数ある時に、一覧表示
setopt auto_menu              # 補完候補が複数あるときに自動的に一覧表示する
setopt auto_param_slash       # 補完した値がパスだった場合、自動的に/を付与する
unsetopt menu_complete        # Do not autoselect the first completion entry.
setopt no_flow_control        # C-s, C-qを無効にする。
setopt glob
setopt glob_complete          # globを展開しないで候補の一覧から補完する。
setopt extended_glob          # 拡張globを有効にする。
setopt mark_dirs              # globでパスを生成したときに、パスがディレクトリだったら最後に「/」をつける。
setopt numeric_glob_sort      # 辞書順ではなく数字順に並べる。
setopt magic_equal_subst      # コマンドライン引数の --prefix=/usr とか=以降でも補完
setopt always_last_prompt     # 無駄なスクロールを避ける
```

### 履歴
履歴の保存場所や、fzfによる履歴検索等を設定した。

```zsh:~/.config/zsh/.zshenv
# History
export HISTFILE="$XDG_DATA_HOME/zsh/history"
export HISTSIZE=10000
export SAVEHIST=10000
```

```zsh:~/.config/zsh/.zoptions
###
# History
setopt hist_ignore_dups       # 直前と同じコマンドラインはヒストリに追加しない
setopt hist_ignore_all_dups   # 重複したヒストリは追加しない
setopt hist_reduce_blanks     # 余分なスペースを削除してヒストリに記録する
setopt hist_no_store          # ヒストリにhistoryコマンドを記録しない
setopt hist_verify            # ヒストリを呼び出してから実行する間に一旦編集できる状態になる
setopt share_history          # シェルのプロセスごとに履歴を共有
setopt extended_history       # 履歴ファイルに時刻を記録
setopt append_history         # 複数の zsh を同時に使う時など history ファイルに上書きせず追加
```

```zsh:~/.config/zsh/.zshrc
# fzf
function select-history() {
  BUFFER=$(history -n -r 1 | fzf --no-sort +m --query "$LBUFFER" --prompt="History > ")
  CURSOR=$#BUFFER
}
zle -N select-history
bindkey '^r' select-history
```

### Zplug
zsh向けのパッケージマネージャとしてはZplugを採用した。

```zsh:~/.config/zsh/.zplug
# zplug

# Check if zplug is installed
if [[ ! -d "$ZPLUG_HOME" ]]; then
  curl -sL --proto-redir -all,https https://raw.githubusercontent.com/zplug/installer/master/installer.zsh| zsh
  source "$ZPLUG_HOME/init.zsh" && zplug update
fi

if [[ -s "$ZPLUG_HOME" ]]; then

  source "$ZPLUG_HOME/init.zsh"

  zplug "zplug/zplug"

  zplug "stedolan/jq", from:gh-r, as:command, rename-to:jq

  zplug "zsh-users/zsh-syntax-highlighting", defer:2
  zplug "b4b4r07/zsh-vimode-visual", defer:3
  zplug "ascii-soup/zsh-url-highlighter"

  zplug "voronkovich/gitignore.plugin.zsh"

  zplug "jhawthorn/fzy", \
    as:command, \
    hook-build:'make'
  zplug "b4b4r07/git-br", \
    as:command, \
    use:'git-br'

  zplug "mollifier/cd-gitroot"

  zplug "mollifier/anyframe"


  # Install plugins if there are plugins that have not been installed
  zplug check || zplug install

  zplug load
fi
```

### その他
あとはaliasだとかanyenvだとかその辺の設定を追加した。
anyenvでpyenvを入れるのがfish shellだと結構大変だったのだが、zshだと超楽だった（これが普通？

今回作成した設定ファイル群は下記にあるのでよろしければ( ﾟдﾟ)つ ﾄﾞｿﾞｰ
https://github.com/k-tada/dotfiles/tree/master/xdg_config_home/zsh