vagrantの各種コマンドを、anything風に操作できるようにする.(zsh+peco+anyframe)


vagrantの操作系が面倒臭く、zsh+peco+anyframeを利用してAnything風に操作できるようにしたのでそのメモです.

![tty.gif](https://qiita-image-store.s3.amazonaws.com/0/31824/ae43a546-4a6a-7466-1bff-a4f418156f4a.gif "tty.gif")

# 背景
本当はPecrantと呼ばれるPeco+VagrantなAnything風ツールがあるのですが、くそ遅い`vagrant global-status`に依存しているコマンドなのでもっさり感が半端ない.（その時間があればコマンド打った方がはy

[Peco & Pecrant が素晴らしい
](http://qiita.com/yungsang/items/72ffa91f62ed113a2cf7)

なので`vagrant global-status`より早い[vagrant-global-status](https://github.com/monochromegane/vagrant-global-status)があるので、今回はそれを使ってよりカジュアルに利用できるようにしたいと思った次第.

# 使ったツール

pecoを利用して独自に作ろうかと思ったら、anyframeという便利なプラグインがあったのでそれを利用して実現しました.
最初はpecoのコマンドを集めた、[cool-peco](http://qiita.com/ryoppy/items/4819d0911bf937dba821)を使ってぷるりしようかと思ったのですが、anyframeは簡単に拡張できて便利だったので…

* peco  
  入力をパイプで受け取って、それをanything風に選択できるIFを提供してくれるツール.  
  [pecoの基礎の基礎](http://qiita.com/xtetsuji/items/05f6f4c1b17854cdd75b)
* anyframe  
  [zshでpecoと連携するためのanyframeというプラグインを作った](http://qiita.com/mollifier/items/81b18c012d7841ab33c3)
* antigen  
  zshのプラグイン管理ツール. anyframeを入れるのに利用.

# インストール

MacOSX上でやっているので、Linux等の方は適宜公式を見て置き換えて下さい.
zsh及びantigenについてはインストールしているものとして割愛します.

## pecoインストール

homebrewな方はコマンド一発

```bash
$ brew install peco
# 以下のコマンドをやってみると、pecoのイメージが掴めるかと思います
$ ls | peco # emacsキーバインドなので、↓Ctrl+n ↑Ctrl+pです
```

## anyframeインストール

antigenを利用してanyframeをインストールする場合は、zshrcに1行追加するだけで済みます.

```
if [[ -f ~/.zsh/antigen/antigen.zsh ]]; then
  source ~/.zsh/antigen/antigen.zsh
  antigen bundle mollifier/anyframe # <= これを追加
  antigen apply
fi
```

追加したら`exec $SHELL -l`等でreload.

# anyframeのカスタムコマンドを作成する

anyframe自体に各種便利コマンドが入っているのですが、vagrant類は存在しないので追加していきます

### anyframeのcustomコマンドを置くディレクトリを作成

anyframeのcustomコマンドを置くディレクトリを作成.

```
# $HOME/.zsh/anyframe-customは任意ですが、それ以下のdirnameは変更不可.
# sources配下には、選択画面となる出力メッセージを生成するスクリプトを配置
$ mkdir -p $HOME/.zsh/anyframe-custom/anyframe-functions/sources
# widgets配下には、作ったスクリプト等を組み合わせて、最終的にユーザーが利用するスクリプトを配置する
$ mkdir -p $HOME/.zsh/anyframe-custom/anyframe-functions/widgets
```

上記で作成したフォルダ配下のスクリプトをanyframeで呼び出しできるよう、zshrcに以下の１行を加えます.

```
if [[ -f ~/.zsh/antigen/antigen.zsh ]]; then
  source ~/.zsh/antigen/antigen.zsh
  
  fpath=($HOME/.zsh/anyframe-custom(N-/) $fpath) # <- 追加
    
  antigen bundle mollifier/anyframe
  antigen apply
fi
```
参考: https://github.com/kegamin/prezto/blob/master/runcoms/zshrc#L94

## sourcesに、選択画面用スクリプトを配置する

```
$ cd $HOME/.zsh/anyframe-custom/anyframe-functions/sources
$ vi anyframe-source-vagrant-global-status
$ vi anyframe-source-vagrant-list-commands
```

### anyframe-source-vagrant-global-status

現在設定されているvagrantのhost情報を出力するスクリプト.
`vagrant-global-status`があれば利用するが、無ければ通常の`vagrant global-status`を利用するようにしました.

```bash
if type vagrant-global-status > /dev/null 2>&1; then
  # faster than ` vagrant global-status`
  # see -> https://github.com/monochromegane/vagrant-global-status
  vagrant-global-status
else
  vagrant global-status | awk '/^[[:alnum:]]{7} /'
fi
```
https://github.com/kegamin/dotfiles/blob/master/.zsh/anyframe-custom/anyframe-functions/sources/anyframe-source-vagrant-global-status

### anyframe-source-vagrant-list-commands

vagrantのどのコマンドを利用するか、anyframeで選択するために作ったスクリプト.
`vagrant list-commands`の結果を利用しようか迷ったけど、「やっぱり遅い」「対象がhostであるコマンド」に限定したかったので、これでいいのか？と思いながら以下のようなソースにした.

```bash
cat << EOL
ssh             connects to machine via SSH
ssh-config      outputs OpenSSH valid configuration to connect to the machine
status          outputs status of the vagrant machine
up              starts and provisions the vagrant environment
halt            stops the vagrant machine
suspend         suspends the machine
resume          resume a suspended vagrant machine
reload          restarts vagrant machine, loads new Vagrantfile configuration
destroy         stops and deletes all traces of the vagrant machine
EOL
```
https://github.com/kegamin/dotfiles/blob/master/.zsh/anyframe-custom/anyframe-functions/sources/anyframe-source-vagrant-list-commands

## widgetsに、選択画面用スクリプトを配置する

sourcesに置いたものを利用して、vagrantコマンドを実行するようなスクリプトをwidgetsに配置していきます.

### anyframe-widget-vagrant

コマンド(ssh/halt/up等)を選択、ホストを選択して`vagrant <command> <host>`を実行するスクリプト.

```bash
local command
command=$(anyframe-source-vagrant-list-commands \
             | anyframe-selector-auto \
             | awk '{print $1}')

anyframe-source-vagrant-global-status \
  | anyframe-selector-auto \
  | awk '{print $1}' \
  | anyframe-action-execute vagrant ${command}
```
https://github.com/kegamin/dotfiles/blob/master/.zsh/anyframe-custom/anyframe-functions/widgets/anyframe-widget-vagrant

### anyframe-widget-vagrant-cdr

選択したホストの、vagrantファイルがある場所に移動するスクリプト.

```bash
anyframe-source-vagrant-global-status \
  | anyframe-selector-auto \
  | awk '{print $5}' \
  | anyframe-action-execute cd
```
https://github.com/kegamin/dotfiles/blob/master/.zsh/anyframe-custom/anyframe-functions/widgets/anyframe-widget-vagrant-cdr

# bindkey設定

コマンドを毎回実行してると勿体無いので、zshrcでbindkey設定します.
以下を参考に、各自のzshrcに合わせて修正して下さい.

```bash
if [[ -f $HOME/.zsh/antigen/antigen.zsh ]]; then
  source $HOME/.zsh/antigen/antigen.zsh

  # 独自追加したanyframeの関数を呼ぶための設定
  fpath=($HOME/.zsh/anyframe-custom(N-/) $fpath)

  antigen bundle mollifier/anyframe
  bindkey '^j^j' anyframe-widget-cdr
  bindkey '^j^r' anyframe-widget-execute-history
  bindkey '^j^g' anyframe-widget-cd-ghq-repository
  bindkey '^j^t' anyframe-widget-tmux-attach
  bindkey '^v^v' anyframe-widget-vagrant # ctrl+v ctrl+vで呼び出し
  bindkey '^v^j' anyframe-widget-vagrant-cdr # ctrl+v ctrl+jで呼び出し

  antigen-apply
fi
```

https://github.com/kegamin/prezto/blob/master/runcoms/zshrc#L94

# 感想

anyframeはコマンド追加が楽で便利ですね.色々なツールで補ってた部分が、anyframeの標準機能で補完できたので入れ替えてさっぱり.

しかし、無理やり感のある`anyframe-widget-vagrant`は微妙なので直したい…