tcsh使いがzshに乗り換えるための.zshrc入門

rvmがtcshを標準でサポートしないようなので、高機能でよく名前を聞くzshに乗り換えることにしました。
tcsh使いから見ると、complete（補完）の仕掛けが今ひとつわかりにくかったので、極力tcshに似せた書き方でzshrcを書いてみました。
zshrcの書き方は良くわかってないので、変なところあるかもしれません。ご容赦ください。

# ~/.zshrc

```zsh:~/.zshrc
# Shigeyuki Osada 2016-05-20

e_normal=`echo -e "¥033[0;30m"`
e_RED=`echo -e "¥033[1;31m"`
e_BLUE=`echo -e "¥033[1;36m"`

export EDITOR=emacs
export LANG=ja_JP.UTF-8
export LESSCHARSET=utf-8
export PATH=$PATH:/sbin:/usr/local/bin:$HOME/bin
export PATH="$PATH:$HOME/.rvm/bin"

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*

### setopt {{{
setopt auto_cd
setopt auto_list
setopt auto_menu
setopt auto_param_keys
setopt auto_param_slash
setopt auto_pushd
setopt autopushd
setopt brace_ccl
setopt chase_links
setopt complete_aliases
setopt correct_all
setopt extended_glob
setopt globdots
setopt hist_ignore_all_dups
setopt hist_no_store
setopt hist_reduce_blanks
setopt inc_append_history
setopt list_packed
setopt list_types
setopt magic_equal_subst
setopt multios
setopt no_clobber
setopt noautoremoveslash
setopt nolistbeep
setopt path_dirs
setopt pushd_ignore_dups
setopt share_history
### }}}

alias j='jobs -l'
alias a='./a.out'
alias e='emacs'
alias ll='ls -l'
alias ls='ls -F'
alias p='ps -aux'
alias bcr='bitcoin-cli -regtest'

export SHELL=/bin/zsh

# Autocomplete
autoload -U compinit
compinit

function _bitcoin-cli(){
  local -a cmds
  if (( CURRENT == 2 ));then
    cmds=('-testnet' '-regtest')
    _describe -t commands "subcommand" cmds
  elif (( CURRENT == 3 ));then
    cmds=('getinfo' 'listunspent' 'getbalance' 'listaccounts' 'generate' \
		  'getrawtransaction' 'getaddressesbyaccount' 'getnewaddress' 'dumpprivkey' \
		  'sendtoaddress')
    _describe -t commands "subcommand" cmds
  else
    _files
  fi

  return 1;
}

compdef _bitcoin-cli bitcoin-cli

function _bcr(){
  local -a cmds
  if (( CURRENT == 2 ));then
    cmds=('getinfo' 'listunspent' 'getbalance' 'listaccounts' 'generate' \
          'getrawtransaction' 'getaddressesbyaccount' 'getnewaddress' 'dumpprivkey' \
          'sendtoaddress')
    _describe -t commands "subcommand" cmds
  else
    _files
  fi

  return 1;
}

compdef _bcr bcr



function _bundle(){
  local -a cmds
  if (( CURRENT == 2 ));then
    cmds=('exec' 'install')
    _describe -t commands "subcommand" cmds
  elif (( CURRENT == 3 ));then
    cmds=('rails' 'rake' )
    _describe -t commands "subcommand" cmds
  elif (( CURRENT == 4 ));then
    cmds=('s' 'g' 'db\:seed' 'db\:reset' 'db\:migrate' 'routes' 'smfg\:issue_asset' \
           'smfg\:send_assets' 'smfg\:send_bitcoins')
    _describe -t commands "subcommand" cmds
  else
    _files
  fi

  return 1;
}

compdef _bundle bundle

# do not care for capital
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
# complete ps
zstyle ':completion:*:processes' command 'ps x -o pid,s,args'


HISTFILE="$HOME/.zhistory"      # Histroty file
HISTSIZE=10000                  # Maximum size of memory
SAVEHIST=10000                  # Maximum number of line
fpath=($HOME/.zsh/functions $fpath)

function history-all { history -E 1 } # Show all hisyory

# history search
autoload history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "^[[A" history-beginning-search-backward-end
bindkey "^[[B" history-beginning-search-forward-end

PROMPT='[%F{yellow} %D %T %f] %F{green}%~%f
%n@%m%# '
```

# 解説
## 補完
基本的には、以下の2行でOK。tcshから見ると、これだけでも過剰なように補完がかかります。(host名補完やmake補完もできます）

```
autoload -U compinit
compinit
```

## ヒストリ補完

```zsh
autoload history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "^[[A" history-beginning-search-backward-end
bindkey "^[[B" history-beginning-search-forward-end
```

矢印キーの上下でヒストリ補完。ポイントは、補完時にカーソルが右端によるところ。通常、パラメタは最後に書くことが多いので、それを修正したいときに便利。先頭にカーソルを持って行きたい時は、「Ctrl+a」でOK。（Emacsキーバインドのとき）

私の環境（mac）では、^[[Aが上キーで、^[[Bが下キーです。

## 特定条件下の補完

あるコマンドだけ、こちらで指定した内容から補完したい、というときもあるかと思います（所謂tcshのcomplete）。

zshでは以下のように表現するそうです。

```zsh:.zshrc
function _bundle(){
  local -a cmds
  if (( CURRENT == 2 ));then
    cmds=('exec' 'install')
    _describe -t commands "subcommand" cmds
  elif (( CURRENT == 3 ));then
    cmds=('rails' 'rake' )
    _describe -t commands "subcommand" cmds
  elif (( CURRENT == 4 ));then
    cmds=('s' 'g' 'db\:seed' 'db\:reset' 'db\:migrate')
    _describe -t commands "subcommand" cmds
  else
    _files
  fi

  return 1;
}

compdef _bundle bundle
```

「補完したいコマンド」に1つずつに、特別な命名規則をつけた「補完function」を定義します。
特別な命名規則とは、コマンド名の先頭に"_"をつけたもの。例えば、"bundle"コマンドであれば、"_bundle"で定義します。
"_bundle"の中で、補完のルールを書いていきます。最後に、compdefを使って、「補完function」と「補完したコマンド」をひも付けます。

まだ補完functionの書き方がわかっていないので、イマイチな補完精度ですが、これをベースにして、zshの様々な機能を使っていくとパワフルなるようです。

ちなみに、.zshrcに補完の定義を書くことは、zshの思想としては少し外れている印象です。zshの主流なやり方では、fpathの通ったディレクトリに、"_"から始まる名前の補完定義ファイルを置いておいて、そこに補完functionを書くようです。
ただし、今回はtcshから移行するという点と、ポタビリ性の点から、.zshrcに全て補完の定義を入れる、という書き方をご紹介しています。

## プロンプト
1行目に日時とカレントディレクトリを、2行目にユーザ名とホスト名を表示するものです。プロンプトに改行コードを入れると、たまに他のアプリで悪さをすることもありますので、そういったものをお使いの方はご注意ください。

```
PROMPT='[%F{yellow} %D %T %f] %F{green}%~%f
%n@%m%# '
```

こんな感じで出ます。

```
[ 16-05-22 18:02 ] ~
osada@mbp16a% 
```

色は%F{色}と%fでくくった箇所で表現するようです。


# 参考サイト
https://gist.github.com/mitukiii/4954559