右对齐提示部分

右对齐提示部分

我确信我曾见过有人将提示符的一部分在终端窗口中向右对齐,然后实际光标从第二行开始。我知道我可以在 PS1 中使用“\n”来实现第二行,但我不知道如何将其部分向右对齐。我看到的只是在两个字符串之间添加了空格吗?

答案1

通过在显示提示符之前显示第一行,您可以相当轻松地实现所需的操作。例如,下面\w在第一行的左侧显示一个提示符,\u@\h在第一行的右侧显示一个提示符。它利用了$COLUMNS包含终端宽度的变量和$PROMPT_COMMAND在 bash 显示提示符之前评估的参数。

print_pre_prompt () 
{ 
    PS1L=$PWD
    if [[ $PS1L/ = "$HOME"/* ]]; then PS1L=\~${PS1L#$HOME}; fi
    PS1R=$USER@$HOSTNAME
    printf "%s%$(($COLUMNS-${#PS1L}))s" "$PS1L" "$PS1R"
}
PROMPT_COMMAND=print_pre_prompt

答案2

根据我在这里找到的信息,我能够找到一种更简单的右对齐解决方案,同时容纳右侧或左侧的可变长度内容,包括对颜色的支持。在此处添加以方便您使用...

颜色注意事项:事实证明,使用\033逃避方式来支持替代方案(不进行\[\]分组)是最兼容的,因此值得推荐。

诀窍是先写右侧内容,然后使用回车符 ( \r) 返回行首并继续在其上覆盖左侧内容,如下所示:

prompt() {
    PS1=$(printf "%*s\r%s\n\$ " "$(tput cols)" 'right' 'left')
}
PROMPT_COMMAND=prompt

我在 Mac OS X 上使用tput cols来检索终端/控制台宽度,因为terminfo我的$COLUMNSvar 没有填充,但您可以通过提供“ ”或您喜欢的任何其他值来替换中的env可替换“ ”值。*%*s${COLUMNS}

下一个示例用于$RANDOM生成包含颜色的不同长度的内容,并展示如何提取函数来重构实现为可重用的函数。

function prompt_right() {
  echo -e "\033[0;36m$(echo ${RANDOM})\033[0m"
}

function prompt_left() {
  echo -e "\033[0;35m${RANDOM}\033[0m"
}

function prompt() {
    compensate=11
    PS1=$(printf "%*s\r%s\n\$ " "$(($(tput cols)+${compensate}))" "$(prompt_right)" "$(prompt_left)")
}
PROMPT_COMMAND=prompt

由于printf假设字符串的长度为字符数,因此我们需要补偿渲染颜色所需的字符数,您会发现它总是少于屏幕的末尾,因为没有补偿未打印的 ANSI 字符。颜色所需的字符保持不变,您会发现 printf 也会考虑长度的变化,例如$RANDOM' 返回的长度,这使我们的右对齐保持完整。

\u但是,特殊 bash 提示符转义序列(即、\w\h、 )则不是这种情况\t,因为它们只会记录长度 2,因为 bash 只会在 printf 呈现字符串后,在显示提示符时才转换它们。这不会影响左侧,但最好避免在右侧使用它们。

如果生成的内容长度保持不变,则无关紧要。就像时间\t选项一样,它将始终在 24 个时间中呈现相同数量的字符(8)。在这些情况下,我们只需要考虑所需的补偿,以适应 2 个字符之间的差异,从而打印时产生 8 个字符。

请记住,您可能需要对\\\某些转义序列进行三重转义,否则这些转义序列对字符串有意义。如以下示例所示,当前工作目录转义\w没有其他意义,因此它可以按预期工作,但如果不先对其进行三重转义,则时间\t(表示制表符)将无法按预期工作。

function prompt_right() {
  echo -e "\033[0;36m\\\t\033[0m"
}

function prompt_left() {
  echo -e "\033[0;35m\w\033[0m"
}

function prompt() {
    compensate=5
    PS1=$(printf "%*s\r%s\n\$ " "$(($(tput cols)+${compensate}))" "$(prompt_right)" "$(prompt_left)")
}
PROMPT_COMMAND=prompt

好开心!

答案3

使用printfwith$COLUMNS效果很好,例如:

printf "%${COLUMNS}s\n" "hello"

对于我来说,这完全是正确的。

答案4

我只是想把我的放在这里。它几乎与 GRML zsh 提示符完全相同(除了 zsh 在新行和退格方面对其提示符的更新稍好一些 - 这在 bash 中是不可能复制的......至少目前非常困难)。

我花了整整三天的时间在这上面(只在运行 arch 的笔记本电脑上进行了测试),所以这里有一个屏幕截图,然后是我 ~/.bashrc 中的内容 :)

正在运行的 bash 提示的屏幕截图

警告-有点疯狂

重要的事- 每个^[(例如^[[34m)实际上是转义字符(char)27。我知道的唯一插入方法是输入ctrl+( [v)(即同时按下和[)。vctrl

# grml battery?
GRML_DISPLAY_BATTERY=1

# battery dir
if [ -d /sys/class/power_supply/BAT0 ]; then
    _PS1_bat_dir='BAT0';
else
    _PS1_bat_dir='BAT1';
fi

# ps1 return and battery
_PS1_ret(){
    # should be at beg of line (otherwise more complex stuff needed)
    RET=$?;

    # battery
    if [[ "$GRML_DISPLAY_BATTERY" == "1" ]]; then
        if [ -d /sys/class/power_supply/$_PS1_bat_dir ]; then
            # linux
            STATUS="$( cat /sys/class/power_supply/$_PS1_bat_dir/status )";
            if [ "$STATUS" = "Discharging" ]; then
                bat=$( printf ' v%d%%' "$( cat /sys/class/power_supply/$_PS1_bat_dir/capacity )" );
            elif [ "$STATUS" = "Charging" ]; then
                bat=$( printf ' ^%d%%' "$( cat /sys/class/power_supply/$_PS1_bat_dir/capacity )" );
            elif [ "$STATUS" = "Full" ] || [ "$STATUS" = "Unknown" ] && [ "$(cat /sys/class/power_supply/$_PS1_bat_dir/capacity)" -gt "98" ]; then
                bat=$( printf ' =%d%%' "$( cat /sys/class/power_supply/$_PS1_bat_dir/capacity )" );
            else
                bat=$( printf ' ?%d%%' "$( cat /sys/class/power_supply/$_PS1_bat_dir/capacity )" );
            fi;
        fi
    fi

    if [[ "$RET" -ne "0" ]]; then
        printf '\001%*s%s\r%s\002%s ' "$(tput cols)" ":( $bat " "^[[0;31;1m" "$RET"
    else
        printf '\001%*s%s\r\002' "$(tput cols)" "$bat "
    fi;
}

_HAS_GIT=$( type 'git' &> /dev/null );

# ps1 git branch
_PS1_git(){
    if ! $_HAS_GIT; then
        return 1;
    fi;
    if [ ! "$( git rev-parse --is-inside-git-dir 2> /dev/null )" ]; then
        return 2;
    fi
    branch="$( git symbolic-ref --short -q HEAD 2> /dev/null )"

    if [ "$branch" ]; then
        printf ' \001%s\002(\001%s\002git\001%s\002)\001%s\002-\001%s\002[\001%s\002%s\001%s\002]\001%s\002' "^[[0;35m" "^[[39m" "^[[35m" "^[[39m" "^[[35m" "^[[32m" "${branch}" "^[[35m" "^[[39m"
    fi;
}

# grml PS1 string
PS1="\n\[\e[F\e[0m\]\$(_PS1_ret)\[\e[34;1m\]${debian_chroot:+($debian_chroot)}\u\[\e[0m\]@\h \[\e[01m\]\w\$(_PS1_git) \[\e[0m\]% "

我仍在努力使颜色可配置,但我对现在的颜色很满意。


目前正在修复疯狂的^[角色和简单的颜色切换:)

相关内容