Tmux + Zsh + Vim 時の dotfiles まとめ

なんとなく自分の開発環境を紹介したくなったので、書きます。
全てにコメントしているとキリがないので、独断と偏見によって選んだポイントの紹介もしていきます。
環境は**Tmux** + **Zsh** + **Vim**です。私の三種の神器です。

リポジトリ: [s4kr4/dotfiles](https://github.com/s4kr4/dotfiles)


# Vim

設定ファイル群は`~/.vim`フォルダにまとめて配置しているので、`.vimrc`内では、GVim/Cygwin用に`runtimepath`の追加をする以外は特に何もしていません。

```vim:~/.vimrc
if has('win32') || has('win64') || has('win32unix')
  set runtimepath+=$HOME/.vim
  set runtimepath+=$HOME/.vim/after
endif

runtime! init/*.vim
runtime! functions.vim
```
`~/.vim`以下のファイル構成はこんな感じです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29000/f1f35179-8cd1-4857-33ee-b482e5e74be8.png)



## ~/.vim/init/*.vim

設定をなんとなく分類して管理しています。
読み込み順は、ファイル名に数字をつけることで制御しています。


### 10_dein.vim

[Shougo/dein.vim](https://github.com/Shougo/dein.vim) とそのプラグインをインストールするスクリプトです。


### 20_general.vim

一般的な設定を記述しています。

#### ファイルエンコード

```vim:~/.vim/20_general.vim
set encoding=utf-8     " バッファ内のエンコード
set fileencoding=utf-8 " ファイル書き込み時のエンコード
scriptencoding utf-8   " Vim Scriptで使用するエンコード
```

#### Neocompleteでの補完時、プレビューウィンドウを表示しない

デフォルトだと、`completeopt`に`preview`が含まれていて、補完時に関数の説明等が表示されます。
これがうっとおしいので、`menuone`のみの設定に変更しています。

```vim:~/.vim/20_general.vim
set completeopt=menuone
```

#### split展開方向

```vim:~/.vim/20_general.vim
set splitbelow    " 上下分割時に、下側にファイルを開く
set splitright    " 左右分割時に、右側にファイルを開く
```

#### バックアップファイルやスワップファイルの作成を抑制

Vimでファイルを編集していると、ディレクトリに変なファイルが勝手に作成されます。
ファイル名末尾に`~`が付加されたものがバックアップファイル、
`.swp`が付加されたものがスワップファイル、
`.un~`が付加されたものがundoファイルです。
私はどれも特に必要を感じていないので、全て無効化しています。

```vim:~/.vim/20_general.vim
set nobackup      " バックアップファイルを作成しない
set nowritebackup " 上書き成功時にバックアップファイルを破棄
set noswapfile    " スワップファイルを作成しない
set noundofile    " undoファイルを作成しない
```

#### 括弧対応ジャンプを強化

Vimにはデフォルトでカーソル下の括弧に対応する括弧へジャンプする機能がありますが、Vimにデフォルトで同梱されている`matchit.vim`を読み込むことで、この機能を強化することができます。
HTMLやXMLのタグ、Rubyのdef~end等もジャンプできるようになります。

```vim:~/.vim/20_general.vim
runtime macros/matchit.vim
```


### 30_edit.vim

編集時の動作に関する設定を記述しています。

#### ファイル選択時のタブ補完強化

```vim:~/.vim/30_edit.vim
set wildmenu wildmode=list:full
```

#### 未保存状態のバッファを切り替え可能にする

例えば`foo.txt`を編集中、一時的に`bar.txt`を閲覧したくなったとき、未保存状態で`:e bar.txt`等と入力すると以下のようなメッセージが出て、バッファを切り替えることができません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29000/e27231af-165d-22e5-6514-082716766b88.png)

以下の設定を追加することで、バッファの切替が可能になります。

```vim:~/.vim/30_edit.vim
set hidden
```

