(超入門)fishでプロンプトを変えたい人へのチュートリアル

###対象とする読者
* Gitのステータスなどをプロンプトに出したいけど他のページを読んでもよくわかんなかった人
* 魔法のコードをコピペして設定するのがなんとなくいやな人
* 痒い所に手が届くプロンプトを作ってみたい人

###対象としない読者
* 答えをすぐに知りたい人（答えを紹介するページではなく答えを**理解するための**ページです）

###読むのにあったほうがいい知識

* **シェルスクリプトの知識**（コマンド置換と変数の定義ができれば多分大丈夫。）
* 設定ファイルをいじった経験（bashrc, vimなどなんでも）

#そもそもどうすればプロンプトを設定できるの？
結論から言うと、fish_prompt というコマンドを再定義することで設定できます。....これでわかるならこんなページ見てないと思うので詳しく解説していきます。
##1.プロンプトの出る仕組みを知る
fishを起動して以下のように打ってみてください

```
foo@bar~> fish_prompt
```
**注意**:"foo>bar~ "はプロンプトなので打たないでください。他の例でも同じです。
以下のような出力が得られると思います。

```
foo@bar~> fish_prompt
foo@bar~> ⏎ 
foo@bar~>
```
おそらく`⏎`は勝手にfishがつけたもです。環境によっては出ないかもしれません。

###解説
enterを押しすぎたのではありません。２行目はfish_promptが「出力」した行で、三行目がコマンドの待ち受け開始時に表示されるプロンプトです。つまりfish_promptというコマンドは、プロンプトを出力するコマンドであり、**毎回このコマンドが実行されることでプロンプトが表示される**のです。よって**このコマンドを定義しなおしてやればいいのです。**.....で、どうやって定義するのか？ functionコマンドを使います。


##2.functionコマンドを使ってプロンプトを変えてみる
とりあえずfishに以下のように打ってみてください。

```bash:first_function
foo@bar~> function first_function
            cd $argv
            ls
          end
```
###解説
* `$argv` というのはfish における引数の配列です。
* `first_function ~/Documents` とでも打って見ればわかると思いますが、`first_function`というコマンドが定義されています。
プログラミングしたことがあるなら関数の定義をしたことがあるかと思いますが、functionコマンドもそれと同じです。
* **これがチンプンカンプンならシェルスクリプトの勉強をしてください。**

ではさっそくfish_promptコマンドを定義し直してプロンプトを変えてみましょう。

```
foo@bar~> function fish_prompt
            echo "Hello world> "
          end
Hello world> 
```
...こんなプロンプト要らないと思うのでいったんfishを閉じてプロンプトを戻してください。first_functionもちゃんと消えるはずです。

##3.設定ファイルで自分のプロンプトを定義してみる
ここまで読めば、「**要は設定ファイルでいい感じのfish_prompt を定義してやりゃあいいんだろ？**」と思うかもしれませんが、それだと設定ファイルがごちゃごちゃするのでよくないです。fishは、何もしなくても`~/.config/fish/functions/`下に置いたファイルを読み込んでくれるのでそこに書きます。
###やってみる
`~/.config/fish/functions/fish_prompt.fish`に以下を書き込んで保存してください。
**注意1**:すでにfunctions/fish_prompt.fishが存在する場合**必ず**バックアップを取ってください。
**注意2**:手動で`.config/fish/config.fish`にfish_promptを書き込んでる人は、いったんコメントアウトしといてください。
**注意3**:XDG_CONFIG_HOME を変更してるなら以下は適宜読み替えてください。


```bash:~/.config/fish/functions/fish_prompt.fish
function fish_prompt --description 'Write out the prompt'
    printf 'hoge@%s%s> ' (prompt_hostname) (prompt_pwd)
end
```
エディタを抜けてもプロンプトが変わってなかったらfish を再起動してください。
###解説
* １行目の`--description`というのは関数の説明です。補完設定とかで役に立つとかなんとか。
* ２行目では、`printf`というfishのbulitin functionを、`'hoge@%s%s'``(prompt_hostname)` `(prompt_pwd)` という3つの引数とともに呼んでいます。
打てばわかりますが、`prompt_hostname`, `prompt_pwd` はコマンドです。それぞれホストネーム、カレントディレクトリを表示します。その出力を（）でコマンド置換しています。"fish コマンド置換"と検索すればコマンド置換については大体わかるはずです。
* `printf`はC言語のそれとほぼ同じ使い方です。詳しくは`help printf`と打ってみてください。
* この方法はfish_configで行った設定を上書きします。

