zshの便利設定2016

こんばんわ。WACULのプログラマー、 @kyoh86 です。
このエントリはWACUL Advent Calendar 2016の12日目の記事です。

年末といえば大掃除ですね。
押入れ、トイレ、玄関、換気扇…普段あまり凝って手を入れないところも、キレイにしていくものです。
そう、例えば `.zshrc` とか。え？やらない？それではいい年は迎えられないでしょうね。

## ソースで語れよ

https://github.com/kyoh86/dotfiles

はい。

ゴッチャゴチャなので、個人的整理も兼ねて記事にしちゃいます。
~~決して当日になってネタが無くて焦っているわけではありません。~~

## はじめに：`fzf`ありがとう

[fzf](
https://github.com/junegunn/fzf
)ほんと便利。pecoより、色々機能が強くて便利。
とはいえ強い機能は殆ど使いこなせてないんですが…。

zsh神（勝手に崇めてる）こと @b4b4r07 さんも記事を書いてますね。

http://qiita.com/b4b4r07/items/9e1bbffb1be70b6ce033

## リポジトリ選んで`cd`しちゃう君

https://github.com/kyoh86/dotfiles/blob/master/function/cd-ghq-repository

ローカルのリポジトリが増えてくると、ディレクトリ選んで `cd` するのも大変なので、特定のパスルールに則っておいて、リポジトリセレクタのように `fzf` で移動できるととても便利です。

```
command ls -d $GOPATH/src/github.com/{wacul,wcl48,kyoh86}/*(N-/) \
  | fzf "$GOPATH/src/github.com/" \
  | anyframe-action-execute cd --
```

僕は普段 `golang` 使いなので、 `${GOPATH}` 配下の特定パスルールで `ls -d hoge/*(N-/)` してしまって、あとは `fzf` で絞り込んでいます。
`ghq list` なんかも悪くは無いんですが、いかんせんthird-partyのリポジトリと自分のリポジトリを分けて管理するのが面倒くさいのと、単純に毎回.git探してしまうのは些か重すぎるので、`ls`で簡略しています。

`anyframe-action-execute` は、`fzf/peco`の薄いラッパー[anyframe](https://github.com/mollifier/anyframe) の1機能です。fzfからパイプして何も考えずにcallできるので、使っています。
こちらも作者のzsh神（勝手に拝んでる）こと @mollifier さんが詳細を記事にしてくださってます。

http://qiita.com/mollifier/items/81b18c012d7841ab33c3

## launchctlのサービス名検索する君

https://github.com/kyoh86/dotfiles/blob/master/function/insert-launchctl

Macだと、launchctlで色々なデーモン・サービスを起動、終了するシーンがあるかとおもいます。が、あのlaunchctlの長いサービス名を覚えられないことが多々。

```
launchctl stop homebrew.mxcl.mongodb
```

**知るか！**

入力保管してくれるプラグインとかも `oh-my-zsh` 系で出回ってるようですが、入力補完って結局「ぼんやり覚えてるけど、実際どうだったかは怪しい」みたいな状態だとあんまり役に立たないので、検索できると便利です。

```
launchctl list | tail -n +2 | awk '{print $3}' \
  | fzf \
  | anyframe-action-insert
```

こういうfunction置いといて、`bindkey` しておくとはかどります。

```
bindkey '^xl' insert-launchctl
bindkey '^x^l' insert-launchctl
```

`launchctl start` まで入力したところで、 `ctrl-x, ctrl-l` と入力すれば、 `mongodb` など雑に検索して、 enter。実に楽です。

## シェル履歴から入力する君

`peco/fzf` 系では鉄板のネタですね。

https://github.com/kyoh86/dotfiles/blob/master/function/put-history

```
history -n 1 | grep -v '.\{200,\}' | awk '!a[$0]++' \
  | fzf --no-sort --query="$LBUFFER" \
  | anyframe-action-put
```

200文字を超える様な履歴は、fzfでも見切れてしまってノイズにしかならないので無視しています。
また、途中まで入力した状態で「あれ、これ前もやった気がする…」となったときのために、 `--query="$LBUFFER"` として、入力済みの内容をもって検索開始されるようにしています。

## 諸々インストールしてる内容を記憶する君

`brew` だ `cask` だ `mas` だと色々なパッケージマネージャを使うのは良いんですが、
はてMac移行の時はどないしましょ、となりがちです。

いざMac移行となるときは、たいていMac先生がお亡くなりになっているので、前もってバックアップはとっておきたい・・・しかし、ズボラでマメに毎日なんて無理だ・・・という僕。

めんどうなので、 `brew` も `cask` も `mas` も、インストールしている内容を自動的に `dotfiles` 配下に保存するようにしています。

https://github.com/kyoh86/dotfiles/blob/master/dots/userjob

```userjob
# Update mas-cli:
if [ -f /usr/local/bin/mas ] ; then
  echo '#!/bin/sh' > ~/.install_mas
  /usr/local/bin/mas upgrade
  /usr/local/bin/mas list \
    | awk '{printf "mas install %s # %s %s %s\n", $1, $2, $3, $4}' >> ~/.install_mas
fi

# Update brew cask:
if [ -f /usr/local/bin/brew ] ; then
  echo '#!/bin/sh' > ~/.install_cask
  /usr/local/bin/brew cask list \
    | awk '{printf "brew cask install %s\n", $1}' >> ~/.install_cask
fi

# Update brew:
if [ -f /usr/local/bin/brew ] ; then
  echo '#!/bin/sh' > ~/.install_brew
  /usr/local/bin/brew leaves \
    | awk '{printf "brew install %s\n", $1}' >> ~/.install_brew
fi
```

こういうshellを書いておいて、

```
ln -fs ${dotfiles}/userjob ~/.userjob
```

とホームディレクトリにリンクしておき、`plist` を登録してlaunchctlで入らせれば、1時間に1回、brewとcaskとmasでインストールされている内容を、~/.install_xxx というファイルで保存してくれます。

https://github.com/kyoh86/dotfiles/blob/master/plist/userjob.plist

さらに、dotfiles配下にそれぞれ

* `install_brew`
* `install_cask`
* `install_mas`

というファイルを用意しておいて、

```
ln -fs ${dotfiles}/install_brew ~/.install_brew
ln -fs ${dotfiles}/install_cask ~/.install_cask
ln -fs ${dotfiles}/install_mas ~/.install_mas
```

とリンクしておけば、内容はdotfiles配下に入るので、たまにcommit & pushしておけば安心です。


## おわりに

画像もない、ソースだけの殺風景な記事ですが、お役に立てれば幸いです。