LoginSignup
13
7

More than 3 years have passed since last update.

zshでプロンプトの右側部分を無理やりにでも先頭行に表示したい

Last updated at Posted at 2020-10-24

やりたいこと

zshで以下2つに当てはまると、2行目にRPROMPT(プロンプトの右側)が来てしまいます。

  • .zshrcPROMPT末尾に改行コードを入れて、コマンドを新しい行から入力するようにしている
  • RPROMPTを有効にしている

下の画像のようになります。
Screen Shot 2020-10-25 at 2.35.28.png

これで困るのが、ターミナルの内容をSlackなどにコピペして共有しようとしたとき、RPROMPTまでコピーされてしまい、それを消す手間ができてしまうということです。

なんでユーザーがコマンドを入力する行と同じ行にRPROMPTを出す仕様なんだろう。。
それをなんとかしたいというニッチな投稿です。

ちなみに何らかの設定で、シンプルにこれを解消する方法は思いつきませんでした。
(RPROMPTは改行コード効きません。ZLE_RPROMPT_INDENTを負の整数にしたりしても無視されます。)

解決方法の案

案1: RPROMPT使うのやめて、ANSIエスケープシーケンスで無理やり制御して描画する

ちょっとこんなやり方しかわからないです。

.zshrcを以下のようにします。

# 出したい情報をCUSTOM_RPROMPTに格納しておく

print_to_rprompt() {
    col=$(( COLUMNS - 8 ))
    print -Pn "\e7\e[1A\e[${col}G${CUSTOM_RPROMPT}\e8"
}

TMOUT=1
TRAPALRM() {
    print_to_rprompt
}

COLUMNSはウィンドウ幅が入っているzshの環境変数です。
右に出す文字を、先頭に半角スペースを挿入することで、全て8文字に統一した上で上記のように実装しました。

制御コードによる操作の説明をします。

  • ESC7: 現在のカーソル位置などを保存する
  • ESC[1A: カーソル位置を1行上に移動
  • ESC[{NUM}G: カーソルを左端からNUMだけ右に移動
  • ESC8: 保存していたカーソル位置などの復帰

そして、TRAPALRMでこれを1秒毎に実行します。
つまり、毎秒printで出したい情報を出し続けるということになります。

私は、gitのstatusと時刻をRPROMPTに出したいのですが、この方法だとプロンプトの右側の情報は保持されずに常に書き換えられるため、時刻はPROMPTにうつしてgitのstatusだけ表示するようにしました。
以下のような感じになります。

Oct-25-2020 03-36-01.gif

毎秒更新するあたり、本来のRPROMPTとは機能が異なってしまっていますが、gitのstatusをリアルタイムで更新して表示してくれるのでむしろ気に入りました。

案2: PROMPTに必要なだけのスペースを計算して挿入する

これでもできそうです。こちらのほうが本来やりたかったことに近いかも。
ただ今回は案1にしました。

案3: tmuxを使う

tmuxでstatus-position topで出来るらしいです。
tmuxにしようかな。。

まとめ

試行錯誤してるうちに、以下のようなプロンプトができました。

  • 複数行プロンプトの場合も、1行目の右側に情報を表示
  • 毎秒更新(エディタでいじればそのステータスが反映される)

なにか他にいい方法があれば、ぜひ教えていただきたいです。。

13
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7