[PATCH 1/2] Allow __git_ps1 to be used in PROMPT_COMMAND
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.oosth...@xs4all.nl --- contrib/completion/git-prompt.sh | 51 +- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 29b1ec9..4fbc1e6 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -10,9 +10,14 @@ #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 @@ -194,11 +199,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 @@ -284,6 +317,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 } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] Allow __git_ps1 to be used in PROMPT_COMMAND
Apologies if you receive this e-mail multiple times, my MTA was misconfigured... 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.oosth...@xs4all.nl --- contrib/completion/git-prompt.sh | 51 +- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 29b1ec9..4fbc1e6 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -10,9 +10,14 @@ #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 @@ -194,11 +199,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 @@ -284,6 +317,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 } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] Allow __git_ps1 to be used in PROMPT_COMMAND
Simon Oosthoek s.oosth...@xs4all.nl writes: __git_ps1 () { + local pcmode=no + #defaults/examples: + local ps1pc_start='\u@\h:\w ' + local ps1pc_end='\$ ' + local printf_format='(%s)' + ... This conversion is wrong, given that ... @@ -284,6 +317,12 @@ __git_ps1 () fi local f=$w$i$s$u - printf -- ${1:- (%s)} $c${b##refs/heads/}${f:+ $f}$r$p ... the original has a SP in front. I've tentatively queued a fix-up patch on the topic branch before merging it to 'pu'. + 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 } -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] Allow __git_ps1 to be used in PROMPT_COMMAND
Simon Oosthoek s.oosth...@xs4all.nl writes: changes __git_ps1 to not just allow use in setting PS1 with __git_ps1 in a command substitution, but also allows __git_ps1 to be used as PROMPT_COMMAND in bash. This has advantages for using color and I think it is more elegant Is and I think necessary? I do not think it matters what _you_ think when judging it is worth including in the future releases ;-) A lot more important thing to say is why it has advantages for using color (remember, it took a few rounds of back and forth with me). Unless you are going to explain the same to all the people who are reading the git log output 6 months down the road, that is a more appropriate thing to write here. contrib/completion/git-prompt.sh | 51 +- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 29b1ec9..c50c94a 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -10,9 +10,14 @@ #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 @@ -194,11 +199,41 @@ __git_ps1_show_upstream () # __git_ps1 accepts 0 or 1 arguments (i.e., format string) +# when called from PS1 using command substitution +# in this mode it returns text to add to bash PS1 prompt (includes branch name) or +# __git_ps1 accepts 0 or 2 arguments when called from PROMPT_COMMAND +# 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, otherwise default start/end strings +# are used. Sorry, but I cannot parse this. Is this meant to be a two-item list, one describing the command substitution mode (zero or 1 arguments) and the other describing the prompt command mode? If so, perhaps replacing the or at the end of the first item with .\n#\n would make it readable. __git_ps1 () { + local pcmode=yes + local ps1pc_start='\u@\h:\w ' + local ps1pc_end='\$ ' + + case $PROMPT_COMMAND in + __git_ps1*) + if [ $# = 2 ]; then + ps1pc_start=$1 + ps1pc_end=$2 + fi + case $PS1 in + *__git_ps1*) + echo '__git_ps1: overwriting PS1 due to PROMPT_COMMAND' Is this supposed to be an error and/or warning message? Why is it worth warning only when you are overwriting __git_ps1 style of PS1 and not other user customization? + ;; + esac + ;; + *) pcmode=no ;; #no output + esac Please align outer case its arms) and esac at the same column, like you did for the inner case/esac. Auto-detetction based on PROMPT_COMMAND is a flaky approach. In practice, nobody will call PROMPT_COMMAND with the __git_ps1 without any parameter (100% people want their prompt to end with some sort of whitespace so they want the what comes after what is computed, aka $2), and even more importantly, nobody has been relying on use of 0 argument form of __git_ps1 in PROMPT_COMMAND. So why not always require 2 args and take that as a cue to go into the pc mode? + 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 @@ -284,6 +319,10 @@ __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($c${b##refs/heads/}${f:+ $f}$r$p)$ps1pc_end + elif [ $pcmode = no ]; then + printf -- ${1:- (%s)} $c${b##refs/heads/}${f:+ $f}$r$p +
Re: [PATCH 1/2] Allow __git_ps1 to be used in PROMPT_COMMAND
Hi Junio thanks for your feedback! On 08/10/12 20:12, Junio C Hamano wrote: Simon Oosthoek s.oosth...@xs4all.nl writes: changes __git_ps1 to not just allow use in setting PS1 with __git_ps1 in a command substitution, but also allows __git_ps1 to be used as PROMPT_COMMAND in bash. This has advantages for using color and I think it is more elegant Is and I think necessary? I do not think it matters what _you_ think when judging it is worth including in the future releases ;-) Hmm, right :-P How about This has advantages for using color without running into prompt-wrapping issues. Only by assigning \[ and \] to PS1 directly can bash know these and the color codes in between don't count in the length of the prompt.? I'll rewrite the patch later on... Isn't it confusing that the color codes don't figure in this patch at all? # __git_ps1 accepts 0 or 1 arguments (i.e., format string) +# when called from PS1 using command substitution +# in this mode it returns text to add to bash PS1 prompt (includes branch name) or +# __git_ps1 accepts 0 or 2 arguments when called from PROMPT_COMMAND +# 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, otherwise default start/end strings +# are used. Sorry, but I cannot parse this. Is this meant to be a two-item list, one describing the command substitution mode (zero or 1 arguments) and the other describing the prompt command mode? If so, perhaps replacing the or at the end of the first item with .\n#\n would make it readable. I agree, that would make it more readable. __git_ps1 () { +local pcmode=yes +local ps1pc_start='\u@\h:\w ' +local ps1pc_end='\$ ' + +case $PROMPT_COMMAND in +__git_ps1*) +if [ $# = 2 ]; then +ps1pc_start=$1 +ps1pc_end=$2 +fi +case $PS1 in +*__git_ps1*) +echo '__git_ps1: overwriting PS1 due to PROMPT_COMMAND' Is this supposed to be an error and/or warning message? Why is it worth warning only when you are overwriting __git_ps1 style of PS1 and not other user customization? That's what this is doing, I wasn't able to make it the other way around. I thought that I could detect when PS1 contained __git_ps1 that it shouldn't overwrite the PS1, which worked, but when PROMPT_COMMAND was set with __git_ps1 and PS1=$(__git_ps1) as well, it gave double output. As PROMPT_COMMAND is relatively obscure I thought a warning when overwriting the PS1 was good, but not unless there was a real conflict (double call to __git_ps1). The warning is only shown once. I don't think it would be possible to detect any other kind of customization without including specific code for it. Do you think it's unnecessary to include a warning? (I think it would take people a long time to figure out why their prompt goes whoopsy without getting a hint that PROMPT_COMMAND messes up the PS1) (OTOH, if you configure PROMPT_COMMAND, you're bound to know a little bit about what you're doing...) Perhaps it's better to just do it. +;; +esac +;; +*) pcmode=no ;; #no output +esac Please align outer case its arms) and esac at the same column, like you did for the inner case/esac. ok Auto-detetction based on PROMPT_COMMAND is a flaky approach. In practice, nobody will call PROMPT_COMMAND with the __git_ps1 without any parameter (100% people want their prompt to end with some sort of whitespace so they want the what comes after what is computed, aka $2), and even more importantly, nobody has been relying on use of 0 argument form of __git_ps1 in PROMPT_COMMAND. So why not always require 2 args and take that as a cue to go into the pc mode? That's a good idea, I'll change that. +if [ $pcmode = yes ]; then +PS1=$ps1pc_start($c${b##refs/heads/}${f:+ $f}$r$p)$ps1pc_end +elif [ $pcmode = no ]; then +printf -- ${1:- (%s)} $c${b##refs/heads/}${f:+ $f}$r$p +fi Are there $pcmode other than yes or no? Why not just else, instead of performing the test twice? I forgot to remove that one, I had a default at some point ;-) Cheers Simon. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] Allow __git_ps1 to be used in PROMPT_COMMAND
Simon Oosthoek s.oosth...@xs4all.nl writes: How about This has advantages for using color without running into prompt-wrapping issues. Only by assigning \[ and \] to PS1 directly can bash know these and the color codes in between don't count in the length of the prompt.? I'll rewrite the patch later on... Isn't it confusing that the color codes don't figure in this patch at all? Since the Subject: is allow ... to be used in PROMPT_COMMAND, it very much is relevant to mention that we need to use PROMPT_COMMAND in order to correctly use \[ and \] to generated zero-width escape sequences, which cannot be done by simply setting PS1 to command substitution. color is just an example; if it makes you uneasy to say color, you can say zero-width escape sequences. It could be \007 (BEL) ;-) I don't think it would be possible to detect any other kind of customization without including specific code for it. Do you think it's unnecessary to include a warning? (I think it would take people a long time to figure out why their prompt goes whoopsy without getting a hint that PROMPT_COMMAND messes up the PS1) I think you need your warning _only_ because you attempt to auto-detect it, when you do not have to. (OTOH, if you configure PROMPT_COMMAND, you're bound to know a little bit about what you're doing...) Yup. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] Allow __git_ps1 to be used in PROMPT_COMMAND
changes __git_ps1 to not just allow use in setting PS1 with __git_ps1 in a command substitution, but also allows __git_ps1 to be used as PROMPT_COMMAND in bash. This has advantages for using color and I think it is more elegant Signed-off-by: Simon Oosthoek soosth...@nieuwland.nl --- contrib/completion/git-prompt.sh | 51 +- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 29b1ec9..c50c94a 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -10,9 +10,14 @@ #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 @@ -194,11 +199,41 @@ __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 returns text to add to bash PS1 prompt (includes branch name) or +# __git_ps1 accepts 0 or 2 arguments when called from PROMPT_COMMAND +# 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, otherwise default start/end strings +# are used. __git_ps1 () { + local pcmode=yes + local ps1pc_start='\u@\h:\w ' + local ps1pc_end='\$ ' + + case $PROMPT_COMMAND in + __git_ps1*) + if [ $# = 2 ]; then + ps1pc_start=$1 + ps1pc_end=$2 + fi + case $PS1 in + *__git_ps1*) + echo '[31m__git_ps1: overwriting PS1 due to PROMPT_COMMAND[0m' + ;; + esac + ;; + *) pcmode=no ;; #no output + 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 @@ -284,6 +319,10 @@ __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($c${b##refs/heads/}${f:+ $f}$r$p)$ps1pc_end + elif [ $pcmode = no ]; then + printf -- ${1:- (%s)} $c${b##refs/heads/}${f:+ $f}$r$p + fi fi } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html