web-dev-qa-db-ja.com

カスタムBashプロンプトがそれ自体を上書きしています

カスタムbashプロンプトを使用してgitブランチを表示しています。

すべてが_/etc/bash/bashrc_にあります:

_function formattedGitBranch {
    _branch="$(git branch 2>/dev/null | sed -e "/^\s/d" -e "s/^\*\s//")"
    # tried these:
    echo -e "\e[0;91m ($_branch)"                       
    echo -e "\e[0;91m ($_branch) \e[m"                  
    echo -e $'\e[0;91m'"($_branch)"
    echo "($_branch)"                                   
    echo "$(tput setaf 2) ($_branch) $(tput setaf 9)"
    printf "\e[0;91m ($_branch)"
}

# color is set before function call
PS1='\[\033[01;34m\] \[\033[0;91m\]$(formattedGitBranch) \$\[\033[00m\] '
# color is set inside function
PS1='\[\033[01;34m\] $(formattedGitBranch) \$\[\033[00m\] '
_

問題は、関数で_$_branch_の色を設定すると、EOLに到達するとプロンプトが上書きされることです。

mmmmmmmmmmmmp/rainyday.js (master) $ mmmmmmmm

可能なすべてのバリアントtputprintf、_$''_表記を試しました。

_PS1_のみに色を設定することで問題を解決しました:

ad@gentoo /tmp/rainyday.js (master) $ mmmmmmm

だが..

  1. プロンプトが上書きされる理由を知りたい
  2. 関数が使用されているときにこの問題を修正する方法

Gentoo Linuxを使用しています。 GNU bash, verze 4.2.37(1)-release (i686-pc-linux-gnu)

32
A.D.

1)プロンプトが上書きされる理由を知りたい

印刷できない文字はすべて_\[_および_\]_でエスケープする必要があるため、そうでない場合 readline はカーソル位置を正しく追跡できません。

プロンプト内の印刷されないエスケープシーケンスは、_\[_および_\]_で囲む必要があります。
_\[ \]_がないと、bashはカラーコードのエスケープシーケンスを構成するバイトが実際に画面上のスペースを占めると考えるため、bashはカーソルが実際にどこにあるかを知ることができません。

_\[_非印刷文字のシーケンスを開始します。 (カラーエスケープシーケンスのように)。これにより、bashはWordの折り返しを正しく計算できます。

_\]_非印刷文字のシーケンスを終了します。 - BashFAQ

...非印刷文字のエスケープに注意してください。これにより、readlineがカーソル位置を正しく追跡できるようになります。 - ss64.com

2)functionが使用されている場合にこの問題を修正する方法

出力がfunctionで使用されるPS内に色を設定する場合、2つのオプションがあります。

  • 関数呼び出し全体をエスケープする:

    PS1='\[ $(formattedGitBranch) \] '

  • または 印刷されないエスケープを置き換えるecho内のシーケンス。つまり、以下を置き換えます。

    _\[_および_\]_ with _\001_ _\002_

    ser grawity に感謝)

  • _echo -e_ わからない bashの_\[_ _\]_なので、これらを_\001_&_\002_ ASCII印刷不可能な文字を印刷可能から区切るための制御コード:

    function formattedGitBranch { echo -e "\001\e[0;91m\002 ($_branch)"; }PS1='$(formattedGitBranch) '

46
A.D.

\e[0;91mのような文字列は、bashがその長さを計算しないように、追加の引用符が必要です。

formattedGitBranchのこれらの文字列を\[\]で囲みます。\[\e[0;91m\]として

あなたは他の場所でそれを正しくやった。ちょうどフォーマットされたGitBranchでそれを逃しました。

11
anishsane

[\と/]内の印刷不可能な文字に注意する必要があります。そうしないと、コマンドプロンプトの真上にカーソルが表示される可能性があります。問題自体で共有されているため、何かを見つけて共有しました:-

同じ行のPS1出力の後にカーソルを取得する場合:

After

いくつかの例:

PS1='[\u@\h:\w]\$
PS1='[\[\033[0;32m\]\u@\h:\[\033[36m\]\W\[\033[0m\]]\$ '

参照リンク: bash PS1の構文

0