Allow __git_ps1 to be used in PROMPT_COMMAND
authorSimon Oosthoek <s.oosthoek@xs4all.nl>
Wed, 10 Oct 2012 19:31:58 +0000 (21:31 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 11 Oct 2012 18:26:14 +0000 (11:26 -0700)
Changes __git_ps1 to allow its use as PROMPT_COMMAND in bash
in addition to setting PS1 with __git_ps1 in a command substitution.
PROMPT_COMMAND has advantages for using color without running
into prompt-wrapping issues. Only by assigning \[ and \] to PS1
directly can bash know that these and the enclosed zero-width codes in
between don't count in the length of the prompt.

Signed-off-by: Simon Oosthoek <s.oosthoek@xs4all.nl>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/completion/git-prompt.sh

index bf20491ec33e467f6b9591d94a2e27bc9e3d93e9..ce67eb75a4f702a976000a94c087678f9a6d7827 100644 (file)
 #    1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).
 #    2) Add the following line to your .bashrc/.zshrc:
 #        source ~/.git-prompt.sh
-#    3) Change your PS1 to also show the current branch:
-#         Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
-#         ZSH:  PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
+#    3a) In ~/.bashrc set PROMPT_COMMAND=__git_ps1
+#        To customize the prompt, provide start/end arguments
+#        PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
+#    3b) Alternatively change your PS1 to call __git_ps1 as
+#        command-substitution:
+#        Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
+#        ZSH:  PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
+#        the optional argument will be used as format string
 #
 # The argument to __git_ps1 will be displayed only if you are currently
 # in a git repository.  The %s token will be the name of the current
@@ -195,11 +200,39 @@ __git_ps1_show_upstream ()
 
 
 # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
-# returns text to add to bash PS1 prompt (includes branch name)
+# when called from PS1 using command substitution
+# in this mode it prints text to add to bash PS1 prompt (includes branch name)
+#
+# __git_ps1 requires 2 arguments when called from PROMPT_COMMAND (pc)
+# in that case it _sets_ PS1. The arguments are parts of a PS1 string.
+# when both arguments are given, the first is prepended and the second appended
+# to the state string when assigned to PS1.
 __git_ps1 ()
 {
+       local pcmode=no
+       #defaults/examples:
+       local ps1pc_start='\u@\h:\w '
+       local ps1pc_end='\$ '
+       local printf_format=' (%s)'
+
+       case "$#" in
+               2)      pcmode=yes
+                       ps1pc_start="$1"
+                       ps1pc_end="$2"
+               ;;
+               0|1)    printf_format="${1:-$printf_format}"
+               ;;
+               *)      return
+               ;;
+       esac
+
        local g="$(__gitdir)"
-       if [ -n "$g" ]; then
+       if [ -z "$g" ]; then
+               if [ $pcmode = yes ]; then
+                       #In PC mode PS1 always needs to be set
+                       PS1="$ps1pc_start$ps1pc_end"
+               fi
+       else
                local r=""
                local b=""
                if [ -f "$g/rebase-merge/interactive" ]; then
@@ -285,6 +318,12 @@ __git_ps1 ()
                fi
 
                local f="$w$i$s$u"
-               printf -- "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p"
+               if [ $pcmode = yes ]; then
+                       PS1="$ps1pc_start("
+                       PS1="$PS1$c${b##refs/heads/}${f:+ $f}$r$p"
+                       PS1="$PS1)$ps1pc_end"
+               else
+                       printf -- "$printf_format" "$c${b##refs/heads/}${f:+ $f}$r$p"
+               fi
        fi
 }