由于zsh中的date命令,多行提示格式错误

时间:2015-11-21 04:16:58

标签: zsh zshrc

我的.zshrc中有以下内容:

setopt PROMPT_SUBST
precmd(){
  echo""
  LEFT="$fg[cyan]$USERNAME@$HOST $fg[green]$PWD"
  RIGHT="$fg[yellow]$(date +%I:%M\ %P)"
  RIGHTWIDTH=$(($COLUMNS-${#LEFT}))
  echo $LEFT${(l:$RIGHTWIDTH:)RIGHT}
}
PROMPT="$ "

这为我提供了以下屏幕截图enter image description here

即使调整大小,右侧的时间部分也始终不会一直到终端的边缘。我认为这是由于$(date +%I:%M\ %P)任何人都知道如何解决这个问题?

编辑:放大屏幕截图

1 个答案:

答案 0 :(得分:2)

虽然您的想法值得称赞,但您遇到的问题是LEFTRIGHT包含ANSI转义序列(对于颜色),它应该是零宽度字符,但仍然计入如果你天真地使用$#name${(l:expr:)name},那么字符串的长度。

另外,作为一种风格问题,你最好使用Zsh的内置prompt expansion,它包含了许多常见的东西,人们可能希望在短促的百分比转义序列中看到它们。特别是,有内置的颜色序列,因此您不需要依赖非标准$fg[blah]

下面是以我喜欢的编码风格写的提示的近似值...不完全是,我把一切都变得非常冗长以便可以理解(希望如此)。在剥离颜色的转义序列并执行快速扩展之后计算左前预装件和右前装工件的长度,这给出了正确的显示长度(我不可能在几分钟内将其甩掉;我将表达式从pure中撕掉)

precmd(){
    local preprompt_left="%F{cyan}%n@%m %F{green}%~"
    local preprompt_right="%F{yellow}%D{%I:%M %p}%f"
    local preprompt_left_length=${#${(S%%)preprompt_left//(\%([KF1]|)\{*\}|\%[Bbkf])}}
    local preprompt_right_length=${#${(S%%)preprompt_right//(\%([KF1]|)\{*\}|\%[Bbkf])}}
    local num_filler_spaces=$((COLUMNS - preprompt_left_length - preprompt_right_length))
    print -Pr $'\n'"$preprompt_left${(l:$num_filler_spaces:)}$preprompt_right"
}

PROMPT="$ "

编辑:在某些终端模拟器中,精确打印$COLUMN个字符可能会包裹该行。在这种情况下,用

替换相应的行
local num_filler_spaces=$((COLUMNS - preprompt_left_length - preprompt_right_length - 1))

编辑结束。

这是非常可定制的,因为您可以在preprompt_leftpreprompt_right中放置几乎任何内容并仍然获得正确的长度 - 只需记住对零宽度序列使用提示转义序列,例如{{1对于颜色,%F{}%f表示粗体等。再次,阅读有关提示展开的文档:http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html

注意:您可能会注意到%B%b扩展为%D{%I:%M %p}之类的内容。这是因为我想使用11:35 PM来获取%P,但不是pm的每个实现都支持strftime。最糟糕的情况:如果您确实需要小写但不支持%P,请使用原始命令代理%P

此外,我使用$(date +'%I:%M %P')代替%~,因此您将获得%/而不是~/Desktop。有些人喜欢,有些则不喜欢。但是,正如我所说,这很容易定制。