How to show git status information on the right side of the terminal?

Do you know if you can configure the bash prompt to show git status / branch information on the right side, how can zsh do this? This random screen shot of the Internet shows what I mean.

Screen shot showing git status on the right side

+7
source share
4 answers

Try the following:

PS1='$(printf "%*s\r%s" $(( COLUMNS-1 )) "[$(git branch 2>/dev/null | grep '^*' | sed s/..//)] $(date +%H:%M:%S)" " heipei@wavefront :$PWD$ ")' 

Note that you will never get behavior that exactly matches only zsh with bash. In the above case, I see the following differences:

  • The right part of the invitation is not cleared when the command is executed ( accept-line event in terms of zsh).
  • The correct part of the prompt will be deleted if you type something, then press <Cu> or <BS> .
  • The correct part of the invitation will not be restored if you type something above it, and then delete the text.
  • The correct part of the tooltip will not disappear if you type something on top of it, although the text in this part will be overwritten.
+9
source

Today I built something similar as follows. Thorough testing has not yet been done ...

 preprompt() { rc=$? c=31 [ $rc -eq 0 ] && c=32 PS1="\[$(color $c)\]$rc\[$(color 0)\] \t \w \$ " # right "prompt" # We cannot use $COLUMNS here, since in new shells the first prompt # will get garbled then. Seems like the correct value of COLUMNS is # in the shell init. printf "%`tput cols`s`tput cr`" "${USER}@${HOST}" } PROMPT_COMMAND=preprompt 
+1
source

In the code below, an invitation will be created that looks like this:

bash enter git status on the right

This is a non-trival to do this in bash because of:

  • The read line mode line processes characters before the prompt is printed , which means that in some cases printf solutions will not work. Because of this:
  • Delete all ANSI CSI codes (e.g. colors) to correctly calculate the length of the printed right pointer
  • The need to use __git_ps1 to solve git edge cases
  • __git_ps1 only displays color in certain circumstances and only inside $PS1
  • Color resolution in __git_ps1 output when removing \[ and \] characters from its output (which cannot be nested)
  • Wrap the entire RHS request in \[ and \] to make sure the prompt doesn't do weird things when viewing / editing / completing commands

 #!/bin/bash # _options=$(shopt -op); set -exu # Save and set shell options for testing ################## # Set the prompt # Sourced from .bashrc ################## # Select git info displayed, see /usr/lib/git-core/git-sh-prompt for more export GIT_PS1_SHOWCOLORHINTS=1 # Make pretty colours inside $PS1 export GIT_PS1_SHOWDIRTYSTATE=1 # '*'=unstaged, '+'=staged export GIT_PS1_SHOWSTASHSTATE=1 # '$'=stashed export GIT_PS1_SHOWUNTRACKEDFILES=1 # '%'=untracked export GIT_PS1_SHOWUPSTREAM="verbose" # 'u='=no difference, 'u+1'=ahead by 1 commit export GIT_PS1_STATESEPARATOR='' # No space between branch and index status export GIT_PS1_DESCRIBE_STYLE="describe" # Detached HEAD style: # describe relative to older annotated tag (v1.6.3.1-13-gdd42c2f) # contains relative to newer annotated tag (v1.6.3.2~35) # branch relative to newer tag or branch (master~4) # default exactly eatching tag # Sets prompt like: # ravi@boxy :~/prj/sample_app[exit]$ master*% u= | 30 Apr 22:27 _set_bash_prompt() { # Set left hand side of the prompt PS1="\ u@ \h:\w\$ " # # Git status # # Save current state of user shopt settings promptvars and extglob local user_shopt user_shopt=$(shopt -p promptvars extglob) # __git_ps1 usually returns literal text "${__git_ps1_branch_name}" rather # than the contained branch name, eg "master". This prevents calculating # the length of the printable characers in the RHS string (used to move the # cursor that many columns left from the terminal right edge.) However if # "shopt promptvars" is unset, __git_ps1 it will include the dereferenced # branch name instead. shopt -qu promptvars # extglob is required for the ${variable//@(pattern)/} replacements shopt -qs extglob # Allow disabling git status and no error if __git_ps1 undefined if [[ ! -v _disable_git_prompt && $(type -t __git_ps1 2>/dev/null) == function ]]; then # __git_ps1 will only make pretty colours inside $PS1 local old_PS1=$PS1 __git_ps1 "" "" "%s" # force colour; no default round bracket (decorations) # Strip "\[" and "\[": non-printable character markers. __git_ps1 outputs # them however the whole of the RHS prompt needs to be included in these # markers, and they can't be nested. git=${PS1//@(\\@(\[|\]))/} PS1=$old_PS1 fi # # Right hand side of prompt # local rhs="" # String to be printed on the right hand side of terminal # Create a string like: "25 Apr 13:15" local date_time printf -v date_time "%(%e %b %H:%M)T" -1 # -1 is current time # Format the RHS prompt [[ -n $git ]] && rhs="$git | " #" rhs+="\e[0;1;31m${date_time}" # Strip ANSI CSI commands (eg colours) to enble counting the length of # printable characters, giving offset of cursor from terminal RHS edge (from # https://www.commandlinefu.com/commands/view/12043/remove-color-special-escape-ansi-codes-from-text-with-sed) # Neither bash not sed support lookbehind zero-length assertions, so it not # possible to ignore "\\e", (ie a literal '\' followed by a literal 'e'), yet # still remove "\e" (ie ESC) local rhs_printable=${rhs//@(\\@(\[|]|[Ee]\[*([0-9;])[a-zA-Z]))/} # or, in using sed (but requires exec): # local rhs_printable=$(sed -e 's,\\[][]\|\\[Ee]\[\([0-9;]\)*[A-Za-z],,g' <<< "$rhs") # Reference: https://en.wikipedia.org/wiki/ANSI_escape_code local Save='\e[s' # Save cursor position local Rest='\e[u' # Restore cursor to save point # Save cursor position, jump to (right hand edge minus N columns) where N is # the length of the printable RHS string. Print the RHS string, then return # to the saved position and print the LHS prompt. # Note: "\[" and "\]" are used so that bash can calculate the number of # printed characters so that the prompt doesn't do strange things when # command line editing/browsing/completion. Ensure that these are not nested. PS1="\[\e[0m${Save}\e[$((COLUMNS - ${#rhs_printable}))G${rhs}${Rest}\]${PS1}" eval "$user_shopt" } # eval "$_options"; unset _options # Restore previous shell options from line 2 
+1
source

One way is to use tput to count the columns of your terminal and subtract the number of characters that will be printed left and right, and then use this number as the number of spaces between the left and right text. Use printf to build a string.

quick example:

 left="[${status}]\ u@ \h:\w\$ " right="$(git symbolic-ref HEAD) $(date +%T)" spaces="$(( $(tput cols) - ${#left} - ${#right} ))" export PS1="$(printf "%s%${spaces}s\n" "$left" "$right")" 
0
source

All Articles