我正在尝试编写一个ZSH主题,该主题根据Git状态(如果在git repo中)显示特定的字符。我以前在Bash中实现了此主题,但是在迁移到ZSH时遇到了一些问题。这可能是我自己的错,但如果有人可以帮助,将不胜感激。
我主题的相关部分:
local jobs="%{$terminfo[bold]$fg[cyan]%}[%{$fg[magenta]%}%j%{$terminfo[bold]$fg[cyan]%}]%{$reset_color%}"
local git_branch='$(git_prompt_info)%{$reset_color%}'
local current_dir="%{$terminfo[bold]$fg[orange]%}%~%{$reset_color%}"
if [[ $UID -eq 0 ]]; then
local user_host="%{$terminfo[bold]$fg[red]%}%n@%m%{$reset_color%}"
local user_symbol="#"
else
local user_host="%{$terminfo[bold]$fg[green]%}%n@%{$fg[red]%}%m%{$reset_color%}"
local user_symbol="$"
fi
function git_has_unstaged() {
if ! $(git diff-files --quiet --ignore-submodules --); then
echo -n "%*! ";
fi;
}
function git_has_uncommitted() {
if [ ! $(git diff --quiet --ignore-submodules --cached; echo "${?}") = "0" ]; then
echo -n "%*+ ";
fi;
}
function git_has_untracked() {
if [ -n "$(git ls-files --others --exclude-standard)" ]; then
echo -n "%*? ";
fi;
}
function git_has_stashed() {
if $(git rev-parse --verify refs/stash &>/dev/null); then
echo -n "%*$ ";
fi;
}
function git_status_symbols() {
echo -n "%{$terminfo[bold]$fg[blue]%}[";
if [ $(git rev-parse --is-inside-work-tree &>/dev/null; echo "${?}") = "0" ]; then
#Now is it Git repo
if [ "$(git rev-parse --is-inside-git-dir 2> /dev/null)" = "false" ]; then
# check if the current directory is in .git before running git checks
# Ensure the index is up to date.
git update-index --really-refresh -q &>/dev/null;
git_has_uncommitted;
git_has_unstaged;
git_has_untracked;
git_has_stashed;
fi;
fi;
echo -n "]%{$reset_color%}";
}
PROMPT="╭─${user_host} ${current_dir} ${jobs} ${git_branch} $(git_status_symbols)
╰─%B${user_symbol}%b "
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg[yellow]%}‹"
ZSH_THEME_GIT_PROMPT_SUFFIX="›%{$reset_color%}"
我的问题是提示中的git_status_symbols值不会根据fs / git中的更新而更新。示例:
╭─theonlyjohnny@phoenix ~/configs [0] ‹bored› []
╰─$ git status
On branch bored
Your branch is up to date with 'origin/bored'.
nothing to commit, working tree clean
╭─theonlyjohnny@phoenix ~/configs [0] ‹bored› []
╰─$ touch ./t
╭─theonlyjohnny@phoenix ~/configs [0] ‹bored› []
╰─$ git_has_untracked
%*? % ╭─theonlyjohnny@phoenix ~/configs [0] ‹bored› []
╰─$ zsh
╭─theonlyjohnny@phoenix ~/configs [0] ‹bored› [1:50:37? ]
╰─$
╭─theonlyjohnny@phoenix ~/configs [0] ‹bored› [1:52:14? ]
╰─$ rm t
╭─theonlyjohnny@phoenix ~/configs [0] ‹bored› [1:52:16? ]
╰─$ git_has_untracked
╭─theonlyjohnny@phoenix ~/configs [0] ‹bored› [1:52:22? ]
╰─$ zsh
╭─theonlyjohnny@phoenix ~/configs [0] ‹bored› []
╰─$
如您所见,虽然我的git_has_untracked
函数正确地回显了?,但直到我启动新的shell时,提示符才会反映出来。删除未跟踪的文件后,git_has_untracked
函数将不再正确回显任何内容。这里有趣的是时间仍然在更新。创建新外壳后,提示再次正确。
任何帮助表示赞赏!谢谢
答案 0 :(得分:0)
之所以发生这种情况,是因为您的PROMPT
变量包含命令替换$(git_status_symbols)
。该评估在分配期间进行一次,而不是在PROMPT
的每次扩展中进行。
解决此问题的最简单方法是使用填充precmd
数组的psvar
,然后以%v
的形式将该值插入到提示中。例如:
precmd () { psvar[1]=$(git_status_symbols); }
PROMPT="╭─${user_host} ${current_dir} ${jobs} ${git_branch} %1v
╰─%B${user_symbol}%b "
另外,请注意zsh拥有自己的vcs支持(用于Git和其他),您可能希望也可能不想使用它来代替编写自定义代码。