Hello world,

Like Paul said in his reply, I also have a "bash monstrosity" as a
Bash prompt. I last spent time tweaking it many years ago, so... This
migh reflect what my head was like in the past, not today :-]

I am attaching here the relevant portion of my .bashrc

> Basically the only improvements over lesser distributions we have are:
> * color: it's not for mere looks, but it visually separates output of
>   commands between themselves
> * full path from ~ (Fedora has only the last component which sucks)

I do consider this to be very important for me. I'm not inlining it
here, as mine is quite verbose, but the colors are defined in
promptFunc(). I don't really follow what you mean by "full path from
~" — Isn't it what \w produces?

> I would like to add at minimum:
> * current git branch (but not -dirty as that can take ages on large repos
>   on slow media -- you want changing directory to be instant)

Yes, I have all this set. I remember it being somewhat slow on large
repos, but I seldom notice it anymore (and on an SSD, it's seldom more
than a couple of seconds on a large Git tree that's not cached). Today
I see this as a heavy number of calls to git, and it always calls git
even if not in a git tree, but... Whatever ☺ This is defined in
parse_git_branch()

> * result of the last command

Yes, I find this to be tremendously useful. I don't absolutely like
the way I handle this (see LAST_RET at the beginning of prompt_func)

> Also, for people who use _many_ terminal tabs while logged on to _many_
> machines like me, I'd also suggest window title.  To simplify the code I've
> personally added parsing this sequence to Linux kernel (as of 3.16).
> I also put the title in ALL UPPERCASE if it's a root session, this helps
> while doing admin tasks.  There's no space for username so I give only
> machine name.

Makes sense. My window title was meant to reflect the previous command
run. But it reflects the last command that _finished_, amd that's not
always immediate.

I also print my regular username in green, but a root login is
presented in red (not only due to the '$' vs. '#' component).

> > I've read a bit on zsh and powerline and the like, but I am annoyed that
> > all those blog posts are quite superficial and do not mention security,
> > interoperability or performance aspects. Frankly any blog post that
> > recommends cloning random repos or even worse, running wget | sh something
> > gives me chills.
> 
> Aye.  Just bash in bashrc should be enough, without iffy Python daemons or
> similar stuff.

I agree. The code I'm sharing here is far from optimal, but it's easy
to follow (after... 5-10 years from its last modification.

> As for powerline: it's not in Unicode, and even worse, illegally uses code
> points that have since been assigned for something else.  Another version of
> powerline uses PUA characters, but also with ill-chosen codepoints that
> clash with popular assignments (CSUR, MUFI).

I'm not aware of Powerline, so I won't comment on it.

> Another thing I've tried but rejected is writing some stuff on the right
> edge of the screen.  This is easy to code and looks good, but causes nasty
> unaligned leftovers if you paste pieces of your console that include the
> prompt, with you not noticing until after the paste is done.

Agree completely.

So, without further ado, my prompt follows:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# Useful to know where we stand while using different version control systems
parse_git_branch() {
    # Yes, temporary, dirty, yada yada yada. Works for me™.
    # --exclude-standard does not exist on git <= 1.5
    git_opts='--exclude-standard'
    branch=`git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'`
    if [ ! -z "$branch" ]
    then
        clean=`git status --porcelain`
        if [ ! -z "$clean" ]
        then
            branch="${branch}*"
            new=`git ls-files -o $git_opts|wc -l`
            del=`git ls-files -d $git_opts|wc -l`
            mod=$(( `git ls-files -m $git_opts|wc -l` - $del ))
            if [ $mod != 0 ]; then branch="${branch}${mod}M"; fi
            if [ $new != 0 ]; then branch="${branch}${new}N"; fi
            if [ $del != 0 ]; then branch="${branch}${del}D"; fi

        fi
    fi
    echo $branch
}

# set a fancy prompt (non-color, unless we know we "want" color)
promptFunc()
{
    LAST_RESULT="$?:$_"
    LAST_RET=${LAST_RESULT/:*/}
    LAST_CMD=${LAST_RESULT/*:/}
    VC_STATUS=`parse_git_branch`
    case "$TERM" in
        screen*|xterm*|rxvt*)
            COLOR_RED="\[\e[31;40m\]"
            COLOR_GREEN="\[\e[32;40m\]"
            COLOR_YELLOW="\[\e[33;40m\]"
            COLOR_BLUE="\[\e[34;40m\]"
            COLOR_MAGENTA="\[\e[35;40m\]"
            COLOR_CYAN="\[\e[36;40m\]"

            COLOR_RED_BOLD="\[\e[31;1m\]"
            COLOR_GREEN_BOLD="\[\e[32;1m\]"
            COLOR_YELLOW_BOLD="\[\e[33;1m\]"
            COLOR_BLUE_BOLD="\[\e[34;1m\]"
            COLOR_MAGENTA_BOLD="\[\e[35;1m\]"
            COLOR_CYAN_BOLD="\[\e[36;1m\]"

            COLOR_NONE="\[\e[0m\]"

            TERM_TITLE="\\033]0;"

            HOST="${COLOR_NONE}@${COLOR_CYAN}\h"
            DIR="${COLOR_YELLOW}『\#』\w"
            PROMPT="${COLOR_GREEN_BOLD}\\$ ${COLOR_NONE}"

            if test ! -z "$VC_STATUS"
            then
                VC=" ${COLOR_CYAN}($VC_STATUS)${COLOR_NONE}"
            else
                VC=
            fi
    
            if test `whoami` != "root"
                then
                USERNAME="${COLOR_GREEN}\u"
            else
                USERNAME="${COLOR_RED}\u"
            fi

            if test $LAST_RET -eq 0
            then
                STATUS="${LAST_RET}"
            else
                STATUS="${COLOR_RED_BOLD}${LAST_RET}${COLOR_NONE} "
            fi
            ;;
        *)
            STATUS=$LAST_RET
            USERNAME="\u"
            HOST="@\h"
            COUNT="[\#]"
            DIR="\w"
            PROMPT="\\$ "
            if test ! -z "$VC_STATUS"
            then
                VC="($VC_STATUS)"
            else
                VC=
            fi
            ;;
    esac

    PS1="${STATUS}${VC} ${USERNAME}${HOST}${DIR}${PROMPT}"

    # If this is an xterm set the title to user@host:dir
    case "$TERM" in
        screen*|xterm*|rxvt*)
            echo -ne "${TERM_TITLE}(${LAST_CMD}:${LAST_RET}) 
${USER}@${HOSTNAME}: ${PWD/$HOME/~}\\007"
            ;;
    esac
}

PROMPT_COMMAND=promptFunc

Reply via email to