Тема ZSH не обновляется из функции

#git #shell #themes #zsh

#git #оболочка #темы #zsh

Вопрос:

Я пытаюсь написать тему ZSH, которая отображает определенные символы в зависимости от статуса Git (если внутри репозитория git). Ранее я реализовывал эту тему в 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 amp;>/dev/null); then
      echo -n "%*$ ";
  fi;
}

function git_status_symbols() {
  echo -n "%{$terminfo[bold]$fg[blue]%}[";
  if [ $(git rev-parse --is-inside-work-tree amp;>/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 amp;>/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 функция правильно повторяет a ? , приглашение не отражает это, пока я не запущу новую оболочку. После удаления неотслеживаемого файла git_has_untracked функция должным образом больше ничего не отображает. Что здесь интересно, так это то, что время все еще обновляется. При создании новой оболочки запрос снова корректен.

Любая помощь приветствуется! Спасибо

Ответ №1:

Это происходит потому, что ваша PROMPT переменная содержит команду подстановки $(git_status_symbols) . Эта оценка происходит один раз во время назначения, а не при каждом расширении PROMPT .

Самый простой способ исправить это — использовать a, 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 и других), которую вы можете использовать, а можете и не использовать вместо написания пользовательского кода.