wormiii
wormiii

Reputation: 167

Cannot get the exact bash prompt I want

What's throwing me off mostly is trying to get new lines as I want. And trust me, I've googled and searched through this site, but can't get exactly what I want. I either get parsing errors or not exactly what I want.

What I want is this

/c/what/ever/folder/here
(gitbranch)
$ STARTTYPING HERE

first line green, second yellow, third white. What I've been able to come up with gives me this:

/c/what/ever/folder/here
 (gitbranch) $ STARTTYPING HERE

note the extra space before (gitbranch) and lack of newline before the "$"

here is my PS1 so far:

parse_git_branch() {
     git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}

PS1="\[\033[32m\]\w\[\033[33m\]\n\$(parse_git_branch)\[\033[00m\] $ "

I'm wanting this because we sometimes have long branch and directory names and hate having my prompt start anywhere but to the far left

Upvotes: 1

Views: 68

Answers (1)

Zac B
Zac B

Reputation: 4232

I think involving sed is generating some output that is really confusing the expansions inside the double-quoted string you're using for PS1.

You could switch to splicing special strings, single-quoted strings, and double quoted ones together (e.g. "$foo"'"not $expanded'$'\n') if you like, but that's a bit confusing.

Instead, why not skip parsing git branch's output at all, and just ask for the branch directly?

Assuming that you want the branch name (second line) not to show up at all when not in a Git repository, this works:

branch=$(git rev-parse --abbrev-ref HEAD 2> /dev/null)
PS1="\[\033[32m\]\w${branch:+\[\033[33m\]\n($branch)}\[\033[00m\]\n$ "

The magic is in the :+ parameter expansion statement: it assigns/returns everything on the right of the plus if the left side is non-empty; nothing otherwise. Think of it a bit like the $cond ? $trueval : $falseval ternary operator in other programming languages.

If you want a default string instead of no second line, try:

PS1="\[\033[32m\]\w\[\033[33m\]\n(${branch:-no branch detected})\[\033[00m\]\n$ "

When you're in a brand new repo, but you haven't committed anything yet, that code will prompt that you're in branch HEAD. If you'd like it to say master or something else, do something like this:

branch=$(git rev-parse --abbrev-ref HEAD 2> /dev/null)
if [ "$branch" = "HEAD" ]; then
    branch="master, brand new"
fi

You're probably already doing this, but if you want your prompt to update when you change directories, running that code once won't work; it'll "stick" with whatever the git branch of where you first ran it was. To make that happen, plug that code into your PROMPT_COMMAND bash variable via a function, like so:

prompt_with_git() {
    branch=$(git rev-parse --abbrev-ref HEAD 2> /dev/null)
    PS1="\[\033[32m\]\w${branch:+\[\033[33m\]\n($branch)}\[\033[00m\]\n$ "
}

PROMPT_COMMAND=prompt_with_git

Once you've sourced that, things should work.

Note that this requires a Git that supports the rev-parse command and arguments used here. Do git rev-parse --abbrev-ref HEAD in a committed repo folder manually to check if yours does; if there's an error, you may need to upgrade your Git.

Upvotes: 1

Related Questions