Tech Tips: 4 Great Things To Do With Your Shell Prompt

scottcarpenterI spend a lot of time on the command line. Since I'm looking at my shell prompt so much, I want it to be as useful as possible. Here are some improvements I've made recently.

This isn't meant as a starter guide on setting your bash prompt, but to review, you might have a standard bash prompt like this, set in your .bashrc or .bash_profile file:

PS1="\u@\h:\W$ "

Where \u is your username, \h the host name of the machine, and \W the current working directory, yielding something like:

scarpent@bigmachine:working$

I've always preferred the full path, with lower-case \w in my PS1. For example:

scarpent@bigmachine:~/tmp/long/path/with/many/dirs$

Okay! Let's look at some stuff we can do with this thing.

1. Add the current Git branch name to your prompt

Working at The Nerdery has meant finally using Git. I love Git as a version control system. (It's also a great friend.)

If you're doing all the wonderful branching that Git makes so easy, it would be nice to see what branch you're on in the prompt. And, people have made this possible!

You'll need the git-prompt.sh script from here:

https://github.com/git/git/tree/master/contrib/completion

(You'll also want git-completion.bash, but that's a subject for another day.)

git-prompt.sh goes in the root of your home directory and you load it from .bashrc or .bash_profile (or wherever):

. ~/.git-prompt.sh

Now you'll have the __git_ps1 function available, and we can modify our example PS1:

PS1='$(__git_ps1 "(%s) ")'"\u@\h:\w$ "

And now we see our branch!

(develop) scarpent@bigmachine:~/tmp/long/path/with/many/dirs$

Notice in the PS1 assignment, we've used a command substitution, $(echo 'like this'), but we don't want the substitution performed at the time of assignment. By wrapping that part of the string in single quotes, it will run dynamically in your terminal session. Also notice we've formatted our output string in double quotes inside the single quotes.

Another cool feature with this function is that it will only show the branch name when you're inside of a directory tree that is a Git working dir.

2. Shorten the working directory path

Now that we've added branch information, maybe the length of our prompt is becoming a concern. But I want to see more than just the current working directory that \W provides. I want to see the parent of the current dir also, at least. Let's see what we can find, maybe something at Stack Overflow...

Ah ha! Look:

Bash: custom PS1 with nice working directory path

Where you'll find a gnarly-but-nifty bit of code to truncate the path cleanly, to give us:

scarpent@bigmachine:~/tmp/.../many/dirs$

I like seeing that first directory also. This one has some more code substitution and quoting going on, so let's break things down a bit:

git_branch='$(__git_ps1 "(%s) ")'

trunclen=20
# This is a LONG line that I didn't want to break up here.
# I hope it copies and pastes nicely for you.
truncated_path='$(echo -n "${PWD/#$HOME/~}" | awk -F "/" '"'"'{if (length($0) > '"$trunclen"') { if (NF>4) print $1 "/" $2 "/.../" $(NF-1) "/" $NF; else if (NF>3) print $1 "/" $2 "/.../" $NF; else print $1 "/.../" $NF; } else print $0;}'"'"')'

# I broke trunclen out, for "truncated length," to call out
# where you can adjust the amount of shortening. Now let's
# get it into PS1 by way of an intermediate code sub:

path='$(eval "echo $truncated_path")'

PS1=${git_branch}"\u@\h:"${path}"$ "

3. Making it pretty

I once eschewed prompt coloring as unneeded ornamentation, but I've found I like it now. It sets off the command line from the resulting output, and it is visually appealing. (And in the final tip below, we'll introduce some variability to our color scheme for differentiating our local machine from remote hosts, providing even more utility.)

ANSI escape sequences enable colors in your terminal, but they introduce a forest of slashes and brackets. Let's break things down even further. (If you're concerned about the growing length of your shell prompt code, just split it out into another file, as I've done. There's no reason our bash profiles can't experience some personal growth. Mine has a twitter account, for example.)

Here's a set of colors that works in my Mac terminal:

     s="\[33"       # color start
    nc="$s[0m\]"    # no color
   red="$s[0;31m\]"
 green="$s[0;32m\]"
