Shell

zsh 不會在提示符中重新載入函式

  • June 16, 2020

我試圖讓 zsh 提示在每次載入新提示時重新載入一個函式。如果函式的輸出是,函式將輸出的版本,pwd但會更短。如果我更改目錄,該功能有效,但不會重新載入。這是 zsh 的問題,而不是函式的問題,因為函式在 ksh 和 csh 中執行良好。我不使用 oh-my-zsh。函式是,文件是。pwd``~/Downloads/Folder``~/D/Folder``_collapsed_pwd``$SHELLDIR/cpwdrc

這是我的.zshrc文件

export SHELLDIR="$XDG_CONFIG_HOME/shells"
export ZSH="$SHELLDIR/zsh"
export HISTFILE="$XDG_DATA_HOME"/zsh/history

autoload -U +X compinit && compinit
fpath=($ZSH/plugins/zsh-completions/src $fpath)
compinit -d $XDG_CACHE_HOME/zsh/zcompdump-artix-5.8

source $SHELLDIR/aliasrc
source $SHELLDIR/colorsrc # contians color substituions

source $SHELLDIR/cpwdrc # contains _collapsed_pwd

source $ZSH/plugins/fzf-tab/fzf-tab.zsh
source $ZSH/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh

setopt prompt_subst

PS1=$(printf "${BOLD}${BLUE}%s${NORM}@%s:[${BLUE}%s${NORM}]:$ " $USER $(hostname) $(_collapsed_pwd) )

這是函式的程式碼_collapsed_pwd

#!/bin/sh
## Collapsed Directory
_collapsed_pwd() {
 pwd | perl -pe '
  BEGIN {
     binmode STDIN,  ":encoding(UTF-8)";
     binmode STDOUT, ":encoding(UTF-8)";
  }; s|^$ENV{HOME}|~|g; s|/([^/.])[^/]*(?=/)|/$1|g; s|/\.([^/])[^/]*(?=/)|/.$1|g
'
}

您在處理時一勞永逸地設置提示的內容.zshrc。噹噹前目錄更改時,您的程式碼中沒有任何內容可以更改提示的內容。

一種解決方案是將更改提示的程式碼放在一個chpwd鉤子中。刪除setopt prompt_subst,因為您不會對PS1.

function set_prompt {
 PS1=$(printf "${BOLD}${BLUE}%s${NORM}@%s:[${BLUE}%s${NORM}]:$ " $USER $(hostname) "${$(_collapsed_pwd)//\%/%%}" )
}
chpwd_functions+=(set_prompt)
cd .

說明:

  • cd .zsh 啟動時觸發chpwd一次鉤子,以便初始設置提示。
  • 如果輸出包含空格,則命令替換周圍的雙引號可防止將其拆分為單獨的單詞。
  • ${…//\%/%%}圍繞_collapsed_pwd更改輸出的替換因為%將被解釋為提示轉義¹。%%``%

或者,設置prompt_subst選項並設置PS1為包含每次顯示提示時都會評估的程式碼的字元串。

setopt prompt_subst
PS1='$(printf "${BOLD}${BLUE}%s${NORM}@%s:[${BLUE}%s${NORM}]:$ " $USER $(hostname) "${$(_collapsed_pwd)//\%/%%}" )'

您可以通過使用 zsh 的內置功能在 prompt 中包含可變數據來大大簡化這一點。首先,這是一個顯示目前目錄的最後兩個組件的提示:

unsetopt prompt_subst
PS1='%B%F{blue}%n%f%b@%m:[%F{blue}%2~%f]:%(!.#.$) '

為了縮寫目錄組件,我認為您必須執行一些 zsh 程式碼,通過chpwd鉤子或通過prompt_subst. 為避免與擴展相關的複雜性,請使用chpwd掛鉤在提示字元串中設置psvar%v引用。psvar

unsetopt prompt_subst
PS1='%B%F{blue}%n%f%b@%m:[%F{blue}%1v%f]:%(!.#.$) '
function abbreviate_pwd {
 psvar[1]=${(%):-%~}
 while [[ $psvar[1] =~ /[^/][^/]+/ ]]; do
   psvar[1]=${psvar[1][1,MBEGIN+1]}${psvar[1][MEND,-1]}
 done
}
chpwd_functions+=(abbreviate_pwd)
cd .

¹為了獲得額外的穩健性,$USER(另請參閱$USERNAME由 自動設置zsh)和$(hostname)(另請參閱$HOST由 自動設置zsh)也應受到保護,但它們通常不包含任何有問題的字元,假設您不更改 的值IFS以包含出現在主機名中的字元。

引用自:https://unix.stackexchange.com/questions/593070