久々にshellをいじろうか…

# Shellの起動が遅い、そして挙動がもたついてきた！

> 本記事は投稿日近くではなく10月20日に書いていたものを投稿していなかったことに気づき投稿しました。部分的には最近記述してます。

筆者やっぱり男の子なので常に一番良いものでありたい！常に一番こそ至高なんだ！！！！
まぁ嘘ですけど〜
卒業研究に追われながらこの記事を書いていますしてかなりげんんじつ逃避したい欲がすごい状態で描いているので文章が途中でおかしくなるのはご容赦ください…
まぁ真面目な話、卒業研究で自分の身に起きた事件（てほどでもないけど）が起きたので備忘録として書いてます。

さて前置きはこのくらいにしておいて！
最近卒業研究でiOSアプリとWebアプリを作ってるんですね、そこで最近Vimerに転身（しようとしてる）した私はShellでいろいろいじる機会が増えました。
するとどうでしょう、何だかShellの起動やコマンドの実行後の反応やコマンドラインの出力が遅いではありませんか！！！
これはVimer(仮)にとっては死活問題です。

というわけで色々ググってみました。
# 原因
ここからはいくつか考えられる原因をつらつら書いていきます。あなたもこの原因に悩まされていたらお力になれるかも⁉︎
（あ〜あの一つ言っておきますが筆者はまだ完全解決はしてません…もし力になっていただける方がいましたら助けてください…いやマジで！！！）

## 原因その1
**シンプルに使用しているPCが働きすぎ**
どういうことかというと、アプリを大量に開き、ブラウザに関しては大量のタブ、あまつさえ動画編集や音楽編集エミュレーターやシミュレーターの起動などPCに莫大な負荷を与えているとCPUやメモリが大量に消費され、キャッシュなども溜まりに溜まりPCそのものの挙動がおかしくなるらしいです。
そんな方はまずは使っていないアプリは落として、タブは消してPCを整理してあげましょう。ついでにいらないキャッシュを消したり再起動したりすると解決するっぽいですよ。

しかし、私まれすけこれではあまり効果はありませんでした。
まぁ実際のところ最近PCの調子はすこぶる悪いのでできるだけ負荷はかけないように浅い真の注意を払っていたので当たり前といえば当たり前ですかね〜

## 原因その2
**PCの容量の問題**
これに関しては正直あまり信じてはいないです。
PCのストレージがカツカツになってるとキャッシュが保存しにくくなってうまく動作しないらしい。
ほんとかよ…だってキャッシュってメインストレージじゃなくてメモリ、いわゆるユニファイドメモリに溜まっていくものでしょ…？
あれあってっるっけ？心配になってきた…
これは記事出てきたけどその記事自体が削除されたのかどうかは知らないけどその記事に行き着くことができなくなったので真偽の確かめようがなくなった…

## 原因その3
**プラグインの入れすぎ、フレームワークが重い**
これはどういうことかというと、フレームワーク私の場合はzshなのでoh-my-zshというものを使っていましたが、このフレーム枠というものはプラグインマネージャーというものを用いてShellの補完機能の拡張をしていたり便利な機能を追加したりしているそうです。そしてこのプラグインマネージャーというものはそれだけ便利な機能を実現させる分起動時間が遅いようです。まぁこれに関しては解決方法としてはいくつかあるらしいのですが、それこそ莫大な量の設定の中から自分でいらないものを消したり、パッケージマネージャーのロードに関する設定をいじったりと色々あるらしいが正直めんどくさい。

> (いやShellの挙動云々で文句言ってるのお前やん…設定ぐらい自分でやれやというのは言わないお約束…)

また、プラグインに関してはプラグインが多くなればなるほど、やはり一つ一つのプラグインの反映まぁいわゆるロードに時間がかかってしまうので遅くなってしまうらしい。これの対処は簡単ですね！
多すぎるってことはおそらく
>A　「お！このプラグインてのがいいらしいインストールして使ってみよ〜う」
B　「A、それよりもこっちのプラグインの方がいいよ！後これもおすすめ！」 
A 「よっしゃそれインストールしてみるわ！」
A 「めっちゃ便利やん！ん⁉︎なになにこれと併用してこれも使うといいだって〜！よっしゃ…」

まぁ全員とは言いませんが多くの方がこの気持ちわかっていただけるんじゃないですか？
というわけでいらないものや使っていないものは消しましょう。
以上解決ですね！

私まれすけフレームワークoh-my-zshを利用してましたので一度消してみましたそこで`time ( zsh -i -c exit )`コマンドを実行したところ起動時間が`3.584`から`0.82`に変化しました(単位が出力されなかったのでわかりにくいですが数値だけを比較してもまぁかなり大きいと思います)。かなり大きな変化ですね！まぁ実際のところ`.zshrc`にはほとんど設定は書かれていませんでしたので早くなるのも当たり前ですがそれでもフレームワークを消しただけでここまで大きな変化出るとは思っていませんでした。

