I\'d like to put my current git
branch into my multi-line ZSH prompt. However, this messes up the two lines - I\'d like them to line up nicely.
Assuming that the prompt-escaped string is stored in a variable FOO
, this will count only user-visible characters:
FOO=$(git_prompt_info)
local zero='%([BSUbfksu]|([FK]|){*})'
FOOLENGTH=${#${(S%%)FOO//$~zero/}}
This comes from this .zshrc.
This is a rough explanation of why it works, liberally quoting from man zshexpn, section PARAMETER EXPANSION
. I'm not 100% sure of the details, so, if you're using this to develop your own equivalent, read the relevant man zshall
sections.
Working from the line FOOLENGTH=${#${(S%%)FOO//$~zero/}}
, we've got a number of bits. Going from the inside out:
$~zero
: The ~
ensures that zero
, which we've defined as '%([BSUbfksu]|([FB]|){*})'
, is treated as a pattern rather than as a plain string.
${(S%%)FOO//$~zero/}
: This matches ${name//pattern/repl}
:
Replace the longest possible match of pattern in the expansion of parameter name by string repl
Note that we don't have a repl
; we replace the longest possible match of pattern
with nothing, thereby removing it.
(S%%)FOO
conducts an expansion on FOO
with several flags set. I don't quite follow it.
${#${(S%%)FOO//$~zero/}}
: ${#spec}
will substitue the length in characters of the result of the substitution spec
, if spec
is a substitution. In our case, spec
is the result of the substitution ${(S%%)FOO//$~zero/}
; so this basically returns the length of characters in the result of the regular expression s/zero//
on FOO
, where zero
is the pattern above.