在上一个命令失败后使用红色$创建Bash命令提示符

时间:2011-08-21 01:39:50

标签: bash shell refactoring return-value command-prompt

我是Bash编程的新手,我正在创建一个自定义Bash命令提示符。我的目标是创建一个提示,当它们与我通常使用的不同时,它只显示登录名和主机名。我还希望在Git版本控制下的目录中将当前的Git分支附加到命令提示符。

我想将登录和主机名部分为绿色,目录路径为蓝色,Git分支部分为粉红色,分隔符(:和$字符)为白色。但是,当先前执行的命令返回除零以外的任何内容时,我想为$ separator red 着色。没有颜色的一般格式如下所示:

loginname@hostname:~/current/path:branchname$

唯一必需的部分是目录路径和$字符。这是我为 .bashrc 文件编写的代码:

MYNAME="gwen"
MYHOST="gwen-laptop"

RED="\[\033[31m\]"
WHITE="\[\033[0m\]"
GREEN="\[\033[01;32m\]"
BLUE="\[\033[01;34m\]"
PINK="\[\033[01;35m\]"

DOLLAR="if [ \$? = 0 ]; then echo ${WHITE}\$; else echo ${RED}\$${NORMAL}; fi"
GITBRN='$(__git_ps1 "\033[0m:\033[01;35m%s")'

USERNM="if [ \u != ${MYNAME} ]; then whoami; fi;"
HOSTNM="if [ \h != ${MYHOST} ]; then echo -n @; hostname; fi;"
COLONM="if [ \u != ${MYNAME} ] || [ \h != ${MYHOST} ]; then echo -n :; fi;"

PS1="${GREEN}\`${USERNM}\`\`${HOSTNM}\`${WHITE}\`${COLONM}\`${BLUE}\w${GITBRN}\`${DOLLAR}\` "

此代码符合我的所有要求,除了它始终使$字符保持白色,并且在适当的时间不会将其涂成红色。 (我怀疑问题是DOLLAR中的“\ $?”引用了先前执行的命令,但是在构造PS1时最后执行了DOLLAR,所以先前的execute语句不再是在PS1构建开始之前运行的命令;它是某种东西这是为了创建命令提示符而执行的。)我不确定如何解决这个问题

此代码很难看,需要重构。我试图将所有颜色代码移动到他们自己的变量中,但是当我在GITBRN的代码中使用这些颜色变量时,事情变得混乱,所以我最终使用了字面颜色。

我花了一整天时间试图让这段代码正常工作,而且我觉得我现在无处可去。任何关于如何在适当的时间将红色美元符号涂成红色的建议将非常受欢迎。我也欢迎重构代码以使其更清晰,更易读。

P.S。我是Ubuntu Linux(Lucid Lynx)的用户。

3 个答案:

答案 0 :(得分:4)

根据bash手册页使用PROMPT_COMMAND变量,该变量在每个主要提示之前执行。

例如(这还不行,我正试图让它正常工作,但我认为这是可能的):

PROMPT_COMMAND="if [ \$? = 0 ]; then DOLLAR="${WHITE}\$${NORMAL}"; else DOLLAR="${RED}\$${NORMAL}"; fi"

修改:由于在PS1内执行命令和非打印字符而感到沮丧(\[\]有时会从字面上打印而不是用作提示到PS1),我想出了这个(在你的提示中用你想要的任何内容替换...):

PROMPT_COMMAND='if [ $? = 0 ]; then DOLLAR_COLOR="\033[0m"; else DOLLAR_COLOR="\033[31m"; fi'
PS1='...\[$(echo -ne $DOLLAR_COLOR)\]$\[\033[m\] '

当然,使用$(),您可以在PS1内添加您喜欢的部分,而不是使用PROMPT_COMMAND,我只是喜欢这样,以便PROMPT_COMMAND包含逻辑和PS1包含显示命令。

答案 1 :(得分:2)

我得到了它的工作:

PROMPT_COMMAND='if [ $? = 0 ]; then PS1="\[\e[32;1m\]\u@\[\e[0m\e[30;47m\]\H\[\e[0m\]:\[\e[34;1m\]\w\[\e[0m\]$ "; else PS1="\[\e[31;1m\]\u@\[\e[0m\e[31;47m\]\H\[\e[0m\]:\[\e[31;1m\]\w\[\e[0m\]$ "; fi'

enter image description here

站在@jtbandes的肩膀上。 @jtbandes是这个想法的原作者。

答案 2 :(得分:1)

以下Alexsandr's answer被修改为仅在命令失败时显示红色,而不是在Stéphane请求时在空命令行上按Enter键时显示红色。

trap 'PREVIOUS_COMMAND=$THIS_COMMAND; THIS_COMMAND=$BASH_COMMAND' DEBUG
read -r -d '' PROMPT_COMMAND << 'END'
    if [ $? = 0 -o $? == 130 -o "$PREVIOUS_COMMAND" = ": noop" ]; then
        PS1='\[\e[32;1m\]\u@\[\e[0m\e[30;47m\]\H\[\e[0m\]:\[\e[34;1m\]\w\[\e[0m\]$ '
    else
        PS1='\[\e[31;1m\]\u@\[\e[0m\e[31;47m\]\H\[\e[0m\]:\[\e[31;1m\]\w\[\e[0m\]$ '
    fi
    : noop
END