# てなわけで解決策！
自分が調べてわかった原因は上の三つです。これらの解決は1原因の文章中に描いた通りです。しかし３に関してはちょっとう〜んて感じですよね…
てことでここからは私が選んだ解決策を提示します。

1. プラグインから脱却する。
2. 自分でできる設定は自分で書く（作る）
3. 必要なプラグインを少しずつ入れる

そもそも私が**oh-my-zsh**を使っていた理由がmacのデフォルトshellが`bash`から`zsh`になってしまい今までbashの設定を反映させる方法を調べながらやるのがめんどく…よく分からなかったからでしたので、この際プラグインで全部やっちゃおう！ということで導入しました！あと、プロンプトのテーマがたくさんあって自分好みのものが作りやすいからです。git周りの設定も今までは`.bashrc`や`.bash_profile`にいちいち書いていました。（まぁこれもプラグインやフレームワーク使えば自分で書かなくても良くはなるけれどもね…）
ここで一つ言っておきますが、`oh-my-zsh`がクソとかは全く思っていません。今まで使っていて補完機能の便利さやGitの設定云々すごく便利なフレームワークです。私はただこの際自分でできることはやってみたいな〜という興味本位で始めたことです。えぇそうですタイトルは半分釣りで半分本音です！

## oh-my-zshとのお別れ

```
$ uninstall_oh_my_zsh
```
今までありがとう！

