🐚

bash で zsh の様な行末自動改行を実現する

2021/07/14に公開

bash を使っていて改行なしの echo を実行した際に

この様に表示されて気持ち悪いと感じる人がいるかもしれません。zsh の場合、この様に改行の無い echo を実行すると以下の様に % が表示され、正しく行頭にプロンプトが表示されます。

bash でもこれがやりたいと思い、調べたところ以下の Stack Overflow 記事が見つかりました。

https://serverfault.com/questions/97503/bash-how-to-know-if-the-last-commands-output-ends-with-a-newline-or-not/97543#97543

この PROMPT_SP はプロンプトを表示される前に出力される文字列で、この StackOverflow の回答では % を表示し、カラム幅の空白で上書きする事で実現しています。

ただこの方法では、starship の様なプロンプトをカスタマイズする系のハックを使っている人には嬉しくありません。

bash では現在のカラム位置を調べる方法として以下を使う事ができます。

echo -en "\E[6n"
read -sdR CURPOS

これを実行すると VT220 をサポートする端末のデバイスステータスが返され、read コマンドにより応答が CURPOS に格納されます。starship の場合、starship_precmd_user_func という変数でプロンプトが表示される前に呼ばれる関数が定義できるので、以下の様に .bashrc に書いておく事で zsh のアレと同じ事が実現できます。

function output_newline(){
  echo -en "\E[6n"
  read -sdR CURPOS
  [ $(echo $CURPOS | cut -d';' -f 2) -gt 1 ] && echo -e "\e[7m%\e[m"
}
starship_precmd_user_func="output_newline"

追記
k-takata さんに良さそうなのを頂いた。

function output_newline(){
  IFS='[;' read -s -d R -p $'\033[6n' -a POS
  [ ${POS[2]} -gt 1 ] && echo -e "\e[7m%\e[m"
}
starship_precmd_user_func="output_newline"

VT220 互換端末でないと表示が崩れる可能性があるのでご注意下さい。

Discussion