fzfで快適なターミナルライフ
以前こんなエントリを書いた。 petitviolet.hatenablog.com
主な理由はfzfについているpreview機能が気に入ったからで、ファイルやGitをインタラクティブに選択する際にpreviewが出来ると助かることが多いため。
逆にpreview機能を必要としないhistory検索とかはpecoを使っているままだったりはする。
どんな感じになるのか
fzfの--preview
オプションを使って便利になる
事前準備とか
環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14 BuildVersion: 18A391 $ zsh --version zsh 5.7 (x86_64-apple-darwin17.7.0) $ fzf --version 0.18.0 (brew)
Zsh Line Editorについて
fzf関係なく、zshで関数に対するショートカットキーを設定したり入力中のバッファをいじるのにZLE(Zsh Line Editor)を使っている。
だいたい↓のあたり。
zle accept-line zle clear-screen zle -N my_function bindkey '<key>' my_function BUFFER='xxx' LBUFFER+='yyy' CURSOR=$#LBUFFER
詳しくはman zshzle
すると読める。
fzfのグローバル設定
FZF_DEFAULT_OPTS
は以下のようにしている。
export FZF_DEFAULT_OPTS="--no-sort --exact --cycle --multi --ansi --reverse --border --sync --bind=ctrl-t:toggle --bind=ctrl-k:kill-line --bind=?:toggle-preview --bind=down:preview-down --bind=up:preview-up"
まあこれはお好みで。
ディレクトリ移動
zshについてくるcdr
コマンドを使っていい感じにディレクトリ移動をする。
ls
に適当なオプションをつけて実行した結果をpreviewで表示している。
あるファイルを探しているけど、どこにあったっけ、と思いながらインタラクティブに選ぶことが出来て便利。
# lsみながらcdrする function select_cdr(){ local selected_dir=$(cdr -l | awk '{ print $2 }' | \ fzf --preview 'f() { sh -c "ls -hFGl $1" }; f {}') if [ -n "$selected_dir" ]; then BUFFER="cd ${selected_dir}" zle accept-line fi zle clear-screen } zle -N select_cdr bindkey '^@' select_cdr
treeコマンドからファイルを選択する
現在のディレクトリ配下からファイルを選択したいけどScalaとか書いてるとディレクトリ構造が深くてめんどくさい、という時にtreeで一覧表示しつつ、そのファイル名を選択できるようにした。
head
でファイルの先頭をpreviewしている。
ignoreしないと死んでしまうとは思うので、そこは適当に付け足したりする必要がありそう。
# treeの一覧からheadしながらファイルを選択する function tree_select() { tree -N -a --charset=o -f -I '.git|.idea|resolution-cache|target/streams|node_modules' | \ fzf --preview 'f() { set -- $(echo -- "$@" | grep -o "\./.*$"); if [ -d $1 ]; then ls -lh $1 else head -n 100 $1 fi }; f {}' | \ sed -e "s/ ->.*\$//g" | \ tr -d '\||`| ' | \ tr '\n' ' ' | \ sed -e "s/--//g" | \ xargs echo } # treeで選択したファイル名を入力する function tree_select_buffer(){ local SELECTED_FILE=$(tree_select) if [ -n "$SELECTED_FILE" ]; then LBUFFER+="$SELECTED_FILE" CURSOR=$#LBUFFER zle reset-prompt fi } zle -N tree_select_buffer bindkey "^t" tree_select_buffer
これを少し応用すると選択したファイルを直接vimで開く、みたいなことも可能。
# treeから選択したファイルをvimで開く function open_from_tree_vim(){ local selected_file=$(tree_select) if [ -n "$selected_file" ]; then BUFFER="vim $selected_file" fi zle accept-line } zle -N open_from_tree_vim bindkey "^v^t" open_from_tree_vim
docker psからプロセスを選択する
docker ps
した結果からイメージを選択してstopしたりlogを見たりする時に使う。
# docker psからdocker log見ながらnameを選ぶ function select_docker_process(){ LBUFFER+=$(docker ps -a --format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Command}}\t{{.CreatedAt}}\t{{.Ports}}\t{{.Networks}}' | \ fzf --preview-window=down --preview 'f() { set -- $(echo -- "$@") if [[ $3 != "ID" ]]; then docker logs --tail 300 $3 fi }; f {}' | \ awk -F '\t' '{ print $2 }' | \ tr "\n" " ") CURSOR=$#LBUFFER zle reset-prompt } zle -N select_docker_process bindkey "^g^d^h" select_docker_process
docker ps --format 'table ...'
が便利でよかった。
git statusで変更のあるファイルから選択する
git status
した結果からファイルを選択してgit add
したりする時に使う。
プレビューでgit diff
が表示されるようにしてある。
untrackedなファイルや既にgit add
したファイルとかについてもgit diff
で差分が見れるようにしたかった面倒な実装になってしまった。
# git statusで対象となるファイルのgit diffみながらファイルを選択する function select_file_from_git_status() { git status -u --short | \ fzf -m --ansi --reverse --preview 'f() { local original=$@ set -- $(echo "$@"); if [ $(echo $original | grep -E "^M" | wc -l) -eq 1 ]; then # staged git diff --color --cached $2 elif [ $(echo $original | grep -E "^\?\?" | wc -l) -eq 0 ]; then # unstaged git diff --color $2 elif [ -d $2 ]; then # directory ls -la $2 else git diff --color --no-index /dev/null $2 # untracked fi }; f {}' |\ awk -F ' ' '{print $NF}' | tr '\n' ' ' } # ↑の関数で選んだファイルを入力バッファに入れる function insert_selected_git_files(){ LBUFFER+=$(select_file_from_git_status) CURSOR=$#LBUFFER zle reset-prompt } zle -N insert_selected_git_files bindkey "^g^s" insert_selected_git_files # ↑の関数で選んだファイルをgit addする function select_git_add() { local selected_file_to_add="$(select_file_from_git_status)" if [ -n "$selected_file_to_add" ]; then BUFFER="git add $(echo "$selected_file_to_add" | tr '\n' ' ')" CURSOR=$#BUFFER fi zle accept-line } zle -N select_git_add bindkey "^g^a" select_git_add
git branchとtagから選択する
git branch
とgit tag
の両方から、branch/tagを選択してcheckoutしたりpush/pullする時に使う。
主にgitのformatを設定するのが面倒くさかった。
# git branchとgit tagの結果からgit logを見ながらbranch/tagを選択する function select_from_git_branch() { local list=$(\ git branch --sort=refname --sort=-authordate --color --all \ --format='%(color:red)%(authordate:short)%(color:reset) %(objectname:short) %(color:green)%(refname:short)%(color:reset) %(if)%(HEAD)%(then)* %(else)%(end)'; \ git tag --color -l \ --format='%(color:red)%(creatordate:short)%(color:reset) %(objectname:short) %(color:yellow)%(align:width=45,position=left)%(refname:short)%(color:reset)%(end)') echo $list | fzf --preview 'f() { set -- $(echo -- "$@" | grep -o "[a-f0-9]\{7\}"); [ $# -eq 0 ] || git --no-pager log --oneline -100 --pretty=format:"%C(red)%ad%Creset %C(green)%h%Creset %C(blue)%<(15,trunc)%an%Creset: %s" --date=short --color $1; }; f {}' |\ sed -e 's/\* //g' | \ awk '{print $3}' | \ sed -e "s;remotes/;;g" | \ perl -pe 's/\n/ /g' } # ↑の関数で選んだbranch/tagを入力バッファに入れる function select_to_insert_branch() { LBUFFER+=$(select_from_git_branch) CURSOR=$#LBUFFER zle reset-prompt } zle -N select_to_insert_branch bindkey "^g^o" select_to_insert_branch # ↑の関数で選んだbranch/tagにgit checkoutする function select_git_checkout() { local selected_file_to_checkout=`select_from_git_branch | sed -e "s;origin/;;g"` if [ -n "$selected_file_to_checkout" ]; then BUFFER="git checkout $(echo "$selected_file_to_checkout" | tr '\n' ' ')" CURSOR=$#BUFFER fi zle accept-line } zle -N select_git_checkout bindkey "^gco" select_git_checkout
まとめ
近況
2019/06/30を持ってFringe81株式会社を退職します。
最終出社でした。ありがとうございました! pic.twitter.com/YRvrLUhBXn
— こむ (@petitviolet) May 24, 2019
2015/04/01で新卒入社したので4年と3ヶ月の在籍ということになりました。
お世話になった方々、本当にありがとうございました。
以下は振り返りのためのチラ裏。
なんでやめるの
4年間仕事して慣れてきた+自分のライフステージが変わり、自分の成長速度が鈍化してきていることにふと気付いたので環境を変えたいなというのが大体の理由。
もちろん完璧な企業はないので細かいのも挙げ始めればないとは言わないが、自分にとっては些末なことが多い。
給与とか待遇は不満ないし、人間関係で悩んだとかも少なくとも自分にはなくて居心地の良い会社だった。
巷でいわれるような給与アップを転職理由にはしないくらい、ちゃんと評価して反映してくれていたので幸せだったと思っている。
Rebuild.fmで4年周期くらいで転職したくなるよねみたいな話があって、なるほどそういうものなのかと勝手に共感してた。
なにしてたの
時系列だとこんな感じ。
- 2015.04~2015.10: Android(ちょっとiOS)でのSDK開発
- 2015.10~2016.12: アドプロダクトAの開発
- 2016.12~2017.04: 旧プロダクトのJava→Scalaへのリプレース
- 2017.04~2018.05: 広告運用サポートツールの開発
- 2018.04~2019.05: アドプロダクトBの開発
新規事業を含めて複数プロダクトに関わることが出来ておいしい経験だった。 技術的な領域も幅広く触れたし、いろんなシステムで障害対応したのも振り返ればいい経験だったと思っている。
スマホ開発エンジニアだったのがサーバサイド開発に移って、そっちの魅力に取り憑かれたのでスマホ開発なりフロントエンドをメインにすることは少なくともしばらくは無さそう。
そしてScalaにはまったおかげでプログラミング力はずいぶん成長したように思う。余談だがついにFreeモナドを実戦投入することはなかった。
また、組織的に「設計」を重視しているのもあり、エンジニアとして幅広く力が身についたと感じる。
開発以外だと採用, インターン, 研修カリキュラム作成, 組織内のコミュニティ活動的なことをしたり。 「何を」「どうやって」作るかも大事だけど、「誰と」作るかも大事だというのに気付かせてくれたなぁと。
課外活動的なものだと、ScalaMatsuriとかScala関西みたいなカンファレンスで登壇できたしGoogle/Microsoftさんとイベントやったりも出来た。 Androidエンジニア時代にはRoppongi.aarを立ち上げたけど、自分が離れてモチベーションとともに自然消滅させてしまったのはちょっと後悔している。
会社はマザーズ上場もしたし、エンジニア組織も入社時は10+人くらいだったのが退職時は50+人くらいになり、オフィスは渋谷(面接時)→六本木ヒルズノースタワー→六本木ヒルズ森タワー→六本木一丁目グランドタワーとバブリー(?)な感じになっていき、THE・急成長する会社を味わうことが出来た。
こんな眺めがいい会社で働くことは今後の人生であるんだろうか。
成長する会社にはそれなりの成長痛もあるんだなというのも見えてよかった。
総じていい経験が出来たし、貴重であろう20代後半を過ごしたことに後悔は無い。
月曜の朝に仕事行きたくない...とかもほぼなかった。子ども出来てからは眠かったけど。
おわりに
というわけで、これからもどうぞよろしくお願いいたします。
ScalaMatsuri2019で発表してきました
「ピュアなドメインを支える技術」というタイトルで発表してきました。
ScalaMatsuriは2017で発表して以来だったので楽しみにしてました。
資料
内容としては関数型プログラミング + CQRSという感じでDDDをどうやってピュアに保って推進するか、というもの。 MonadとかKleisliとかCQRSみたいなウッとなりやすい言葉を出しつつどうやってわかりやすく伝えるかに腐心したので、何かしら伝わっていると嬉しい。
感想
大変ありがたいことにScalaMatsuriに応募したトークが当選したので準備がんばるぞ
— こむ (@petitviolet) March 11, 2019
だめだ緊張する
— こむ (@petitviolet) June 28, 2019
発表だん!嬉しいコメントが多くてふわふわする
— こむ (@petitviolet) June 28, 2019
時間はたっぷりあったはずなのに、なぜか直前まで原稿書いたりスライドを微修正したりして他の人の発表を十分に楽しめなかったのを大いに後悔している。。
運営の皆さまも本当にありがとうございました! WiFiも快適でカフェスペースもあり、何も困ることがなかったです。
ScalaMatsuriは今後も参加したいところです。