【问题标题】:Count length of user-visible string for zsh prompt计算 zsh 提示的用户可见字符串的长度
【发布时间】:2012-05-12 13:49:48
【问题描述】:

我想将我当前的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 提示符而不是提示符转义序列的字符?

【问题讨论】:

    标签: zsh


    【解决方案1】:

    假设提示转义的字符串存储在变量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~ 确保我们定义为 '%([BSUbfksu]|([FB]|){*})'zero 被视为模式而不是纯字符串。

    2. ${(S%%)FOO//$~zero/}:这匹配${name//pattern/repl}

      用字符串repl替换参数名扩展中pattern的最长可能匹配

      请注意,我们没有repl;我们将pattern 的最长匹配项替换为空,从而将其删除。
      (S%%)FOOFOO 进行扩展,并设置了几个标志。我不太明白。

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

    【讨论】:

    • (S) 使匹配成为非贪婪的,从而将“最长可能匹配”变成“最短匹配”(如果没有它 {*} 在模式中将把 %F{blue}%M%F{yellow}%#%f 之类的东西变成 %# , 虽然它应该把它变成%M%#),(%%) 对字符串执行提示扩展,遵循 PROMPT_* 选项。注意:如果 PROMPT 字符串包含具有某些副作用的命令,则应避免使用此方法:例如,如果您想使用它来计算提示显示的频率。大多数情况下,您不会因此而受苦。
    • 是的,所有(*) 标志都在man zshexpn 的参数扩展部分中描述。
    • @ZyX 谢谢。我在zshexpn 页面中看到了S 的解释,但不确定它是如何适应的。
    • 不适用于日期格式,例如%D{%a %b %d, %I:%M:%S%P}
    • @beardtree 是的。但是该日期格式返回的字符串将不包含特定于提示的字符(例如颜色代码)。您可以使用date='%D{%a %b %d, %I:%M:%S%P}', length=${#${date}}} 计算它。
    【解决方案2】:

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

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

    例如

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

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

    echo $#plain_str
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-11
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多