ちなみに、裏に未保存のバッファがある状態でVimを終了しようとすると、ちゃんと警告してくれます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29000/f90cd3c8-347f-c9b3-4fe0-0481cd6332fe.png)


### 40_keymap.vim

各種keymapを設定しています。
VimScriptの`has`を使って、環境ごとに設定するkeymapを変化させたりしています。

#### Shift + Enter でノーマル状態のまま改行挿入 (GVim)

このkeymapはGVimでしか動作しないようです。

```vim:~/.vim/40_keymap.vim
if has("gui_running")
  nnoremap <silent> <S-CR> :<C-u>call append(expand('.'), '')<CR>j
endif
```

#### `;`, `:`キーの入れ替え (macOS)

英字キーボードのMacBookを使用していることと、`;` よりも `:` の使用頻度が高いことから、両者の入力を入れ替えています。

```vim:~/.vim/40_keymap.vim
if has("mac")
  nnoremap ; :
  nnoremap : ;
endif
```


### 90_visual.vim

見た目に関する設定を記述しています。

#### ステータスライン

[このあたり](http://vimwiki.net/?%27statusline%27)を参考にして、色々表示しています。
`%{}`で括るとコマンドの結果を表示できるので、[tpope/vim-fugitive](https://github.com/tpope/vim-fugitive) でGitのブランチを表示したり、ファイルのエンコードを表示したりしています。

```vim:~/.vim/init/90_visual.vim
set statusline=%F%m%r%h%w%{fugitive#statusline()}%=[TYPE:%Y][FMT:%{&fileformat}][ENC:%{&fileencoding}][LINE:%l/%L]
```

#### GUIパーツの非表示化 (GVim)

以前書いた以下の記事のとおりです。

[透明感のあるVim環境をめざして - Qiita](https://qiita.com/s4kr4/items/b2c1b692ec430fe24f15)

#### 全角スペース・行末スペースの可視化

プログラマたるもの、ソースコード中の無駄なスペースや全角スペースは殲滅していかなければなりません。
以下の設定で、それらを赤くハイライトしています。

```vim:~/.vim/init/90_visual.vim
augroup highlightSpace
  autocmd!
  autocmd Colorscheme * hi IdeographicSpace term=underline ctermbg=DarkRed guibg=DarkRed
  autocmd VimEnter,WinEnter * match IdeographicSpace /　\|\s\+$/
augroup END
```


## ~/.vim/after/indent/*.vim

ファイルタイプごとのインデント設定です。
例えばRubyのインデントはスペース2つなので、`ruby.vim`に以下を記述しています。
`tabstop`, `softtabstop`, `shiftwidth`が紛らわしいですが、それぞれ

- tabstop => タブ文字の表示幅
- softtabstop => TabキーやBackSpaceキー等でカーソルが動く幅
- shiftwidth => autoindentで挿入される幅

という意味です。

```vim:~/.vim/after/indent/ruby.vim
setlocal expandtab
setlocal tabstop=2
setlocal softtabstop=2
setlocal shiftwidth=2
```


## ~/.vim/ftdetect/*.vim

Vimはたいていのファイルタイプを自動で認識してくれますが、拡張子からファイルタイプを推測できないものはここで指定します。

例えば*.themeファイルをPHPとして読み込みたい場合、`theme.vim`に以下のように記述しておきます。

```vim:~/.vim/ftdetect/theme.vim
autocmd BufRead,BufNewFile *.theme setfiletype php
```

## ~/.vim/{dein,dein_lazy}.toml

`dein.vim`で読み込むプラグインリストです。
`dein.toml`には、Vim起動時に読み込むプラグインを書いています。
また、`dein_lazy.toml`には、ファイルタイプなどに合わせて遅延読み込みするプラグインを書いています。

各プラグインの個別設定は`~/.vim/plugins/*.vim`に配置し、こんな感じでプラグイン読み込み時の`hook_add`フックを利用して読み込んでいます。

```toml:~/.vim/dein.toml
[[plugins]]
repo = 'terryma/vim-multiple-cursors'
hook_add = 'source $HOME/.vim/plugins/vim-multiple-cursors.vim'
```


### dein.toml

ファイルタイプにかかわらず、必ず読み込むプラグイン

- [cocopon/iceberg.vim](https://github.com/cocopon/iceberg.vim)
    - カラースキーム

- [chriskempson/vim-tomorrow-theme](https://github.com/chriskempson/vim-tomorrow-theme)
    - カラースキーム

- [sjl/badwolf](https://github.com/sjl/badwolf)
    - カラースキーム

- [terryma/vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors)
    - 同じ名前の変数や、正規表現にマッチする複数箇所を同時編集できる便利プラグイン

```vim:~/.vim/plugins/vim-multiple-cursors.vim
" 複数箇所の同時編集時、NeoCompleteを無効にする
function! Multiple_cursors_before()
  if exists(':NeoCompleteLock')==2
    exe 'NeoCompleteLock'
    echo 'Disabled Neocomplete'
  endif
endfunction

function! Multiple_cursors_after()
  if exists(':NeoCompleteUnlock')==2
    exe 'NeoCompleteUnlock'
    echo 'Disabled Neocomplete'
  endif
endfunction
```

- [tpope/vim-fugitive](https://github.com/tpope/vim-fugitive)
    - Vim内からgitコマンド各種を使える

- [kana/vim-submode](http://github.com/kana/vim-submode)
    - Vimに独自のmode(submode)を追加できる

```vim:~/.vim/plugins/vim-submode.vim
" submodeから抜けるまでの時間
let g:submode_timeoutlen = 300

" Space + >>>...等で分割ウィンドウを連続リサイズ
call submode#enter_with('winsize', 'n', 's', '<Space>>', '<C-w>>')
call submode#enter_with('winsize', 'n', 's', '<Space><', '<C-w><')
call submode#enter_with('winsize', 'n', 's', '<Space>+', '<C-w>-')
call submode#enter_with('winsize', 'n', 's', '<Space>-', '<C-w>+')

call submode#map('winsize', 'n', 's', '>', '<C-w>>')
call submode#map('winsize', 'n', 's', '<', '<C-w><')
call submode#map('winsize', 'n', 's', '+', '<C-w>-')
call submode#map('winsize', 'n', 's', '-', '<C-w>+')

" Space + hhh...等で分割ウィンドウを連続移動
call submode#enter_with('winmove', 'n', 's', '<Space>h', '<C-w>h')
call submode#enter_with('winmove', 'n', 's', '<Space>j', '<C-w>j')
call submode#enter_with('winmove', 'n', 's', '<Space>k', '<C-w>k')
call submode#enter_with('winmove', 'n', 's', '<Space>l', '<C-w>l')

call submode#map('winmove', 'n', 's', 'h', '<C-w>h')
call submode#map('winmove', 'n', 's', 'j', '<C-w>j')
call submode#map('winmove', 'n', 's', 'k', '<C-w>k')
call submode#map('winmove', 'n', 's', 'l', '<C-w>l')
```

- [osyo-manga/vim-over](https://github.com/osyo-manga/vim-over)
    - %s等で一括置換するとき、どこが置換されるのかが動的にハイライトされる

- [tyru/caw.vim](https://github.com/tyru/caw.vim)
    - ファイルタイプを判別して自動でコメントアウト/コメントインできる

```vim:~/.vim/plugins/caw.vim
" Ctrl + Cの連続でコメントをトグル
nmap <C-c><C-c> <Plug>(caw:hatpos:toggle)
vmap <C-c><C-c> <Plug>(caw:hatpos:toggle)
```

- [thinca/vim-splash](https://github.com/thinca/vim-splash)
    - Vim起動時に好きなAAを表示できる。

```vim:~/.vim/plugins/vim-splash.vim
" AAが書かれているファイルを指定
let g:splash#path = $HOME."/.vim/splash/helloworld.txt"
```

```vim:~/.vim/splash/helloworld.txt
 _   _      _ _                               _     _   _
| | | | ___| | | ___      __      _____  _ __| | __| | | |
| |_| |/ _ \ | |/ _ \     \ \ /\ / / _ \| '__| |/ _  | | |
|  _  |  __/ | | (_) | _   \ V  V / (_) | |  | | (_| | |_|
|_| |_|\___|_|_|\___/ | )   \_/\_/ \___/|_|  |_|\__,_| (_)
                      |/
s4kr4
github  : github.com/s4kr4
qiita   : qiita.com/s4kr4
twitter : @s4kr4m4
```


### dein_lazy.toml

状況に応じて読み込むプラグイン

- [digitaltoad/vim-pug](https://github.com/digitaltoad/vim-pug)
    - pug編集用

- [elzr/vim-json](https://github.com/elzr/vim-json)
    - json編集用

```vim:~/.vim/plugins/neocomplete.vim
" JSONファイルでダブルクォーテーションを表示
let g:vim_json_syntax_conceal = 0
```

- [hail2u/vim-css3-syntax](https://github.com/hail2u/vim-css3-syntax)
    - CSS3シンタックス強化

- [leafgarland/typescript-vim](https://github.com/leafgarland/typescript-vim)
    - TypeScript編集用

- [mattn/emmet-vim](https://github.com/mattn/emmet-vim)
    - HTMLを超楽に入力できる

- [mxw/vim-jsx](https://github.com/mxw/vim-jsx)
    - JSX編集用

```vim:~/.vim/plugins/vim-jsx.vim
" 拡張子が.jsのファイルでもJSXシンタックスを有効にする
let g:jsx_ext_required = 0
```

- [nelsyeung/twig.vim](https://github.com/nelsyeung/twig.vim)
    - Twig編集用

- [othree/html5.vim](https://github.com/othree/html5.vim)
    - HTML5シンタックス強化

- [pangloss/vim-javascript](https://github.com/pangloss/vim-javascript)
    - JavaScriptシンタックス強化

```vim:~/.vim/plugins/vim-javascript.vim
" flowの文法対応
let g:javascript_plugin_flow = 1
```

- [posva/vim-vue](https://github.com/posva/vim-vue)
    - Vue.js開発用

- [Shougo/neocomplete.vim](https://github.com/Shougo/neocomplete.vim)
    - 言わずと知れた補完プラグイン

```vim:~/.vim/plugins/neocomplete.vim
" Use neocomplete
let g:neocomplete#enable_at_startup = 1
" Use smartcase
let g:neocomplete#enable_smart_case = 1
" Start completion with 2 chars
let g:neocomplete#auto_completion_start_length = 2
" Not ignore underbars
let g:neocomplete#enable_underbar_completion = 1
" Number of completion list
let g:neocomplete#max_list = 30

if !exists('g:neocomplete#keyword_patterns')
  let g:neocomplete#keyword_patterns = {}
endif
" Ignore Japanese
let g:neocomplete#keyword_patterns['default'] = '\h\w*'

" Use <TAB> to move list
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<S-TAB>"

" Enable omni completion.
augroup SetOmniCompletionSetting
  autocmd FileType css setlocal omnifunc=csscomplete#CompleteCSS
  autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags
  autocmd FileType javascript setlocal omnifunc=javascriptcomplete#CompleteJS
  autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
  autocmd FileType php setlocal omnifunc=phpcomplete#CompletePHP
  autocmd FileType ruby setlocal omnifunc=rubycomplete#Complete
  autocmd FileType xml setlocal omnifunc=xmlcomplete#CompleteTags
augroup END

" Enable heavy omni completion.
if !exists('g:neocomplete#sources#omni#input_patterns')
  let g:neocomplete#sources#omni#input_patterns = {}
endif
```

- [Shougo/neosnippet](https://github.com/Shougo/neosnippet)
    - netcomplete.vimでスニペットを扱える

- [Shougo/neosnippet-snippets](https://github.com/Shougo/neosnippet-snippets)
    - netsnippetに便利スニペット追加

- [slim-template/vim-slim](https://github.com/slim-template/vim-slim)
    - Slim編集用


# Zsh

Zshの設定ファイル群は`~/.zsh`に配置しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29000/b1622024-0b46-9514-836a-737f0048c452.png)

Vimと同様に、`~/.zshrc`を起点に順次読み込みます。

```zsh:~/.zshrc
if [ -z "${DOTPATH:-}" ]; then
    DOTPATH=~/.dotfiles; export DOTPATH
fi

# 設定ファイル順次読み込み
for file in "${HOME}"/.zsh/init/*.zsh; do
    . "$file"
done

# zplugはTmux内でだけ読み込む
if [[ -n "$TMUX" ]]; then
    . "${HOME}"/.zsh/zplug.zsh
fi

# Tmux起動
if has tmux; then
    tmuxx
fi
```

Zshのプラグイン管理には [zplulg/zplug](https://github.com/zplug/zplug) を使用していますが、Tmux外でプラグインを読み込むのは時間の無駄なので、Tmux内でZshを起動したときのみプラグインを読み込むようにしています。


## ~/.zsh/init/*.zsh

### ~/.zsh/init/10_env.zsh

環境変数の設定を行います。

#### 自作スクリプトのPATHを通す

自分で書いたスクリプトは`~/bin`に置くようにしているので、そこにPATHを通します。

```zsh:~/.zsh/init/10_env.zsh
export PATH=$PATH:$HOME/bin
```

#### anyenvのPATHを通す

各envの管理に [riywo/anyenv](https://github.com/riywo/anyenv) を使っているので、こちらのPATHを通します。
Tmuxと併用すると問題があるようなので、公式のREADME通りではなく下記のようにしています。

```zsh:~/.zsh/init/10_env.zsh
if [[ -d ${HOME}/.anyenv ]]; then
    PATH="$HOME/.anyenv/bin:$PATH"
    eval "$(anyenv init -)"

    for d in `ls $HOME/.anyenv/envs`; do
        export PATH="$HOME/.anyenv/envs/$d/shims:$PATH"
    done
fi
```
参考: [anyenvで開発環境を整える - Qiita](https://qiita.com/luckypool/items/f1e756e9d3e9786ad9ea)

#### ローカル設定用のPATHを通す

どんな環境でも使うようなスクリプトや環境変数はdotfilesで管理していますが、会社や家だけで使う設定まで管理下に入れると気持ち悪いので、そうしたものは管理下から外しています。
以下の設定により、ローカル限定のスクリプトを`~/bin_local`に配置、環境変数設定を`~/.env_local.zsh`に書くことで、それぞれが存在するときだけ読み込ませることができます。

```zsh:~/.zsh/init/10_env.zsh
if [[ -e ${HOME}/bin_local ]]; then
    PATH="$HOME/bin_local:$PATH"
fi
if [[ -e ${HOME}/.env_local.zsh ]]; then
    source ${HOME}/.env_local.zsh
fi
```

### ~/.zsh/init/20_functions.zsh

Zsh内で使いたい関数をまとめて書いています。

例えば、作ったディレクトリにそのまま移動できる`mkcd`関数があります。

```zsh:~/.zsh/init/20_functions.zsh
...

mkcd() {
    mkdir -p "$1"
    [ $? -eq 0 ] && cd "$1"
}

...
```

### ~/.zsh/init/30_aliases.zsh

エイリアスを登録します。

#### `ls` のカラー設定(OS別)

`ls`コマンドの結果に色を付けます。
macOSとそれ以外では`ls`に色を付けるためのオプションが異なるため、OS別に分岐しています。

```zsh:~/.zsh/init/30_aliases.zsh
case "${OSTYPE}" in
darwin*)
    alias ls='ls -G'
    ;;
*)
    alias ls='ls --color=auto'
    ;;
esac
```

#### ローカル設定を読み込む

`~/.zsh/init/10_env.zsh`と同様に、特定の環境でのみ使用したいエイリアスを`~/.local_aliases`に登録し、ここで読み込みます。

```zsh:~/.zsh/init/30_aliases.zsh
if [[ -e ${HOME}/.local_aliases ]]; then
    source ${HOME}/.local_aliases
fi
```

### ~/.zsh/init/40_keybinds.zsh

Zshのキーバインド設定です。

`vi`風のキーバインドを基本に、`emacs`風の操作を多少混ぜた感じにしています。

```zsh:~/.zsh/init/40_keybinds.zsh
bindkey -d
bindkey -v

bindkey '^A' beginning-of-line
bindkey '^E' end-of-line
bindkey '^N' down-line-or-history
bindkey '^P' up-line-or-history

bindkey -M viins '^B' backward-char
bindkey -M viins '^F' forward-char
```

### ~/.zsh/init/80_others.zsh

その他の雑多な設定を詰め込んでいます。

#### `ls`の色設定

`ls`で表示されるファイルの色設定です。

環境変数によって設定できますが、GNU系とBSD系で参照する環境変数が違うので、同じ色になるようにしています。
また、`ls`のTAB補完で表示されるファイルにも色を付けるよう、zstyleを設定しています。

```zsh:~/.zsh/init/80_others.zsh
# GNU系
export LS_COLORS='no=00:fi=00:di=01;36:ln=36:pi=31:so=33:bd=44;37:cd=44;37:ex=01;32:mi=00:or=36'

# BSD系
export LSCOLORS=GxgxdxbxCxegedabagacad

# TAB補完時に色表示
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
```

[ここ](https://unix.stackexchange.com/questions/20721/testing-ls-colors-in-zsh) にあるテストスクリプトで確認すると、こんな感じの色になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29000/3b8add49-7e1b-b344-4df1-104569de3945.png)

#### TAB補完強化

TAB補完の強化設定です。

```zsh:~/.zsh/init/80_others.zsh
# ファイル名補完時、大文字/小文字を区別しない
zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}' '+m:{a-z}={A-Z}'
```

![comp.gif](https://qiita-image-store.s3.amazonaws.com/0/29000/e6c8ccca-dce2-6754-bcfa-f7a6be1f2a53.gif)

```zsh:~/.zsh/init/80_others.zsh
# "kill [TAB]" でプロセスIDを補完する
zstyle ':completion:*:processes' command "ps au"
zstyle ':completion:*:processes' menu yes select=2
```

![kill.gif](https://qiita-image-store.s3.amazonaws.com/0/29000/2cb92468-5fb7-717c-d6a8-2a8baf937606.gif)

```zsh:~/.zsh/init/80_others.zsh
# オプション補完時の、オプション/説明のセパレータ
zstyle ':completion:*' list-separator '-->'
```

![ls.gif](https://qiita-image-store.s3.amazonaws.com/0/29000/c00cac7a-ed73-94fe-dba4-2432553162dc.gif)


#### 区切り文字設定

Ctrl+Wで単語を消すとき等の区切り文字を設定します。

```zsh:~/.zsh/init/80_others.zsh
zstyle ':zle:*' word-chars ' /=;@:{}[]()<>,|.'
zstyle ':zle:*' word-style unspecified
```

#### `cd`コマンド省略

ディレクトリ移動のたびに`cd`なんて打ってられないので、`auto_cd`を有効にして、ディレクトリ名のみで移動できるようにします。
上記のファイル名補完と合わせると、かなり楽になります。

```zsh:~/.zsh/init/80_others.zsh
setopt auto_cd
```

#### Shell内のVimで `Ctrl + S`、`Ctrl + Q`を使用可能にする

GVimでは問題ないのですが、Shell内でVimを立ち上げると`Ctrl + S`、`Ctrl + Q`等のキーバインドがShellに食われて使用できなくなります。
以下の設定でそれを抑制できます。

```zsh:~/.zsh/init/80_others.zsh
stty -ixon
```

#### zmv有効化

解説は他サイトに譲りますが、`mv`コマンドをzshで拡張した`zmv`が超便利なので有効化しておきます。

```zsh:~/.zsh/init/80_others.zsh
autoload -Uz zmv
```

参考: [zsh の zmv を使って簡単に複数ファイルを一括リネームする](http://mollifier.hatenablog.com/entry/20101227/p1)


### ~/.zsh/init/90_visual.zsh

見た目の設定を書いています。

#### プロンプト

状況に応じて、プロンプトを出し分けています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29000/f642c7bf-2c8c-a478-1d1d-e61a444e8632.png)

法則は以下のとおりです。

- ユーザー名
    - 一般ユーザ => 緑
    - root => 赤
- ホスト名+カレントディレクトリ
    - ローカル => 青
    - リモート => オレンジ
- 末尾記号
    - 挿入(通常)モード => `>`
    - コマンドモード => `|`
- カレントディレクトリの深さ
    - 5より浅い場合 => そのまま表示
    - 5以上深い場合 => 末尾の3つのみ表示、それ以前は`...`で省略

```zsh:~/.zsh/init/90_visual.zsh
color_red="%{^[[38;5;196m%}"
color_green="%{^[[38;5;046m%}"
color_blue="%{^[[38;5;045m%}"
color_orange="%{^[[38;5;202m%}"
color_gray="%{^[[38;5;242m%}"
color_end="%{^[[0m%}"

case ${UID} in
    # root
    0)
        PROMPT_USER="${color_red}%n${color_end}"
        ;;

    # other
    *)
        PROMPT_USER="${color_green}%n${color_end}"
        ;;

esac

if [ -n "${REMOTEHOST}${SSH_CONNECTION}" ]; then
    # remote connection
    PROMPT_PATH_COLOR="${color_orange}"
else
    # local
    PROMPT_PATH_COLOR="${color_blue}"
fi

PROMPT_PATH="%(5~,.../%3~,%~)"

PROMPT_STRING="${PROMPT_USER}@${PROMPT_PATH_COLOR}%m:${PROMPT_PATH}${color_end}"

function zle-line-init zle-keymap-select {
    case $KEYMAP in
        vicmd|visual)
            SUFFIX="|"
            ;;
        *)
            SUFFIX=">"
            ;;
    esac
    PROMPT=$'\n'"${PROMPT_STRING} ${SUFFIX} "
    zle reset-prompt
}

zle -N zle-line-init
zle -N zle-keymap-select
```

#### 右プロンプト表示

ターミナル番号と時間を表示しています。

```zsh:~/.zsh/init/90_visual.zsh
RPROMPT="${color_gray}%y [%D{%m/%d} %*]${color_end}"
```

## ~/.zsh/zplug.zsh

[zplulg/zplug](https://github.com/zplug/zplug) で管理するプラグインのリストです。

```zsh:~/.zsh/zplug.zsh
if [[ ! -e ~/.zplug/init.zsh ]]; then
    git clone https://github.com/zplug/zplug ~/.zplug
fi

source ~/.zplug/init.zsh

zplug "zplug/zplug"

# コマンドに色をつける
zplug "zsh-users/zsh-syntax-highlighting", \
    defer:2

# cd便利化
zplug "b4b4r07/enhancd", \
    use:init.sh

# HTTPステータスコードの確認に便利
zplug "b4b4r07/http_code"

# インタラクティブフィルタ
zplug "jhawthorn/fzy", \
    as:command, \
    rename-to:fzy, \
    hook-build:"make && sudo make install"

# historyからコマンドをサジェストさせる
zplug "zsh-users/zsh-autosuggestions"

if [[ $OSTYPE == *darwin* ]]; then
    # GitHub 操作をshellから可能にする
    zplug "github/hub", \
        from:gh-r, \
        as:command, \
        use:"*darwin*amd64*"
fi
```

#### auto_cd 時も enhancd の候補に追加する

[b4b4r07/enhancd](https://github.com/b4b4r07/enhancd)は、過去に移動したディレクトリの候補リストからインタラクティブに選択し、移動できるプラグインです。
大変便利なのですが、上述の`auto_cd`を使ってディレクトリ移動した際は候補リストに挿入されないようなので、`zsh-hook`を使用して無理やり突っ込んでいます。

```zsh:~/.zsh/zplug.zsh
if zplug check --verbose "b4b4r07/enhancd"; then
    add-zsh-hook chpwd __enhancd::cd::after
fi
```

# Tmux

### ~/.tmux.conf

よくローカル/リモートで`Tmux`を2重に立ち上げて作業をしているのですが、設定ファイル内で条件分岐等を行う術が無いようなので、ローカル用とリモート用でファイルを分けています。
実際に使うときは、`~/.tmux.conf`をそれぞれに対するSymlinkとすることで、リネームの手間を省いています。

```sh
# ローカル
~/.tmux.conf  ->  ~/.dotfiles/.tmux.conf

# リモート
~/.tmux.conf  ->  ~/.dotfiles/.tmux.remote.conf
```

下の画像は、ローカルTmuxのウィンドウでタブを3つ開き、そのうち1つのタブでサーバにsshして、サーバ内のTmuxでまたタブを3つ開いている様子です。

![tmux.png](https://qiita-image-store.s3.amazonaws.com/0/29000/e8005042-2cbc-ae80-7f9f-2106cdf8414d.png)


#### キーバインド

ローカル/リモートでプレフィックスキーが被らないようにしています。

```tmux:~/.dotfiles/.tmux.conf
set-option -g prefix C-x
bind-key C-x send-prefix
```

```tmux:~/.dotfiles/.tmux.remote.conf
set-option -g prefix C-r
bind-key C-r send-prefix
```

#### ローカル/リモートでステータスバーの色変更

`zsh`のプロンプトと同様に、`Tmux`のステータスバーも色分けをしています。
色味も統一して、青系とオレンジ系にしています。

```tmux:~/.dotfiles/.tmux.conf
set-option -g status-left "  #[bg=colour021,fg=white] Host:#h #[bg=colour027,fg=white] Session:#S #[bg=colour033,fg=black] Window:#W(#P) #[bg=default,fg=default]"
set-option -g status-right "#(tmux-network)#[bg=colour021,fg=white] %Y-%m-%d (%a) %H:%M:%S #[bg=default,fg=default]"
```

```tmux:~/.dotfiles/.tmux.remote.conf
set-option -g status-left "  #[bg=colour202,fg=black] Host:#h #[bg=colour208,fg=black] Session:#S #[bg=colour172,fg=black] Window:#W(#P) #[bg=default,fg=default]"
set-option -g status-right "#(tmux-network)#[bg=colour202,fg=black] %Y-%m-%d (%a) %H:%M:%S #[bg=default,fg=default]"
```

#### ネットワーク状況を表示 (ローカル/リモート共通)

以前 [Cygwinでネットワーク状況を表示する記事](https://qiita.com/s4kr4/items/6e13e6b966b62a468392) を書きましたが、その後macOSにも対応しています。OSで分岐させて、[こちら](https://qiita.com/arks22/items/a792d9d43d913c373520)を参考にスクリプト([tmux-network](https://github.com/s4kr4/dotfiles/blob/master/bin/tmux-network))を修正しました。

```tmux:~/.tmux.conf
set-option -g status-left-length 60
set-option -g status-right-length 60
set-option -g status-left "  #[bg=colour202,fg=black] Host:#h #[bg=colour208,fg=black] Session:#S #[bg=colour172,fg=black] Window:#W(#P) #[bg=default,fg=default]"
set-option -g status-right "#(tmux-network)#[bg=colour202,fg=black] %Y-%m-%d (%a) %H:%M:%S #[bg=default,fg=default]"
```


# おわり

記事を書くにあたって、自分でも忘れていた設定を思い出したり、不要な設定を削除する等、いろいろ整理できてよかったです。