【zsh】いろいろなプロンプト表記 まとめ

# 経緯
なんかいいプロンプトの表示ないかなって調べてると`bash`勢が多くて、`zsh`じゃコピペで使えないし変換するのもめんどくさいので公式doc見て勉強することにした。

# 本記事の内容
- 公式docを自分なりに和訳、実行してみたただの**備忘録**です

```zsh:Terminal
man zshmisc 
```

https://zsh.sourceforge.io/Doc/Release/Prompt-Expansion.html#Prompt-Expansion

# 環境

```zsh:Terminal
sw_vers && zsh --version
```

| System | Version |
| :-: | :-: |
| OS | MacOS Monterey(12.1) |
| zsh | zsh 5.8 (x86_64-apple-darwin21.0) |

# 手短に
<details>
<summary>このメモを保存してから</summary><div>

```text:memo
  login information\n
%%l: %l\n
%%M: %M\n
%%m: %m\n
%%n: %n\n
%%y: %y\n\n

  shell state\n
%%#: %#\n
%%?: %?\n
%%_: %_\n
%%^: %^\n
%%d: %d\n
%%/: %/\n
%%3d: %3d\n
%%2d: %2d\n
%%1d: %1d\n
%%-1d: %-1d\n
%%-2d: %-2d\n
%%~: %~\n
%%c: %c\n
%%.: %.\n
%%C: %C\n\n

%%e: %e\n
%%!: %!\n
%%i: %i\n
%%I: %I\n
%%j: %j\n
%%L: %L\n
%%N: %N\n
%%x: %x\n

date and time\n
%%D: %D\n
%%T: %T\n
%%t: %t\n
%%@: %@\n
%%*: %*\n
%%w: %w\n
%%W: %W\n
%%D{%%H:%%M:%%S.%%.}: %D{%H:%M:%S.%.}\n\n

  visual effects\n
%%B %%b: %B hello world %b\n
%%U %%u: %U hello world %u\n
%%E: %E hello world\n
%%F{red} %%f: %F{red} hello world %f\n
%%K{blue} %%k: %K{blue} hello world %k\n
%%S: %S hello world %s\n
%%{string%%}: %{h$e'l"l#o! w2o+r*l^d%}\n
```

</div>
</details>


```zsh:Terminal
print -P `cat memo`
```
でも試せます。

# 実行の仕方
プロンプトに表示されているような`ユーザー名`や`カレントディレクトリ`は特別なシーケンスで表している。

例えば、
| 表示 | シーケンス |
| :-: | :-: |
| ユーザー名 | %n |
| カレントディレクトリ | %d |

みたいに。

これを反映したいときは
```zsh:Termial
export PS1="%n %d "
```
とすればすぐに反映されるはず。
> PS2, PS3とかもあったりします

ただ、いちいちシェル変数の中身を変えるのは面倒なので
`built-inコマンド`である`print`関数に`-P`オプションをつけてやると簡単に確認することができます。

```zsh:Termial
print -P %d

>> /Users/sho/Test
```

---

　　以降、私の環境で`print`関数を使って確認したものです。

---
# ログイン情報
| シーケンス | 意味 |
| :-: | :-: |
| %n | ユーザー名。`echo $USERNAME`に同じ |
| %M | localhostを含むホスト名 |
| %m | %Mの「.local」を除いたホスト名 |
| %y | デバイスの名前。接頭辞の「/dev/」は省略される |
| %l | デバイスの名前。接頭辞の「/dev/ttys」は省略される |

```zsh:自分の場合
 %l: s002
 %M: syoshika.local
 %m: syoshika
 %n: sho
 %y: ttys002
```

デフォルトだと、
`sho@syoshika`のように`%n`と`%m`が使われていたんですね。

# シェルの状態
## Part1
| シーケンス | 意味 |
| :-: | :-: |
| %# | シェルが管理者権限で実行される場合「#」、それ以外は「%」 |
| %? | 1つ前の実行のステータスを表示。`echo $?`と同じかも |
| %_ | パーサーの状態。通常時は何も表示されないけど、「pipe」「for」「quote」の最中とかだと出てくる |
| %^ | パーサーの状態を**逆から**表示。「%_」を逆から表示しているだけ |
| %d %/ | カレントディレクトリを表示（絶対パス） |
| %1d %2d | カレントディレクトリを、**下位**ディレクトリから指定された数字分表示する |
| %-1d %-2d | カレントディレクトリを、**上位**ディレクトリから指定された数字分表示する |
| %~ | カレントディレクトリがホームディレクトリ($HOME)を含む場合、「~」で省略 |
| %c %C %. | カレントディレクトリを表示（相対パス） |

```zsh:自分の場合
 %#: %
 %?: 0
 %_: 
 %^: 
 %d: /Users/sho/Test
 %/: /Users/sho/Test
 %3d: /Users/sho/Test
 %2d: sho/Test
 %1d: Test
 %-1d: /Users
 %-2d: /Users/sho
 %~: ~/Test
```
### 「%_」「%^」

パーサーの状態とは、こんな感じのこと。
```zsh:Terminal
print | for i in `seq 1`; do; print -P %_; done

>> pipe for
```

```zsh:Terminal
print | for i in `seq 1`; do; print -P %^; done

>> for pipe
```

## Part2
| シーケンス | 意味 |
| :-: | :-: |
| %L | シェルの深さを表示。`echo $SHLVL`に同じ。 |
| %j | バックグラウンドで動いている処理の数を表示 |
| %N | 現在実行しているスクリプト、shell関数の名前を表示。`echo $0`に同じ。 |
| %x | 「%N」と同じ。ただしshell関数の名前と`eval`は**表示されず**、その関数が**定義されたファイル名**を表示する。 |
| %e | shell関数とか`eval`の深さを表示。「%N」がセットされる度にインクリメントが走るっぽい。 |
| %i | 現在実行しているコマンドが何番目かを表示。シェルのソースファイルだったら何行目かを表示。 |
| %I | 「%i」と同じ。ただし、shell関数ならばその関数が定義されている行番号を表示。 |
| %h %! | 実行したコマンドの`history`番号を表示 |

