Yet Another Neat $PS1 Prompt for Bash
(With google returning more than a million hits for the search “bash PS1”, it may be a little presumptive that I have anything to add to the conversation, but this was an interesting exercise for me, so I’ll share it anyways. Besides this may actually be my most nitpicky *nix nerd post yet.)
Here’s my brand new … super-duper space-saving, non-forking, color-changing PS1 prompt (that doesn’t mess up readline!)
export PS1='[\[\e[$(((($?>0))*31))m\]\h:\W\[\e[00m\]]\$ 'I happened across a blog post (8 Useful and Interesting Bash Prompts) covering different PS1 prompts that people are using. I hadn’t thought of it before, but the first prompt ”Show Happy face upon successful execution“ caught my attention because I write a lot of scripts, and of those many are used by other programs–so return codes are important, and not something I always remember to check. I hadn’t thought of it before, but I liked the idea! Anyways, it got me thinking about how it works … a lot of the fancy PS1 formulas you see out there are running several commands (even if it isn’t obvious–generally if a bracket or tick is involved, there’s a subshell forking out.) When your system is grinding to a halt, every fork counts. So I don’t like the idea of running an additional shell script every time I press enter. So, the example that Joshua Price provides, while really cool, adds extra forks every time you hit the return key. This is pretty easy to demonstrate using bash’s “set -x” command:

PS1='[\h:\W]\$ 'I like it because it tells me what host I’m on, the short directory name, and whether or not I’m root. I like compact, and this is nice because I wrap lines less often. That’s what I want it to look like when I’m done (smileys are a cool novelty, but it’s extraneous, I only want useful information in a compact form.) So, this is what I came up with …
PS1='[\[\e[$(((($?>0))*31))m\]\h:\W\[\e[00m\]]\$ 'And before I dissect what it does, let’s compare “forkiness” … (and see how it looks too.)

[tag:~]$ true; echo $(( (( $? > 0 )) * 31 )) 0 [tag:~]$ false; echo $(( (( $? > 0 )) * 31 )) 31It’d be easy to do green and red, or other color combinations too, it’s just basic math at that point. The rest is pretty simple. Where you see \[ or \] those are actually escape sequences for readline! Readline counts the number of characters present and uses that to determine where to place the cursor; ANSI escape sequences get counted too, and the escapes specify that the enclosed section shouldn’t be counted. Without those escapes, long lines get weird when you edit them, text doesn’t get overwritten in the right places, and your cursor appears in the wrong place with no obvious way to position it correctly. In other words, things get a little weird. Then the colors … \e[31m will change the foreground color to red, and \e[0m will return it to the terminal’s default. So near the end of the prompt, we always reset back even if not needed.