更改 bash 输出格式会导致奇怪的行为

更改 bash 输出格式会导致奇怪的行为

我已将我的 bash 输出格式更改为如下格式:

在此处输入图片描述

我对此非常满意。我通过将此代码添加到.bashrc

set_PS1()
{
    local RESET=$(tput sgr0 )
    local BOLD=$(tput bold )
    local RED=$(tput setaf 1 )
    local GREEN=$(tput setaf 2 )
    local YELLOW=$(tput setaf 3 )
    local BLUE=$(tput setaf 4 )
    local CYAN=$(tput setaf 6 )

    local WHOAMI='\u'
    local WHERE='\w'
    local HOSTNAME='\h'
    local TIME='\D{%H:%M:%S}'


     exit_code_prompt() {
        local EXIT_CODE=$?
        local RED=$(tput setaf 1 )
        local GREEN=$(tput setaf 2 )
        if [ $EXIT_CODE -ne 0 ]; then
            echo -e "$RED$BOLD\xE2\x9C\x98 $EXIT_CODE \xE2\x86\x92"  # Red cross mark symbol
        else
            echo -e "$GREEN$BOLD\xE2\x9C\x93 \xE2\x86\x92"  # Green checkmark symbol
        fi
    }

    local LINE_1="$BOLD$YELLOW$TIME $CYAN$WHOAMI$BLUE@$CYAN$HOSTNAME$RESET$BOLD":" $BLUE$WHERE$RESET"
    local LINE_2="$BOLD\$(exit_code_prompt) "$RESET$BOLD' \$: '$RESET


    PS1="$LINE_1\n$LINE_2"

    unset -f set_PS1
}

set_PS1

我的问题是,如果我有一个长度超过一行的命令,它不会换行,而是覆盖同一行的内容(仅在视觉表示中):

在此处输入图片描述

现在,当我删除完整的命令时,它也会删除部分 bash 提示符:

在此处输入图片描述

\[这可以通过添加和来解决\]

    local LINE_1="\[$BOLD$YELLOW$TIME $CYAN$WHOAMI$BLUE@$CYAN$HOSTNAME$RESET$BOLD":" $BLUE$WHERE$RESET\]"
    local LINE_2="\[$BOLD\$(exit_code_prompt) "$RESET$BOLD' \$: \]'$RESET

但另一个问题仍然存在。当我循环浏览最后使用的命令时,它会删除提示符号$

在此处输入图片描述

我该如何解决这个问题?

我已经研究过使用zsh,但我不想失去bash我已经习惯的键盘快捷键等功能......

更新:下面是我更新后的代码,但仍然不起作用:

set_PS1()
{
    local Reset="\\[$(tput sgr0 )\\]"
    local Bold="\\[$(tput bold )\\]"
    local Red="\\[$(tput setaf 1 )\\]"
    local Green="\\[$(tput setaf 2 )\\]"
    local Yellow="\\[$(tput setaf 3 )\\]"
    local Blue="\\[$(tput setaf 4 )\\]"
    local MagentaBG="\\[$(tput setab 5 )\\]"
    local Cyan="\\[$(tput setaf 6 )\\]"

    local Whoami='\u'
    local Where='\w'
    local Hostname='\h'
    local Time='\D{%H:%M:%S}'
    local Exit_Code="$?"

    exit_code_prompt() {
        local Exit_Code="$?"
        local Red="$(tput setaf 1 )"
        local Green="$(tput setaf 2 )"
        if [ $Exit_Code -ne 0 ]; then
            printf "$Red\xE2\x9C\x98 $Exit_Code \xE2\x86\x92 " # Red cross mark symbol
        else
            printf "$Green\xE2\x9C\x93 \xE2\x86\x92 " # Green checkmark symbol
        fi
    }

    local Line_1="$Bold$Yellow$Time $Cyan$Whoami$Blue@$Cyan$Hostname$Reset$Bold":" $Blue$Where$Reset"
    local Line_2="$Bold\$(exit_code_prompt)$Reset$Bold \$: $Reset"

    PS1="$Line_1\n$Line_2"

    unset -f set_PS1
}

set_PS1

我会遇到和以前一样的问题。超过一行的文本会出现在同一行的开头并被覆盖。循环执行命令会导致提示的一部分被删除,或者导致出现视觉错误,显示无法访问的上一个命令的一部分。

更新2:问题肯定出在exit_code_prompt功能上。当我将其删除时,$Line_2一切都按预期运行。

答案1

按照@Daniel 的建议,使用

    local RESET="\\[$(tput sgr0 )\\]"

与所有其他颜色代码类似。

6.9 控制提示在手册中:

\[
    Begin a sequence of non-printing characters. This could be used to
    embed a terminal control sequence into the prompt.

\]
    End a sequence of non-printing characters.

回到你的问题:

当我循环浏览最后使用的命令时,它会删除提示符号

这是因为如果没有\[\]来包装控制序列,bash 就无法正确计算提示的长度。

相关内容