计算zsh提示符的用户可见字符串的长度

时间:2012-05-12 13:49:49

标签: zsh

我想将当前的git分支放入我的多行ZSH提示符中。然而,这会弄乱两条线 - 我希望它们很好地排成一行。


┌─(simont@charmander:s000)─[master *]────────────────
───(~  )─┐  
└─(127:15:44)──                       ──(Sat,May12)─┘

应该是:


┌─(simont@charmander:s000)─[master *]─────────(~  )─┐  
└─(127:15:44)──                       ──(Sat,May12)─┘

git分支是从oh-my-zsh函数git_prompt_info()中获取的,它为我提供了分支,脏状态和一堆快速转义功能,可以很好地为事物着色。

如何计算可见插入ZSH提示符的字符 - 而不是提示转义序列?

2 个答案:

答案 0 :(得分:11)

假设提示转义的字符串存储在变量FOO中,这将只计算用户可见的字符:

                                                                                                                                
FOO=$(git_prompt_info)                                                                                                                     
local zero='%([BSUbfksu]|([FK]|){*})'
FOOLENGTH=${#${(S%%)FOO//$~zero/}} 

这来自this .zshrc

这是粗略对其工作原理的解释,从man zshexpnPARAMETER EXPANSION部分引用。我不是100%确定细节,因此,如果您使用它来开发自己的等效内容,请阅读相关的man zshall部分。

FOOLENGTH=${#${(S%%)FOO//$~zero/}}行开始,我们有很多位。从内到外:

  1. $~zero~确保我们定义为zero的{​​{1}}被视为模式而不是普通字符串。

  2. '%([BSUbfksu]|([FB]|){*})':符合${(S%%)FOO//$~zero/}

      

    用字符串repl

    替换参数名称扩展中模式的最长匹配

    请注意,我们没有${name//pattern/repl};我们将repl的最长匹配替换为空,从而删除它  pattern(S%%)FOO上进行扩展,并设置了多个标记。我不太关注它。

  3. FOO:如果${#${(S%%)FOO//$~zero/}}是替换,则${#spec}将替换替换spec结果的字符长度。在我们的例子中,spec是替换spec的结果;所以这基本上返回${(S%%)FOO//$~zero/}上正则表达式s/zero//的结果中的字符长度,其中FOO是上面的模式。

答案 1 :(得分:2)

不确定如何使用内置zsh命令执行此操作,但可以使用sed剥离颜色信息(如文档here所示):

sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"

e.g。

plain_str=$(git_prompt_info | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g")

将从字符串中删除所有转义序列。现在的长度很简单:

echo $#plain_str