ご注文は選択することですか?


cdコマンド改造記事第4回です。
前回の記事:ご注文は親ディレクトリに戻ることですか?

また、cdコマンドに手を入れていきます。

今回は、Simplistic interactive filtering toolのPecoを使っていきます。

第4羽「pecoをするお話」

何番煎じか分かりませんが、pecoという選択ツールを導入して使っていこうと思います。
fzfとかもあるので、シェル変数とか環境変数にして色んなツールを選択できるように汎用的にしていけたらいいですね。(その予定はないですけど)

pecoの導入

リポジトリ通りにいれてください。
普通に、リリースページからバイナリ落としてPATHに入れるだけです。

なにをpecoるのか?

まず、サンプルとして一番記事の多いコマンド履歴をpecoってみましょう。

仕様はテキトーな感じでいいよね。
- 新しい履歴が上に来ること
- 同じ履歴は最近のモノだけでいいこと(重複して表示しない)

bashrc
peco_history()
{
  local descending_order
  if which sort &> /dev/null; then
    descending_order='sort -r'
  elif which tac &> /dev/null; then
    descending_order='tac'
  else
    descending_order='tail -r'
  fi
  local trim_line_number='sed -re "s/^\s+[0-9]+\s+//"'
  local trim_duplication='awk '\''!dictionaty[$0]++'\'''
  local CMD=$(\history \
              | eval $descending_order \
              | eval $trim_line_number \
              | eval $trim_duplication \
              | peco --query "${READLINE_LINE}")
  READLINE_LINE="${CMD}"  # Input to terminal's readline
  READLINE_POINT=${#CMD}  # Set cursor
}

bind -x '"\C-r": peco_history'

スクリプト解説

まず、このスクリプトは処理したいことをコマンドで示し、それをローカル変数に格納するスタイルを取っています。

でないと、アホの私は土日を過ぎると「このコマンドは何を実現したいんだ……?」となってしまうからです。

  • descending_order
    新しい履歴を上に持ってくる仕様を満たすために、降順に並び替える処理を担当しています。 どれもこれもbashのビルトインじゃなかったので持ってるかどうかを調べています。
    とりあえず3つも調べたらどれかは持ってるでしょ(´・_・`)tacはMacではダメとかなんとか
  • trim_line_number
    今回は履歴の取得にhistoryコマンドをビルトイン実行しているのですが、履歴番号を付与してしまうのでそれを取り除きます。
  • trim_duplication
    履歴表示は重複させない仕様を満たすため、辞書式配列を作ることで実現しています。
    awkでこんなの考えた人天才ですね

これらは変数に格納されるので、所定の順番にevalコマンドで実行して最後にpecoへパイプします。

  • --queryオプション
    pecoのqueryオプションは初期QUERYとして文字列を渡すようです。
    既に入力されている文字列を渡すことで、入力途中で実行すると最初からその文字列で絞込ませておくことができます。

最後にterminalへ反映させるために変数に結果を格納します。

  • READLINE_LINE
    terminalへ入力されている文字列をpecoで選択した結果に置き換えます。
    pecoで複数選択した場合のケア?知らねー
  • READLINE_POINT
    terminalのカーソルの位置を文字列の最後にしています。
    変数に#をつけると、変数展開が行われて文字列を取得することができます。
    参考:【シェル芸人への道】Bashの変数展開と真摯に向き合う

最後は、これをデフォルトでは履歴検索を担当しているショートカットキーをbindコマンドで上書きして終わりです。

最後

こんな感じで使えます。
結構便利ですね。

git logをパースするとか色々しておくと便利かもしれませんね。
もうちょっと、このpecoを使っていきたいと思います。

というか、コマンド名タイポしたときに、
その間違えたコマンドを履歴に書き込まない方法とかありませんかね?(´・_・`)ダレカー