如果整个 PROMPT 太长,则提示扩展 ZSH 删除主机名

Prompt Expansion ZSH Remove Hostname if entire PROMPT is too long

目前,我的 zshrc 看起来像这样

setopt prompt_subst # real time reevaluation of prompt
zmodload zsh/mathfunc # int function
function widthHelper() { echo $(( int(${COLUMNS:-80}) * /100)) } # calc % of prompt
outWidth='$(widthHelper 40)'
inWidth='$(widthHelper 90)'
export PROMPT="%F{cyan}%${outWidth}<◀︎<%f" # truncation based on terminal width
PROMPT+="%(l." # inner truncation group
PROMPT+="%F{cyan}%8>‣>%n%>>%f" # username truncated
PROMPT+="%-${inWidth}(l. %F{blue}%5>‣>%m%>>%f.) " # hostname truncated
PROMPT+=".)" # end truncation
PROMPT+="%F{magenta}%1~%f%<< " # pwd 1 depth
PROMPT+="%# " # privilege group

influenced by this questionmy other question

当前按预期工作的内容

  1. 它将主机名和用户名截断为常量值
  2. 它根据 widthHelper() 动态截断整个 PROMPT,这允许我调整终端大小并动态截断 PROMPT

目前,我有这条线在工作,但不是以我想要的方式工作

PROMPT+="%-${inWidth}(l. %F{blue}%5>‣>%m%>>%f.) " # hostname truncated

我想要的

我想让主机名的显示取决于整个PROMPT的长度,而不是在当前终端的宽度上COLUMNS.

即如果我输入一个名称很长的目录,我希望主机名消失 before 我开始截断整个提示。但我确实希望两者都发生 按此顺序

  1. 主机名会消失(这种情况发生但不依赖于 PROMPT 长度,而是依赖于整个终端的宽度,COLUMNS
  2. 整个提示将开始在左侧截断(目前有效

例子

如果我在一个目录中 ~ 然后移动到一个名称很长的目录 ~/abcdefghijklmnopqrstuvwxyzabcd 我希望主机名消失,但是发生的事情是我的提示首先被截断了。

william‣ wmbp‣ ~ %                                                                          
william‣ wmbp‣ ~ % cd abcdefghijklmnopqrstuvwxyzabcd                                        
◀︎m‣ wmbp‣ abcdefghijklmnopqrstuvwxyzabcd %                                                  

我想要的

william‣ wmbp‣ ~ %                                                                          
william‣ wmbp‣ ~ % cd abcdefghijklmnopqrstuvwxyzabcd                                        
william‣ abcdefghijklmnopqrstuvwxyzabcd %                                                  

如果我可以使 # hostname truncated 行取决于 PROMPT 长度,那么我就可以解决这个问题。

tldr

如何根据当前 PROMPT 的长度删除部分 PROMPT

好的,所以我解决了我自己的问题,但首先我不得不说这个问题是有缺陷的,因为我将提示的长度控制在终端的固定百分比 window 上。所以,我不能指望提示会这样做

william‣ wmbp‣ ~ %                                                                          
william‣ wmbp‣ ~ % cd abcdefghijklmnopqrstuvwxyzabcd                                        
william‣ abcdefghijklmnopqrstuvwxyzabcd %

但我能做的就是期待终端这样做

william‣ wmbp‣ Desktop %
william‣ wmbp‣ Desktop % cd abcdefghijk
william‣ abcdefghijk %

因为 % 从一行到下一行对齐。

我得到这个解决方案的方法是在我的 zshrc

中使用它
LENGTH_OF_USERNAME=8
LENGTH_OF_HOSTNAME=5
# calc % of prompt
function termWidthPercentHelper() { echo $(( int(${COLUMNS:-80}) * /100)) }
function hostNameInPromptHelper() {
    # if you are in the home directory or if you are in a directory with a name
    # that has a length which is less than % of the terminal's width
    if [[ ${PWD##*/} == ${HOME##*/} ]] || [[ ${#PWD##*/} -lt $(termWidthPercentHelper ) ]] then
        echo "%F{blue}%${LENGTH_OF_HOSTNAME}>‣>%m%>>%f "
    fi
}
PROMPT_PERCENTAGE='$(termWidthPercentHelper 30)'
HOST_NAME_IN_PROMPT='$(hostNameInPromptHelper 9)'
# left prompt
export PROMPT="%F{cyan}%${PROMPT_PERCENTAGE}<◀︎<%f" # truncation based on terminal width
PROMPT+='%(l.' # inner truncation group
PROMPT+="%F{cyan}%${LENGTH_OF_USERNAME}>‣>%n%>>%f " # username truncated
PROMPT+="${HOST_NAME_IN_PROMPT}"
PROMPT+='.)' # end truncation
PROMPT+='%F{magenta}%1~%f%<< ' # pwd 1 depth
PROMPT+='%# ' # privilege group

我用函数调用 PROMPT+="${HOST_NAME_IN_PROMPT}" 替换了旧行 PROMPT+="%-${inWidth}(l. %F{blue}%5>‣>%m%>>%f.) " # hostname truncated。这样我就可以检查当前目录的长度,然后显示 主机名 或者如果当前目录太长则不显示主机名。

帮助我找到这个解决方案的事情

  1. [[ ${PWD##*/} == ${HOME##*/} ]] returns 如果您在主目录中则为真
  2. ${#PWD##*/} gives the length of the present working directory without calling a subprocess

结论

如果我想将整个提示保留在我的终端屏幕的某个百分比,如之前命名的 widthHelper 函数调用中所示,我想做的事情是不可能的。

如果我输入一个名称很长的目录(请参阅上面 hostNameInPromptHelper 的定义),我的终端将无法显示我的 PROMPT 的一部分。我还调整了提示的屏幕百分比值(即 PROMPT_PERCENTAGE='$(termWidthPercentHelper 30)')和在我不显示之前目录名称的长度可以占用我的屏幕百分比的值主机名(即 HOST_NAME_IN_PROMPT='$(hostNameInPromptHelper 9)')。这些值对我有用,但如果您可能想调整这些值直到您喜欢您的提示。

来源