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

3

以下是我.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
请将您的屏幕截图裁剪到仅包含终端(现在如果不放大很难看到问题),无论您的背景有多漂亮... - 4ae1e1
1个回答

4
虽然您的想法值得赞扬,但您遇到的问题是您的LEFTRIGHT包含ANSI转义序列(用于颜色),这些序列应该是零宽字符,但如果您天真地使用$#name${(l:expr:)name},它们仍然会被计算为字符串的长度。
此外,从风格上讲,最好使用Zsh的内置提示扩展,它将许多人们可能想在其提示中看到的常见内容包装在短百分号转义序列中。特别是,有内置的颜色序列,因此您不需要依赖非标准的$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中放入任何东西,仍然可以得到正确的长度 - 只需记住使用提示转义序列用于零宽度序列,例如,%F{}%f表示颜色,%B%b表示粗体等。再次阅读有关提示扩展的文档:http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html

注意:您可能会注意到%D{%I:%M %p}扩展为像11:35 PM这样的内容。那是因为我想使用%P来获取pm,但并不是每个strftime实现都支持%P。最坏的情况是:如果您真的想要小写但不支持%P,请使用原始命令替换$(date +'%I:%M %P')

此外,我使用%~而不是%/,这样你会得到~/Desktop而不是/c/Users/johndoe/Desktop。有些人喜欢,有些人不喜欢。然而,正如我所说,这很容易自定义。

非常感谢!我不在乎上午/下午的大小写,实际上更喜欢大写字母(我的系统时钟使用大写字母)。但是有一件事情需要注意,由于某些原因它打印了太多空格,结果导致换行。你知道是什么原因吗? - Lord_Zane 55
@Lord_Zane55 嗯,这有点奇怪,但我模糊地记得在 Windows cmd 和 PowerShell 上打印 $COLUMN 个空格会换行(当我开发一些 Python 库时)。你能否尝试将 num_filler_spaces 的定义替换为 local num_filler_spaces=$((COLUMNS - preprompt_left_length - preprompt_right_length - 1)),看看是否有所帮助?如果没有,请提供一个新的截图,并在函数末尾添加 print $COLUMNS $preprompt_left_length $preprompt_right_length $num_filler_spaces,并向我展示您得到的数字? - 4ae1e1
运行完美!非常感谢!另外,%~ 无法使用,因为我在使用 cywgin(很遗憾这是在 Windows 上获取 zsh 的唯一方式)。路径实际上是 /cygdrive/c/...。我正在尝试弄清楚如何将 /c/users/lord_zane 替换为 ~,我可能会调用一个 Python 脚本,因为 re 模块会使它变得非常容易。 - Lord_Zane 55
顺便说一句,我认为你看到的包装行为可能是由于光标。有ANSI转义序列来隐藏和显示光标,但这更麻烦,所以如果你不在意一个悬挂的空格(存在吗?),那么当前的解决方案就可以了。 - 4ae1e1
没有多余的空间了,加上-1就解决了。它看起来像我的原始截图,但时间在最右边。 - Lord_Zane 55
@Lord_Zane55 很棒,知道了。我担心时间和右边缘之间多了一个空格。 - 4ae1e1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接