ワンライナー打つのしんどい
CSV落として該当の列だけ抜き出すときにcat hoge.csv | awk ...
とか、fzfでプレビューして〇〇するみたいなときにcat hoge.txt | fzf --preview...
など、
大体打つコマンドって決まってくると思う。
.zshrc
や.sh
ファイルなどに直接Shellを書いていくときは、エディタのコード補完が効くので特に面倒ではないが、
Terminal上でサクッとワンライナーで実行したいときに、いちいち定型文を書いていくのがとても面倒である。
「Terminalに打っている段階でもSnippetみたいな補完ができたらいいな...」と思って、その方法について考えてみる。
zle(Zsh Line Editor)とfzfの組み合わせで実現できる
こんな感じで打っている途中にfzfで補完を出して、選択したらTerminalに打ち込まれるようになる。
zleってなんなの?
下記のサイトが死ぬほど参考になるのでぜひ見てほしい。
ようはzshに搭載されている機能で、Terminal上の文字列やカーソル位置をShellScript上で操作できる。
Terminal上の文字列やカーソルはtput
コマンドを駆使すればやれんこともないが、キーバインドに設定したりコマンド実行後に〇〇するなど、何かの動作をhookしたいときにzle
を使うのが便利なので覚えておいて損なし。
もっと細かく知りたい人はman zshzle
で見れる。Web版もある。
Snippetっぽいものを実現する
.zshrc
に下記を記載して、source ~/.zshrc
すれば終了。Terminal上でCtrl-o
を押せばSnippetが出てくる。
# 自作ウィジェット show_snippets() { local snippets=$(cat ~/zsh_snippet | fzf | cut -d':' -f2-) LBUFFER="${LBUFFER}${snippets}" zle reset-prompt } # 自作ウィジェットを登録 zle -N show_snippets # 自作ウィジェットを`Ctrl-o`で呼び出す bindkey '^o' show_snippets
Snippetファイルとして~/zsh_snippet
を作成しておく。自分の場合はこんな感じ。
awk:'{print $1}' fzf:--prompt "" fzf:--preview fzf:--preview-window=down:40% printf:printf "\e[33m${1}\e[m\n"
このファイルをcat ~/zsh_snippet | fzf | cut -d':' -f2-
で読み込んでるっていう感じ。
json
ファイルにしてjq
コマンド使ってfzfのpreviewにコマンドの説明を出す、みたいにちょっとリッチにしてもいいと思う。
まああくまで補助的なものだしParser的な問題になってくるのでそんなにこだわらなくてもいいんじゃないかな。シンプルイズベスト。
ちょびっと解説
肝は$LBUFFER
っていう変数。これはzshで最初から用意されているもので、Left BUFFER
の略。
何が入っているかというと、現在のカーソル位置より左にある文字列が入っている。
LBUFFER="cat ~/zsh_snippet"
となる
なのでLBUFFER="${LBUFFER}${snippets}"
の部分で
「今まで打っていたコマンド」+「fzfで選択した文字列」
を繋げてるって感じ。
他にも色々変数は用意されているので詳しくはman zshzle
。
あとキーバインド枯渇問題があるが、bindkey '^x^o' show_snippets
のようにすればCtrl-xo
と複数の文字で登録できるので自分なりのprefixを設定すれば良さそう。
bindkey
で今設定されているものが見れるので自作のウィジェットを登録する前に要確認。
終わり
- 自作関数つくる
- ウィジェットとして登録する
- キーバインドに登録する
っていうめちゃくちゃ簡単な3ステップなのでスーパーベリーイージーマーケット。
当初はHyperのプラグインとして作るしかないかなあと思っていたがzleとfzfだけで十分機能を満たせた。
VimのSnippetっぽく$1に設定したところにジャンプするとか、直前の単語であらかじめsnippetを絞るとかもっとリッチにはできそうだがとりあえずこの辺に留める。