2013-03-15 [長年日記]
_ shellのコマンド履歴をanything風にインクリメンタル検索して実行
shell の便利コマンドcanything をインストールしてみました。標準入力で入ってきたリストをインクリメンタルに絞り込んで、選択した行を標準出力へ出すものです。(emacsな人へはCUIなanythingと言えば伝わるかなと。)
これを使って便利なものができないかなと思い、過去のコマンド履歴からインクリメンタルサーチするコマンドを作ってみました。C-rのanything版です。現在はこんな感じで、選択したコマンドをshellに入力した状態にします。あらかじめ canything をインストールしておいてください。また、最後の「入力した状態にする」でtmuxの機能を使っています。(shellの標準機能で文字入力をする方法をご存知の方はぜひ教えてください。)
- for mac
alias h="history -10000 | sed -e 's/^\s*[0-9]*\s*//' | tail -r | canything | sed -e 's/^(.*)$/\"\0\"/' | xargs tmux send-keys "
- for linux
alias h="history -10000 | sed -e 's/^\s*[0-9]*\s*//' | tac | canything | sed -e 's/^.*$/\"\0\"/' | xargs tmux send-keys"
(個々のコマンドはあとで説明していきます。)標準機能のCtrl+r よりも速く分かりやすく選べて快適!.tmux.conf に以下のように書いてホットキーに登録するとさらに便利。(-nはグローバルにキー割り当てするオプション、hコマンドの前にC-u しているのは既に何か入力している時に消す処理。)
bind-key -n M-r send-keys C-u h ENTER
ちょー便利です。:)
以下、ここまでの歩みを。最初はこんな風に選択したコマンドを実行していました。
history -10000 | sed -e 's/^\s*[0-9]*\s*//' | canything | source /dev/stdin
history -10000 は過去10000件の履歴を出します。sed コマンドでhistoryで出力される先頭についてる数字とかを除いてコマンドだけにします。canything にコマンド一覧を入力して、ユーザーが選んだコマンドが標準出力に出てパイプされます。渡ってきた文字列を実行しているのが source /dev/stdin です。(evalでやろうとしたのですがうまくいかず。)
使ってみたら以下の問題があることが分かりました。
- 実際に実行するコマンドが標準出力に表示されない
- 実行したコマンドが実行履歴に残らない。(ので、↑ボタンで戻ると h コマンドになってて不便)
- 選んだコマンドを修正できない ってことは、コマンド実行までやらずに、選んだコマンドをshellに入力した状態にできたら、その方が嬉しいのかも。あと、history は古い順だったので、tac コマンドで逆順にして最近使ったものを最初に表示するように。そしてできたのが最初に出したコマンドでした。
history -10000 | tac | sed -e 's/^\s*[0-9]*\s*//' | canything | sed -e 's/^.*$/\"\0\"/' | xargs tmux send-keys
現在の問題点。
-
なんか標準入力の前の行に選択した文字列が表示されてしまう tmux send-key の仕様かな?標準入力に文字を入力する他の方法ないかな?
-
uniqしたい unix の uniq は標準入出力には使えないぽい。
> unix の uniq は標準入出力には使えないぽい。<br><br>え、そんなことなくない?<br><br>$ printf "aaa\nbbb\nccc\naaa\n" | sort | uniq<br>aaa<br>bbb<br>ccc<br><br>$ man sort より。<br>> so it may be necessary to sort the files first.
ほんとだー!!!(manのその記述を読んで、ファイルのソートしかできないのかと思ってました・・・。)ありがとうございます!!