34

I'm using custom bash prompt to show git branch.

Everything is in /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\] '

Problem is that when I set color for $_branch in the function, my prompt will be overwritten when EOL is reached:

mmmmmmmmmmmmp/rainyday.js (master) $ mmmmmmmm

Tried all possible variants tput, printf, $'' notation.

I solved the problem by setting the colour only in PS1:

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

But..

  1. I would like to know why it is overwriting my prompt
  2. How to fix this issue when function is used

I'm using Gentoo Linux. GNU bash, verze 4.2.37(1)-release (i686-pc-linux-gnu)

4

3 回答 3

55

1)我想知道为什么它会覆盖我的提示

因为每个不可打印的字符都必须被转义\[\]否则readline无法正确跟踪光标位置。

您必须在提示符中放置\[任何\]非打印转义序列。
没有\[ \]bash 会认为构成颜色代码的转义序列的字节实际上会占用屏幕上的空间,因此 bash 将无法知道光标的实际位置。

\[ 开始一系列非打印字符。(如颜色转义序列)。这允许 bash 正确计算自动换行。

\] 结束一系列非打印字符。-- Bash常见问题

...注意非打印字符的转义,这些确保 readline 可以正确跟踪光标位置。-- ss64.com

2)如何解决这个问题function2)使用

如果要在其中function使用其输出的内部设置颜色,则PS有两个选项。

  • 要么转义整个函数调用:

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

  • 或者替换里面的非打印转义序列echo。也就是说,替换:

    \[\]\001 \002

    (感谢用户的感谢!)

  • echo -e 不知道bash \[ \],因此您必须用\001& \002ASCII 控制代码替换这些以将不可打印字符与可打印字符分隔开:

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

于 2013-10-21T18:01:03.240 回答
14

类似的字符串\e[0;91m需要额外的引用,以防止 bash 计算其长度。

将这些字符串从formattedGitBranchin \[&括起来\]\[\e[0;91m\]

你已经在其他地方正确地做到了。只是在格式化的 GitBranch 中错过了它。

于 2013-09-30T11:01:42.913 回答
0

您必须注意 [\ 和 /] 内的不可打印字符,否则您可能会将光标放在命令提示符的顶部,因为它本身有问题,所以我找到了一些东西并分享了它:-

为了在同一行的 PS1 输出后获取光标:

后

几个例子:

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

参考链接:bash PS1 的语法

于 2017-05-10T15:10:04.653 回答