Powerline風のプロンプトを作りました。とりあえずインストールは以下に書いてあります:
まだまだ勉強中ですから、非効率な記述とかあるんじゃないかと思うので、コメントいただけるとありがたいです。
また、いいね&ストックいただけると励みになります!
動機
僕は以前、Powerline-shellを使っていました。
しかし、Powerline系のプロンプトだと、Gitリポジトリでのステータス表示アイコンがNerdFontsだかPowerlineFontsの全角っぽいグリフなんです。
NerdFontsのグリフは、UnicodeのPrivate領域を使用していて、全角半角がしっかりと区別されないんですね。
すると問題が発生したんです。
表示がずれる。
僕のターミナルエミュレータ(うち、特にCrostiniのやつ)では、このグリフ、全角幅で表示されるのに半角幅と認識されて、入力位置が一文字ずれたりするんです。
じゃあ、Gitステータス表示をかえればいいじゃんか。とは思ったんだけど...よくわかんない。
公式のカスタマイズドキュメント読んでも、よくわかりませんでした。僕の読解力がないのかな。
そうなったらたどり着くのは一箇所です。 自分で作ったる
方針
まず、PowerlineやらPowerline-shellのカスタマイズがよくわからなかった原因として、コード群が複雑なところです。
そして、pipでインストールするPythonスクリプトなので、余計わからん。(個人の感想です)
そこで、以下の方針を立てました。
- できるだけ簡潔にする
- 比較的カスタマイズ(特に文字と色周り)をしやすくする
- シェルスクリプトで書く
- Gitステータス表示にはgit-prompt.shを使う(半角記号で表してくれるため)
シェルスクリプトだと多少速度は犠牲になるかもですが、もともとがPythonだったので大した問題はないですね。
命名
prow(船の舳先)とpromptをかけ合わせて、Prowptとしました。この名前、完成前まで何回も変更してたどり着いたんですよ。まあだからといって完璧な名前でもないと思ってる。ネーミングセンスがほしい。
設計
大まか、というか雑に設計、というかコードの方針を立てていきます。
- カスタマイズしたい項目(各セグメント(Powerlineにおける、各項目のブロックのこと)の内容や色)はすべて個別の変数に保存することで、外部スクリプト(ユーザ設定で、変数定義が含まれる)を読み込むことでカスタマイズできるようにする
- 可読性・メンテナンスの観点から、各セグメントそれぞれに表示用の関数を作る
- 色に関しては、ANSIで定義されている256色を使えるように、256色表示のためのANSIエスケープシーケンスを格納した関数を用意する(説明下手。実際のコード内では
prowpt_ansi_color
という関数になってます。見ればわかると思います。) - 全体において、BashとZsh両方に対応できるようにする。BashとZshで異なる項目は、条件分岐を行うか、別スクリプトを使用する。
実装
以下のような構造で実装しました。->
はsourceでの読み込みを表します。
Bash -> prowpt.bash ──────┐
各シェル固有の設定 │ メインのコード ユーザ設定
Zsh -> prowpt.plugin.zsh ─┴─> prowpt-core.sh -> ~/.config/prowpt/config.sh
(Unicode罫線素片って便利だねこれ。)
詳しいコードはリポジトリをご覧ください。
簡単な解説
prowpt.bash, prowpt.plugin.zsh
各シェル固有の設定を行っています。
各シェルによる挙動の違いはこの記事を参考にしてください。
例えば、プロンプト内でのエスケープ文字とか。Bashだと\u
なのがZshだと%*
になったりするからね。
それ以外は基本的にprowpt-core.sh
内で条件分岐してます。
最後に、$PS1
なり$PROMPT
なりに、各セグメントを格納しています。その際、プロンプト表示前に再読込を行い、プロンプトを最新の状態に保っています。
prowpt-core.sh
- 各種変数定義
- ユーザ設定の読み込み
-
prowpt_init
: プロンプト表示前に実行するコマンド群 -
prowpt_ansi_color
: ANSI256色を表示するのを完結にするための関数 - それ以下は各セグメントの表示内容
※各セグメントの末尾にはセグメントデリミタ(三角形などの区切り文字)がありますが、そこの背景色は次のセグメントの背景色にしなきゃいけませんでしたので、表示順を変えるだけじゃ不自然になってしまいます。どうにかここを簡単にしたい。
git-prompt.sh
これは単なるhttps://github.com/git/git/blob/master/contrib/completion/git-prompt.shのコピーです。
以上!
わからないなりに頑張って調べながら作ってみました。満足しています。
唯一、不足していると思った点があります。ターミナルエミュレータの幅が足りない際や、zsh-autosuggestionによるサジェストの表示時、tab補完時などに、表示が崩れてしまう点です。
解決方法を考えたり調べたりしてみたんんですが、よくわかりませんでした。もしご存知の方いらっしゃいましたらお知らせいただきたいです...!