Coloring the CLI Prompt

I discovered something that I would like to share.

Since most systems today support color (xterm-color, vt100-color, vt102-color, vt220-color, mv100, etc...), I did some experimenting and was able to get a color prompt using ksh(1) (It's shells/pdksh from the ports.).

First step is to get the ANSI color codes which can be found here.

Next is to tailor your prompt. In vi, I used <CTRL>-V and then hit <ESC> to generate a literal 0x1B character. So to get a blue foreground color, you would do <CTRL>-V<ESC>[34m. With this, my PS1 assignment looks like this:

Code:
PS1='^[[32m$HOSTNAME^[[37m:^[[33m$PWD^[[31m ! ^[[35m\$\$\$ ->^[[0m'
Since different shells have different requirements, you will need to experiment to see what your shell requires. I put this line in my ~/.profile and it works like a charm.

One more thing, you cannot just mouse copy the above code into your prompt and expect it to work. You MUST do the <CTRL>-V <ESC> sequence to generate the ^[ character, otherwise it's just a carat and a opening bracket.
 
My choice.

In .cshrc I've got:
Code:
set prompt = "\n%{\033[31m%}%/ %{\033[1;33m%}%m%{\033[1;33m%}%% %{\033[0m%} "

For root, a slight change to make things clear:
Code:
set prompt = "\n%{\033[31m%}%/ %{\033[1;34m%}%m%{\033[1;34m%}%# %{\033[0m%} "

On a long screen of multiple commands and outputs, I find it important to see where the prompts were. Without color, and with my eyes, I find that near impossible otherwise. Also, when there's a stack of screens, the one with the root prompt sticks out.
 
Since people are posting their root prompts, I'll share mine:

Code:
PS1='^[[47m^[[30m$HOSTNAME^[[30m:^[[35m$PWD^[[34m ! ^[[31m### ->^[[0m'

This one will stick out because of the [47m code which sets the background to white.
 
This is what my prompt looks like.
 

Attachments

  • Thu Dec 24 01:54:22 EST 2015.png
    Thu Dec 24 01:54:22 EST 2015.png
    140.6 KB · Views: 1,761
Here is mine, not very fancy but it really helps me out with info split up.
Capture.PNG

.cshrc:
Code:
set red="%{\033[1;31m%}"
set blue="%{\033[1;34m%}"
set end="%{\033[0m%}"
...
set prompt = "\n${red}%m:${blue}%~ \n${end}%# "
...
unset red blue end
 
My prompt is a bit more involved I guess. I mainly use shells/zsh now, but wanted to emulate the zsh(1) prompt I'm using for tcsh(1). I kind of succeeded, though there's probably a better way to set this up or at the very least, clean it up.


prompts.png

The image shows from top to bottom:
  1. zsh(1) (user prompt)
  2. tcsh(1) (user prompt)
  3. tcsh(1) (root prompt)
I ended up having to use tcsh(1)'s precmd/postcmd functions to get what I wanted. Since I was using them anyway, I also decided it might be nice to use them to also update the window title as well with the currently running command. If a command is not currently running, it shows the current ${SHELL} environment variable in the title instead as seen above.

I have the following snippets in my .tcshrc file to enable this:

Code:
[...]

if ($?prompt) then
    # Did this because I'm using sc(4) instead of vt(4) due to Nvidia being lazy -
    # and I want a higher console resolution, therefore, no font bling on the console :(
    if ($tty =~ ttyv*) then
        if ($USER == root) then
            set prompt = "%{\033[0;31m%} >>>%{\033[0m%} "
            set rprompt = "[%{\033[0;31m%}%P%{\033[0m%}]"
        else
            set prompt = "%{\033[1;34m%} >>>%{\033[0m%} "
            set rprompt = "[%{\033[0;33m%}%P%{\033[0m%}]"
        endif 
    else
        if ($USER == root) then
            set prompt = "%{\033[0;31m%} ❯❯❯%{\033[0m%} "
            set rprompt = "[%{\033[0;31m%}%P%{\033[0m%}]"
        else
            set prompt = "%{\033[1;34m%} ❯❯❯%{\033[0m%} "
            set rprompt = "[%{\033[0;33m%}%P%{\033[0m%}]"
        endif
    endif

[...]

if ( $?TERM ) then
    switch ( $TERM )
        case xterm*:
        case rxvt*:
        case eterm:
        alias precmd 'printf "\033]0;$TERM ":" ( "tcsh" ) - [`tty | cut -c6-12`] - $USER@$HOST":" $cwd \007" \\
            ; echo "" ; echo "^[[0;40;34m $user^[[0;40;31m"@"^[[0;40;32m$HOST ^[[0;40;36m$cwd ^[[0;30m^[0"'
        alias postcmd 'printf "\033]0;$TERM ":" ( \!# ) - [`tty | cut -c6-12`] - $USER@$HOST":" $cwd \007"'
        breaksw

        case screen*:
        alias precmd 'printf "\033]0;[`tty | cut -c6-12`] - $USER@$HOST":" $cwd \007" \\
            ;  echo "" ; echo "^[[0;40;34m $user^[[0;40;31m"@"^[[0;40;32m$HOST ^[[0;40;36m$cwd ^[[0;30m^[0"'
        alias postcmd 'printf "\033]0;[`tty | cut -c6-12`] - $USER@$HOST":" $cwd \007"'
        breaksw

        default:
        alias cwdcmd ''printf "\033]0;[`tty | cut -c6-12`] - $USER@$HOST":" $cwd \007"''
        breaksw
    endsw
endif
 
In vi(1), I used <CTRL>-V and then hit <ESC> to generate a literal 0x1B character.
No need to torture us with vi(1) and literal escape characters. This can be copy-pasted:

ksh:
PS1=`echo -e '\033[32m$HOSTNAME\033[37m:\033m$PWD\033[31m ! \033[35m\$\$\$ ->\033[0m'`

bash(1):
PS1="\e[32m\H\e[37m:\em\w\e[31m \# \e[35m$$\$"

sh(1), but without the current command number:
cd () { chdir "$@" && PS1=`echo -e "\e[32m$HOST\e[37m:\em$PWD\e[31m \e[35m$$$ ->\e[0m"`; } && cd .

tcsh(1), but without the shell process number:
set prompt = '%{\033[32m%}%M%{\033[37m%}:%{\033m%}%/%{\033[31m%} %! %{\033[35m%}$ ->%{\033[0m%} '

Programmatically figuring out whether your current terminal supports all the codes you want to use is a bit more difficult. Here's what I do in my .cshrc (because I'm trying to maintain csh(1) compatibility as well):

Code:
    ### plain prompts; usually overridden below
    if ($?tcsh) then
        set prompt = "[%m] %t %c %# "
        set symlinks = chase    # in prompt, use real directory name, not symlink
        set noding              # in prompt, don't say "DING!" at the top of the hour
    else
        set mch = `hostname -s`
        set prompt = "${mch:q}: {\!} % "
    endif

    ### if terminal supports ANSI text formatting reset (of bold, underline, etc.)
    if ({ ( tput me >& /dev/null || tput sgr0 >& /dev/null ) }) then

        ### if terminal supports setting ANSI foreground color (thus, ANSI color codes in general)
        if ({ ( tput AF 37 >& /dev/null || tput setaf 37 >& /dev/null ) }) then
            if ($?tcsh) then
                ### use fancy tcsh prompt with bold, underline, and color
                set prompt = "%{\033[0m\033[1;30m%}%U[%m] %t%u %B%{\033[33m%}%c%b %# "
            endif
        else
            ### use fancy tcsh prompt with bold & underline but without color
            if ($?tcsh) set prompt = "%U[%m] %t%u %B%c%b %# "
       endif
    endif
(In my real .cshrc I do other color stuff besides setting the prompt; I'm just showing the prompt stuff here.)

Another test I use, not shown here, is if ({ (termname | fgrep -q 256color) }) so I can know whether it's OK to use extended color codes (the ones with ";5;nnn"). I use the csh(1)/tcsh(1) builtin termname because $TERM could refer to an unsupported terminal type, in which case no codes would work (presumably).
 
All I know is I have been saved many times by <Esc> :q <Enter> :)

How do I nominate this thread to be moved to the Howtos and FAQs forum?
 
Back
Top