在 PS1 中重新转义括号

l0b*_*0b0 5 bash prompt escape-characters

正如其他人所指出的,颜色代码PS1应该用括号括起来\[\]以避免它们占用水平空间。我已将必要的代码添加到.bashrc

highlight()
{
    if [ -x /usr/bin/tput ]
    then
        printf '\['
        tput bold
        printf '\]'
        printf '\['
        tput setaf $1
        printf '\]'
    fi
    shift
    printf -- "$@"
    if [ -x /usr/bin/tput ]
    then
        printf '\['
        tput sgr0
        printf '\]'
    fi
}

highlight_error()
{
    highlight 1 "$@"
}
Run Code Online (Sandbox Code Playgroud)

最后一个函数用于PS1普通和转义命令替换中,以便能够根据前一个命令的结果更改字符串:

# Exit code
PS1="\$(exit_code=\${?#0}
highlight_error \"\${exit_code}\${exit_code:+ }\")"

...

if [ "$USER" == 'root' ]
then
    PS1="${PS1}$(highlight_error '\u')"
else
    PS1="${PS1}\u"
fi
Run Code Online (Sandbox Code Playgroud)

问题是转义的括号作为文字输出,所以我的提示在运行一个不存在的命令后看起来像这样:

\[\]\[\]127 \[\]user@machine:/path
$
Run Code Online (Sandbox Code Playgroud)

将逃生者包裹highlight_error起来printf %b并没有帮助。如何修复输出以便我可以将这些函数用于正常和转义命令替换

Mik*_*kel 4

似乎任何转义序列实际上都PS1需要包装在\[and\]中,但是如果您调用产生输出的函数或命令,则不需要包装它。

那么为什么不直接移动

"\$(exit_code=\${?#0}
highlight_error \"\${exit_code}\${exit_code:+ }\")"
Run Code Online (Sandbox Code Playgroud)

函数内部的东西,例如

print_error_if_error()
{
    exit_code=$?
    if [ $exit_code -ne 0 ]; then
        highlight_error "$exit_code "
    fi
}
Run Code Online (Sandbox Code Playgroud)

然后我想你可以删除所有的\[东西\]......

highlight()
{
    if [ -x /usr/bin/tput ]
    then
        tput bold
        tput setaf $1
    fi
    shift
    printf -- "$@"
    if [ -x /usr/bin/tput ]
    then
        tput sgr0
    fi
}

highlight_error()
{
    highlight 1 "$@"
}

PS1='$(print_error_if_error)'

# ...

if [ "$USER" = 'root' ]
then
    PS1="${PS1}$(highlight_error '\u')"
else
    PS1="${PS1}\u"
fi
Run Code Online (Sandbox Code Playgroud)