emacsを使っているとterminalでもanything的にいろいろやりたくなるんだけど、そういう時にこれまでzawというツールを使ってきた。
- https://github.com/zsh-users/zaw
- zaw.zshで最近移動したディレクトリに移動する - $shibayu36->blog;
- zawを使って最近更新したブランチをチェックアウトする - $shibayu36->blog;
zaw結構便利なんだけど問題点もある。
- 読み込む行数が増えてくると遅くなる
- 履歴検索で10万行とか行くと動かないので致命的
- zshに完全に紐付いてしまって、気軽には使えない
で、この前YAPCでid:moozさんと話してて、percolという便利ツール作ってると聞いたので、試してみた。
percolとは
紹介記事などがあるので、それを参考に。
簡単に言うとterminal版anythingもしくはUnite。標準入力で与えたものを行単位で絞込み、行を選択すると最後に標準出力でその行を出力するだけ。このインターフェースのお陰で適当にpipeでつなげるだけでも便利に使えるようになっている。
以下は履歴検索して複数選択すると、標準出力にそれらが出力される様子。
インストール
pipで入れるらしい(https://github.com/mooz/percol#pypi)。brewでpythonをインストールしていると、pipコマンドが付いてくるのでそれで入れる。
$ pip install percol
設定
まずemacs風に扱うために~/.percol.d/rc.pyを編集。
## keymap # Mac で delete(backspace)が効くようにする SPECIAL_KEYS.update({ 127: '<backspace>' }) percol.import_keymap({ "C-a" : lambda percol: percol.command.beginning_of_line(), "C-e" : lambda percol: percol.command.end_of_line(), "C-b" : lambda percol: percol.command.backward_char(), "C-f" : lambda percol: percol.command.forward_char(), "C-d" : lambda percol: percol.command.delete_forward_char(), "C-h" : lambda percol: percol.command.delete_backward_char(), "C-k" : lambda percol: percol.command.kill_end_of_line(), "C-y" : lambda percol: percol.command.yank(), "C-n" : lambda percol: percol.command.select_next(), "C-p" : lambda percol: percol.command.select_previous(), "C-v" : lambda percol: percol.command.select_next_page(), "M-v" : lambda percol: percol.command.select_previous_page(), "M-<" : lambda percol: percol.command.select_top(), "M->" : lambda percol: percol.command.select_bottom(), "C-m" : lambda percol: percol.finish(), "C-j" : lambda percol: percol.finish(), "C-g" : lambda percol: percol.cancel(), "M-c" : lambda percol: percol.command.toggle_case_sensitive(), "M-m" : lambda percol: percol.command.toggle_finder(FinderMultiQueryMigemo), "M-r" : lambda percol: percol.command.toggle_finder(FinderMultiQueryRegex) })
次にpercolでいろいろ関数を作りやすいようにする。.zshrcにpercolを使った便利ツール書きまくると管理できなくなるので、特定ディレクトリにpercolのsourceを置いておいてそれを読み込む設定を書く。
# ~/.zshrc # setting for percol source ~/.zsh/percol.zsh
# ~/.zsh/percol.zsh # load percol sources for f (~/.zsh/percol-sources/*) source "${f}"
上記の設定をそれぞれ作っておけば、~/.zsh/percol-sources/以下のファイルはzsh起動時に全てsourceしてくれるので、このディレクトリに便利コマンド設定を作っておけば良い。
履歴検索をpercolで
とりあえず履歴検索してコマンドを選択できるようにする。https://gist.github.com/mitukiii/4234173 が非常に参考になる。
~/.zsh/percol-sources/select-history.zshというファイルを作り、以下をコピペ。
function percol-select-history() { local tac if which tac > /dev/null; then tac="tac" else tac="tail -r" fi BUFFER=$(history -n 1 | \ eval $tac | \ percol --query "$LBUFFER") CURSOR=$#BUFFER zle clear-screen } zle -N percol-select-history
あとは適当に.zshrcなりにkeybindを追加。
bindkey '^r' percol-select-history
これでC-rを押したら、履歴検索してターミナルに表示するということが出来るようになった。
git-recent-branchesをpercolで
以前gitのbranchを更新順に並べてcheckoutできるやつをzawで作った。http://shibayu36.hatenablog.com/entry/2013/06/04/203833 。これをpercolでやってみる。
~/.zsh/percol-sources/git-recent-branches.zsh というファイルを作り、以下をコピペ。
function percol-git-recent-branches () { local selected_branch=$(git for-each-ref --format='%(refname)' --sort=-committerdate refs/heads | \ perl -pne 's{^refs/heads/}{}' | \ percol --query "$LBUFFER") if [ -n "$selected_branch" ]; then BUFFER="git checkout ${selected_branch}" zle accept-line fi zle clear-screen } zle -N percol-git-recent-branches function percol-git-recent-all-branches () { local selected_branch=$(git for-each-ref --format='%(refname)' --sort=-committerdate refs/heads refs/remotes | \ perl -pne 's{^refs/(heads|remotes)/}{}' | \ percol --query "$LBUFFER") if [ -n "$selected_branch" ]; then BUFFER="git checkout -t ${selected_branch}" zle accept-line fi zle clear-screen } zle -N percol-git-recent-all-branches
あとは適当に.zshrcにキーバインドを追加。
bindkey '^x^b' percol-git-recent-branches bindkey '^xb' percol-git-recent-all-branches
これでブランチを選択してcheckout出来るようになった。
プロセス検索をpercolで
あとpercolは標準入力を受け取って標準出力に表示するだけなので、プラグインみたいなのを作らなくても適当にコマンドラインでpipeに渡すだけでも便利に使える。
例えばプロセス検索して選択してkillするやつは以下のように書ける。便利ですね。
$ ps ax | percol | awk '{ print $1 }' | xargs kill
まとめ
percolの紹介しました。zawと比べて拡張性には欠けますが、シンプルなお陰でパイプでいい感じにコマンド作れて非常に便利です。あと速いのでzawとかで履歴検索が出来なかった人は使ってみると良さそうに思いました。