## さてとりあえず最低限の設定をし始めようか
とりあえず`.zshrc`の編集
実はzshが　macのデフォルトShellになった時に自分で改造することに挑戦はしていたのですがフレームワークを使っていたのでその記事も見てみたい方がいましたら是非どうぞ
 [zshがMacで標準shellになったらしいので数時間悩んでみた](https://qiita.com/daikimare/items/c2190ac252d08decc502)

何やっていいか分からないのでとりあえず自分の`.zshrc`を乗っけます。

```:.zshrc
## 補完機能の導入
autoload -Uz compinit
compinit -u

## 補完の背景色付け
autoload -Uz colors
colors
zstyle ':completion:*' list-colors "${LS_COLORS}"

zstyle ':completion:*' menu select

# 単語の途中で補完を有効化
setopt complete_in_word

# 補完候補をハイライト
zstyle ':completion:*:default' menu select=1
# キャッシュの利用による補完の高速化
zstyle ':completion::complete:*' use-cache true
# 大文字、小文字を区別せず補完する
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

# aliasの設定
alias gonbe="pokemon 446"
alias rukario="pokemon 448"
alias syandera="pokemon 609"
alias ls="ls -G"    # ディレクトリの色付け
alias l="ls -a"
alias ll="ls -l"
alias la="ls -la"

# app alias
alias android="open /Applications/Android\ Studio.app/"     # AndroidStadio起動
alias chrome="open /Applications/Google\ Chrome.app "       # GoogleChrome起動
alias xcode="open /Applications/Xcode.app/ sample.xcodeproj/"   #Xcode起動
alias slack="open /Applications/Slack.app "   #Slack起動
alias fire="open /Applications/Firefox.app" # firefox起動
alias safari="open /Applications/Safari.app" 

# git alias
alias gpl="git pull"
alias gps="git push"
alias gcm="git commit"
alias gad="git add"
alias gss="git status"
alias gs="git stash"

# anyenvの設定
eval "$(anyenv init -)"

# python
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

# openssl
export PATH=/usr/local/opt/openssl/bin:$PATH

# flutter
export PATH="$PATH:$HOME/development/flutter/bin"

# Golang
export GOENV_ROOT=$HOME/.goenv
export PATH=$GOENV_ROOT/bin:$PATH
eval "$(goenv init -)"

# Ruby
eval "$(rbenv init - zsh)"

# git
export PATH="/opt/homebrew/bin:$PATH"

# starship
eval "$(starship init zsh)"

# anyenv update
if [[ $TERM != linux && ! $PROMPT_COMMAND =~ _update_ps1 ]]; then
  PROMPT_COMMAND="_update_ps1; $PROMPT_COMMAND"
fi
```

とりあえずこんな感じです。aliasに関してはコメントアウトの通りなんです。そのほかには開発ようのツールがいくつかありますがこれはPATHを通してるだけなので皆さんお使いの言語であったりツールの公式リファレンスをお読みになって設定してください。自分はこんな感じです。
しかし、皆さんこう思っているはず！
**『は！こいつGitがどうちゃこうちゃらほざいてたくせにGitの設定aliasだけとか舐めてんのか！あ〜！それはいいにしてもプロンプトすら全くいじってねーじゃねーか！どつき回すぞ！！！』**
Gitの設定はまぁできるにはできるんですけどやはりめんどくさいっス！
さらにいえばプロンプトいじりもめんどいっス！
てなわけで自分ここにだけプラグインを使うっスよ！
### Starship導入
StrashipはRust製プロンプトの描画プラグインらしいです。
またすごいのが、Starshipは`bash`,`zsh`,`fish`といったさまざまなShellで動くということです。
なので多くのユーザーが脳死で利用することができるという強みを持っています。
個人的に面白いと思ったのがプロンプトに絵文字を出現させることができるのがおもろいな〜とおもいました。
ではインストールしていきます！！

```
$ brew install starship
```
そうしましたら各々のShellの設定ファイルにpathを通してあげてください。
僕の場合は`zsh`なので`.zshrc`にpathを描いていきます。おのおのshellはあると思うので`.(shellの名前)rc`に描いていけばいいと思います。
そうしましたらShellの再起動もしくは`$ source ~/.zshrc`で反映させます。するとshellの描画がかなり綺麗になりました！
私はさらに各ディレクトリに移動した時にそこのディレクトリで使われている言語のバージョンが表示されて欲しいのでそこの設定をしていきます。
詳しくは[公式リファレンス](https://starship.rs/)をご参照くださいと言いたいのですが一応こちらも私のstarshipの設定を見せておこうと思います。

```:.config/starship.toml
# 実行結果の前後に余白を入れない
add_newline = false
# プロンプトの表示設定
format = """
$directory\
$git_branch\
$git_commit\
$git_state\
$git_metrics\
$git_status\
$hg_branch\
$docker_context\
$aws\
$nodejs\
$golang\
$kotlin\
$package
$character\
"""

[character]
error_symbol = "[❯✗❯](bold #9F5CBC)"
success_symbol = "[❯❯](bold #4DFFF5)"

[directory]
style = "#00DFFF"
truncation_length = 4
truncate_to_repo = false
truncation_symbol = "…/"

[git_status]
conflicted = "💥"
ahead = "🏎💨"
behind = "😰"
diverged = "😵"
up_to_date = "✓"
untracked = "🤷‍"
stashed = "📦"
modified = "📝"
staged = '[++\($count\)](green)'
renamed = "🏷"
deleted = "🗑"

[aws]
symbol = "☁️ "
style = "bold blue"
[aws.region_aliases]
ap-northeast-1 = "jp-tokyo"
ap-northeast-3 = "jp-osaka"

[docker_context]
format = "via [🐋 $context](blue bold)"

[nodejs]
symbol = " "
version_format = "v${raw}"
format = "via [$symbol $version](bold green) "
detect_extensions = ["js", "mjs", "cjs", "ts"]
detect_files = ["package.json", ".node-version"]
detect_folders = ["node_modules"]

[golang]
symbol = " "
version_format = "v${raw}"
format = "via [$symbol $version](bold cyan)"
detect_extensions = ["go"]
detect_files = ["go.mod", "go.sum", "glide.yaml", "Gopkg.yml", "Gopkg.lock", ".go-version"]

[kotlin]
symbol = "🅺 "
kotlin_binary = "kotlin"

[package]
disabled = true
```
これで一通り設定終了です。
starshipの設定ファイルは**$HOME**の`.config`の中に作りましょう。
各言語によって細かい設定ができて、その設定を反映する際は[lang name]の言語の名前をformatの中に書いて上げ得ることで出力されます。すごく便利！！！
設定がごちゃつかずまとまっているのですごくみやすいです。
ここまできてなんですが一応手順みたいなものです↓
.configディレクトリがない場合

```
$ mkdir ~/.config && touch ~/.config/starship.toml
```
.configがある場合

```
$ touch ~/.config/starship.toml
```
あとはvimなりVSCodeで編集してください。
さてここまでである程度設定は終わりました。
## さて起動速度を検証してみよう！
先ほどの`time ( zsh -i -c exit )`こちらを実行していきましょう。
すこし何も設定なしと比べると遅くはなってしまいましたが`1.288`という数値がでてフレームワークの時よりかなり早くなりました。これはすごい！！！
しかし、補完機能の部分で今までは文字を打って矢印上を押すと直近でその文字から始まるコマンドを補完で出してくれましたがそれはoh-my-zshの機能なのでつかえなくなってしまいました　。つまり矢印上ボタンを押すと普通のヒストリーの履歴しか出てこなくなってしまいました。これは悲しい😞
しかし、それ以上に早く描画されるというのは大きな収穫だったので個人的には満足してます。
# おまけ
ここからはおまけです…
興味ない人はすっ飛ばしてもらってOKです。

## とはいえShellが質素でテンションが上がんね〜
ここまで様々な設定をしてきましたがなんだか今まで使っていたShellとはUIが異なっていたり、機能が制限されていたりと、まぁ言っちゃえば質素すぎてテンションが上がらん…もっとこうテンションの上がるようなShellにしたい！
そんなことを考えていたら近くで開発をしていたとあるエンジニアの方のShellに**Pikachu**がいるではありませんか！あ、けして覗こうとお思ったわけではなくたまたま目に入っただけでっすよ…
まぁかくゆう私も実は一時期ポケモンにどハマりしていた時期がありまして、ポケモンと一緒に開発したいな〜とかとち狂ったこと考え始めたんですね！

## 世の中同じようなこと考える変態エンジニアがいっぱいるんだな〜
そこで私もShellにポケモンを召喚することにしました。
するとどこかの変態がそんな人たちのためのライブラリを作っていました！！！
それがこちら！
[Pokemon-Terminal](https://github.com/LazoCoder/Pokemon-Terminal)

こちらは素晴らしいライブラリですね！自分の推しポケモンを連れて開発ができるようになるまさに私が求めていたパーフェクトなものです！
というわけで導入〜
## インストールしていきます
このPokemon-TerminalというものはPythonで作られておりインストールもPythonで行うことができます。
> しかし動作環境はPythonとはいっても3系になるので2系ではインストールできませんのでご注意を！さらにいうと3系のかでも3.7以上でないとインストールできないようです。先駆者の方々の記事を見ると3.6だとか結構いろんなバージョンでいけると書いてありましたが最近アップデートされたのせいなのかどうかわかりませんが3.7以上でないとダメというエラーが自分のところでは出てしまったので自分はPython3.9で構築させてもらいました。

使用方法はREADMEに全て書いてあるのですがざっくりいうと以下のような感じでやっていきます
1. python3のインストール
2. ローカルをpython3環境に変更する
3. pipを使ってPokemon-Terminalをインストール
4. インストールを反映させる
5. おともにしたいPokemonを指定する
6. 終わり〜

> インストールに関しては `node` でも可能のようですがおそらくpipが推奨だと思います。nodeで行っている事例がほとんど見られなかったので多分pipでやるのが一番安心だと思います！

### Pythonの設定
`$ python -V`で3.7以上でしたら問題なく行けます。
もしそれ以外でしたらアップデートをお勧めします。自分pyenvを使ってるのでアップデートは以下の通りです。

- 最新かつ安定版が3.9.4ということでこちらをインストールします。

```
$ pyenv install 3.9.4
```
- 次にPCのPythonを3.9.4に変更します

```
$ pyenv global 3.9.4
```
### インストール
先ほどインストールしたPython3.9.4を用いてインストールします
Pythonではライブラリなどのパッケージ管理をpipというもで行なっています。
ちょうどNode.js(JavaScript/TypeScript)のnpmやnpx、yarnにあたるものですね。
インストールのコマンドは以下の通りです

```
$ pip install git+https://github.com/LazoCoder/Pokemon-Terminal.git
```
もしエラーが出た場合はpipのバージョンを指定しろと怒られる場合があります。その際は以下のどちらかを実行してみてください。

```
$ pip3 install git+https://github.com/LazoCoder/Pokemon-Terminal.git  # Python3系であればなんでも
```

```
$ pip3.9 install git+https://github.com/LazoCoder/Pokemon-Terminal.git  # Python３．９〜
```
どちらかでいけると思います。

> *上記のコマンドはあくまで私が3.9.4を利用しているからです。もし3.7~3.8を利用している方であれば自身のPythonのバージョンに合わせてください。
インストール手順は以上で終了です。

## 動作確認をしてみましょう
まずはShellを再起動してみましょう
`$ exec $SHELL`これで再起動できます。
その後`$ pokemon`と実行してみてください、おそらくランダムでポケモンがセットされるはずです。
もし特定のpokemonが出したい時は図鑑番号や名前同時に指定してください。ここで注意なのが名前は英名ですのでピカチュウを出したい時はpikatyuuではなくpikachuになり、ガーディーの場合はga-dhi-ではなくgrowlitheになります。
`$ pokemo (図鑑番号or名前)`
そのほかにも地方ごとにランダム出力したり、タイプごとにランダム出力したりできます。

```:example
$ pokemon -r kanto
$ pokemon -t fire
```
こんな感じで行えます。

自分はゴンベやルカリオ、シャンデラをよく出してるのでaliasまで作ってしまいました…

ぜひみなさんShell芸を楽しんでみてください。
以上おまけでした