### 「%L」
これ結構便利な気がする。
`bash`とか`root`ユーザーでログインして、抜けるときに何回分抜ければいいか忘れてターミナルをログアウトしちゃった経験ありません？

```zsh:Terminal
print -P %L
zsh
print -P %L

>> 1
   2
```

### 「%N %x %e」
`%N`も適宜セットされていく。
```zsh:Terminal
print -P %N
function syoshika(){ print -P %N }
syoshika

>> -zsh
syoshika
```

そして、`%e`の深さも`%N`がセットされるたびに増えてく。
`$PS4`のデバッグとして役立つ（らしい）。
```zsh:Terminal
print -P %N %e && 
eval print -P %N %e && 
eval eval print -P %N %e

>> -zsh 0
  (eval) 1
  (eval) 2
```

また、`%x`はshell関数を表示してくれないが、

```zsh:~/.zshrc
...
...
function syoshika(){ print -P %x }
...
```
として読み込んで実行すると、定義したファイル名が出てくる。

```zsh:Terminal
syoshika

>> /Users/sho/.zshrc
```
便利、なのかがわからん。

### 「%i」
ソースファイル内の何番目かを確認できます。
```zsh:shell.sh
print -P %I
print -P %I
print -P %I
print -P %I
```

```zsh:Terminal
zsh shell.sh

>> 1
2
3
4
```

### 「%j」

`%j`は`sleep`をバックグラウンドに送って試してみます。
```zsh:Terminal
sleep 10&; sleep 10&; print -P %j

>> [1] 33457
   [2] 33458
   2

[2]  + done       sleep 10
[1]  + done       sleep 10
```

# 日付や時間
文字で説明するよりも、結果を見た方がわかりやすいです。
| シーケンス | 意味 |
| :-: | :-: |
| %D | yy-mm-dd |
| %T | hh : minmin |
| %t %@ | hh : minmin(AM or PM) |
| %* | hh : minmin : ss |
| %w | day dd |
| %W | monthmonth/dd/yy |
| %D{string} | `string`のフォーマットで表示 |

```zsh:自分の環境
 %D: 22-11-06
 %T: 20:39
 %t:  8:39PM
 %@:  8:39PM
 %*: 20:39:21
 %w: 日 6
 %W: 11/06/22
 %D{%H:%M:%S.%.}: 20:39:21.859
```
### 「%D」
`%D`は**MacOS**が[POSIX](https://ja.wikipedia.org/wiki/POSIX)に準拠しているため、`%.`で小数点以降の秒も表示できる。
> WindowsはCygwinとかでPOSIX互換の環境を構築できるかも

**GNU拡張**が有効であれば、`%9`は`%N`と同義として処理される。
```zsh:Terminal
print -P %D{%H:%M:%S.%9.}

>> 21:42:55.533683000
```
少数9桁まで表示できるみたいだけど、自分は6桁までで丸められてしまっている。

> gettimeofdayのシステムコールを呼び出すことができるOSであればよさそう。

https://man7.org/linux/man-pages/man2/gettimeofday.2.html

# 視覚的な状態
**太字**とか<ins>下線</ins>とかの表示です。
色に関しては[ANSIエスケープコード](https://qiita.com/PruneMazui/items/8a023347772620025ad6)を使わずに変更ができます。
| シーケンス | 意味 |
| :-: | :-: |
| %% | `%`文字自身を表示 |
| %B | **太字**開始 |
| %b | **太字**終了 |
| %U | <ins>下線</ins>開始 |
| %u | <ins>下線</ins>終了 |
| %E | 行末までクリア |
| %S | スタンダードモードを開始 |
| %s | スタンダードモードを終了 |
| %F{color} | `%F{red}`とすると、それ以降 <font color=red>赤文字</font> で表示する。 |
| %f | `%F{color}`を終了 |
| %K{color} | `%K{blue}`とすると、それ以降の背景色を青色で表示する。 |
| %k | `%K{color}`を終了 |
| %{ string %} | `string`通りに出力 |
| %{string%??G%} | `string`がうまく表示できないときに、`??G`で表示幅を調整して表示する |

![スクリーンショット 2022-11-06 22.35.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/777324/bb849427-1269-8944-d036-81452d434110.png)

### 「%F %K」
使える色の名前は以下のサイトの通り。

https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
>  black, red, green, yellow, blue, magenta, cyan and white, 

`#` から始まる16進数のカラーコード（`%f{#55C502}`）が使えたので、結局何色でも端末が対応していれば表示ができるみたい


# 結果

結局、俺得のプロンプト表示は
```zsh:Terminal
export PS1="%F{green}%B%* %n[d:%L][s:%?] ..%2d %f%b%# "
```
- 緑がなんかかっこいい
- 時間が見れるの好き
- 深さを忘れちゃうので`d:%L`追加
- shellいじることが多くなったので一応`status`も追加
- ディレクトリは2つまででいい


![スクリーンショット 2022-11-06 23.55.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/777324/07a32220-d73a-7545-b8a7-756822ff5995.png)

ちょっとだせぇ笑

# 終わりに
最後の三項演算子については時間があるときに追記しようと思います。
調べてる途中で気づいたけど、`color`ではなく`colour`だったのでドキュメントってイギリス英語なのかなぁ。
`zsh`自体はアメリカのプリンストン大学が発祥らしいんだけどね。
自分が使っているものや、おすすめのプロンプト表示があれば教えてほしいです。