9

My terminal has a default prompt format like this one:

username@boxname /path/to/current/directory $

The code that produces it looks like this: (it has some color definitions too)

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\]'

If the path to the current directory gets too long it becomes unpleasant to work with the terminal because you constantly break lines. In such cases I would prefer a format that produces a shorter string like this one:

username@boxname current_dir_name $

The code that produces it would look like this (again with color):

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] $(basename ${PWD}) \$ \[\033[00m\]'

Does anyone know how I could easily toggle the format of the current terminal window from one style to the other by just typing for example: prompttoggle?

heemayl
  • 91,753
Rotareti
  • 559
  • 6
    Are you aware of bash's PROMPT_DIRTRIM parameter? – steeldriver Sep 07 '16 at 22:41
  • @steeldriver not until now. Toggling between PROMPT_DIRTRIM=0 and PROMPT_DIRTRIM=1 seems simpler than toggling between different values for PS1 and the result is almost the same. Thanks for the info! – Rotareti Sep 07 '16 at 23:41
  • Using PROMPT_DIRTRIM one could also add arguments to the command. If you pass no argument you toggle between PROMPT_DIRTRIM=0 and PROMPT_DIRTRIM=1 and if you pass a number as an argument you set PROMPT_DIRTRIM to it. promptlen would be a more appropriate name for the command then. – Rotareti Sep 07 '16 at 23:47

5 Answers5

10

Store both your long and short PS1 variables under a different name:

PS1short='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\]'
PS1long='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] $(basename ${PWD}) \$ \[\033[00m\]'

Make sure to set PS1to one of them initially:

PS1="$PS1long"

Then you can make an alias like this to toggle between the two PS1 values:

alias prompttoggle='if test "$PS1" = "$PS1long" ; then PS1="$PS1short" ; else PS1="$PS1long" ; fi'

Adding all four lines to your ~/.bashrc file will ake the command available in your Bash sessions, here are they again for easier copying:

PS1short='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\]'
PS1long='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] $(basename ${PWD}) \$ \[\033[00m\]'
PS1="$PS1long"
alias prompttoggle='if test "$PS1" = "$PS1long" ; then PS1="$PS1short" ; else PS1="$PS1long" ; fi'
Byte Commander
  • 107,489
7

You can use a tiny bash function:

prompttoggle () { 
    if [[ $PS1 = *basename* ]]; then 
        export PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\]'
    else 
        export PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] $(basename ${PWD}) \$ \[\033[00m\]'
    fi ;}

The function above matches if the current $PS1 contains basename, if yes, then the PS1 without basename is set otherwise the one with basename is set.

Put the function in your ~/.bashrc to get it available in all interactive sessions.

Example:

foo@bar:~/spam/egg$ prompttoggle () { 
>     if [[ $PS1 = *basename* ]]; then 
>         export PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\]'
>     else 
>         export PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] $(basename ${PWD}) \$ \[\033[00m\]'
>     fi ;}

foo@bar:~/spam/egg$ prompttoggle 

foo@bar egg $ prompttoggle

foo@bar ~/spam/egg $
heemayl
  • 91,753
5

Or... make two very tiny functions and add to the end of your ~/.bashrc

# short prompt
promptshort() { export PS1=$(echo "$PS1" | sed 's/\\w/\\W/g') ; }

# full length prompt
promptlong() { export PS1=$(echo "$PS1" | sed 's/\\W/\\w/g') ; }

for a shortened prompt, type promptshort, to go back to the full path, type promptlong

\W shows the current working directory only so $(basename ${PWD}) is overkill imho

You could combine into one function but "long" and "short" are descriptive and both have less keystrokes than "toggle" ;)

Instead of adding a line to override PS1 I prefer to tweak the code that sets it (for example, uncomment force_color_prompt=yes and edit the line after [ "$color_prompt" = yes ]; then)

Zanna
  • 70,465
3

Here's a ~/.bashrc function definition that I personally use to reset/toggle my prompt from regular prompt to just $. Adapt it as necessary to suit your needs.

resetps() {
    if [ "$PS1" = "$ " ] 
    then
        PS1=$OLDPS1 
    else
        OLDPS1=$PS1 
        export OLDPS1 
        PS1="$ " 
    fi 
} 
Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
1

This is an answer to your problem (long directories break the command line) and not specifically to your question (how to change the command prompt on the fly.)

I solved this problem years ago with this prompt:

PS1='\[\e[32;1m\]$? \u@\h \[\e[35;1m\]\w\[\e[m\]\n\$ '
#    └──green───┘         └──purple──┘  └─norm─┘

What this does:

  1. output the exit value of the previous command (this is incredibly useful)
  2. output the current user and host in one color
  3. output the working directory in another color (adjust the colors to your taste)
  4. output the dollar and space on a new line, ending the color sequences before the line break

This gives you all the space you need for your command, does not shift it right when you are in a deep directory structure, does not mangle the typing line with color codes (avoiding strange bugs that happen sometimes), while still giving you the colored hint on where the output of one command ended and the next one begun:

enter image description here

Tobia
  • 575
  • 2
  • 5
  • 15