Zsh初心者がzshrcを色々調べたの晒してみる

![zsh_logo.png](https://qiita-image-store.s3.amazonaws.com/0/258841/33af3943-50cb-7472-7b07-9000432306c5.png)
## 背景

あるところにZshを熱く語ってくる友人がいました。
聞けば聞くほど興味が出てきたのでとりあえず入門してみたのでzshrcを色々調べた時の使えそうな者たちです。
お暇な方は見てってください。
zsh歴は1週間程度です。超ど素人の記事なので達人の方々は得られる情報は少ないと思います。。。

## 環境

CeotOS 7.6へインストールしてみます。
入れてみたZshのバージョンは5.0.2です。

``` bash
$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)

$ zsh --version
zsh 5.0.2 (x86_64-redhat-linux-gnu)
```

ちなみに最新バージョンは5.7
変更点等々は下記のサイトで確認できます。
yumとかaptだと最新版は入れられないので最新がいい人は下記から落としてインストールが必要です。

http://zsh.sourceforge.net/Arc/source.html

## 対象読者

* 「bashに不満はないけどzshってよく聞くし使ってみたいな」
* 「zshのカスタマイズやってみたい」

って人を対象にします。

## Zshとは

Zsh(Z Shell)とはシェルの種類の1つです。
拡張機能が多彩で自分好みに育ててく感覚が楽しいらしいです。
最近だとfishとかxonshとかも有名です。

有名な特徴としては下記2点

* タブ補完が強力
* 柔軟性があり自在にカスタマイズが可能

ちなみにソースはGitHubで見ることが出来ます。
[zsh-users/zsh](https://github.com/zsh-users/zsh)

## 導入

導入はとても簡単です。
RHEL系ならyum、Debian系ならaptで入ります。

``` bash
# RHEL
$ sudo yum install -y zsh

# debian
$ sudo apt install -y zsh
```

デフォルトでbashではなくzshでログインしたいなら下記コマンドを使用します。
次回以降はbashではなくzshになります。

``` bash
# デフォルト
$ echo $SHELL
/bin/bash

# ログインシェルを変更
$ which zsh
/usr/bin/zsh
$ chsh -s /usr/bin/zsh

# 再ログインして確認
$ echo $SHELL
/usr/bin/zsh
```

## zshrc(コメント付き)

GitHubでも一応公開しています。
更新はこっちでやってくので興味ある方は見てみてください。
■ [ryuichi1208/dotfiles](https://github.com/ryuichi1208/dotfiles)

``` bash
# -----------------------------
# Lang
# -----------------------------
#export LANG=ja_JP.UTF-8
#export LESSCHARSET=utf-8

# -----------------------------
# General
# -----------------------------
# 色を使用
autoload -Uz colors ; colors

# エディタをvimに設定
export EDITOR=vim

# Ctrl+Dでログアウトしてしまうことを防ぐ
#setopt IGNOREEOF

# パスを追加したい場合
export PATH="$HOME/bin:$PATH"

# cdした際のディレクトリをディレクトリスタックへ自動追加
setopt auto_pushd

# ディレクトリスタックへの追加の際に重複させない
setopt pushd_ignore_dups

# emacsキーバインド
bindkey -e

# viキーバインド
#bindkey -v

# フローコントロールを無効にする
setopt no_flow_control

# ワイルドカード展開を使用する
setopt extended_glob

# cdコマンドを省略して、ディレクトリ名のみの入力で移動
setopt auto_cd

# コマンドラインがどのように展開され実行されたかを表示するようになる
#setopt xtrace

# 自動でpushdを実行
setopt auto_pushd

# pushdから重複を削除
setopt pushd_ignore_dups

# ビープ音を鳴らさないようにする
#setopt no_beep

# カッコの対応などを自動的に補完する
setopt auto_param_keys

# ディレクトリ名の入力のみで移動する
setopt auto_cd

# bgプロセスの状態変化を即時に知らせる
setopt notify

# 8bit文字を有効にする
setopt print_eight_bit

# 終了ステータスが0以外の場合にステータスを表示する
setopt print_exit_value

# ファイル名の展開でディレクトリにマッチした場合 末尾に / を付加
setopt mark_dirs

# コマンドのスペルチェックをする
setopt correct

# コマンドライン全てのスペルチェックをする
setopt correct_all

# 上書きリダイレクトの禁止
setopt no_clobber

# sudo の後ろでコマンド名を補完する
zstyle ':completion:*:sudo:*' command-path /usr/local/sbin /usr/local/bin \
                   /usr/sbin /usr/bin /sbin /bin /usr/X11R6/bin

# ps コマンドのプロセス名補完
zstyle ':completion:*:processes' command 'ps x -o pid,s,args'

# パスの最後のスラッシュを削除しない
setopt noautoremoveslash

# 各コマンドが実行されるときにパスをハッシュに入れる
#setopt hash_cmds

# rsysncでsshを使用する
export RSYNC_RSH=ssh

# その他
umask 022
ulimit -c 0

# -----------------------------
# Prompt
# -----------------------------
# %M    ホスト名
# %m    ホスト名
# %d    カレントディレクトリ(フルパス)
# %~    カレントディレクトリ(フルパス2)
# %C    カレントディレクトリ(相対パス)
# %c    カレントディレクトリ(相対パス)
# %n    ユーザ名
# %#    ユーザ種別
# %?    直前のコマンドの戻り値
# %D    日付(yy-mm-dd)
# %W    日付(yy/mm/dd)
# %w    日付(day dd)
# %*    時間(hh:flag_mm:ss)
# %T    時間(hh:mm)
# %t    時間(hh:mm(am/pm))
PROMPT='%F{cyan}%n@%m%f:%~# '

# -----------------------------
# Completion
# -----------------------------
# 自動補完を有効にする
autoload -Uz compinit ; compinit

# 単語の入力途中でもTab補完を有効化
#setopt complete_in_word

# コマンドミスを修正
setopt correct

# 補完の選択を楽にする
zstyle ':completion:*' menu select

# 補完候補をできるだけ詰めて表示する
setopt list_packed

# 補完候補にファイルの種類も表示する
#setopt list_types

# 色の設定
export LSCOLORS=Exfxcxdxbxegedabagacad

# 補完時の色設定
export LS_COLORS='di=01;34:ln=01;35:so=01;32:ex=01;31:bd=46;34:cd=43;34:su=41;30:sg=46;30:tw=42;30:ow=43;30'

# キャッシュの利用による補完の高速化
zstyle ':completion::complete:*' use-cache true

# 補完候補に色つける
autoload -U colors ; colors ; zstyle ':completion:*' list-colors "${LS_COLORS}"
#zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}

# 大文字・小文字を区別しない(大文字を入力した場合は区別する)
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

# manの補完をセクション番号別に表示させる
zstyle ':completion:*:manuals' separate-sections true

# --prefix=/usr などの = 以降でも補完
setopt magic_equal_subst

# -----------------------------
# History
# -----------------------------
# 基本設定
HISTFILE=$HOME/.zsh-history
HISTSIZE=100000
SAVEHIST=1000000

# ヒストリーに重複を表示しない
setopt histignorealldups

# 他のターミナルとヒストリーを共有
setopt share_history

# すでにhistoryにあるコマンドは残さない
setopt hist_ignore_all_dups

# historyに日付を表示
alias h='fc -lt '%F %T' 1'

# ヒストリに保存するときに余分なスペースを削除する
setopt hist_reduce_blanks

# 履歴をすぐに追加する
setopt inc_append_history

# ヒストリを呼び出してから実行する間に一旦編集できる状態になる
setopt hist_verify

#余分なスペースを削除してヒストリに記録する
#setopt hist_reduce_blanks

# historyコマンドは残さない
#setopt hist_save_no_dups

# ^R で履歴検索をするときに * でワイルドカードを使用出来るようにする
#bindkey '^R' history-incremental-pattern-search-backward
#bindkey "^S" history-incremental-search-forward

# ^P,^Nを検索へ割り当て
#bindkey "^P" history-beginning-search-backward-end
#bindkey "^N" history-beginning-search-forward-end

# -----------------------------
# Alias
# -----------------------------
# グローバルエイリアス
alias -g L='| less'
alias -g H='| head'
alias -g G='| grep'
alias -g GI='| grep -ri'

# エイリアス
alias lst='ls -ltr --color=auto'
alias ls='ls --color=auto'
alias la='ls -la --color=auto'
alias ll='ls -l --color=auto'

alias du="du -Th"
alias df="df -Th"
alias su="su -l"
alias so='source'
alias vi='vim'
alias vz='vim ~/.zshrc'
alias c='cdr'
alias cp='cp -i'
alias rm='rm -i'
alias mkdir='mkdir -p'
alias ..='c ../'
alias back='pushd'
alias diff='diff -U1'

alias tma='tmux attach'
alias tml='tmux list-window'

alias dki="docker run -i -t -P"
alias dex="docker exec -i -t"
alias drmf='docker stop $(docker ps -a -q) && docker rm $(docker ps -a -q)'

# -----------------------------
# Plugin
# -----------------------------
# root のコマンドはヒストリに追加しない
#if [ $UID = 0 ]; then
#  unset HISTFILE
#  SAVEHIST=0
#fi

#function h {
#  history
#}

#function g() {
#  egrep -r "$1" .
#}

function t()
{
  tmux new-session -s $(pwd |sed -E 's!^.+/([^/]+/[^/]+)$!\1!g' | sed -e 's/\./-/g')
}

function psgrep() {
  ps aux | grep -v grep | grep "USER.*COMMAND"
  ps aux | grep -v grep | grep $1
}

function dstop()
{
  docker stop $(docker ps -a -q);
}

function drm()
{
  docker rm $(docker ps -a -q);
}

# -----------------------------
# Plugin
# -----------------------------
# zplugが無ければインストール
if [[ ! -d ~/.zplug ]];then
  git clone https://github.com/zplug/zplug ~/.zplug
fi

# zplugを有効化する
source ~/.zplug/init.zsh

# プラグインList
# zplug "ユーザー名/リポジトリ名", タグ
zplug "zsh-users/zsh-completions"
zplug "zsh-users/zsh-autosuggestions"
zplug "zsh-users/zsh-syntax-highlighting", defer:2
zplug "b4b4r07/enhancd", use:init.sh
#zplug "junegunn/fzf-bin", as:command, from:gh-r, file:fzf

# インストールしていないプラグインをインストール
if ! zplug check --verbose; then
  printf "Install? [y/N]: "
  if read -q; then
      echo; zplug install
  fi
fi

# コマンドをリンクして、PATH に追加し、プラグインは読み込む
zplug load --verbose

# -----------------------------
# PATH
# -----------------------------
case "${OSTYPE}" in
  darwin*)
    export PATH=/opt/local/bin:/opt/local/sbin:$PATH
    export MANPATH=/opt/local/share/man:/opt/local/man:$MANPATH
  ;;
esac

# -----------------------------
# Python
# -----------------------------
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
#eval "$(pyenv init -)"
alias pipallupgrade="pip freeze --local | grep -v '^\-e' | cut -d = -f 1  | xargs pip install -U"

# -----------------------------
# Golang
# -----------------------------
if which go > /dev/null 2>&1  ; then
  export CGO_ENABLED=1
  export GOPATH=$HOME/dev/go
  export PATH=$PATH:$(go env GOROOT)/bin:$GOPATH/bin
fi

# -----------------------------
# Git
# -----------------------------
function gt() {
  is_in_git_repo || return
  git tag --sort -version:refname |
  fzf-down --multi --preview-window right:70% \
    --preview 'git show --color=always {} | head -200'
}

function gr() {
  is_in_git_repo || return
  git remote -v | awk '{print $1 "\t" $2}' | uniq |
  fzf-down --tac \
    --preview 'git log --oneline --graph --date=short --pretty="format:%C(auto)%cd %h%d %s" {1} | head -200' |
  cut -d$'\t' -f1
}

function gs() {
  is_in_git_repo || return
  git stash list | fzf-down --reverse -d: --preview 'git show --color=always {1}' |
  cut -d: -f1
}
```

Bashで使ってたaliasとかfunctionはそのまま持ってきてzsh特有の設定を追記したって感じです。
この長さだと分けたい気持ちが強いです。

## 感想

Bashと違ってZshはインストールが必要なので業務で使うことはあまりなさそう。
ただ家で遊ぶ分には面白いなって思いました。
勉強&経験不足なのでZshの恩恵は正直受けきれてないと思うのでこれからもzshrc含め広げてこうと思います。

別サーバにSSH接続して作業することが多い現状だがこれが変われば業務でも使えるかもしれませんね。。。

## 雰囲気

コマンドを打ってtabを打つだけで下記のような入力候補が色付きで出力されます。
ファイルやシンボリックリンク、ディレクトリが一目でわかるようになってます。

![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/258841/de25b2d5-0502-f9b4-1961-12ea1b30ff63.png)

ショートオプションやロングオプションの補完も効きます。
bash-completionと違って方向キーで簡単に選択できるので便利です。
manやpsコマンドの引数も補完が効きます。

![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/258841/0074fd8f-4457-995a-438b-b04675ed4eee.png)

コマンド + 「-」でtabを入力するとusageも見ることが可能です。

![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/258841/ce0d94f2-b148-9a69-f3ad-05962851e5b3.png)


## 小ネタ

Zshインストールするとテトリスが一緒に入る。
遊び方はもせっかくなので載せておきます。

``` bash
# 下記コマンドを入力
$ autoload -Uz tetris
$ zle -N tetris

# ESC + 「x」キーを入力し「testris」と入力
$ 
execute: tetris

root@OPST-N394:~#
|                      |   Score: 1
|                      |
|                      |   Game parameters: 11x20, 2.5Hz
|                      |
|                      |   Keys:   left: a j
|                      |         rotate: s k
|                      |          right: d l
|        ******        |           drop: space
|        **            |           quit: q
|                      |
|                      |
|                      |
|        ()()          |
|  ()()()  ()()        |
|  ()()      ()()      |
|()()()()()()()()  ()()|
|  ()()  ()    ()()()  |
|  ()()()()()  ()  ()  |
|()()()()()()()()()()  |
|()()  ()()()()()()()  |
+----------------------+
```

ちなみにq でゲームから抜けれます。
暇つぶしには使えそうですね～。

## 参考リンク

● [初心者向け：Zshの導入](https://qiita.com/iwaseasahi/items/a2b00b65ebd06785b443)
● [とりあえずZshを使えば良いんだろう？](https://qiita.com/ktr_type23/items/3eb782f98c7a5f4c60b0)
● [お前らのターミナルはダサい](https://qiita.com/kinchiki/items/57e9391128d07819c321)
● [Shellライフをそこそこ快適に！僕のこだわりzsh設定](https://suin.io/568)
● [zshで究極のオペレーションを](http://gihyo.jp/dev/serial/01/zsh-book/0001)
● [zshを使用してみよう！](http://labs.septeni.co.jp/entry/2015/12/25/142201)
● [How to Configure your macOs Terminal with Zsh like a Pro](https://medium.freecodecamp.org/how-to-configure-your-macos-terminal-with-zsh-like-a-pro-c0ab3f3c1156)
● [Oh My Zsh](https://ohmyz.sh/)