こんにちは!!!
広告事業本部でアプリケーションエンジニアをしている森田です!!
みなさん、Zsh使ってますか??
僕は昨年、新卒で入社したタイミングでbashから乗り換えて使い始めました。
業務でMacを使用するようになり、シェルを立ち上げるたびに「デフォルトZshやから乗り換えてな」的なメッセージが出てくるのが嫌で乗り換ることになりました...
きっかけとしてはこの通り受動的なものだったのですが、使ってみると意外と高機能でプラグインも豊富で以前よりよい開発体験を得ることができています。
乗り換えたてのころ、まわりの皆さんがどんな設定にしているのかなと気になり、
「ゾッシュってどんな設定にしてますか?」
と聞いたことがあり、場が一瞬???となったことがありました。
このブログではそんな僕がZshをズィーシェルと読むことを知り、業務のためにZshの設定ファイル.zshrc
をいじってきた、その積み重ねの結果を共有させていただきます。
はじめに
このブログでは、新卒入社して約1年半の僕が実際に使用している.zshrc
を恥ずかしながらも公開し、その後、軽い補足やお気に入りポイントの紹介をさせていただきます。
そもそもシェルとは何か?やZsh、.zshrc
とは何か?、Zshの便利なプラグインの話などはこのブログでは紹介いたしません。
なので、下記のような方々はこのブログの内容が参考になるかもしれません。
- 業務でZshを使用している方
- Zshのカスタマイズをしてみたい方
逆に下記のような方々にはこの記事の内容は合わないかもしれません。
- シェル??Zsh??何それ??って方
- fishしか勝たんみたいな方
- Zshチョットワカル方
業務で使用している.zshrc
大公開
早速ですが、僕が実際に業務で使用している.zshrc
のブログ用を公開いたします。
# starship 有効化 ---------------------------------------------- eval "$(starship init zsh)" # 補完機能有効化 ---------------------------------------------- autoload -Uz compinit compinit ## 補完で小文字でも大文字にマッチさせる =========================== zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' ## 補完候補を一覧表示したとき、Tabや矢印で選択できるようにする =========================== zstyle ':completion:*:default' menu select=1 ## sudo で補完有効化 =========================== zstyle ':completion:*:sudo:*' command-path /usr/local/sbin /usr/local/bin \ /usr/sbin /usr/bin /sbin /bin /usr/X11R6/bin # シンタックスハイライト有効化 ---------------------------------------------- source /opt/homebrew/opt/zsh-syntax-highlighting/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh # サジェスト有効化 ---------------------------------------------- source /opt/homebrew/opt/zsh-autosuggestions/share/zsh-autosuggestions/zsh-autosuggestions.zsh # コマンド履歴検索 有効化 ---------------------------------------------- function peco-history-selection() { BUFFER=`history -n 1 | tac | awk '!a[$0]++' | peco` CURSOR=$#BUFFER zle reset-prompt } zle -N peco-history-selection bindkey '^H' peco-history-selection ## 履歴保存管理 =========================== HISTFILE=$ZDOTDIR/.zsh-history HISTSIZE=100000 SAVEHIST=1000000 # rbenv 有効化 ---------------------------------------------- export PATH="$HOME/.rbenv/bin:$PATH" eval "$(rbenv init - zsh)" # options ---------------------------------------------- setopt auto_cd # alias ---------------------------------------------- ## global =========================== alias -g G='| grep' alias -g H='| head' alias -g L='| less' alias -g C='| pbcopy' ## ls =========================== alias ls='ls -G' alias la='ls -a' alias ll='ls -alF' ## cd =========================== alias d='cd ~/dev' alias ~='cd ~' alias ..='cd ..' alias ...='cd ../..' alias ....='cd ../../..' alias prj='cd ~/dev/project_root' alias playgorund='cd /Users/morita/local/playground' ## git =========================== alias g='git' alias ga='git add' alias gc='git commit -m' alias gac='git add . && git commit -m' alias gca='git commit --amend' alias gcan='git commit --amend --no-edit' alias gcam='git commit --amend -m' alias gr='git reset HEAD^' alias gco='git checkout' alias gs='git switch' alias gs-='git switch -' alias gl='git log --oneline' alias gb='git branch' alias gcp='git cherry-pick' alias main='git switch main' alias master='git switch master' ## docker =========================== alias da='docker attach' alias dc_='docker-compose' alias dup_='docker-compose up' alias de_='docker-compose exec' alias dc='docker compose' alias dup='docker compose up' alias de='docker compose exec' ### container =========================== #### rails alias crspec='docker compose exec rails bin/rspec' alias crs='docker compose exec rails bin/rspec $(git status -s "*_spec.rb" | cut -c4-)' alias crubocop='docker compose exec rails bundle exec rubocop' alias crb='docker compose exec rails bundle exec rubocop $(git status -s "*.rb" | cut -c4-)' alias crba='docker compose exec rails bundle exec rubocop -a $(git status -s "*.rb" | cut -c4-)' alias crbA='docker compose exec rails bundle exec rubocop -A $(git status -s "*.rb" | cut -c4-)' alias cconsole='docker compose exec rails bin/rails c' alias csandbox='docker compose exec rails bin/rails c --sandbox' alias cc='docker compose exec rails bin/rails c' alias crails='docker compose exec rails bin/rails' alias cdb='docker compose exec rails bin/rails db' alias cr='docker compose exec rails' alias crsh='docker compose exec rails bash' alias cspring='docker compose exec rails bin/spring' alias css='docker compose exec rails bin/spring server' alias csst='docker compose exec rails bin/spring stop' #### react alias cre='docker compose exec react' alias cresh='docker compose exec react bash' alias cnpm='docker compose exec react npm' alias ccheck='docker compose exec react npm run check' alias cfix='docker compose exec react npm run check:fix' alias cbuild='docker compose exec react npm run build' alias ctest='docker compose exec react npx vitest run' ## other =========================== alias python='python3' alias zshrc='code ~/.zshrc' # alias ssh='~/zsh/ssh-iterm-setting' # func ## ffmpeg cgif () { # convert to gif local ext=${2:-mov} local r=${3:-10} ffmpeg -i $1.$ext -r $r $1.gif } ## pbcopy cwc () { # copy with command local res=$(eval $@); echo $res local all="${@}\n\n${res}" echo $all | pbcopy } ## review review () { local cnt=$(gh pr list --search "review-requested:@me" | wc -l) if [ $cnt -eq 0 ]; then echo "No review request" else gh pr list --search "review-requested:@me" -w fi } # 勝手に追加される系 ---------------------------------------------- ### MANAGED BY RANCHER DESKTOP START (DO NOT EDIT) export PATH="/Users/morita/.rd/bin:$PATH" ### MANAGED BY RANCHER DESKTOP END (DO NOT EDIT) export PATH="/opt/homebrew/opt/mysql-client/bin:$PATH" export PATH="/opt/homebrew/opt/curl/bin:$PATH" # The next line updates PATH for the Google Cloud SDK. if [ -f '/Users/morita/Downloads/google-cloud-sdk/path.zsh.inc' ]; then . '/Users/morita/Downloads/google-cloud-sdk/path.zsh.inc'; fi # The next line enables shell command completion for gcloud. if [ -f '/Users/morita/Downloads/google-cloud-sdk/completion.zsh.inc' ]; then . '/Users/morita/Downloads/google-cloud-sdk/completion.zsh.inc'; fi
解説
ここからは補足や、お気に入りポイントのお話をしていきます!!
setopt
.zshrc
のsetoptでオプションをオンオフできるんですが、オプションの内容がman zshoptions
で確認できます!!
> man zshoptions ZSHOPTIONS(1) General Commands Manual ZSHOPTIONS(1) NAME zshoptions - zsh options ~~~ Changing Directories AUTO_CD (-J) If a command is issued that can't be executed as a normal command, and the command is the name of a directory, perform the cd command to that directory. This option is only applicable if the option SHIN_STDIN is set, i.e. if commands are being read from standard input. The option is designed for interactive use; it is recommended that cd be used explicitly in scripts to avoid ambiguity. ~~~
調べても散文的で網羅的に確認する方法が分からず困っていましたが、社内向けChatGPTに聞いたところ教えてもらいました!!便利!!
エイリアス
ここからはエイリアスについてお話ししていきます!!
詳しい説明は省かせていただくのですが、エイリアスを設定することでショートカット的にコマンドを実行できます!!
例えばalias g='git'
だと下記2コマンドが同等の挙動をします。
> git switch blog
> g switch blog
プロジェクトへのcd
alias prj='cd ~/dev/project_root'
この部分、お気に入りです!!
どのディレクトリにいてもすごく短いコマンドで目的のディレクトリに行けます!!
複数プロジェクトでいろんなディレクトリに行ったりするので満足度が高いです!!!!
設定も簡単でコスパもいいです。
コンテナ内でコマンド実行
### container =========================== #### rails alias crspec='docker compose exec rails bin/rspec' ~~~
このあたりですね、このコンテナ内でコマンド実行するエイリアスが一番使っているかもしれないです!!
現在関わっている全ての開発でDockerを使用しており、コンテナ内でコマンドを実行したいことがよくあります。
ですが、普段はホストでイケてるプロンプトのZshで作業しています。
コンテナ内のシェルがbashで何のカスタマイズもしていないので、コンテナ内のシェルに入るだけで なんかな〜 という気持ちになります。
だからといって毎回 docker compose exec container_name ~~
をタイピングするのも長すぎて大変です。
そこで、よく使うコマンドをエイリアス設定することで、コンテナ内のシェルで打つコマンドと同じ長さ、むしろ短かったりする長さで実行できます!!
タイポも減るし、最高です。
↓↓↓イケてるプロンプトのZsh↓↓↓
コミットしていないファイルをリント、テスト
alias crb='docker compose exec rails bundle exec rubocop $(git status -s "*.rb" | cut -c4-)'
このgit status -s "*.rb" | cut -c4-
の部分です!!
git status -s "*.拡張子"
の部分でコミットしていない特定の拡張子のファイルをステータスを伴って取得しています。
cut -c4-
でファイル名のみを抽出しています。
こうして得たファイル名の一覧をここではrubocopに渡して、リント、フォーマットしています。
一ファイルずつやるのはなかなか時間がかかるのでこれも重宝しています!!
ただ、削除したりリネームしたファイルも持ってきちゃうので、それでエラーになってしまいます。
伸び代ですね。
関数
ここからは.zshrc
に定義している関数についてお話ししていきます!!
ここでも関数の詳細については省かせていただくのですが、.zshrc
に関数を定義することでコマンドっぽく使うことができるようになります。
review () { local cnt=$(gh pr list --search "review-requested:@me" | wc -l) if [ $cnt -eq 0 ]; then echo "No review request" else gh pr list --search "review-requested:@me" -w fi }
例えば上記のようにreview
関数を定義すると、コマンドラインからreview
を実行できるようになります!!
> review
No review request
review関数
僕が所属する組織では、Findy Team+を用いた開発サイクルタイムの改善施策を進めています。
その中でレビューの優先度を意識的に上げようと考えたのですが、ブラウザを開いてGitHubを開いてレビュー依頼がきているPRを見つける流れが煩わしかったです。
レビュー依頼がきているPRのリストがサクッと開けたらいいのになぁーーと思って調べていました。
そこでgh
でいい感じにできそう、でも、レビュー依頼がない時もブラウザ開くの微妙やなというところに行きつきました。
そんな微妙やなを解決するのにちょっとした関数を.zshrc
に定義するのがいいんです!!
これで僕のレビュー体験も上がるし、チームとしての開発サイクルの改善にもつながるので最高ですね!!
蛇足なんですが、↓のURLでレビュー依頼きてるPRの一覧を開くことはできます。
https://github.com/:organization/:repository/pulls?q=is%3Apr+is%3Aopen+reviewer%3A%40me
ただ、やっぱりターミナルで作業している時にブラウザに移動するのが煩わしいのと、ブラウザに移動して依頼がきていないときに微妙な気持ちになるのが嫌だったんですよね。
今後やりたいこと
ここまでいくつかお気に入りポイントを紹介させていただきました。
もっと紹介したいくらい、お気に入りポイントがいっぱいあります。
ですが、もっとよくなるやろ!!!!!!ってところもいっぱいあります。
ここではそんな伸び代を挙げておきます。
aliasをabbrにリプレイスしたい
aliasだとhistoryに省略した形で残ってしまうのですが、abbrを使用すると、実行時に省略形から実際のコマンドに展開されます!!
作業ログを共有したりする時に便利なんですが、シェルの立ち上げ時が微妙な感じなので試行錯誤中です...
カレントブランチと派生元ブランチ間で差分があるファイルを取得してリント、テストしたい
コミットしていないファイルをリント、テスト
の項で変更しているファイルをまとめてリントしている、とお話しさせていただきました。
実は色々妥協していて、本来は
- 派生元ブランチを自動取得
- 派生元ブランチとカレントブランチでのファイルの差分を取得
- まとめてリントする
が理想でした。
だったんですが、派生元ブランチの自動取得が難しくて妥協しちゃいました...
いつか理想の形に持っていきたい...
派生元ブランチさえ取得できたらファイルの一覧はgit diff --name-only $parent_branch
で取得できるはず、なのでもう一歩な感じはあります。
差分があるファイルのテストファイルを抽出してテストしたい
前項とコミットしていないファイルをリント、テスト
の項に関わりがあるのですが、これはどちらも変更があったファイルのみを持ってきています。
ただ、これだとテストする時に、実はテストファイル変更し忘れてた!!をカバーできないです。
なので、変更があったプロダクトコードのファイルからテストコードファイルを特定して、それらをテストしたいんです!!
テストコードファイルの特定自体は、ファイルの命名規則がしっかりしていればsedなど使ってすぐにできるとは思います。
ただ、テストコードにすでに差分があったら?とかパターンを考えて実装まで行かないところで止まっちゃっています...
よくないですね!!!!
関数をファイル分割したい
.zshrc
が肥大化してきているので、関数をファイル分割したいなと思ってます。
先ほども出てきた社内ChatGPTに教えてもらったところ、.zshrc
ファイル内でsource function_file.sh
すればいいみたいです!!
簡単そう!!でもディレクトリ構成どうしよ!!ってなってます。こんなんばっかですね。
おわりに
このブログでは恥ずかしながら僕が業務で使用している.zshrc
を公開し、お気に入りポイントを紹介させていただきました。
Zshはプロンプトや拡張機能をいじるだけでも開発体験が爆増するのですが、一歩踏み込んでカスタマイズすることでより好みの使い心地になっていきますね。
本ブログを最後までお読みいただきありがとうございました!!