yellow="$s[0;33m\]"
  blue="$s[0;34m\]"
purple="$s[0;35m\]"  
  cyan="$s[0;36m\]"
 white="$s[1;37m\]"

And then if you feel so inclined, you can mark up all of your prompt components separately before assembling them:

git_branch=${purple}'$(__git_ps1 "(%s) ")'
      user=${red}"\u"
        at=${white}"@"
      host=${blue}"\h"
     colon=${green}":"
      path=${cyan}'$(eval "echo ${truncated_path}")'
    prompt=${yellow}"$ "

# make sure to turn off coloring at the end with ${nc}!
PS1=${git_branch}${user}${at}${host}${colon}${path}${prompt}${nc}

There are more things you can include in your prompt, like bash history numbers and dates and just about anything you can think of, but let's try staying on the brighter side of sanity. For something less psychedelic, I use:

git_branch=${blue}'$(__git_ps1 "(%s) ")'
      host=${green}"\h:"
      path=${purple}'$(eval "echo ${truncated_path}")'"$ "

PS1=${git_branch}${host}${path}{$nc}

(I've determined I don't need to see my username on the prompt, but I do want to see the host.)

For all that work, I'm treated to this soothing landscape:

shell-prompt

It's almost as if Bob Ross painted it.

4. Remembering where you are

Even though the host name is right there in the prompt, I've colored my remote prompts differently, as an extra reminder that I'm not on my local machine. For that I rely on behavior of the "who am i" command. I've observed that the output has parentheses only when logged in remotely, allowing this kind of thing:

if [[ -n "$(who am i | grep \()" ]]; then
    host=${red}"\h:"
    path=${white}'$(eval "echo ${truncated_path}")'"$ "
else
    host=${green}"\h:"
    path=${purple}'$(eval "echo ${truncated_path}")'"$ "
fi

We're really engaging all the senses here, aren't we? Well, not really. Not yet. Next week I'll share with you how to incorporate smell and taste into your bash prompt.

Putting it all together, at long last, but promptly:

A Shell Prompt

# A functional AND decorative shell prompt

     s="\[33"       # color start
    nc="$s[0m\]"    # no color
   red="$s[0;31m\]"
 green="$s[0;32m\]"
yellow="$s[0;33m\]"
  blue="$s[0;34m\]"
purple="$s[0;35m\]"  
  cyan="$s[0;36m\]" # we could remove or comment out
 white="$s[1;37m\]" # unused colors, of course...

# shorten working directory path
trunclen=20
truncated_path='$(echo -n "${PWD/#$HOME/~}" | awk -F "/" '"'"'{if (length($0) > '"$trunclen"') { if (NF>4) print $1 "/" $2 "/.../" $(NF-1) "/" $NF; else if (NF>3) print $1 "/" $2 "/.../" $NF; else print $1 "/.../" $NF; } else print $0;}'"'"')'

# "who am i" is a check to see if logged in over ssh
if [[ -n "$(who am i | grep \()" ]]; then
    host=${red}
    path=${white}
else
    host=${green}
    path=${purple}
fi
host+="\h:"
path+='$(eval "echo ${truncated_path}")'"$ "

git_branch=${blue}'$(__git_ps1 "(%s) ")'

PS1=${git_branch}${host}${path}${nc}

export PS1

Scott Carpenter was first introduced to programming in 1981 when Scott's dad, an electrical engineer, gave him his first computer to encourage his interest in programming. It worked – in 1998 Scott graduated from St. Cloud State University with his Bachelor of Science in business computer information systems. Scott went on to work for Cargill for 15 years as a Software Developer where he focused on application integration, integration design and development. In 2013, Scott’s journey brought him to The Nerdery where he puts his technical expertise to use as a PHP, WordPress and Java developer.

Published on 08/17/2016

Share with friends
Software Engineer (Java)
Viewing Comments
comments powered by Disqus

Get in Touch

Want to find out if The Nerdery is the right partner for you? We'd love to talk with you. Start the conversation or learn how to submit an RFP through the form linked below.
Contact Us