プロンプトを元に戻すには`~/.config/fish/functions/fish_prompt.fish`を消してください。



#プロンプトをカスタマイズするのに使えるテクニック
ここまでで、プロンプトを手動で変えるにはどこをどうすればいいか大体分かったと思うので、あとはカスタムに使うパーツを勉強するだけです。

##文字に色を付ける　～set_colorコマンド～
###使い方
`set_color`は出力の色を変更するコマンドです。
`fish ＜色＞`　でその後の出力の色を変えられます。`＜色＞`は`black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `brblack`, `brred`, `brgreen`, `bryellow`, `brblue`, `brmagenta`, `brcyan`, `brwhite`のほか、１６進数とかでも指定できるようです。詳しくは`man set_color`を参照してください。また、[この方の設定ファイル](https://qiita.com/kubosho_/items/79fc05c4068cbd2ecccf)に書いてある、変数に代入しておくという`set_color`の使い方は覚えておいて損はないと思います。

###やってみる
fishで以下を実行してみてください。
`hoge@bar~> printf '%s %s %s' (set_color yellow)(echo $USER) (set_color cyan)(prompt_pwd) (set_color red)(echo "> ")   `
###解説
こまけえこたあいいんだよって人は読む必要ないです。上のようにすればプロンプトの途中で色を変えられるってわけです。

* printf関数の引数は`'%s %s %s'`, `(set_color yellow)(echo $USER)` `(set_color cyan)(prompt_pwd)` `(set_color red)(echo "> ")` 
の４つであることに注意してください。実行の流れは以下のようになります。
* printf関数が第一引数をパースしていって、`%s`を処理するために第二引数の`(set_color yellow)(echo hey)`が展開されます。
* このとき、まず`set_color yellow`が実行され、出力が黄色に設定されます。次に
`echo $USER` が実行され、第一引数の`'%s'`の部分が黄色で出力されます。
* printfは`　`と出力したのち、二つ目の`%s`のために第三引数を展開します。`set_color cyan`が実行され出力が青に設定され、`prompt_pwd`が実行され二つ目の'%s'が出力されます。以下同様です。

##Gitのステータスを表示　～__fish_git_prompt コマンド～
シェルスクリプトをゴリゴリ書く自信のある人なら、[ココにあるように](https://github.com/kubosho/dotfiles/blob/46f2f08/.config/fish/config.fish#L50-L87)コマンド置換などを使ってステータスでもなんでもだせますが、しんどいのでこちらがおすすめです。[ココに書いてあるように](https://qiita.com/mom0tomo/items/b593c0e98c1eea70a114)、`~/.config/fish/config.fish`で変数を設定することで表示される文字列をカスタマイズできます。

##特定の変数などを表示 ～prompt_ 系コマンド～
ここにまとめておきます。

```bash:
#hostnameを表示
prompt_hostname
#カレントディレクトリを表示
prompt_pwd
```

##右側にもいろいろ表示する　～fish_right_prompt～
`fish_right_prompt`という名前のコマンドを定義するとfishは右側にその出力を出します。デフォルトではこんな名前のコマンドは定義されていないようなのですが、定義すると勝手に表示し始めます。
###使用例
```bash:~/.config/fish/functions/fish_right_prompt.fish
function fish_right_prompt 
    date +"%H:%M"
end
```
こんな感じになる。
![fish_qiita3.png](https://qiita-image-store.s3.amazonaws.com/0/212512/879f1449-085b-33ca-4a47-e269b51435a4.png)


#参考にさせて頂いたURL
[fish公式サイト](http://fishshell.com)
[上のサイトの日本語訳を集めたサイト（非公式）](http://fish.rubikitch.com/)
[arch wikiのfishのページ](https://wiki.archlinux.jp/index.php/Fish)