Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
percol 入れて zsh と組み合わせたら超便利

percol 入れて zsh と組み合わせたら超便利

だったので紹介

percol とは

percol は入力の1行を1候補として,部分一致かつ AND 検索で絞り込みし,選択した候補を出力するコマンドです.端的に言えば Emacs の anything.el のコマンド版です.

anything 的な絞りこみコマンド percol の紹介 - 備忘録

環境

Mac OS X 10.8.2
zsh 5.0.0 (x86_64-apple-darwin12.2.0)

percol のインストール

Python 製のツールなので pip で入れる

sudo pip install percol

migemo のインストール

percol と migemo を組み合わせて使うと便利なので是非入れよう

brew install cmigemo

Python のバインディングを入れる

curl -O http://www.atzm.org/etc/files/pymigemo/pymigemo-0.4.tar.gz
sudo pip install pymigemo-0.4.tar.gz

percol を設定する

上記紹介記事を参考に自分好みに設定

mkdir ~/.percol.d
vim ~/.percol.d/rc.py
import sys, commands
from percol.command import SelectorCommand
from percol.key import SPECIAL_KEYS
from percol.finder import FinderMultiQueryMigemo, FinderMultiQueryRegex

## prompt
# Case Insensitive / Match Method に応じてプロンプトに表示
def dynamic_prompt():
    prompt = ur""
    if percol.model.finder.__class__ == FinderMultiQueryMigemo:
        prompt += "[Migemo]"
    elif percol.model.finder.__class__ == FinderMultiQueryRegex:
        prompt += "[Regexp]"
    else:
        prompt += "[String]"
    if percol.model.finder.case_insensitive:
        prompt += "[a]"
    else:
        prompt += "[A]"
    prompt += "> %q"
    return prompt

percol.view.__class__.PROMPT = property(lambda self: dynamic_prompt())

## migemo
# Mac と Ubuntu で辞書のパスを変える
if sys.platform == "darwin":
    FinderMultiQueryMigemo.dictionary_path = "/usr/local/Cellar/cmigemo/20110227/share/migemo/utf-8/migemo-dict"
else:
    FinderMultiQueryMigemo.dictionary_path = "/usr/local/share/migemo/utf-8/migemo-dict"

## kill
# Mac の場合は kill(yank)をクリップボードと共有する
if sys.platform == "darwin":
    def copy_end_of_line_as_kill(self):
        commands.getoutput("echo " + self.model.query[self.model.caret:] + " | pbcopy")
        self.model.query  = self.model.query[:self.model.caret]

    def paste_as_yank(self):
        self.model.insert_string(commands.getoutput("pbpaste"))

    SelectorCommand.kill_end_of_line = copy_end_of_line_as_kill
    SelectorCommand.yank = paste_as_yank

## 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)
})

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 --match-method migemo --query "$LBUFFER")
    CURSOR=$#BUFFER
    zle clear-screen
}
zle -N percol-select-history
bindkey '^r' percol-select-history

ドキュメントっぽいのをインクリメント検索する

function percol-search-document() {
    if [ $# -ge 1 ]; then
        DOCUMENT_DIR=$*
    else
        DOCUMENT_DIR=($HOME/Dropbox)
        if [ -d $HOME/Documents ]; then
            DOCUMENT_DIR=($HOME/Documents $DOCUMENT_DIR)
        fi
    fi
    SELECTED_FILE=$(echo $DOCUMENT_DIR | \
        xargs find | \
        grep -E "\.(txt|md|pdf|key|numbers|pages|doc|xls|ppt)$" | \
        percol --match-method migemo)
    if [ $? -eq 0 ]; then
        echo $SELECTED_FILE | sed 's/ /\\ /g'
    fi
}
alias pd='percol-search-document'

locate コマンドから結果を更に検索

function percol-search-locate() {
    if [ $# -ge 1 ]; then
        SELECTED_FILE=$(locate $* | percol --match-method migemo)
        if [ $? -eq 0 ]; then
            echo $SELECTED_FILE | sed 's/ /\\ /g'
        fi
    else
        bultin locate
    fi
}
alias ps='percol-search-locate'

パイプで渡してよく使うコマンドをエイリアスで定義しとくと便利

alias -g E="| xargs emacsclient -n"
alias -g O="| xargs open"
alias -g P="| percol --match-method migemo"
alias -g C="| pbcopy"
alias -g L="| less"
alias -g H="| head"
alias -g T="| tail"
alias -g G="| grep"
alias -g S="| sed"

こんな感じで使える

percol-search-document ~/Document/Memo O # "~/Document/Memo" 内を検索し選択したファイルを開く
percol-locate rb E # Ruby っぽいファイルを検索し選択したファイルを Emacs で開く

その他

Git の log をフィルタして何かするエイリアスとか作ったら便利そう

参考リンク

anything 的な絞りこみコマンド percol の紹介 - 備忘録
anything 的絞りこみコマンド percol が migemo 対応しました - 備忘録

ncaq commented Apr 8, 2014

zshのBUFFER変数をこれで知りました
ありがとうごございます

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment